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
}