From 53b811112179294687ae600ab7f1047550cf322d Mon Sep 17 00:00:00 2001 From: Dax Raad Date: Tue, 4 Aug 2026 17:04:51 -0400 Subject: [PATCH] refactor: rename tool call ID fields --- packages/ai/src/tool.ts | 16 ++--- packages/ai/test/tool-runtime.test.ts | 2 +- packages/ai/test/tool.types.ts | 4 +- packages/cli/src/acp/event.ts | 28 ++++----- packages/cli/src/acp/permission.ts | 2 +- packages/cli/src/run/noninteractive.ts | 36 +++++------ packages/cli/test/acp/event-behavior.test.ts | 16 ++--- .../cli/test/acp/permission-behavior.test.ts | 22 +++---- packages/cli/test/run/noninteractive.test.ts | 16 ++--- packages/client/src/effect/api/api.ts | 10 +-- .../client/src/promise/generated/types.ts | 32 +++++----- packages/core/src/session/message-updater.ts | 16 ++--- packages/core/src/session/runner/llm.ts | 2 +- .../src/session/runner/publish-llm-event.ts | 62 +++++++++---------- packages/core/src/tool.ts | 6 +- packages/core/src/tool/AGENTS.md | 2 +- packages/core/src/tool/mcp.ts | 2 +- packages/core/src/tool/plugin/edit.ts | 2 +- packages/core/src/tool/plugin/glob.ts | 2 +- packages/core/src/tool/plugin/grep.ts | 2 +- packages/core/src/tool/plugin/patch.ts | 2 +- packages/core/src/tool/plugin/question.ts | 4 +- packages/core/src/tool/plugin/read.ts | 2 +- packages/core/src/tool/plugin/shell.ts | 14 ++--- packages/core/src/tool/plugin/skill.ts | 2 +- packages/core/src/tool/plugin/subagent.ts | 2 +- packages/core/src/tool/plugin/webfetch.ts | 2 +- packages/core/src/tool/plugin/websearch.ts | 2 +- packages/core/src/tool/plugin/write.ts | 2 +- packages/core/test/database-migration.test.ts | 8 +-- packages/core/test/mcp.test.ts | 2 +- packages/core/test/session-generate.test.ts | 6 +- .../test/session-runner-tool-events.test.ts | 2 +- .../test/session-runner-tool-registry.test.ts | 2 +- packages/core/test/session-runner.test.ts | 38 ++++++------ .../core/test/session-tool-progress.test.ts | 14 ++--- packages/core/test/tool-execute.test.ts | 2 +- packages/core/test/tool-question.test.ts | 4 +- packages/plugin/src/effect/tool.ts | 4 +- packages/plugin/src/promise/tool.ts | 4 +- packages/schema/src/permission.ts | 2 +- packages/schema/src/question.ts | 2 +- packages/schema/src/session-event.ts | 2 +- packages/schema/src/tool.ts | 2 +- packages/schema/test/event-manifest.test.ts | 2 +- .../src/backend/simulated-provider.ts | 2 +- packages/simulation/src/protocol/index.ts | 2 +- .../test/simulated-provider.test.ts | 16 ++--- packages/tui/src/context/data.tsx | 18 +++--- packages/tui/src/mini/demo.ts | 4 +- packages/tui/src/mini/stream-v2.subagent.ts | 34 +++++----- packages/tui/src/mini/stream-v2.transport.ts | 52 ++++++++-------- packages/tui/src/mini/types.ts | 4 +- packages/tui/src/routes/session/index.tsx | 2 +- .../tui/src/routes/session/permission.tsx | 2 +- packages/tui/src/routes/session/rows.ts | 4 +- packages/tui/test/cli/tui/data.test.tsx | 12 ++-- .../tui/test/mini/permission.shared.test.ts | 6 +- .../tui/test/mini/stream-v2.transport.test.ts | 58 ++++++++--------- packages/www/content/docs/build/plugins.mdx | 4 +- 60 files changed, 314 insertions(+), 314 deletions(-) diff --git a/packages/ai/src/tool.ts b/packages/ai/src/tool.ts index 25df2be2878..44dd6984a30 100644 --- a/packages/ai/src/tool.ts +++ b/packages/ai/src/tool.ts @@ -24,7 +24,7 @@ export type ToolExecute, Success extends Tool ) => Effect.Effect, ToolFailure> export interface ToolModelOutputInput { - readonly callID: ToolCallPart["id"] + readonly id: ToolCallPart["id"] readonly parameters: Parameters readonly output: Output } @@ -59,7 +59,7 @@ export interface Definition, Success extends /** @internal */ readonly _project: ( parameters: Schema.Schema.Type, - callID: ToolCallPart["id"], + id: ToolCallPart["id"], output: unknown, ) => ToolOutputType /** @internal */ @@ -173,8 +173,8 @@ export function make(config: TypedToolConfig | DynamicToolConfig): AnyTool { toStructuredOutput: config.toStructuredOutput, _decode: Effect.succeed, _encode: Effect.succeed, - _project: (parameters, callID, output) => - project(config.toModelOutput, config.toStructuredOutput, parameters, callID, output), + _project: (parameters, id, output) => + project(config.toModelOutput, config.toStructuredOutput, parameters, id, output), _legacyResult: config.toModelOutput === undefined && config.toStructuredOutput === undefined, _definition: new ToolDefinition({ name: "", @@ -193,8 +193,8 @@ export function make(config: TypedToolConfig | DynamicToolConfig): AnyTool { toStructuredOutput: config.toStructuredOutput, _decode: Schema.decodeUnknownEffect(config.parameters), _encode: Schema.encodeEffect(config.success), - _project: (parameters, callID, output) => - project(config.toModelOutput, config.toStructuredOutput, parameters, callID, output), + _project: (parameters, id, output) => + project(config.toModelOutput, config.toStructuredOutput, parameters, id, output), _legacyResult: false, _definition: new ToolDefinition({ name: "", @@ -239,12 +239,12 @@ const project = ( toModelOutput: ((input: ToolModelOutputInput) => ReadonlyArray) | undefined, toStructuredOutput: ((output: unknown) => unknown) | undefined, parameters: unknown, - callID: ToolCallPart["id"], + id: ToolCallPart["id"], output: unknown, ): ToolOutputType => ToolOutput.make( toStructuredOutput?.(output) ?? output, - toModelOutput?.({ callID, parameters, output }) ?? + toModelOutput?.({ id, parameters, output }) ?? (typeof output === "string" ? [{ type: "text", text: output }] : []), ) diff --git a/packages/ai/test/tool-runtime.test.ts b/packages/ai/test/tool-runtime.test.ts index 227f07fc245..85ea829b437 100644 --- a/packages/ai/test/tool-runtime.test.ts +++ b/packages/ai/test/tool-runtime.test.ts @@ -169,7 +169,7 @@ describe("LLMClient tools", () => { LLMEvent.toolCall({ id: "call_projected", name: "projected", input: { prefix: "count" } }), ) - expect(calls).toEqual([{ callID: "call_projected", parameters: { prefix: "count" }, output: { count: "2" } }]) + expect(calls).toEqual([{ id: "call_projected", parameters: { prefix: "count" }, output: { count: "2" } }]) expect(dispatched.result).toEqual({ type: "text", value: "count:2" }) expect(dispatched.output).toEqual({ structured: { count: "2" }, content: [{ type: "text", text: "count:2" }] }) expect(dispatched.events).toEqual([ diff --git a/packages/ai/test/tool.types.ts b/packages/ai/test/tool.types.ts index 2bd33df545f..611de720e63 100644 --- a/packages/ai/test/tool.types.ts +++ b/packages/ai/test/tool.types.ts @@ -27,8 +27,8 @@ Tool.make({ parameters: Schema.Struct({ city: Schema.String }), success: Schema.Struct({ forecast: Schema.NumberFromString }), execute: () => Effect.succeed({ forecast: 1 }), - toModelOutput: ({ callID, parameters, output }) => [ - { type: "text", text: `${callID}:${parameters.city}:${output.forecast}` }, + toModelOutput: ({ id, parameters, output }) => [ + { type: "text", text: `${id}:${parameters.city}:${output.forecast}` }, ], }) diff --git a/packages/cli/src/acp/event.ts b/packages/cli/src/acp/event.ts index 380da2e22e8..33fcdd21837 100644 --- a/packages/cli/src/acp/event.ts +++ b/packages/cli/src/acp/event.ts @@ -72,7 +72,7 @@ export async function streamTurn(input: { if (next.done) throw new Error("event stream disconnected during prompt execution") const event = next.value if (event.type === "permission.asked" && event.data.sessionID === input.sessionID) { - const tool = event.data.source?.callID ? tools.get(event.data.source.callID) : undefined + const tool = event.data.source?.id ? tools.get(event.data.source.id) : undefined await replyPermission({ client: input.client, connection: input.connection, @@ -120,11 +120,11 @@ export async function streamTurn(input: { } if (event.type === "session.tool.input.started") { assistantMessageID = event.data.assistantMessageID - tools.set(event.data.callID, { name: event.data.name, input: {}, metadata: {}, content: [] }) + tools.set(event.data.id, { name: event.data.name, input: {}, metadata: {}, content: [] }) await update({ sessionUpdate: "tool_call", ...pendingToolCall({ - toolCallId: event.data.callID, + toolCallId: event.data.id, toolName: event.data.name, state: { input: {} }, cwd: input.cwd, @@ -134,13 +134,13 @@ export async function streamTurn(input: { } if (event.type === "session.tool.called") { assistantMessageID = event.data.assistantMessageID - const current = tools.get(event.data.callID) ?? emptyToolState() + const current = tools.get(event.data.id) ?? emptyToolState() current.input = event.data.input - tools.set(event.data.callID, current) + tools.set(event.data.id, current) await update({ sessionUpdate: "tool_call_update", ...runningToolUpdate({ - toolCallId: event.data.callID, + toolCallId: event.data.id, toolName: current.name, state: { input: current.input }, cwd: input.cwd, @@ -149,13 +149,13 @@ export async function streamTurn(input: { continue } if (event.type === "session.tool.progress") { - const current = tools.get(event.data.callID) + const current = tools.get(event.data.id) if (!current) continue current.metadata = event.data.metadata await update({ sessionUpdate: "tool_call_update", ...runningToolUpdate({ - toolCallId: event.data.callID, + toolCallId: event.data.id, toolName: current.name, state: { input: current.input }, cwd: input.cwd, @@ -164,8 +164,8 @@ export async function streamTurn(input: { continue } if (event.type === "session.tool.success") { - const current = tools.get(event.data.callID) ?? emptyToolState() - tools.delete(event.data.callID) + const current = tools.get(event.data.id) ?? emptyToolState() + tools.delete(event.data.id) await syncEditedFiles({ connection: input.connection, writeTextFile: input.writeTextFile, @@ -178,7 +178,7 @@ export async function streamTurn(input: { await update({ sessionUpdate: "tool_call_update", ...completedToolUpdate({ - toolCallId: event.data.callID, + toolCallId: event.data.id, toolName: current.name, input: current.input, metadata: event.data.metadata, @@ -188,12 +188,12 @@ export async function streamTurn(input: { continue } if (event.type === "session.tool.failed") { - const current = tools.get(event.data.callID) ?? emptyToolState() - tools.delete(event.data.callID) + const current = tools.get(event.data.id) ?? emptyToolState() + tools.delete(event.data.id) await update({ sessionUpdate: "tool_call_update", ...errorToolUpdate({ - toolCallId: event.data.callID, + toolCallId: event.data.id, toolName: current.name, input: current.input, metadata: event.data.metadata ?? current.metadata, diff --git a/packages/cli/src/acp/permission.ts b/packages/cli/src/acp/permission.ts index 948ad0eeace..d32073442ea 100644 --- a/packages/cli/src/acp/permission.ts +++ b/packages/cli/src/acp/permission.ts @@ -31,7 +31,7 @@ export async function replyPermission(input: { sessionId: input.sessionID, toolCall: { ...pendingToolCall({ - toolCallId: input.event.data.source?.callID ?? input.event.data.id, + toolCallId: input.event.data.source?.id ?? input.event.data.id, toolName, state: { input: toolInput, title: permissionTitle(toolName, toolInput, previews) }, cwd: input.cwd, diff --git a/packages/cli/src/run/noninteractive.ts b/packages/cli/src/run/noninteractive.ts index dd4634fa69b..7d18fb7af06 100644 --- a/packages/cli/src/run/noninteractive.ts +++ b/packages/cli/src/run/noninteractive.ts @@ -300,7 +300,7 @@ export async function runNonInteractivePrompt(input: Input) { if (event.type === "session.tool.input.started") { flushStep() - tools.set(toolKey(event.data.assistantMessageID, event.data.callID), { + tools.set(toolKey(event.data.assistantMessageID, event.data.id), { id: partID(event.id), timestamp: time, assistantMessageID: event.data.assistantMessageID, @@ -312,18 +312,18 @@ export async function runNonInteractivePrompt(input: Input) { continue } if (event.type === "session.tool.input.ended") { - const current = tools.get(toolKey(event.data.assistantMessageID, event.data.callID)) + const current = tools.get(toolKey(event.data.assistantMessageID, event.data.id)) if (current) current.raw = event.data.text continue } if (event.type === "session.tool.input.delta") { - const current = tools.get(toolKey(event.data.assistantMessageID, event.data.callID)) + const current = tools.get(toolKey(event.data.assistantMessageID, event.data.id)) if (current) current.raw = (current.raw ?? "") + event.data.delta continue } if (event.type === "session.tool.called") { flushStep() - const key = toolKey(event.data.assistantMessageID, event.data.callID) + const key = toolKey(event.data.assistantMessageID, event.data.id) const current = tools.get(key) tools.set(key, { id: current?.id ?? partID(event.id), @@ -340,18 +340,18 @@ export async function runNonInteractivePrompt(input: Input) { continue } if (event.type === "session.tool.progress") { - const current = tools.get(toolKey(event.data.assistantMessageID, event.data.callID)) + const current = tools.get(toolKey(event.data.assistantMessageID, event.data.id)) if (current) { current.metadata = event.data.metadata } continue } if (event.type === "session.tool.success") { - const key = toolKey(event.data.assistantMessageID, event.data.callID) + const key = toolKey(event.data.assistantMessageID, event.data.id) const current = tools.get(key) ?? fallbackTool(event) const tool: SessionMessageAssistantTool = { type: "tool", - id: event.data.callID, + id: event.data.id, name: current.tool, executed: event.data.executed, providerState: current.providerState, @@ -365,11 +365,11 @@ export async function runNonInteractivePrompt(input: Input) { time: { created: current.timestamp, ran: current.timestamp, completed: time }, } const part: MiniToolPart = { - id: current.id, + partID: current.id, sessionID: input.sessionID, messageID: event.data.assistantMessageID, type: "tool", - callID: event.data.callID, + id: event.data.id, tool: current.tool, state: { status: "completed", @@ -392,14 +392,14 @@ export async function runNonInteractivePrompt(input: Input) { continue } if (event.type === "session.tool.failed") { - const key = toolKey(event.data.assistantMessageID, event.data.callID) + const key = toolKey(event.data.assistantMessageID, event.data.id) const current = tools.get(key) ?? fallbackTool(event) const error = event.data.error.message const metadata = event.data.metadata ?? current.metadata const content = event.data.content ?? nonEmptyToolContent(current.content) const tool: SessionMessageAssistantTool = { type: "tool", - id: event.data.callID, + id: event.data.id, name: current.tool, executed: event.data.executed, providerState: current.providerState, @@ -414,11 +414,11 @@ export async function runNonInteractivePrompt(input: Input) { time: { created: current.timestamp, ran: current.timestamp, completed: time }, } const part: MiniToolPart = { - id: current.id, + partID: current.id, sessionID: input.sessionID, messageID: event.data.assistantMessageID, type: "tool", - callID: event.data.callID, + id: event.data.id, tool: current.tool, state: { status: "error", @@ -578,11 +578,11 @@ export async function runNonInteractivePrompt(input: Input) { const key = toolKey(message.id, item.id) if (renderedTools.has(key) || item.state.status === "streaming" || item.state.status === "running") continue const part: MiniToolPart = { - id: projectedPartID(message.id, `tool-${item.id}`), + partID: projectedPartID(message.id, `tool-${item.id}`), sessionID: input.sessionID, messageID: message.id, type: "tool", - callID: item.id, + id: item.id, tool: item.name, state: item.state.status === "completed" @@ -771,8 +771,8 @@ function partID(eventID: string) { return `prt_${eventID.replace(/^evt_/, "")}` } -function toolKey(messageID: string, callID: string) { - return `${messageID}\u0000${callID}` +function toolKey(messageID: string, id: string) { + return `${messageID}\u0000${id}` } function contentKey(messageID: string, ordinal: number) { @@ -786,7 +786,7 @@ function projectedPartID(messageID: string, part: string) { function fallbackTool(event: { id: string created: number - data: { assistantMessageID: string; callID: string } + data: { assistantMessageID: string; id: string } }): ToolState { return { id: partID(event.id), diff --git a/packages/cli/test/acp/event-behavior.test.ts b/packages/cli/test/acp/event-behavior.test.ts index fabdcb8198b..998b2b665b0 100644 --- a/packages/cli/test/acp/event-behavior.test.ts +++ b/packages/cli/test/acp/event-behavior.test.ts @@ -200,7 +200,7 @@ describe("acp event behavior", () => { durableEvent("session.tool.input.started", { sessionID: "ses_tools", assistantMessageID: "msg_tools", - callID: "call_ok", + id: "call_ok", name: "shell", }), ) @@ -208,7 +208,7 @@ describe("acp event behavior", () => { durableEvent("session.tool.called", { sessionID: "ses_tools", assistantMessageID: "msg_tools", - callID: "call_ok", + id: "call_ok", input: { command: "printf done", workdir: "sub" }, executed: false, }), @@ -217,7 +217,7 @@ describe("acp event behavior", () => { ephemeralEvent("session.tool.progress", { sessionID: "ses_tools", assistantMessageID: "msg_tools", - callID: "call_ok", + id: "call_ok", metadata: { phase: 1 }, }), ) @@ -225,7 +225,7 @@ describe("acp event behavior", () => { durableEvent("session.tool.success", { sessionID: "ses_tools", assistantMessageID: "msg_tools", - callID: "call_ok", + id: "call_ok", metadata: { exit: 0 }, content: [{ type: "text", text: "done" }], executed: true, @@ -235,7 +235,7 @@ describe("acp event behavior", () => { durableEvent("session.tool.input.started", { sessionID: "ses_tools", assistantMessageID: "msg_tools", - callID: "call_fail", + id: "call_fail", name: "read", }), ) @@ -243,7 +243,7 @@ describe("acp event behavior", () => { durableEvent("session.tool.called", { sessionID: "ses_tools", assistantMessageID: "msg_tools", - callID: "call_fail", + id: "call_fail", input: { path: "/workspace/missing.ts" }, executed: false, }), @@ -252,7 +252,7 @@ describe("acp event behavior", () => { ephemeralEvent("session.tool.progress", { sessionID: "ses_tools", assistantMessageID: "msg_tools", - callID: "call_fail", + id: "call_fail", metadata: { bytes: 0 }, }), ) @@ -260,7 +260,7 @@ describe("acp event behavior", () => { durableEvent("session.tool.failed", { sessionID: "ses_tools", assistantMessageID: "msg_tools", - callID: "call_fail", + id: "call_fail", error: { type: "tool.error", message: "not found" }, metadata: { bytes: 0 }, content: [{ type: "text", text: "opening" }], diff --git a/packages/cli/test/acp/permission-behavior.test.ts b/packages/cli/test/acp/permission-behavior.test.ts index 27a317fdd32..d32150bd409 100644 --- a/packages/cli/test/acp/permission-behavior.test.ts +++ b/packages/cli/test/acp/permission-behavior.test.ts @@ -43,14 +43,14 @@ describe("acp permission behavior", () => { permissionAsked("ses_allow", "perm_once", { action: "shell", metadata: { command: "printf hello" }, - source: { type: "tool", messageID: "msg_allow", callID: "call_once" }, + source: { type: "tool", messageID: "msg_allow", id: "call_once" }, }), ) send( permissionAsked("ses_allow", "perm_always", { action: "read", metadata: { path: "/workspace/file.ts" }, - source: { type: "tool", messageID: "msg_allow", callID: "call_always" }, + source: { type: "tool", messageID: "msg_allow", id: "call_always" }, }), ) send(durableEvent("session.execution.succeeded", { sessionID: "ses_allow" })) @@ -166,7 +166,7 @@ describe("acp permission behavior", () => { durableEvent("session.tool.input.started", { sessionID: "ses_edit", assistantMessageID: "msg_edit", - callID: "call_edit", + id: "call_edit", name: "edit", }), ) @@ -174,7 +174,7 @@ describe("acp permission behavior", () => { durableEvent("session.tool.called", { sessionID: "ses_edit", assistantMessageID: "msg_edit", - callID: "call_edit", + id: "call_edit", input: { path: "file.ts", oldString: "before", newString: "after" }, executed: false, }), @@ -182,7 +182,7 @@ describe("acp permission behavior", () => { send( permissionAsked("ses_edit", "perm_edit", { action: "edit", - source: { type: "tool", messageID: "msg_edit", callID: "call_edit" }, + source: { type: "tool", messageID: "msg_edit", id: "call_edit" }, }), ) }, @@ -192,7 +192,7 @@ describe("acp permission behavior", () => { durableEvent("session.tool.success", { sessionID: "ses_edit", assistantMessageID: "msg_edit", - callID: "call_edit", + id: "call_edit", metadata: { files: [{ file: "file.ts" }], replacements: 1 }, content: [{ type: "text", text: "edited" }], executed: true, @@ -256,7 +256,7 @@ describe("acp permission behavior", () => { durableEvent("session.tool.input.started", { sessionID: "ses_patch", assistantMessageID: "msg_patch", - callID: "call_patch", + id: "call_patch", name: "patch", }), ) @@ -264,7 +264,7 @@ describe("acp permission behavior", () => { durableEvent("session.tool.called", { sessionID: "ses_patch", assistantMessageID: "msg_patch", - callID: "call_patch", + id: "call_patch", input: { patchText }, executed: false, }), @@ -272,7 +272,7 @@ describe("acp permission behavior", () => { send( permissionAsked("ses_patch", "perm_patch", { action: "edit", - source: { type: "tool", messageID: "msg_patch", callID: "call_patch" }, + source: { type: "tool", messageID: "msg_patch", id: "call_patch" }, }), ) }, @@ -285,7 +285,7 @@ describe("acp permission behavior", () => { durableEvent("session.tool.success", { sessionID: "ses_patch", assistantMessageID: "msg_patch", - callID: "call_patch", + id: "call_patch", metadata: { files: [{ file: "first.ts" }, { file: "second.ts" }] }, content: [{ type: "text", text: "patched" }], executed: true, @@ -499,7 +499,7 @@ function permissionAsked( input: { readonly action?: string readonly metadata?: Record - readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly id: string } } = {}, ) { return ephemeralEvent("permission.asked", { diff --git a/packages/cli/test/run/noninteractive.test.ts b/packages/cli/test/run/noninteractive.test.ts index c8a57d3637b..2fabd599c27 100644 --- a/packages/cli/test/run/noninteractive.test.ts +++ b/packages/cli/test/run/noninteractive.test.ts @@ -109,7 +109,7 @@ function failedTool(inputID: string): V2Event[] { data: { sessionID: "ses_1", assistantMessageID: "msg_failed_tool", - callID: "call_failed_tool", + id: "call_failed_tool", name: "shell", }, }, @@ -121,7 +121,7 @@ function failedTool(inputID: string): V2Event[] { data: { sessionID: "ses_1", assistantMessageID: "msg_failed_tool", - callID: "call_failed_tool", + id: "call_failed_tool", input: { command: "printf partial && false" }, executed: true, }, @@ -133,7 +133,7 @@ function failedTool(inputID: string): V2Event[] { data: { sessionID: "ses_1", assistantMessageID: "msg_failed_tool", - callID: "call_failed_tool", + id: "call_failed_tool", metadata: { checkpoint: 1 }, }, }, @@ -145,7 +145,7 @@ function failedTool(inputID: string): V2Event[] { data: { sessionID: "ses_1", assistantMessageID: "msg_failed_tool", - callID: "call_failed_tool", + id: "call_failed_tool", error: { type: "unknown", message: "tool failed" }, metadata: { checkpoint: 1 }, content: [{ type: "text", text: "partial output" }], @@ -168,7 +168,7 @@ function successfulGrep(inputID: string): V2Event[] { data: { sessionID: "ses_1", assistantMessageID: "msg_grep", - callID: "call_grep", + id: "call_grep", name: "grep", }, }, @@ -180,7 +180,7 @@ function successfulGrep(inputID: string): V2Event[] { data: { sessionID: "ses_1", assistantMessageID: "msg_grep", - callID: "call_grep", + id: "call_grep", input: { pattern: "needle" }, executed: true, }, @@ -193,7 +193,7 @@ function successfulGrep(inputID: string): V2Event[] { data: { sessionID: "ses_1", assistantMessageID: "msg_grep", - callID: "call_grep", + id: "call_grep", metadata: { matches: 2 }, content: [{ type: "text", text }], executed: false, @@ -561,7 +561,7 @@ describe("runNonInteractivePrompt", () => { type: "tool_use", part: { type: "tool", - callID: "call_failed_tool", + id: "call_failed_tool", tool: "shell", state: { status: "error", diff --git a/packages/client/src/effect/api/api.ts b/packages/client/src/effect/api/api.ts index 9bf0a785019..ce59c9c12b7 100644 --- a/packages/client/src/effect/api/api.ts +++ b/packages/client/src/effect/api/api.ts @@ -605,7 +605,7 @@ export type Endpoint5_26Output = readonly data: { readonly sessionID: Session.ID readonly assistantMessageID: SessionMessage.ID - readonly callID: string + readonly id: string readonly name: string } } @@ -619,7 +619,7 @@ export type Endpoint5_26Output = readonly data: { readonly sessionID: Session.ID readonly assistantMessageID: SessionMessage.ID - readonly callID: string + readonly id: string readonly text: string } } @@ -633,7 +633,7 @@ export type Endpoint5_26Output = readonly data: { readonly sessionID: Session.ID readonly assistantMessageID: SessionMessage.ID - readonly callID: string + readonly id: string readonly input: { readonly [x: string]: unknown } readonly executed: boolean readonly state?: SessionMessage.ProviderState | undefined @@ -649,7 +649,7 @@ export type Endpoint5_26Output = readonly data: { readonly sessionID: Session.ID readonly assistantMessageID: SessionMessage.ID - readonly callID: string + readonly id: string readonly content: readonly [ ( | { readonly type: "text"; readonly text: string } @@ -685,7 +685,7 @@ export type Endpoint5_26Output = readonly data: { readonly sessionID: Session.ID readonly assistantMessageID: SessionMessage.ID - readonly callID: string + readonly id: string readonly error: { readonly type: string; readonly message: string; readonly status?: number | undefined } readonly content?: | readonly [ diff --git a/packages/client/src/promise/generated/types.ts b/packages/client/src/promise/generated/types.ts index 87c8a3105bf..a8f8d88b989 100644 --- a/packages/client/src/promise/generated/types.ts +++ b/packages/client/src/promise/generated/types.ts @@ -297,7 +297,7 @@ export type FormExternalField = { key: string; type: "external"; url: string; ti export type FormValue = string | number | boolean | Array -export type PermissionSource = { type: "tool"; messageID: string; callID: string } +export type PermissionSource = { type: "tool"; messageID: string; id: string } export type PermissionSavedInfo = { id: string; projectID: string; action: string; resource: string } @@ -486,7 +486,7 @@ export type Pty = { export type QuestionOption = { label: string; description: string } -export type QuestionTool = { messageID: string; callID: string } +export type QuestionTool = { messageID: string; id: string } export type QuestionAnswer = Array @@ -744,7 +744,7 @@ export type SessionToolInputStarted = { type: "session.tool.input.started" durable: { aggregateID: string; seq: number; version: 1 } location?: LocationRef - data: { sessionID: string; assistantMessageID: string; callID: string; name: string } + data: { sessionID: string; assistantMessageID: string; id: string; name: string } } export type SessionToolInputEnded = { @@ -754,7 +754,7 @@ export type SessionToolInputEnded = { type: "session.tool.input.ended" durable: { aggregateID: string; seq: number; version: 1 } location?: LocationRef - data: { sessionID: string; assistantMessageID: string; callID: string; text: string } + data: { sessionID: string; assistantMessageID: string; id: string; text: string } } export type SessionCompactionAdmitted = { @@ -915,7 +915,7 @@ export type SessionToolInputDelta = { metadata?: { [x: string]: any } type: "session.tool.input.delta" location?: LocationRef - data: { sessionID: string; assistantMessageID: string; callID: string; delta: string } + data: { sessionID: string; assistantMessageID: string; id: string; delta: string } } export type SessionToolProgress = { @@ -924,7 +924,7 @@ export type SessionToolProgress = { metadata?: { [x: string]: any } type: "session.tool.progress" location?: LocationRef - data: { sessionID: string; assistantMessageID: string; callID: string; metadata: { [x: string]: JsonValue } } + data: { sessionID: string; assistantMessageID: string; id: string; metadata: { [x: string]: JsonValue } } } export type SessionCompactionDelta = { @@ -1380,7 +1380,7 @@ export type SessionToolCalled = { data: { sessionID: string assistantMessageID: string - callID: string + id: string input: { [x: string]: any } executed: boolean state?: SessionMessageProviderState7 @@ -1831,7 +1831,7 @@ export type SessionToolSuccess = { data: { sessionID: string assistantMessageID: string - callID: string + id: string content: [ToolContent1, ...Array] metadata?: { [x: string]: JsonValue } executed: boolean @@ -1849,7 +1849,7 @@ export type SessionToolFailed = { data: { sessionID: string assistantMessageID: string - callID: string + id: string error: SessionStructuredError content?: [ToolContent1, ...Array] metadata?: { [x: string]: JsonValue } @@ -4472,7 +4472,7 @@ export type PermissionCreateInput = { readonly resources: ReadonlyArray readonly save?: ReadonlyArray readonly metadata?: { readonly [x: string]: JsonValue } - readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly id: string } readonly agent?: string | null }["id"] readonly action: { @@ -4481,7 +4481,7 @@ export type PermissionCreateInput = { readonly resources: ReadonlyArray readonly save?: ReadonlyArray readonly metadata?: { readonly [x: string]: JsonValue } - readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly id: string } readonly agent?: string | null }["action"] readonly resources: { @@ -4490,7 +4490,7 @@ export type PermissionCreateInput = { readonly resources: ReadonlyArray readonly save?: ReadonlyArray readonly metadata?: { readonly [x: string]: JsonValue } - readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly id: string } readonly agent?: string | null }["resources"] readonly save?: { @@ -4499,7 +4499,7 @@ export type PermissionCreateInput = { readonly resources: ReadonlyArray readonly save?: ReadonlyArray readonly metadata?: { readonly [x: string]: JsonValue } - readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly id: string } readonly agent?: string | null }["save"] readonly metadata?: { @@ -4508,7 +4508,7 @@ export type PermissionCreateInput = { readonly resources: ReadonlyArray readonly save?: ReadonlyArray readonly metadata?: { readonly [x: string]: JsonValue } - readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly id: string } readonly agent?: string | null }["metadata"] readonly source?: { @@ -4517,7 +4517,7 @@ export type PermissionCreateInput = { readonly resources: ReadonlyArray readonly save?: ReadonlyArray readonly metadata?: { readonly [x: string]: JsonValue } - readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly id: string } readonly agent?: string | null }["source"] readonly agent?: { @@ -4526,7 +4526,7 @@ export type PermissionCreateInput = { readonly resources: ReadonlyArray readonly save?: ReadonlyArray readonly metadata?: { readonly [x: string]: JsonValue } - readonly source?: { readonly type: "tool"; readonly messageID: string; readonly callID: string } + readonly source?: { readonly type: "tool"; readonly messageID: string; readonly id: string } readonly agent?: string | null }["agent"] } diff --git a/packages/core/src/session/message-updater.ts b/packages/core/src/session/message-updater.ts index 6d9c4723ff2..af1aa353365 100644 --- a/packages/core/src/session/message-updater.ts +++ b/packages/core/src/session/message-updater.ts @@ -111,9 +111,9 @@ export function update(adapter: Adapter, event: SessionEvent.Event) { type DraftText = WritableDraft type DraftReasoning = WritableDraft - const latestTool = (assistant: DraftAssistant | undefined, callID?: string) => + const latestTool = (assistant: DraftAssistant | undefined, id?: string) => assistant?.content.findLast( - (item): item is DraftTool => item.type === "tool" && (callID === undefined || item.id === callID), + (item): item is DraftTool => item.type === "tool" && (id === undefined || item.id === id), ) const latestText = (assistant: DraftAssistant | undefined) => @@ -331,7 +331,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) { castDraft( SessionMessage.AssistantTool.make({ type: "tool", - id: event.data.callID, + id: event.data.id, name: event.data.name, time: { created: event.created }, state: SessionMessage.ToolStateStreaming.make({ status: "streaming", input: "" }), @@ -343,13 +343,13 @@ export function update(adapter: Adapter, event: SessionEvent.Event) { "session.tool.input.delta": () => Effect.void, "session.tool.input.ended": (event) => { return updateOwnedAssistant(event.data.assistantMessageID, (draft) => { - const match = latestTool(draft, event.data.callID) + const match = latestTool(draft, event.data.id) if (match && match.state.status === "streaming") match.state.input = event.data.text }) }, "session.tool.called": (event) => { return updateOwnedAssistant(event.data.assistantMessageID, (draft) => { - const match = latestTool(draft, event.data.callID) + const match = latestTool(draft, event.data.id) if (match) { match.executed = event.data.executed match.providerState = event.data.state @@ -366,7 +366,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) { }, "session.tool.progress": (event) => { return updateOwnedAssistant(event.data.assistantMessageID, (draft) => { - const match = latestTool(draft, event.data.callID) + const match = latestTool(draft, event.data.id) if (match && match.state.status === "running") { match.state.metadata = event.data.metadata } @@ -376,7 +376,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) { // never reaches into ephemeral progress history. "session.tool.success": (event) => { return updateOwnedAssistant(event.data.assistantMessageID, (draft) => { - const match = latestTool(draft, event.data.callID) + const match = latestTool(draft, event.data.id) if (match && match.state.status === "running") { match.executed = event.data.executed || match.executed === true match.providerResultState = event.data.resultState @@ -394,7 +394,7 @@ export function update(adapter: Adapter, event: SessionEvent.Event) { }, "session.tool.failed": (event) => { return updateOwnedAssistant(event.data.assistantMessageID, (draft) => { - const match = latestTool(draft, event.data.callID) + const match = latestTool(draft, event.data.id) if (match && (match.state.status === "streaming" || match.state.status === "running")) { match.executed = event.data.executed || match.executed === true match.providerResultState = event.data.resultState diff --git a/packages/core/src/session/runner/llm.ts b/packages/core/src/session/runner/llm.ts index 6586c659d0b..e92685c68dd 100644 --- a/packages/core/src/session/runner/llm.ts +++ b/packages/core/src/session/runner/llm.ts @@ -488,7 +488,7 @@ const layer = Layer.effect( yield* bus.publish(SessionEvent.Tool.Failed, { sessionID, assistantMessageID: message.id, - callID: tool.id, + id: tool.id, error: { type: "aborted", message: `Tool execution interrupted: ${tool.name}` }, executed: tool.executed === true, }) diff --git a/packages/core/src/session/runner/publish-llm-event.ts b/packages/core/src/session/runner/publish-llm-event.ts index 99dc0ad77b5..cafbefd67a5 100644 --- a/packages/core/src/session/runner/publish-llm-event.ts +++ b/packages/core/src/session/runner/publish-llm-event.ts @@ -78,7 +78,7 @@ const hostedContent = (result: ToolResultValue): NonEmptyContent => { * between a check (`tool.settled`, `stepStarted`, ...) and its mark, so check-and-mark * stays atomic under cooperative scheduling. (2) Never require a cross-source event * order: each publishing fiber is sequential, so per-source order holds by construction, - * and consumers fold by callID/ordinal rather than global position. + * and consumers fold by id/ordinal rather than global position. */ export const createLLMEventPublisher = (bus: Pick, input: Input) => { const tools = new Map< @@ -188,14 +188,14 @@ export const createLLMEventPublisher = (bus: Pick, inp }), true, ) - const toolInput = fragments("tool input", (callID, value) => + const toolInput = fragments("tool input", (id, value) => Effect.gen(function* () { - const tool = tools.get(callID) - if (!tool) return yield* Effect.die(new Error(`Tool input end before start: ${callID}`)) + const tool = tools.get(id) + if (!tool) return yield* Effect.die(new Error(`Tool input end before start: ${id}`)) yield* bus.publish(SessionEvent.Tool.Input.Ended, { sessionID: input.sessionID, assistantMessageID: tool.assistantMessageID, - callID, + id, text: value, }) }), @@ -225,7 +225,7 @@ export const createLLMEventPublisher = (bus: Pick, inp yield* bus.publish(SessionEvent.Tool.Input.Started, { sessionID: input.sessionID, assistantMessageID, - callID: event.id, + id: event.id, name: event.name, }) }) @@ -258,7 +258,7 @@ export const createLLMEventPublisher = (bus: Pick, inp yield* bus.publish(SessionEvent.Tool.Failed, { sessionID: input.sessionID, assistantMessageID: tool.assistantMessageID, - callID: event.id, + id: event.id, error: { type: "tool.input-json", message: "Tool call arguments were malformed JSON and were not executed. Retry with valid JSON.", @@ -272,14 +272,14 @@ export const createLLMEventPublisher = (bus: Pick, inp yield* flushFragments() }) - const failTool = Effect.fnUntraced(function* (callID: string, error: SessionError.Error) { - const tool = tools.get(callID) + const failTool = Effect.fnUntraced(function* (id: string, error: SessionError.Error) { + const tool = tools.get(id) if (!tool || tool.settled) return false tool.settled = true yield* bus.publish(SessionEvent.Tool.Failed, { sessionID: input.sessionID, assistantMessageID: tool.assistantMessageID, - callID, + id, error, ...failureSnapshot(tool), executed: tool.providerExecuted, @@ -289,10 +289,10 @@ export const createLLMEventPublisher = (bus: Pick, inp const failTools = Effect.fnUntraced(function* (error: SessionError.Error, mode: "all" | "hosted" | "uncalled") { let failed = false - for (const [callID, tool] of tools) { + for (const [id, tool] of tools) { if (tool.settled || (mode === "hosted" && !tool.providerExecuted) || (mode === "uncalled" && tool.called)) continue - failed = (yield* failTool(callID, error)) || failed + failed = (yield* failTool(id, error)) || failed } return failed }) @@ -328,9 +328,9 @@ export const createLLMEventPublisher = (bus: Pick, inp return yield* failTools(error, scope) }) - const assistantMessageIDForTool = (callID: string) => { - const tool = tools.get(callID) - return tool ? Effect.succeed(tool.assistantMessageID) : Effect.die(new Error(`Unknown tool call: ${callID}`)) + const assistantMessageIDForTool = (id: string) => { + const tool = tools.get(id) + return tool ? Effect.succeed(tool.assistantMessageID) : Effect.die(new Error(`Unknown tool call: ${id}`)) } const publish = Effect.fn("SessionRunner.publishLLMEvent")(function* (event: LLMEvent) { @@ -399,7 +399,7 @@ export const createLLMEventPublisher = (bus: Pick, inp yield* bus.publish(SessionEvent.Tool.Input.Delta, { sessionID: input.sessionID, assistantMessageID: tool.assistantMessageID, - callID: event.id, + id: event.id, delta: event.text, }) return @@ -424,7 +424,7 @@ export const createLLMEventPublisher = (bus: Pick, inp yield* bus.publish(SessionEvent.Tool.Called, { sessionID: input.sessionID, assistantMessageID: tool.assistantMessageID, - callID: event.id, + id: event.id, input: asRecord(event.input), executed: tool.providerExecuted, state: providerState(event.providerMetadata), @@ -450,7 +450,7 @@ export const createLLMEventPublisher = (bus: Pick, inp yield* bus.publish(SessionEvent.Tool.Failed, { sessionID: input.sessionID, assistantMessageID: tool.assistantMessageID, - callID: event.id, + id: event.id, error: { type: "tool.execution", message: stringify(event.result.value) }, ...failureSnapshot(tool), executed, @@ -461,7 +461,7 @@ export const createLLMEventPublisher = (bus: Pick, inp yield* bus.publish(SessionEvent.Tool.Success, { sessionID: input.sessionID, assistantMessageID: tool.assistantMessageID, - callID: event.id, + id: event.id, content: hostedContent(event.result), executed, resultState, @@ -478,7 +478,7 @@ export const createLLMEventPublisher = (bus: Pick, inp yield* bus.publish(SessionEvent.Tool.Failed, { sessionID: input.sessionID, assistantMessageID: tool.assistantMessageID, - callID: event.id, + id: event.id, error: event.message === `Unknown tool: ${event.name}` ? { type: "tool.unknown", message: event.message } @@ -508,30 +508,30 @@ export const createLLMEventPublisher = (bus: Pick, inp } }) - const progress = Effect.fnUntraced(function* (callID: string, update: Tool.Metadata) { - const tool = tools.get(callID) + const progress = Effect.fnUntraced(function* (id: string, update: Tool.Metadata) { + const tool = tools.get(id) if (!tool?.called || tool.settled) - return yield* Effect.die(new Error(`Tool progress outside running call: ${callID}`)) + return yield* Effect.die(new Error(`Tool progress outside running call: ${id}`)) tool.progress = update yield* bus.publish(SessionEvent.Tool.Progress, { sessionID: input.sessionID, assistantMessageID: tool.assistantMessageID, - callID, + id, metadata: update, }) }) /** Publishes one canonical terminal event for a locally executed tool call. */ const toolExecution = Effect.fnUntraced(function* ( - callID: string, + id: string, name: string, result: Tool.Result, ) { - const tool = tools.get(callID) - if (!tool?.called) return yield* Effect.die(new Error(`Tool execution before call: ${callID}`)) + const tool = tools.get(id) + if (!tool?.called) return yield* Effect.die(new Error(`Tool execution before call: ${id}`)) if (tool.name !== name) - return yield* Effect.die(new Error(`Tool execution name changed for ${callID}: ${tool.name} -> ${name}`)) - if (tool.settled) return yield* Effect.die(new Error(`Duplicate tool execution: ${callID}`)) + return yield* Effect.die(new Error(`Tool execution name changed for ${id}: ${tool.name} -> ${name}`)) + if (tool.settled) return yield* Effect.die(new Error(`Duplicate tool execution: ${id}`)) tool.settled = true const content = typeof result.content === "string" @@ -539,11 +539,11 @@ export const createLLMEventPublisher = (bus: Pick, inp : result.content === undefined ? [] : [...result.content] - if (content.length === 0) return yield* Effect.die(new Error(`Tool execution has no content: ${callID}`)) + if (content.length === 0) return yield* Effect.die(new Error(`Tool execution has no content: ${id}`)) yield* bus.publish(SessionEvent.Tool.Success, { sessionID: input.sessionID, assistantMessageID: tool.assistantMessageID, - callID, + id, content: [content[0], ...content.slice(1)], ...(result.metadata === undefined ? {} : { metadata: result.metadata }), executed: tool.providerExecuted, diff --git a/packages/core/src/tool.ts b/packages/core/src/tool.ts index 43bc900c46a..e5e54f53d45 100644 --- a/packages/core/src/tool.ts +++ b/packages/core/src/tool.ts @@ -93,7 +93,7 @@ const layer = Layer.effect( sessionID: context.sessionID, agent: context.agent, messageID: context.messageID, - callID: context.callID, + id: context.id, input, } yield* hooks.trigger("tool", "execute.before", beforeEvent) @@ -106,7 +106,7 @@ const layer = Layer.effect( sessionID: context.sessionID, agent: context.agent, messageID: context.messageID, - callID: context.callID, + id: context.id, input: beforeEvent.input, } if ("failure" in execution) { @@ -228,7 +228,7 @@ const layer = Layer.effect( sessionID: input.sessionID, agent: input.agent, messageID: input.messageID, - callID: Tool.CallID.make(input.call.id), + id: Tool.CallID.make(input.call.id), progress: input.progress ?? (() => Effect.void), } if (input.call.name === "execute" && codemodeTool) diff --git a/packages/core/src/tool/AGENTS.md b/packages/core/src/tool/AGENTS.md index a6bc1541dfc..3b76ddad800 100644 --- a/packages/core/src/tool/AGENTS.md +++ b/packages/core/src/tool/AGENTS.md @@ -22,7 +22,7 @@ Location-scoped built-in layers acquire `Permission.Service` and every other req const source = { type: "tool" as const, messageID: context.messageID, - callID: context.callID, + id: context.id, } ``` diff --git a/packages/core/src/tool/mcp.ts b/packages/core/src/tool/mcp.ts index d82e45ae33e..8023b5d85b4 100644 --- a/packages/core/src/tool/mcp.ts +++ b/packages/core/src/tool/mcp.ts @@ -59,7 +59,7 @@ export const layer = Layer.effectDiscard( source: { type: "tool", messageID: context.messageID, - callID: context.callID, + id: context.id, }, }) const result = yield* mcp diff --git a/packages/core/src/tool/plugin/edit.ts b/packages/core/src/tool/plugin/edit.ts index 4fe50ed30ab..1fc5d55461e 100644 --- a/packages/core/src/tool/plugin/edit.ts +++ b/packages/core/src/tool/plugin/edit.ts @@ -129,7 +129,7 @@ export const Plugin = { const permissionSource = { type: "tool" as const, messageID: context.messageID, - callID: context.callID, + id: context.id, } if (input.oldString === input.newString) { return yield* new ToolFailure({ diff --git a/packages/core/src/tool/plugin/glob.ts b/packages/core/src/tool/plugin/glob.ts index 71ea80bbff5..f6bf172922f 100644 --- a/packages/core/src/tool/plugin/glob.ts +++ b/packages/core/src/tool/plugin/glob.ts @@ -61,7 +61,7 @@ export const Plugin = { execute: (input, context) => Effect.gen(function* () { const searchPath = input.path === "undefined" || input.path === "null" ? undefined : input.path - const source = { type: "tool" as const, messageID: context.messageID, callID: context.callID } + const source = { type: "tool" as const, messageID: context.messageID, id: context.id } const target = yield* mutation.resolve({ path: searchPath ?? ".", kind: "directory" }) const external = target.externalDirectory if (external) diff --git a/packages/core/src/tool/plugin/grep.ts b/packages/core/src/tool/plugin/grep.ts index 3c6d9b77b4d..0e517142357 100644 --- a/packages/core/src/tool/plugin/grep.ts +++ b/packages/core/src/tool/plugin/grep.ts @@ -76,7 +76,7 @@ export const Plugin = { output: Output, execute: (input, context) => Effect.gen(function* () { - const source = { type: "tool" as const, messageID: context.messageID, callID: context.callID } + const source = { type: "tool" as const, messageID: context.messageID, id: context.id } const target = yield* mutation.resolve({ path: input.path ?? "." }) if (target.externalDirectory) yield* permission.assert({ diff --git a/packages/core/src/tool/plugin/patch.ts b/packages/core/src/tool/plugin/patch.ts index 0433b47e9b8..407c020e875 100644 --- a/packages/core/src/tool/plugin/patch.ts +++ b/packages/core/src/tool/plugin/patch.ts @@ -95,7 +95,7 @@ export const Plugin = { const source = { type: "tool" as const, messageID: context.messageID, - callID: context.callID, + id: context.id, } if (!input.patchText) return yield* new ToolFailure({ message: "patchText is required" }) const hunks = yield* Effect.fromResult(Patch.parse(input.patchText)).pipe( diff --git a/packages/core/src/tool/plugin/question.ts b/packages/core/src/tool/plugin/question.ts index f402cb350de..2a054bf257c 100644 --- a/packages/core/src/tool/plugin/question.ts +++ b/packages/core/src/tool/plugin/question.ts @@ -70,7 +70,7 @@ export const Plugin = { resources: ["*"], sessionID: context.sessionID, agent: context.agent, - source: { type: "tool", messageID: context.messageID, callID: context.callID }, + source: { type: "tool", messageID: context.messageID, id: context.id }, }) .pipe( Effect.mapError((error) => new ToolFailure({ message: "Permission denied: question", error })), @@ -81,7 +81,7 @@ export const Plugin = { title: "Questions", metadata: { kind: "question", - tool: { messageID: context.messageID, callID: context.callID }, + tool: { messageID: context.messageID, id: context.id }, }, fields: [ toField(input.questions[0], 0), diff --git a/packages/core/src/tool/plugin/read.ts b/packages/core/src/tool/plugin/read.ts index 5ff8bee77f5..ce56f732455 100644 --- a/packages/core/src/tool/plugin/read.ts +++ b/packages/core/src/tool/plugin/read.ts @@ -56,7 +56,7 @@ export const Plugin = { const source = { type: "tool" as const, messageID: context.messageID, - callID: context.callID, + id: context.id, } const target = yield* mutation.resolve({ path: input.path, kind: "directory" }) const external = target.externalDirectory diff --git a/packages/core/src/tool/plugin/shell.ts b/packages/core/src/tool/plugin/shell.ts index ae6413df1e3..8a8ce3d707b 100644 --- a/packages/core/src/tool/plugin/shell.ts +++ b/packages/core/src/tool/plugin/shell.ts @@ -89,10 +89,10 @@ export const Plugin = { const notifyWhenDone = Effect.fn("ShellTool.notifyWhenDone")(function* ( sessionID: SessionSchema.ID, - callID: string, + id: string, command: string, ) { - yield* runtime.job.wait({ id: callID }).pipe( + yield* runtime.job.wait({ id: id }).pipe( Effect.flatMap((result) => { const state = result.info?.status === "completed" @@ -111,7 +111,7 @@ export const Plugin = { : "Command cancelled" return runtime.session.synthetic({ sessionID, - text: `\n${text}\n`, + text: `\n${text}\n`, description: command, metadata: { source: "shell", state }, }) @@ -134,7 +134,7 @@ export const Plugin = { const source = { type: "tool" as const, messageID: context.messageID, - callID: context.callID, + id: context.id, } const timeout = input.background === true ? (input.timeout ?? 0) : (input.timeout ?? DEFAULT_TIMEOUT_MS) let finalTimeout = timeout @@ -227,7 +227,7 @@ export const Plugin = { Effect.onInterrupt(() => shell.remove(info.id).pipe(Effect.ignore)), ) const job = yield* runtime.job.start({ - id: context.callID, + id: context.id, type: name, title: info.command, metadata: { sessionID: context.sessionID, shellID: info.id }, @@ -236,7 +236,7 @@ export const Plugin = { if (input.background === true) { yield* runtime.job.background(job.id) - yield* notifyWhenDone(context.sessionID, context.callID, info.command) + yield* notifyWhenDone(context.sessionID, context.id, info.command) return { output: BACKGROUND_STARTED, shellID: info.id, @@ -250,7 +250,7 @@ export const Plugin = { ) if (result?.type === "backgrounded") { yield* shell.timeout(info.id, 0) - yield* notifyWhenDone(context.sessionID, context.callID, info.command) + yield* notifyWhenDone(context.sessionID, context.id, info.command) return { output: BACKGROUND_STARTED, shellID: info.id, diff --git a/packages/core/src/tool/plugin/skill.ts b/packages/core/src/tool/plugin/skill.ts index f8a4109a63a..d24d2a80f20 100644 --- a/packages/core/src/tool/plugin/skill.ts +++ b/packages/core/src/tool/plugin/skill.ts @@ -75,7 +75,7 @@ export const Plugin = { save: [skill.id], sessionID: context.sessionID, agent: context.agent, - source: { type: "tool", messageID: context.messageID, callID: context.callID }, + source: { type: "tool", messageID: context.messageID, id: context.id }, }) const directory = path.dirname(skill.location) const files = diff --git a/packages/core/src/tool/plugin/subagent.ts b/packages/core/src/tool/plugin/subagent.ts index 2c73e79f911..0538234ce8e 100644 --- a/packages/core/src/tool/plugin/subagent.ts +++ b/packages/core/src/tool/plugin/subagent.ts @@ -159,7 +159,7 @@ export const Plugin = { source: { type: "tool", messageID: context.messageID, - callID: context.callID, + id: context.id, }, }) .pipe(Effect.mapError((error) => new ToolFailure({ message: `Subagent denied: ${agent.id}`, error }))) diff --git a/packages/core/src/tool/plugin/webfetch.ts b/packages/core/src/tool/plugin/webfetch.ts index b42cdd718ce..f01f59b5fef 100644 --- a/packages/core/src/tool/plugin/webfetch.ts +++ b/packages/core/src/tool/plugin/webfetch.ts @@ -139,7 +139,7 @@ export const Plugin = { metadata: input, sessionID: context.sessionID, agent: context.agent, - source: { type: "tool", messageID: context.messageID, callID: context.callID }, + source: { type: "tool", messageID: context.messageID, id: context.id }, }) const { body, contentType } = yield* Effect.gen(function* () { diff --git a/packages/core/src/tool/plugin/websearch.ts b/packages/core/src/tool/plugin/websearch.ts index b605d33daab..a3b241cc84b 100644 --- a/packages/core/src/tool/plugin/websearch.ts +++ b/packages/core/src/tool/plugin/websearch.ts @@ -47,7 +47,7 @@ export const Plugin = { metadata: input, sessionID: context.sessionID, agent: context.agent, - source: { type: "tool", messageID: context.messageID, callID: context.callID }, + source: { type: "tool", messageID: context.messageID, id: context.id }, }) const result = yield* ctx.websearch.query(input).pipe( Effect.catch((error) => { diff --git a/packages/core/src/tool/plugin/write.ts b/packages/core/src/tool/plugin/write.ts index 332ade279e1..e04d7ef7ad9 100644 --- a/packages/core/src/tool/plugin/write.ts +++ b/packages/core/src/tool/plugin/write.ts @@ -67,7 +67,7 @@ export const Plugin = { const source = { type: "tool" as const, messageID: context.messageID, - callID: context.callID, + id: context.id, } const target = yield* mutation.resolve({ path: input.path, kind: "file" }) const external = target.externalDirectory diff --git a/packages/core/test/database-migration.test.ts b/packages/core/test/database-migration.test.ts index 6dd4be0a4a9..1a313051bb0 100644 --- a/packages/core/test/database-migration.test.ts +++ b/packages/core/test/database-migration.test.ts @@ -714,7 +714,7 @@ describe("DatabaseMigration", () => { sql`INSERT INTO event VALUES ('evt_success', 'session.tool.success.1', ${JSON.stringify({ sessionID: "ses_test", assistantMessageID: "msg_tools", - callID: "call_hosted", + id: "call_hosted", structured: {}, content: [], result: { type: "json", value: [{ url: "https://example.com" }] }, @@ -725,7 +725,7 @@ describe("DatabaseMigration", () => { sql`INSERT INTO event VALUES ('evt_failed', 'session.tool.failed.1', ${JSON.stringify({ sessionID: "ses_test", assistantMessageID: "msg_tools", - callID: "call_failed", + id: "call_failed", error: { type: "tool.execution", message: "timed out" }, metadata: { truncated: false }, executed: false, @@ -795,7 +795,7 @@ describe("DatabaseMigration", () => { expect(JSON.parse(event!.data)).toEqual({ sessionID: "ses_test", assistantMessageID: "msg_tools", - callID: "call_hosted", + id: "call_hosted", structured: {}, content: [], result: { type: "json", value: [{ url: "https://example.com" }] }, @@ -806,7 +806,7 @@ describe("DatabaseMigration", () => { expect(JSON.parse(failedEvent!.data)).toEqual({ sessionID: "ses_test", assistantMessageID: "msg_tools", - callID: "call_failed", + id: "call_failed", error: { type: "tool.execution", message: "timed out" }, metadata: { truncated: false }, executed: false, diff --git a/packages/core/test/mcp.test.ts b/packages/core/test/mcp.test.ts index ae1a28c7e18..f98a380f5bf 100644 --- a/packages/core/test/mcp.test.ts +++ b/packages/core/test/mcp.test.ts @@ -928,7 +928,7 @@ it.effect("waits for permission before calling an MCP tool", () => source: { type: "tool", messageID: toolIdentity.messageID, - callID: "call_mcp_permission", + id: "call_mcp_permission", }, }) expect(calls).toBe(0) diff --git a/packages/core/test/session-generate.test.ts b/packages/core/test/session-generate.test.ts index eba19650838..a3f416ce303 100644 --- a/packages/core/test/session-generate.test.ts +++ b/packages/core/test/session-generate.test.ts @@ -255,19 +255,19 @@ it.effect("generates from fresh settled Session context without durable mutation yield* bus.publish(SessionEvent.Tool.Input.Started, { sessionID, assistantMessageID: activeAssistant, - callID: "active-call", + id: "active-call", name: "echo", }) yield* bus.publish(SessionEvent.Tool.Input.Ended, { sessionID, assistantMessageID: activeAssistant, - callID: "active-call", + id: "active-call", text: "{}", }) yield* bus.publish(SessionEvent.Tool.Called, { sessionID, assistantMessageID: activeAssistant, - callID: "active-call", + id: "active-call", input: {}, executed: false, }) diff --git a/packages/core/test/session-runner-tool-events.test.ts b/packages/core/test/session-runner-tool-events.test.ts index 82c6a869159..b33aa91d549 100644 --- a/packages/core/test/session-runner-tool-events.test.ts +++ b/packages/core/test/session-runner-tool-events.test.ts @@ -237,7 +237,7 @@ test("success event data can carry provider-executed result state", () => { const decoded = Schema.decodeUnknownSync(SessionEvent.Tool.Success.data)({ sessionID, assistantMessageID: SessionMessage.ID.create(), - callID: "call-old", + id: "call-old", content: [{ type: "file", uri: `data:image/png;base64,${base64}`, mime: "image/png" }], executed: true, resultState: { diff --git a/packages/core/test/session-runner-tool-registry.test.ts b/packages/core/test/session-runner-tool-registry.test.ts index aacbb700692..0dc5244a18a 100644 --- a/packages/core/test/session-runner-tool-registry.test.ts +++ b/packages/core/test/session-runner-tool-registry.test.ts @@ -339,7 +339,7 @@ describe("Tool", () => { call: { type: "tool-call", id: "call-context", name: "context", input: {} }, }) expect(contexts).toEqual([ - { sessionID, ...identity, callID: Tool.CallID.make("call-context"), progress: expect.any(Function) }, + { sessionID, ...identity, id: Tool.CallID.make("call-context"), progress: expect.any(Function) }, ]) }), ) diff --git a/packages/core/test/session-runner.test.ts b/packages/core/test/session-runner.test.ts index 99e8e023724..eb83723d5fc 100644 --- a/packages/core/test/session-runner.test.ts +++ b/packages/core/test/session-runner.test.ts @@ -935,7 +935,7 @@ describe("SessionRunnerLLM", () => { yield* TestLLM.push(TestLLM.tool("call-location", "location_context", { query: "hello" }), []) const bus = yield* Bus.Service const progressFiber = yield* bus.subscribe(SessionEvent.Tool.Progress).pipe( - Stream.filter((event) => event.data.sessionID === sessionID && event.data.callID === "call-location"), + Stream.filter((event) => event.data.sessionID === sessionID && event.data.id === "call-location"), Stream.take(1), Stream.runCollect, Effect.forkScoped({ startImmediately: true }), @@ -949,7 +949,7 @@ describe("SessionRunnerLLM", () => { sessionID, agent: Agent.ID.make("build"), messageID: expect.stringMatching(/^msg_/), - callID: Tool.CallID.make("call-location"), + id: Tool.CallID.make("call-location"), progress: expect.any(Function), }, ]) @@ -2382,7 +2382,7 @@ describe("SessionRunnerLLM", () => { expect(requests).toHaveLength(2) expect(messageRoles(requests[1])).toEqual(["user", "assistant", "tool"]) - expect(authorizations).toMatchObject([{ sessionID, callID: "call-echo" }]) + expect(authorizations).toMatchObject([{ sessionID, id: "call-echo" }]) expect(executions).toEqual(["hello"]) const context = yield* session.context(sessionID) expect(context).toMatchObject([ @@ -2994,19 +2994,19 @@ describe("SessionRunnerLLM", () => { yield* bus.publish(SessionEvent.Tool.Input.Started, { sessionID, assistantMessageID, - callID: "call-interrupted", + id: "call-interrupted", name: "echo", }) yield* bus.publish(SessionEvent.Tool.Input.Ended, { sessionID, assistantMessageID, - callID: "call-interrupted", + id: "call-interrupted", text: '{"text":"stale"}', }) yield* bus.publish(SessionEvent.Tool.Called, { sessionID, assistantMessageID, - callID: "call-interrupted", + id: "call-interrupted", input: { text: "stale" }, executed: false, }) @@ -3051,19 +3051,19 @@ describe("SessionRunnerLLM", () => { yield* bus.publish(SessionEvent.Tool.Input.Started, { sessionID, assistantMessageID, - callID: "call-hosted-interrupted", + id: "call-hosted-interrupted", name: "web_search", }) yield* bus.publish(SessionEvent.Tool.Input.Ended, { sessionID, assistantMessageID, - callID: "call-hosted-interrupted", + id: "call-hosted-interrupted", text: '{"query":"stale"}', }) yield* bus.publish(SessionEvent.Tool.Called, { sessionID, assistantMessageID, - callID: "call-hosted-interrupted", + id: "call-hosted-interrupted", input: { query: "stale" }, executed: true, state: { itemId: "call-hosted-interrupted" }, @@ -3102,7 +3102,7 @@ describe("SessionRunnerLLM", () => { yield* bus.publish(SessionEvent.Tool.Input.Started, { sessionID, assistantMessageID, - callID: "call-pending-interrupted", + id: "call-pending-interrupted", name: "echo", }) requests.length = 0 @@ -4120,7 +4120,7 @@ describe("SessionRunnerLLM", () => { { type: "session.tool.failed.2", data: { - callID: "call-malformed", + id: "call-malformed", error: { type: "provider.invalid-output", message: "Invalid JSON input for tool call echo" }, }, }, @@ -4220,7 +4220,7 @@ describe("SessionRunnerLLM", () => { .all() .pipe(Effect.orDie) expect(durable.find((event) => event.type === "session.tool.input.ended.1")?.data).toMatchObject({ - callID: "call-malformed", + id: "call-malformed", text: raw, }) }), @@ -4616,13 +4616,13 @@ describe("SessionRunnerLLM", () => { const assistant = requireAssistant(yield* session.context(sessionID)) const bus = yield* recordedStepSettlementEvents(sessionID, assistant.id) - expect(bus.map((event) => ({ type: event.type, callID: event.data.callID }))).toEqual([ - { type: "session.step.started.1", callID: undefined }, - { type: "session.tool.called.1", callID: "call-local-raw-failure" }, - { type: "session.tool.called.1", callID: "call-hosted-raw-failure-pair" }, - { type: "session.tool.failed.2", callID: "call-local-raw-failure" }, - { type: "session.tool.failed.2", callID: "call-hosted-raw-failure-pair" }, - { type: "session.step.failed.1", callID: undefined }, + expect(bus.map((event) => ({ type: event.type, id: event.data.id }))).toEqual([ + { type: "session.step.started.1", id: undefined }, + { type: "session.tool.called.1", id: "call-local-raw-failure" }, + { type: "session.tool.called.1", id: "call-hosted-raw-failure-pair" }, + { type: "session.tool.failed.2", id: "call-local-raw-failure" }, + { type: "session.tool.failed.2", id: "call-hosted-raw-failure-pair" }, + { type: "session.step.failed.1", id: undefined }, ]) expect( bus.filter((event) => event.type.startsWith("session.step.") && event.type !== "session.step.started.1"), diff --git a/packages/core/test/session-tool-progress.test.ts b/packages/core/test/session-tool-progress.test.ts index fc57c92c52d..74c312ebec2 100644 --- a/packages/core/test/session-tool-progress.test.ts +++ b/packages/core/test/session-tool-progress.test.ts @@ -65,18 +65,18 @@ describe("Tool.Metadata", () => { if (!row) return yield* Effect.die("Missing projected assistant") return Schema.decodeUnknownSync(SessionMessage.Assistant)({ ...row.data, id: row.id, type: row.type }) }) - const start = (callID: string) => + const start = (id: string) => Effect.gen(function* () { yield* service.publish(SessionEvent.Tool.Input.Started, { sessionID, assistantMessageID, - callID, + id, name: "bash", }) yield* service.publish(SessionEvent.Tool.Called, { sessionID, assistantMessageID, - callID, + id, input: { command: "pwd" }, executed: false, }) @@ -90,7 +90,7 @@ describe("Tool.Metadata", () => { const progress = yield* service.publish(SessionEvent.Tool.Progress, { sessionID, assistantMessageID, - callID: "call-success", + id: "call-success", metadata: { phase: "checkpoint" }, }) expect((yield* readAssistant).content[0]).toMatchObject({ @@ -100,7 +100,7 @@ describe("Tool.Metadata", () => { const success = yield* service.publish(SessionEvent.Tool.Success, { sessionID, assistantMessageID, - callID: "call-success", + id: "call-success", metadata: { phase: "done" }, content: content("complete"), executed: false, @@ -113,13 +113,13 @@ describe("Tool.Metadata", () => { yield* service.publish(SessionEvent.Tool.Progress, { sessionID, assistantMessageID, - callID: "call-failed", + id: "call-failed", metadata: { phase: "checkpoint" }, }) const failed = yield* service.publish(SessionEvent.Tool.Failed, { sessionID, assistantMessageID, - callID: "call-failed", + id: "call-failed", error: { type: "unknown", message: "boom" }, metadata: { phase: "checkpoint" }, content: content("before failure"), diff --git a/packages/core/test/tool-execute.test.ts b/packages/core/test/tool-execute.test.ts index fcfcb7aea4b..adcc4925021 100644 --- a/packages/core/test/tool-execute.test.ts +++ b/packages/core/test/tool-execute.test.ts @@ -12,7 +12,7 @@ const context = { sessionID: Session.ID.make("ses_execute"), agent: Agent.ID.make("build"), messageID: SessionMessage.ID.make("msg_execute"), - callID: Tool.CallID.make("call_execute"), + id: Tool.CallID.make("call_execute"), progress: () => Effect.void, } diff --git a/packages/core/test/tool-question.test.ts b/packages/core/test/tool-question.test.ts index 8cbda1118d5..9193ecab25b 100644 --- a/packages/core/test/tool-question.test.ts +++ b/packages/core/test/tool-question.test.ts @@ -166,7 +166,7 @@ describe("QuestionTool", () => { expect(capturedInput()).toEqual({ sessionID, title: "Questions", - metadata: { kind: "question", tool: { messageID: toolIdentity.messageID, callID: "call-question" } }, + metadata: { kind: "question", tool: { messageID: toolIdentity.messageID, id: "call-question" } }, fields: [ { key: "q0", @@ -212,7 +212,7 @@ describe("QuestionTool", () => { expect(capturedInput()).toEqual({ sessionID, title: "Questions", - metadata: { kind: "question", tool: { messageID: toolIdentity.messageID, callID: "call-question" } }, + metadata: { kind: "question", tool: { messageID: toolIdentity.messageID, id: "call-question" } }, fields: [ { key: "q0", diff --git a/packages/plugin/src/effect/tool.ts b/packages/plugin/src/effect/tool.ts index 3672496d620..28320552abc 100644 --- a/packages/plugin/src/effect/tool.ts +++ b/packages/plugin/src/effect/tool.ts @@ -17,7 +17,7 @@ export interface ToolHooks { readonly sessionID: Session.ID readonly agent: Agent.ID readonly messageID: SessionMessage.ID - readonly callID: Tool.CallID + readonly id: Tool.CallID input: unknown } readonly "execute.after": { @@ -25,7 +25,7 @@ export interface ToolHooks { readonly sessionID: Session.ID readonly agent: Agent.ID readonly messageID: SessionMessage.ID - readonly callID: Tool.CallID + readonly id: Tool.CallID readonly input: unknown } & ( | { diff --git a/packages/plugin/src/promise/tool.ts b/packages/plugin/src/promise/tool.ts index 4070a4a6007..26cf58180a4 100644 --- a/packages/plugin/src/promise/tool.ts +++ b/packages/plugin/src/promise/tool.ts @@ -34,7 +34,7 @@ interface ToolHooks { readonly sessionID: Session.ID readonly agent: Agent.ID readonly messageID: SessionMessage.ID - readonly callID: Tool.CallID + readonly id: Tool.CallID input: unknown } readonly "execute.after": { @@ -42,7 +42,7 @@ interface ToolHooks { readonly sessionID: Session.ID readonly agent: Agent.ID readonly messageID: SessionMessage.ID - readonly callID: Tool.CallID + readonly id: Tool.CallID readonly input: unknown } & ( | { diff --git a/packages/schema/src/permission.ts b/packages/schema/src/permission.ts index e7e7fc7baeb..2faebd42416 100644 --- a/packages/schema/src/permission.ts +++ b/packages/schema/src/permission.ts @@ -17,7 +17,7 @@ export const Source = Schema.Union([ Schema.Struct({ type: Schema.Literal("tool"), messageID: Schema.String, - callID: Schema.String, + id: Schema.String, }), ]).annotate({ identifier: "Permission.Source" }) export type Source = typeof Source.Type diff --git a/packages/schema/src/question.ts b/packages/schema/src/question.ts index d427cd1eaec..beb634d15b0 100644 --- a/packages/schema/src/question.ts +++ b/packages/schema/src/question.ts @@ -45,7 +45,7 @@ export interface Prompt extends Schema.Schema.Type {} export const Tool = Schema.Struct({ messageID: Schema.String, - callID: Schema.String, + id: Schema.String, }).annotate({ identifier: "Question.Tool" }) export interface Tool extends Schema.Schema.Type {} diff --git a/packages/schema/src/session-event.ts b/packages/schema/src/session-event.ts index 4a00ae4b4b9..f9cad0d1121 100644 --- a/packages/schema/src/session-event.ts +++ b/packages/schema/src/session-event.ts @@ -365,7 +365,7 @@ export namespace Tool { const ToolBase = { ...Base, assistantMessageID: SessionMessage.ID, - callID: Schema.String, + id: Schema.String, } export namespace Input { diff --git a/packages/schema/src/tool.ts b/packages/schema/src/tool.ts index f0f122ba2ec..f2e82a4f303 100644 --- a/packages/schema/src/tool.ts +++ b/packages/schema/src/tool.ts @@ -15,7 +15,7 @@ export interface Context { readonly sessionID: Session.ID readonly agent: Agent.ID readonly messageID: SessionMessage.ID - readonly callID: CallID + readonly id: CallID readonly progress: (update: Metadata) => Effect.Effect } diff --git a/packages/schema/test/event-manifest.test.ts b/packages/schema/test/event-manifest.test.ts index bd08c653a5c..40955425c79 100644 --- a/packages/schema/test/event-manifest.test.ts +++ b/packages/schema/test/event-manifest.test.ts @@ -177,7 +177,7 @@ describe("public event manifest", () => { const tool = SessionEvent.Tool.Called.data.make({ sessionID, assistantMessageID, - callID: "call_test", + id: "call_test", input: {}, executed: true, state: { itemId: "item_test" }, diff --git a/packages/simulation/src/backend/simulated-provider.ts b/packages/simulation/src/backend/simulated-provider.ts index 84b36d5878b..f4ead942d92 100644 --- a/packages/simulation/src/backend/simulated-provider.ts +++ b/packages/simulation/src/backend/simulated-provider.ts @@ -477,7 +477,7 @@ const makeToolDriver = Effect.fn("SimulatedProvider.makeToolDriver")(function* ( sessionID: context.sessionID, agent: context.agent, messageID: context.messageID, - callID: context.callID, + id: context.id, }, } const pending: PendingToolInvocation = { diff --git a/packages/simulation/src/protocol/index.ts b/packages/simulation/src/protocol/index.ts index 573baf1f834..5c63f464047 100644 --- a/packages/simulation/src/protocol/index.ts +++ b/packages/simulation/src/protocol/index.ts @@ -503,7 +503,7 @@ export namespace Backend { sessionID: Schema.String, agent: Schema.String, messageID: Schema.String, - callID: Schema.String, + id: Schema.String, }), }) export interface ToolInvocation extends Schema.Schema.Type {} diff --git a/packages/simulation/test/simulated-provider.test.ts b/packages/simulation/test/simulated-provider.test.ts index e21b5f3b065..2142dd545db 100644 --- a/packages/simulation/test/simulated-provider.test.ts +++ b/packages/simulation/test/simulated-provider.test.ts @@ -279,7 +279,7 @@ test("controls arbitrary tools through scoped SDK overlays", async () => { expect.objectContaining({ name: "lookup", description: "Look up a value" }), ) const progress: Tool.Metadata[] = [] - const executeCall = (callID: string, query: string) => + const executeCall = (id: string, query: string) => toolSet.execute({ sessionID: Session.ID.make("ses_simulated_tools"), agent: Agent.ID.make("build"), @@ -287,7 +287,7 @@ test("controls arbitrary tools through scoped SDK overlays", async () => { progress: (update) => Effect.sync(() => progress.push(update)), call: { type: "tool-call", - id: callID, + id: id, name: "lookup", input: { query }, }, @@ -302,7 +302,7 @@ test("controls arbitrary tools through scoped SDK overlays", async () => { sessionID: "ses_simulated_tools", agent: "build", messageID: "msg_simulated_tools", - callID: "call_success", + id: "call_success", }, }) const successID = requireString(requireRecord(successInvocation.params).id) @@ -420,25 +420,25 @@ test("controls arbitrary tools through scoped SDK overlays", async () => { invocations.map((invocation) => { const params = requireRecord(invocation.params) const context = requireRecord(params.context) - return [requireString(context.callID), requireString(params.id)] + return [requireString(context.id), requireString(params.id)] }), ) - for (const [id, callID, value] of [ + for (const [requestID, toolID, value] of [ [5, "call_second", "second result"], [6, "call_first", "first result"], ] as const) { socket.send( JSON.stringify({ jsonrpc: "2.0", - id, + id: requestID, method: "tool.finish", params: { - id: byCall.get(callID), + id: byCall.get(toolID), output: { structured: value, content: [{ type: "text", text: value }] }, }, }), ) - expect(yield* Queue.take(messages)).toMatchObject({ id, result: { ok: true } }) + expect(yield* Queue.take(messages)).toMatchObject({ id: requestID, result: { ok: true } }) } expect(yield* Fiber.join(concurrent[0])).toMatchObject({ output: "first result", diff --git a/packages/tui/src/context/data.tsx b/packages/tui/src/context/data.tsx index b6fc7be6bbb..92423a9bcbb 100644 --- a/packages/tui/src/context/data.tsx +++ b/packages/tui/src/context/data.tsx @@ -208,10 +208,10 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ const item = messages.findLast((item) => item.type === "compaction" && item.status === "running") return item?.type === "compaction" ? item : undefined }, - latestTool(assistant: SessionMessageAssistant | undefined, callID?: string) { + latestTool(assistant: SessionMessageAssistant | undefined, id?: string) { return assistant?.content.findLast( (item): item is SessionMessageAssistantTool => - item.type === "tool" && (callID === undefined || item.id === callID), + item.type === "tool" && (id === undefined || item.id === id), ) }, latestText(assistant: SessionMessageAssistant | undefined) { @@ -592,7 +592,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ message.update(event.data.sessionID, (draft, index) => { message.assistant(draft, index, event.data.assistantMessageID)?.content.push({ type: "tool", - id: event.data.callID, + id: event.data.id, name: event.data.name, time: { created: event.created }, state: { status: "streaming", input: "" }, @@ -603,7 +603,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ message.update(event.data.sessionID, (draft, index) => { const match = message.latestTool( message.assistant(draft, index, event.data.assistantMessageID), - event.data.callID, + event.data.id, ) if (match?.state.status === "streaming") match.state.input += event.data.delta }) @@ -612,7 +612,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ message.update(event.data.sessionID, (draft, index) => { const match = message.latestTool( message.assistant(draft, index, event.data.assistantMessageID), - event.data.callID, + event.data.id, ) if (match?.state.status === "streaming") match.state.input = event.data.text }) @@ -621,7 +621,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ message.update(event.data.sessionID, (draft, index) => { const match = message.latestTool( message.assistant(draft, index, event.data.assistantMessageID), - event.data.callID, + event.data.id, ) if (!match) return match.time.ran = event.created @@ -634,7 +634,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ message.update(event.data.sessionID, (draft, index) => { const match = message.latestTool( message.assistant(draft, index, event.data.assistantMessageID), - event.data.callID, + event.data.id, ) if (match?.state.status !== "running") return match.state.metadata = event.data.metadata @@ -644,7 +644,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ message.update(event.data.sessionID, (draft, index) => { const match = message.latestTool( message.assistant(draft, index, event.data.assistantMessageID), - event.data.callID, + event.data.id, ) if (match?.state.status !== "running") return match.state = { @@ -662,7 +662,7 @@ export const { use: useData, provider: DataProvider } = createSimpleContext({ message.update(event.data.sessionID, (draft, index) => { const match = message.latestTool( message.assistant(draft, index, event.data.assistantMessageID), - event.data.callID, + event.data.id, ) if (!match || (match.state.status !== "streaming" && match.state.status !== "running")) return match.state = { diff --git a/packages/tui/src/mini/demo.ts b/packages/tui/src/mini/demo.ts index dcf6bf35372..5d1cbb6ecc2 100644 --- a/packages/tui/src/mini/demo.ts +++ b/packages/tui/src/mini/demo.ts @@ -373,7 +373,7 @@ function askPermission(state: State, item: Permit): void { resources: item.patterns, metadata: item.metadata ?? {}, save: item.always, - source: { type: "tool", messageID: item.ref.msg, callID: item.ref.call }, + source: { type: "tool", messageID: item.ref.msg, id: item.ref.call }, tool, }, }) @@ -805,7 +805,7 @@ function emitForm(state: State, kind: FormKind = "question"): void { title: form.title, metadata: kind === "question" - ? { kind: "question", tool: { messageID: ref.msg, callID: ref.call } } + ? { kind: "question", tool: { messageID: ref.msg, id: ref.call } } : { kind: "mcp", message: `Synthetic ${kind} MCP elicitation` }, fields: form.fields, } diff --git a/packages/tui/src/mini/stream-v2.subagent.ts b/packages/tui/src/mini/stream-v2.subagent.ts index 6f1fdf56c75..d1ff8556d01 100644 --- a/packages/tui/src/mini/stream-v2.subagent.ts +++ b/packages/tui/src/mini/stream-v2.subagent.ts @@ -164,13 +164,13 @@ function text(value: unknown): string | undefined { return next || undefined } -function sourceKey(messageID: string, callID: string) { - return `${messageID}\u0000${callID}` +function sourceKey(messageID: string, id: string) { + return `${messageID}\u0000${id}` } function permissionTool(request: PermissionRequest, tools: Map) { if (request.source?.type !== "tool") return request - const tool = tools.get(sourceKey(request.source.messageID, request.source.callID)) + const tool = tools.get(sourceKey(request.source.messageID, request.source.id)) return tool ? { ...request, tool } : request } @@ -444,7 +444,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac ...new Set( permissions.flatMap((request) => { if (request.source?.type !== "tool") return [] - const key = sourceKey(request.source.messageID, request.source.callID) + const key = sourceKey(request.source.messageID, request.source.id) return child.toolSources.has(key) ? [] : [request.source.messageID] }), ), @@ -475,7 +475,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac permissions.some( (request) => request.source?.type === "tool" && - !child.toolSources.has(sourceKey(request.source.messageID, request.source.callID)), + !child.toolSources.has(sourceKey(request.source.messageID, request.source.id)), ) ) throw new Error("Permission source tool is unavailable") @@ -737,12 +737,12 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac return } if (event.type === "session.tool.input.started") { - if (child.finishedTools.has(sourceKey(event.data.assistantMessageID, event.data.callID))) return + if (child.finishedTools.has(sourceKey(event.data.assistantMessageID, event.data.id))) return childTool( child, { type: "tool", - id: event.data.callID, + id: event.data.id, name: event.data.name, state: { status: "streaming", input: "" }, time: { created: event.created }, @@ -752,7 +752,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac return } if (event.type === "session.tool.input.delta" || event.type === "session.tool.input.ended") { - const current = child.tools.get(sourceKey(event.data.assistantMessageID, event.data.callID)) + const current = child.tools.get(sourceKey(event.data.assistantMessageID, event.data.id)) if (!current || current.part.state.status !== "streaming") return childTool( child, @@ -769,14 +769,14 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac return } if (event.type === "session.tool.called") { - const key = sourceKey(event.data.assistantMessageID, event.data.callID) + const key = sourceKey(event.data.assistantMessageID, event.data.id) if (child.finishedTools.has(key)) return const current = child.tools.get(key) childTool( child, { type: "tool", - id: event.data.callID, + id: event.data.id, name: current?.part.name ?? "tool", executed: event.data.executed, providerState: event.data.state, @@ -790,7 +790,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac return } if (event.type === "session.tool.progress") { - const key = sourceKey(event.data.assistantMessageID, event.data.callID) + const key = sourceKey(event.data.assistantMessageID, event.data.id) if (child.finishedTools.has(key)) return const current = child.tools.get(key) const part = current?.part @@ -798,7 +798,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac child, { type: "tool", - id: event.data.callID, + id: event.data.id, name: part?.name ?? "tool", executed: part?.executed, providerState: part?.providerState, @@ -819,7 +819,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac return } if (event.type === "session.tool.success" || event.type === "session.tool.failed") { - const key = sourceKey(event.data.assistantMessageID, event.data.callID) + const key = sourceKey(event.data.assistantMessageID, event.data.id) if (child.finishedTools.has(key)) return const current = child.tools.get(key) const part = current?.part @@ -828,7 +828,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac child, { type: "tool", - id: event.data.callID, + id: event.data.id, name: part?.name ?? "tool", executed: event.data.executed, providerState: part?.providerState, @@ -947,11 +947,11 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac if (!active(signal)) return if (event.type === "session.tool.input.started") { if (canonicalToolName(event.data.name) === "subagent") - pendingCalls.set(sourceKey(event.data.assistantMessageID, event.data.callID), {}) + pendingCalls.set(sourceKey(event.data.assistantMessageID, event.data.id), {}) return } if (event.type === "session.tool.called") { - const key = sourceKey(event.data.assistantMessageID, event.data.callID) + const key = sourceKey(event.data.assistantMessageID, event.data.id) if (pendingCalls.has(key)) pendingCalls.set(key, event.data.input) return } @@ -961,7 +961,7 @@ export function createSubagentTracker(input: SubagentTrackerInput): SubagentTrac event.type !== "session.tool.failed" ) return - const key = sourceKey(event.data.assistantMessageID, event.data.callID) + const key = sourceKey(event.data.assistantMessageID, event.data.id) const pending = pendingCalls.get(key) if (event.type !== "session.tool.progress") pendingCalls.delete(key) const found = childSessionID(record(event.data.metadata)) diff --git a/packages/tui/src/mini/stream-v2.transport.ts b/packages/tui/src/mini/stream-v2.transport.ts index e58811ec204..ad249c6eb5e 100644 --- a/packages/tui/src/mini/stream-v2.transport.ts +++ b/packages/tui/src/mini/stream-v2.transport.ts @@ -91,12 +91,12 @@ type Wait = { } // One active session.shell call. The HTTP response is the completion signal; -// callID correlates the live shell events once shell.started is observed, and +// id correlates the live shell events once shell.started is observed, and // abort cancels the blocking request when the user interrupts the turn. type ShellWait = { eventID: string messageID: string - callID?: string + id?: string resolve: () => void abort: () => void } @@ -291,27 +291,27 @@ function streamPartKey(messageID: string, partID: string) { return `${messageID}\u0000${partID}` } -function permissionSourceKey(messageID: string, callID: string) { - return streamPartKey(messageID, callID) +function permissionSourceKey(messageID: string, id: string) { + return streamPartKey(messageID, id) } function permissionTool(request: PermissionRequest, tools: Map) { if (request.source?.type !== "tool") return request - const tool = tools.get(permissionSourceKey(request.source.messageID, request.source.callID)) + const tool = tools.get(permissionSourceKey(request.source.messageID, request.source.id)) return tool ? { ...request, tool } : request } // Direct shell calls use one "start" commit rendering `$ command` and one "progress" // commit rendering the merged output (see toolEntryBody in tool.ts). function shellCommit( - callID: string, + id: string, command: string, next: Pick, ): StreamCommit { return { kind: "tool", source: "tool", - partID: `shell:${callID}`, + partID: `shell:${id}`, tool: "shell", shell: { command }, ...next, @@ -319,7 +319,7 @@ function shellCommit( } function shellTerminal( - callID: string, + id: string, command: string, shell: { status: string; exit?: number | string }, output: { output: string; cursor: number; size: number; truncated: boolean }, @@ -332,10 +332,10 @@ function shellTerminal( : shell.status === "exited" ? `Shell exited with code ${shell.exit ?? "unknown"}` : `Shell ${shell.status}` - if (!error) return [shellCommit(callID, command, { text, phase: "progress", toolState: "completed" })] + if (!error) return [shellCommit(id, command, { text, phase: "progress", toolState: "completed" })] return [ - ...(text ? [shellCommit(callID, command, { text, phase: "progress", toolState: "running" })] : []), - shellCommit(callID, command, { text: error, phase: "final", toolState: "error", toolError: error }), + ...(text ? [shellCommit(id, command, { text, phase: "progress", toolState: "running" })] : []), + shellCommit(id, command, { text: error, phase: "final", toolState: "error", toolError: error }), ] } @@ -570,7 +570,7 @@ export async function createSessionTransport(input: StreamInput): Promise state.permissions.some( (request) => - request.source?.type === "tool" && permissionSourceKey(request.source.messageID, request.source.callID) === key, + request.source?.type === "tool" && permissionSourceKey(request.source.messageID, request.source.id) === key, ) const pruneToolSources = () => { @@ -647,7 +647,7 @@ export async function createSessionTransport(input: StreamInput): Promise { const pending = new Set( permissions.flatMap((request) => - request.source?.type === "tool" ? [permissionSourceKey(request.source.messageID, request.source.callID)] : [], + request.source?.type === "tool" ? [permissionSourceKey(request.source.messageID, request.source.id)] : [], ), ) const messageIDs = [ ...new Set( permissions.flatMap((request) => { if (request.source?.type !== "tool") return [] - const key = permissionSourceKey(request.source.messageID, request.source.callID) + const key = permissionSourceKey(request.source.messageID, request.source.id) return state.toolSources.has(key) ? [] : [request.source.messageID] }), ), @@ -992,7 +992,7 @@ export async function createSessionTransport(input: StreamInput): Promise SessionMessageAssistantTool | undefined) return createMemo(() => { if (local.permission.mode === "auto") return false const request = data.session.permission.list(ctx.sessionID)?.[0] - return request?.source?.type === "tool" && request.source.callID === part()?.id + return request?.source?.type === "tool" && request.source.id === part()?.id }) } diff --git a/packages/tui/src/routes/session/permission.tsx b/packages/tui/src/routes/session/permission.tsx index d2a9ee10dd1..4b427eacf5a 100644 --- a/packages/tui/src/routes/session/permission.tsx +++ b/packages/tui/src/routes/session/permission.tsx @@ -123,7 +123,7 @@ export function PermissionPrompt(props: { request: PermissionRequest; directory? if (!tool) return { input: undefined, metadata: undefined } const message = data.session.message.get(props.request.sessionID, tool.messageID) if (message?.type !== "assistant") return { input: undefined, metadata: undefined } - const part = message.content.find((part) => part.type === "tool" && part.id === tool.callID) + const part = message.content.find((part) => part.type === "tool" && part.id === tool.id) if (part?.type === "tool" && part.state.status !== "streaming") { return { input: part.state.input, metadata: part.state.metadata } } diff --git a/packages/tui/src/routes/session/rows.ts b/packages/tui/src/routes/session/rows.ts index 928a9fe01ad..14ffe29d21d 100644 --- a/packages/tui/src/routes/session/rows.ts +++ b/packages/tui/src/routes/session/rows.ts @@ -68,7 +68,7 @@ export function createSessionRows(sessionID: Accessor) { function pendingPermissions() { return new Set( (data.session.permission.list(sessionID()) ?? []).flatMap((request) => - request.source?.type === "tool" ? [request.source.callID] : [], + request.source?.type === "tool" ? [request.source.id] : [], ), ) } @@ -255,7 +255,7 @@ export function createSessionRows(sessionID: Accessor) { data.on("session.tool.input.started", (event) => { if (event.data.sessionID === sessionID()) appendPart( - { messageID: event.data.assistantMessageID, partID: event.data.callID }, + { messageID: event.data.assistantMessageID, partID: event.data.id }, { type: "tool", name: event.data.name }, ) }), diff --git a/packages/tui/test/cli/tui/data.test.tsx b/packages/tui/test/cli/tui/data.test.tsx index e8c6f4095c6..430775bd18f 100644 --- a/packages/tui/test/cli/tui/data.test.tsx +++ b/packages/tui/test/cli/tui/data.test.tsx @@ -880,7 +880,7 @@ test("completes exploration when a queued prompt is promoted", async () => { data: { sessionID, assistantMessageID: "message-assistant", - callID: "call-read", + id: "call-read", name: "read", }, }) @@ -951,7 +951,7 @@ test("classifies live tool rows independently of their call ID", async () => { data: { sessionID, assistantMessageID: "message-assistant", - callID: "reasoning:0", + id: "reasoning:0", name: "bash", }, }) @@ -2485,7 +2485,7 @@ test("settles pending tools when a live failure arrives", async () => { data: { sessionID: "session-1", assistantMessageID: "msg_explicit_assistant_9", - callID: "call-1", + id: "call-1", name: "bash", }, }) @@ -2497,7 +2497,7 @@ test("settles pending tools when a live failure arrives", async () => { data: { sessionID: "session-1", assistantMessageID: "msg_explicit_assistant_9", - callID: "call-1", + id: "call-1", input: {}, executed: false, state: { call: true }, @@ -2510,7 +2510,7 @@ test("settles pending tools when a live failure arrives", async () => { data: { sessionID: "session-1", assistantMessageID: "msg_explicit_assistant_9", - callID: "call-1", + id: "call-1", metadata: { sessionID: "session-child", status: "running" }, }, }) @@ -2533,7 +2533,7 @@ test("settles pending tools when a live failure arrives", async () => { data: { sessionID: "session-1", assistantMessageID: "msg_explicit_assistant_9", - callID: "call-1", + id: "call-1", error: { type: "unknown", message: "aborted" }, executed: false, resultState: { result: true }, diff --git a/packages/tui/test/mini/permission.shared.test.ts b/packages/tui/test/mini/permission.shared.test.ts index 2b73f0aae7d..84a9ae3f479 100644 --- a/packages/tui/test/mini/permission.shared.test.ts +++ b/packages/tui/test/mini/permission.shared.test.ts @@ -89,7 +89,7 @@ describe("run permission shared", () => { permissionInfo( req({ action: "shell", - source: { type: "tool", messageID: "msg-shell", callID: "call-shell" }, + source: { type: "tool", messageID: "msg-shell", id: "call-shell" }, tool: canonicalToolPart( "shell", { @@ -134,7 +134,7 @@ describe("run permission shared", () => { req({ action: "websearch", metadata: { provider: "parallel" }, - source: { type: "tool", messageID: "msg-search", callID: "call-search" }, + source: { type: "tool", messageID: "msg-search", id: "call-search" }, tool: canonicalToolPart( "websearch", { @@ -157,7 +157,7 @@ describe("run permission shared", () => { const request = req({ action: "edit", resources: ["src/index.ts"], - source: { type: "tool", messageID: "msg-edit", callID: "call-edit" }, + source: { type: "tool", messageID: "msg-edit", id: "call-edit" }, tool: canonicalToolPart( "edit", { diff --git a/packages/tui/test/mini/stream-v2.transport.test.ts b/packages/tui/test/mini/stream-v2.transport.test.ts index 604384c9256..7dcb2772f2b 100644 --- a/packages/tui/test/mini/stream-v2.transport.test.ts +++ b/packages/tui/test/mini/stream-v2.transport.test.ts @@ -416,7 +416,7 @@ describe("V2 mini transport", () => { sessionID: "ses_child", action: "shell", resources: ["git status --short"], - source: { type: "tool", messageID: "msg_child_source", callID: "call_child_source" }, + source: { type: "tool", messageID: "msg_child_source", id: "call_child_source" }, } const client = sdk({ streams: [events], @@ -2032,7 +2032,7 @@ describe("V2 mini transport", () => { created: index * 3 + 1, type: "session.tool.input.started", durable: durable("ses_1", index * 3), - data: { sessionID: "ses_1", assistantMessageID: messageID, callID: "call_repeated", name: "read" }, + data: { sessionID: "ses_1", assistantMessageID: messageID, id: "call_repeated", name: "read" }, }) events.push({ id: `evt_repeated_called_${index}`, @@ -2042,7 +2042,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: messageID, - callID: "call_repeated", + id: "call_repeated", input: { path: `${index + 1}.txt` }, executed: true, }, @@ -2055,7 +2055,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: messageID, - callID: "call_repeated", + id: "call_repeated", metadata: {}, content: [{ type: "text", text: "" }], executed: true, @@ -2098,7 +2098,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_progress", - callID: "call_progress", + id: "call_progress", name: "shell", }, }) @@ -2110,7 +2110,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_progress", - callID: "call_progress", + id: "call_progress", input: { command: "printf partial && false" }, executed: true, }, @@ -2122,7 +2122,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_progress", - callID: "call_progress", + id: "call_progress", metadata: { checkpoint: 1 }, }, }) @@ -2134,7 +2134,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_progress", - callID: "call_progress", + id: "call_progress", error: { type: "unknown", message: "boom" }, metadata: { checkpoint: 1 }, content: [{ type: "text", text: "partial" }], @@ -2933,7 +2933,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_failed_subagent", - callID: "call_failed_subagent", + id: "call_failed_subagent", name: "subagent", }, }) @@ -2945,7 +2945,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_failed_subagent", - callID: "call_failed_subagent", + id: "call_failed_subagent", input: { agent: "explore", description: "Inspect failure", prompt: "inspect" }, executed: true, }, @@ -2958,7 +2958,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_failed_subagent", - callID: "call_failed_subagent", + id: "call_failed_subagent", error: { type: "unknown", message: "subagent failed" }, metadata: { sessionID: "ses_child_failed", status: "running" }, executed: true, @@ -2996,7 +2996,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_subagent", - callID: "call_subagent", + id: "call_subagent", name: "subagent", }, }) @@ -3008,7 +3008,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_subagent", - callID: "call_subagent", + id: "call_subagent", input: { agent: "explore", description: "Inspect progress", prompt: "inspect" }, executed: true, }, @@ -3020,7 +3020,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_subagent", - callID: "call_subagent", + id: "call_subagent", metadata: { sessionID: "ses_child_progress", status: "running" }, }, }) @@ -3046,7 +3046,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_child_progress", assistantMessageID: "msg_child_tool", - callID: "call_child_shell", + id: "call_child_shell", name: "shell", }, }) @@ -3058,7 +3058,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_child_progress", assistantMessageID: "msg_child_tool", - callID: "call_child_shell", + id: "call_child_shell", input: { command: "printf child && false" }, executed: true, }, @@ -3070,7 +3070,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_child_progress", assistantMessageID: "msg_child_tool", - callID: "call_child_shell", + id: "call_child_shell", metadata: { checkpoint: "child" }, }, }) @@ -3083,7 +3083,7 @@ describe("V2 mini transport", () => { sessionID: "ses_child_progress", action: "shell", resources: ["printf child && false"], - source: { type: "tool", messageID: "msg_child_tool", callID: "call_child_shell" }, + source: { type: "tool", messageID: "msg_child_tool", id: "call_child_shell" }, }, }) events.push({ @@ -3094,7 +3094,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_child_progress", assistantMessageID: "msg_child_tool", - callID: "call_child_shell", + id: "call_child_shell", error: { type: "unknown", message: "child boom" }, metadata: { checkpoint: "child" }, content: [{ type: "text", text: "child partial" }], @@ -3531,24 +3531,24 @@ describe("V2 mini transport", () => { footer: ui.api, }) const states = () => ui.events.flatMap((event) => (event.type === "stream.subagent" ? [event.state] : [])) - const inputStarted = (callID: string, name: string, seq: number) => + const inputStarted = (id: string, name: string, seq: number) => events.push({ - id: `evt_started_${callID}`, + id: `evt_started_${id}`, created: seq, type: "session.tool.input.started", durable: durable("ses_child", seq), - data: { sessionID: "ses_child", assistantMessageID: "msg_tool_projected", callID, name }, + data: { sessionID: "ses_child", assistantMessageID: "msg_tool_projected", id, name }, }) - const called = (callID: string, input: Record, seq: number) => + const called = (id: string, input: Record, seq: number) => events.push({ - id: `evt_called_${callID}`, + id: `evt_called_${id}`, created: seq, type: "session.tool.called", durable: durable("ses_child", seq), data: { sessionID: "ses_child", assistantMessageID: "msg_tool_projected", - callID, + id, input, executed: true, }, @@ -3567,7 +3567,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_child", assistantMessageID: "msg_tool_projected", - callID: "call_terminal", + id: "call_terminal", metadata: {}, content: [{ type: "text", text: "found" }], executed: true, @@ -3705,7 +3705,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_parent_a", - callID: "call_sub", + id: "call_sub", name: "subagent", }, }) @@ -3717,7 +3717,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_parent_a", - callID: "call_sub", + id: "call_sub", input: { agent: "explore", description: "Find things", prompt: "go", background: true }, executed: true, }, @@ -3730,7 +3730,7 @@ describe("V2 mini transport", () => { data: { sessionID: "ses_1", assistantMessageID: "msg_parent_a", - callID: "call_sub", + id: "call_sub", metadata: { sessionID: "ses_child", status: "running", output: "" }, content: [{ type: "text", text: "" }], executed: true, diff --git a/packages/www/content/docs/build/plugins.mdx b/packages/www/content/docs/build/plugins.mdx index 955a7a150ff..1b109bd2cf6 100644 --- a/packages/www/content/docs/build/plugins.mdx +++ b/packages/www/content/docs/build/plugins.mdx @@ -344,8 +344,8 @@ argument to `tools.add` to configure the registration with `execute` CodeMode tool. Set `codemode: false` to expose it directly to the provider. -The executor receives a second context argument containing `sessionID`, -`agent`, `messageID`, `callID`, and `progress`. A tool with `output` +The executor receives a second context argument containing `id`, `sessionID`, +`agent`, `messageID`, and `progress`. A tool with `output` must return `output`; Effect and Standard Schema codecs validate it, while raw JSON Schema definitions enforce JSON compatibility only. A tool without `output` returns model-visible `content` instead.