Skip to content

Commit 5d0e87a

Browse files
committed
feat(message): add external flag to ToolPart to exclude plugin tool calls from model context
External tool parts are displayed in the TUI and persisted, but excluded from toModelMessages() to prevent orphaned tool_use/tool_result pairs. Plugins and HTTP endpoints can mark their tool executions as external.
1 parent da2e91c commit 5d0e87a

File tree

2 files changed

+629
-0
lines changed

2 files changed

+629
-0
lines changed

packages/opencode/src/session/message-v2.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,10 @@ export namespace MessageV2 {
344344
tool: z.string(),
345345
state: ToolState,
346346
metadata: z.record(z.string(), z.any()).optional(),
347+
/** When true, this tool execution was initiated externally (not by the LLM).
348+
* External parts are displayed in the TUI and persisted, but excluded from
349+
* model messages to prevent orphaned tool_use/tool_result pairs. */
350+
external: z.boolean().optional(),
347351
}).meta({
348352
ref: "ToolPart",
349353
})
@@ -719,6 +723,9 @@ export namespace MessageV2 {
719723
type: "step-start",
720724
})
721725
if (part.type === "tool") {
726+
// External tool executions (from plugins/HTTP, not LLM) are display-only.
727+
// Including them would create orphaned tool_use/tool_result pairs.
728+
if (part.external) continue
722729
toolNames.add(part.tool)
723730
if (part.state.status === "completed") {
724731
const outputText = part.state.time.compacted ? "[Old tool result content cleared]" : part.state.output

0 commit comments

Comments
 (0)