-
Notifications
You must be signed in to change notification settings - Fork 212
Expand file tree
/
Copy pathSwitchModeTool.ts
More file actions
88 lines (69 loc) · 2.7 KB
/
Copy pathSwitchModeTool.ts
File metadata and controls
88 lines (69 loc) · 2.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import delay from "delay"
import { Task } from "../task/Task"
import { formatResponse } from "../prompts/responses"
import { defaultModeSlug, getModeBySlug } from "../../shared/modes"
import { BaseTool, ToolCallbacks } from "./BaseTool"
import type { ToolUse } from "../../shared/tools"
interface SwitchModeParams {
mode_slug: string
reason: string
}
export class SwitchModeTool extends BaseTool<"switch_mode"> {
readonly name = "switch_mode" as const
async execute(params: SwitchModeParams, task: Task, callbacks: ToolCallbacks): Promise<void> {
const { mode_slug, reason } = params
const { askApproval, handleError, pushToolResult } = callbacks
try {
if (!mode_slug) {
task.consecutiveMistakeCount++
task.recordToolError("switch_mode")
pushToolResult(await task.sayAndCreateMissingParamError("switch_mode", "mode_slug"))
return
}
task.consecutiveMistakeCount = 0
// Verify the mode exists
const targetMode = getModeBySlug(mode_slug, (await task.providerRef.deref()?.getState())?.customModes)
if (!targetMode) {
task.recordToolError("switch_mode")
task.didToolFailInCurrentTurn = true
pushToolResult(formatResponse.toolError(`Invalid mode: ${mode_slug}`))
return
}
// Check if already in requested mode
const currentMode = (await task.providerRef.deref()?.getState())?.mode ?? defaultModeSlug
if (currentMode === mode_slug) {
task.recordToolError("switch_mode")
task.didToolFailInCurrentTurn = true
pushToolResult(`Already in ${targetMode.name} mode.`)
return
}
const completeMessage = JSON.stringify({ tool: "switchMode", mode: mode_slug, reason })
const didApprove = await askApproval("tool", completeMessage)
if (!didApprove) {
return
}
// Switch the mode using shared handler
// via: "switch_mode" — explicit tool call
await task.providerRef.deref()?.handleModeSwitch(mode_slug, "switch_mode")
pushToolResult(
`Successfully switched from ${getModeBySlug(currentMode)?.name ?? currentMode} mode to ${
targetMode.name
} mode${reason ? ` because: ${reason}` : ""}.`,
)
await delay(500) // Delay to allow mode change to take effect before next tool is executed
} catch (error) {
await handleError("switching mode", error as Error)
}
}
override async handlePartial(task: Task, block: ToolUse<"switch_mode">): Promise<void> {
const mode_slug: string | undefined = block.params.mode_slug
const reason: string | undefined = block.params.reason
const partialMessage = JSON.stringify({
tool: "switchMode",
mode: mode_slug ?? "",
reason: reason ?? "",
})
await task.ask("tool", partialMessage, block.partial).catch(() => {})
}
}
export const switchModeTool = new SwitchModeTool()