feat: create new tools list_active_intents and select_active_intent

This commit is contained in:
leuel-a 2026-02-20 11:41:07 +03:00
parent ef17942cd4
commit e0d0019192
13 changed files with 76 additions and 19 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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[]
}

View file

@ -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

View file

@ -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<void> {
throw new Error("Method not implemented.")
}
}

View file

@ -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<ToolResult>,
ctx: HookContext,
): Promise<ToolResult> {
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
}
}

View file

@ -290,12 +290,13 @@ export const TOOL_DISPLAY_NAMES: Record<ToolName, string> = {
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<ToolGroup, ToolGroupConfig> = {
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"],