From 1ff42d8ca374ccd90e2558bdf9a21ed72f56b7c8 Mon Sep 17 00:00:00 2001 From: ops Date: Wed, 4 Feb 2026 03:29:34 +0100 Subject: [PATCH 1/2] Port tool-stop-metadata from opencode Allow custom tools to send stop tag metadata. --- packages/opencode/src/session/processor.ts | 7 +++++++ packages/opencode/src/tool/registry.ts | 21 +++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/packages/opencode/src/session/processor.ts b/packages/opencode/src/session/processor.ts index 57c038afa..58f451b94 100644 --- a/packages/opencode/src/session/processor.ts +++ b/packages/opencode/src/session/processor.ts @@ -36,6 +36,7 @@ export namespace SessionProcessor { let attempt = 0 let needsCompaction = false let stepStart = 0 // kilocode_change + let shouldStopAfterTool = false const result = { get message() { @@ -190,6 +191,10 @@ export namespace SessionProcessor { }, }) + if (value.output.metadata?.stop === true) { + shouldStopAfterTool = true + } + delete toolcalls[value.toolCallId] } break @@ -358,6 +363,7 @@ export namespace SessionProcessor { continue } if (needsCompaction) break + if (shouldStopAfterTool) break } } catch (e: any) { log.error("process", { @@ -424,6 +430,7 @@ export namespace SessionProcessor { if (needsCompaction) return "compact" if (blocked) return "stop" if (input.assistantMessage.error) return "stop" + if (shouldStopAfterTool) return "stop" return "continue" } }, diff --git a/packages/opencode/src/tool/registry.ts b/packages/opencode/src/tool/registry.ts index 5d61cfa48..b59d2862b 100644 --- a/packages/opencode/src/tool/registry.ts +++ b/packages/opencode/src/tool/registry.ts @@ -70,11 +70,24 @@ export namespace ToolRegistry { worktree: Instance.worktree, } as unknown as PluginToolContext const result = await def.execute(args as any, pluginCtx) - const out = await Truncate.output(result, {}, initCtx?.agent) + if (typeof result === "string") { + const out = await Truncate.output(result, {}, initCtx?.agent) + return { + title: id, + output: out.truncated ? out.content : result, + metadata: { truncated: out.truncated, outputPath: out.truncated ? out.outputPath : undefined }, + } + } + const res = result as { title?: string; output: string; metadata?: { [key: string]: any } } + const out = await Truncate.output(res.output, {}, initCtx?.agent) return { - title: "", - output: out.truncated ? out.content : result, - metadata: { truncated: out.truncated, outputPath: out.truncated ? out.outputPath : undefined }, + title: res.title ?? id, + output: out.truncated ? out.content : res.output, + metadata: { + ...(res.metadata ?? {}), + truncated: out.truncated, + outputPath: out.truncated ? out.outputPath : undefined, + }, } }, }), From 2495de180bb7aeb8825dcda072e1bad7619427db Mon Sep 17 00:00:00 2001 From: ops Date: Sat, 21 Feb 2026 23:20:02 +0100 Subject: [PATCH 2/2] fix: update ToolDefinition type, add validation for structured return --- packages/opencode/src/tool/registry.ts | 11 ++++++----- packages/plugin/src/tool.ts | 4 +++- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/opencode/src/tool/registry.ts b/packages/opencode/src/tool/registry.ts index b59d2862b..2d83819bb 100644 --- a/packages/opencode/src/tool/registry.ts +++ b/packages/opencode/src/tool/registry.ts @@ -78,13 +78,14 @@ export namespace ToolRegistry { metadata: { truncated: out.truncated, outputPath: out.truncated ? out.outputPath : undefined }, } } - const res = result as { title?: string; output: string; metadata?: { [key: string]: any } } - const out = await Truncate.output(res.output, {}, initCtx?.agent) + if (typeof result !== "object" || result === null || !("output" in result)) + throw new Error(`Tool ${id} returned unexpected value: ${typeof result}`) + const out = await Truncate.output(result.output, {}, initCtx?.agent) return { - title: res.title ?? id, - output: out.truncated ? out.content : res.output, + title: result.title ?? id, + output: out.truncated ? out.content : result.output, metadata: { - ...(res.metadata ?? {}), + ...(result.metadata ?? {}), truncated: out.truncated, outputPath: out.truncated ? out.outputPath : undefined, }, diff --git a/packages/plugin/src/tool.ts b/packages/plugin/src/tool.ts index 23aa512d9..cfe3ce362 100644 --- a/packages/plugin/src/tool.ts +++ b/packages/plugin/src/tool.ts @@ -26,10 +26,12 @@ type AskInput = { metadata: { [key: string]: any } } +export type ToolResult = string | { title?: string; output: string; metadata?: Record } + export function tool(input: { description: string args: Args - execute(args: z.infer>, context: ToolContext): Promise + execute(args: z.infer>, context: ToolContext): Promise }) { return input }