diff --git a/packages/types/src/tool.ts b/packages/types/src/tool.ts index 3655a5f29e..1c81f4c6f5 100644 --- a/packages/types/src/tool.ts +++ b/packages/types/src/tool.ts @@ -47,6 +47,7 @@ export const toolNames = [ "generate_image", "custom_tool", "select_active_intent", + "list_active_intents", ] as const export const toolNamesSchema = z.enum(toolNames) diff --git a/src/core/assistant-message/presentAssistantMessage.ts b/src/core/assistant-message/presentAssistantMessage.ts index 2c75943cd9..dacdd07675 100644 --- a/src/core/assistant-message/presentAssistantMessage.ts +++ b/src/core/assistant-message/presentAssistantMessage.ts @@ -17,6 +17,7 @@ import { Task } from "../task/Task" import { listFilesTool } from "../tools/ListFilesTool" import { readFileTool } from "../tools/ReadFileTool" import { readCommandOutputTool } from "../tools/ReadCommandOutputTool" +import { listActiveIntentsTool } from "../tools/ListActiveIntents" import { selectActiveIntentTool } from "../tools/SelectActiveIntent" import { writeToFileTool } from "../tools/WriteToFileTool" import { editTool } from "../tools/EditTool" @@ -336,8 +337,10 @@ export async function presentAssistantMessage(cline: Task) { return readFileTool.getReadFileToolDescription(block.name, block.nativeArgs) } return readFileTool.getReadFileToolDescription(block.name, block.params) - case "select_active_intent": + case "list_active_intents": return `[${block.name}]` + case "select_active_intent": + return `[${block.name}] for '${block.params.path}'` case "write_to_file": return `[${block.name} for '${block.params.path}']` case "apply_diff": @@ -679,7 +682,19 @@ export async function presentAssistantMessage(cline: Task) { } switch (block.name) { + case "list_active_intents": + await listActiveIntentsTool.handle(cline, block as ToolUse<"list_active_intents">, { + askApproval, + handleError, + pushToolResult, + }) + break case "select_active_intent": + await selectActiveIntentTool.handle(cline, block as ToolUse<"select_active_intent">, { + askApproval, + handleError, + pushToolResult, + }) break case "write_to_file": await checkpointSaveAndMark(cline) diff --git a/src/core/prompts/tools/native-tools/index.ts b/src/core/prompts/tools/native-tools/index.ts index adbb294ecb..81e44645ba 100644 --- a/src/core/prompts/tools/native-tools/index.ts +++ b/src/core/prompts/tools/native-tools/index.ts @@ -21,6 +21,7 @@ import switchMode from "./switch_mode" import updateTodoList from "./update_todo_list" import writeToFile from "./write_to_file" import selectActiveIntent from "./select_active_intent" +import listActiveIntents from "./list_active_intents" export { getMcpServerTools } from "./mcp_server" export { convertOpenAIToolToAnthropic, convertOpenAIToolsToAnthropic } from "./converters" @@ -70,6 +71,7 @@ export function getNativeTools(options: NativeToolsOptions = {}): OpenAI.Chat.Ch updateTodoList, writeToFile, selectActiveIntent, + listActiveIntents, ] satisfies OpenAI.Chat.ChatCompletionTool[] } diff --git a/src/core/prompts/tools/native-tools/list_active_intents.ts b/src/core/prompts/tools/native-tools/list_active_intents.ts new file mode 100644 index 0000000000..37e8fd5b4f --- /dev/null +++ b/src/core/prompts/tools/native-tools/list_active_intents.ts @@ -0,0 +1,12 @@ +import type OpenAI from "openai" + +const LIST_ACTIVE_INTENT_DESCRIPTION = `` +// TODO: add params here later for the list active intents + +export default { + type: "function", + function: { + name: "list_active_intents", + description: LIST_ACTIVE_INTENT_DESCRIPTION, + }, +} satisfies OpenAI.Chat.ChatCompletionTool diff --git a/src/core/tools/ListActiveIntents.ts b/src/core/tools/ListActiveIntents.ts new file mode 100644 index 0000000000..83a2a079e0 --- /dev/null +++ b/src/core/tools/ListActiveIntents.ts @@ -0,0 +1,10 @@ +import { Task } from "../task/Task" +import { BaseTool, ToolCallbacks } from "./BaseTool" + +export class ListActiveIntent extends BaseTool<"list_active_intents"> { + readonly name = "list_active_intents" as const + + override execute(_params: any, _task: Task, _callbacks: ToolCallbacks): Promise { + throw new Error("Method not implemented.") + } +} diff --git a/src/hooks/HookEngine.ts b/src/hooks/HookEngine.ts index 3f94f0d407..3da5988ddf 100644 --- a/src/hooks/HookEngine.ts +++ b/src/hooks/HookEngine.ts @@ -1,25 +1,41 @@ -import { Task } from "../core/task/Task" -import { OrchestrationStore } from "../orchestration/OrchestrationStore" - -interface HookEngineOptions { - task: Task -} - export class HookEngine { - private readonly store: OrchestrationStore + private preHooks: PreHook[] = [] + private postHooks: PostHook[] = [] - constructor({ task }: HookEngineOptions) { - this.store = new OrchestrationStore({ workspaceRoot: task.cwd }) + registerPre(hook: PreHook) { + this.preHooks.push(hook) } - /** Called before any tool execution */ - preToolHook() { - this.store.ensureInitialized() + registerPost(hook: PostHook) { + this.postHooks.push(hook) } - /** Called after any tool execution */ - postToolHook() {} + /** + * Wrap a tool execution with pre/post hooks. + * `exec` is your existing tool runner: (toolName, args) => result + */ + async runTool( + call: ToolCall, + exec: (call: ToolCall) => Promise, + ctx: HookContext, + ): Promise { + for (const hook of this.preHooks) { + const decision = await hook(call, ctx) + if (decision.action === "short_circuit") { + // Even short-circuited results go through post hooks (optional, but useful) + for (const post of this.postHooks) { + await post(call, decision.result, ctx) + } + return decision.result + } + } - /** */ - preLLMHook() {} + const result = await exec(call) + + for (const post of this.postHooks) { + await post(call, result, ctx) + } + + return result + } } diff --git a/src/hooks/postHooks/intentUpdater.ts b/src/hooks/postHooks/intentUpdater.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/hooks/postHooks/lessonRecorder.ts b/src/hooks/postHooks/lessonRecorder.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/hooks/postHooks/traceWriter.ts b/src/hooks/postHooks/traceWriter.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/hooks/preHooks/authorization.ts b/src/hooks/preHooks/authorization.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/hooks/preHooks/intentHandshake.ts b/src/hooks/preHooks/intentHandshake.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/hooks/preHooks/scopeGuard.ts b/src/hooks/preHooks/scopeGuard.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/shared/tools.ts b/src/shared/tools.ts index d64aeb8bfe..6b9c676861 100644 --- a/src/shared/tools.ts +++ b/src/shared/tools.ts @@ -290,12 +290,13 @@ export const TOOL_DISPLAY_NAMES: Record = { generate_image: "generate images", custom_tool: "use custom tools", select_active_intent: "select the active intent", + list_active_intents: "list active intents", } as const // Define available tool groups. export const TOOL_GROUPS: Record = { read: { - tools: ["read_file", "search_files", "list_files", "codebase_search"], + tools: ["read_file", "search_files", "list_files", "codebase_search", "select_active_intent"], }, edit: { tools: ["apply_diff", "write_to_file", "generate_image"],