diff options
Diffstat (limited to 'packages/kernel/src')
| -rw-r--r-- | packages/kernel/src/runtime/dispatch.ts | 4 | ||||
| -rw-r--r-- | packages/kernel/src/runtime/run-turn.test.ts | 65 | ||||
| -rw-r--r-- | packages/kernel/src/runtime/run-turn.ts | 3 |
3 files changed, 72 insertions, 0 deletions
diff --git a/packages/kernel/src/runtime/dispatch.ts b/packages/kernel/src/runtime/dispatch.ts index e0be1b4..01f0043 100644 --- a/packages/kernel/src/runtime/dispatch.ts +++ b/packages/kernel/src/runtime/dispatch.ts @@ -18,6 +18,7 @@ export async function executeToolCall( turnId: string, toolSpan?: Span, cwd?: string, + computerId?: string, ): Promise<ToolResult> { if (tool === undefined) { return { content: `Unknown tool: ${call.name}`, isError: true }; @@ -34,6 +35,7 @@ export async function executeToolCall( log: toolSpan?.log ?? createNoopLogger(), conversationId, ...(cwd !== undefined ? { cwd } : {}), + ...(computerId !== undefined ? { computerId } : {}), }; // Race the tool's execute promise against the abort signal so a tool // that hangs (ignores ctx.signal, or blocks on something the signal @@ -74,6 +76,7 @@ export function createStepDispatcher( turnId: string, toolSpans: Map<string, Span>, cwd?: string, + computerId?: string, ): StepDispatcher { let activeCount = 0; let unsafeRunning = false; @@ -112,6 +115,7 @@ export function createStepDispatcher( turnId, tcSpan, cwd, + computerId, ); activeCount--; if (entry.tool?.concurrencySafe === false) unsafeRunning = false; diff --git a/packages/kernel/src/runtime/run-turn.test.ts b/packages/kernel/src/runtime/run-turn.test.ts index 0d4c59d..08d3055 100644 --- a/packages/kernel/src/runtime/run-turn.test.ts +++ b/packages/kernel/src/runtime/run-turn.test.ts @@ -835,6 +835,71 @@ describe("runTurn", () => { expect(capturedCwd).toBeUndefined(); }); + it("forwards computerId from RunTurnInput to ToolExecuteContext", async () => { + let capturedComputerId: string | undefined = "SENTINEL_NOT_SET"; + + const tool = createFakeTool("computercheck", async (_input, ctx) => { + capturedComputerId = ctx.computerId; + return { content: "ok" }; + }); + + const provider = createFakeProvider([ + [ + { type: "tool-call", toolCallId: "tc1", toolName: "computercheck", input: {} }, + { type: "finish", reason: "tool-calls" }, + ], + [ + { type: "text-delta", delta: "done" }, + { type: "finish", reason: "stop" }, + ], + ]); + + await runTurn({ + provider, + messages: [userMessage], + tools: [tool], + dispatch: { maxConcurrent: 1, eager: false }, + conversationId: "tab-test", + turnId: "turn-test", + emit: () => {}, + computerId: "ssh-host-alias", + }); + + expect(capturedComputerId).toBe("ssh-host-alias"); + }); + + it("forwards undefined computerId when RunTurnInput has no computerId", async () => { + let capturedComputerId: string | undefined = "SENTINEL_NOT_SET"; + + const tool = createFakeTool("computercheck", async (_input, ctx) => { + capturedComputerId = ctx.computerId; + return { content: "ok" }; + }); + + const provider = createFakeProvider([ + [ + { type: "tool-call", toolCallId: "tc1", toolName: "computercheck", input: {} }, + { type: "finish", reason: "tool-calls" }, + ], + [ + { type: "text-delta", delta: "done" }, + { type: "finish", reason: "stop" }, + ], + ]); + + await runTurn({ + provider, + messages: [userMessage], + tools: [tool], + dispatch: { maxConcurrent: 1, eager: false }, + conversationId: "tab-test", + turnId: "turn-test", + emit: () => {}, + }); + + expect(capturedComputerId).toBeUndefined(); + }); + it("aggregates usage across multiple steps", async () => { const provider = createFakeProvider([ [ diff --git a/packages/kernel/src/runtime/run-turn.ts b/packages/kernel/src/runtime/run-turn.ts index f5d80d3..940c77f 100644 --- a/packages/kernel/src/runtime/run-turn.ts +++ b/packages/kernel/src/runtime/run-turn.ts @@ -117,6 +117,7 @@ interface StepContext { readonly turnSpan: Span | undefined; readonly toolSpans: Map<string, Span>; readonly cwd: string | undefined; + readonly computerId: string | undefined; readonly now: (() => number) | undefined; /** Per-turn provider options (model, systemPrompt, …) threaded to stream(). */ readonly providerOpts: ProviderStreamOptions | undefined; @@ -295,6 +296,7 @@ async function executeStep(ctx: StepContext): Promise<StepResult> { ctx.turnId, ctx.toolSpans, ctx.cwd, + ctx.computerId, ); const timing: TimingState = { @@ -522,6 +524,7 @@ export async function runTurn(input: RunTurnInput): Promise<RunTurnResult> { turnSpan, toolSpans, cwd: input.cwd, + computerId: input.computerId, now, providerOpts: input.providerOpts, }); |
