From c94f1563f5efc8a21b48b62058699924266efb63 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 04:10:49 +0800 Subject: [PATCH] test(acp-example): five snapshot scenarios + cancel/error input ops MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the first cut of snapshot scenarios, each asserting a normalized stdout transcript golden and (for model turns) a re-persisted session-log golden: - text-turn, tool-call-turn, multi-turn: RECORDED against the real API — the committed session.jsonl is a genuine harvested log; replay derives the model script from it and reproduces deterministically with no key. tool-call-turn exercises the real bash executor (echo SNAPSHOT_OK → tool/call + tool/result + a post-tool answer step). - error-finish, cancel: AUTHORED via a replay.override.json sidecar (the live API can't be coaxed into a deterministic 401 or mid-stream cancel). error- finish replays a {kind:throw} 401 → the bridge answers the prompt with a JSON-RPC error and the log records turn/end{kind:error}; cancel replays a {kind:hang} → stopReason:cancelled. Two input-DSL ops support these: promptExpectError (awaits the prompt, asserts it rejects — the editor's view of a failed turn — and swallows it) and promptAndCancel (dispatches the prompt unawaited, waits until the client OBSERVES the streamed agent_message_chunk, then cancels — pinning frame order so the cancel transcript is deterministic; fixes a flake Codex caught where the late chunk and the cancelled response could interleave either way). Scenarios carry a `recorded` flag so test:snapshot:record only re-runs the live-API ones. reasoning/max-tokens scenarios are deferred (hard to force deterministically from the live model). Per docs/rfc/implemented/2026-06-19. --- examples/acp-agent/tests/acp.snapshot.ts | 29 +- examples/acp-agent/tests/snapshot-harness.ts | 56 +- .../tests/snapshots/cancel/input.json | 7 + .../snapshots/cancel/replay.override.json | 3 + .../tests/snapshots/cancel/session.golden.txt | 95 ++ .../tests/snapshots/cancel/session.jsonl | 1 + .../tests/snapshots/cancel/stdout.golden.txt | 62 + .../tests/snapshots/error-finish/input.json | 7 + .../error-finish/replay.override.json | 3 + .../snapshots/error-finish/session.golden.txt | 79 + .../snapshots/error-finish/session.jsonl | 1 + .../snapshots/error-finish/stdout.golden.txt | 49 + .../tests/snapshots/multi-turn/input.json | 8 + .../snapshots/multi-turn/session.golden.txt | 929 +++++++++++ .../tests/snapshots/multi-turn/session.jsonl | 66 + .../snapshots/multi-turn/stdout.golden.txt | 615 +++++++ .../tests/snapshots/text-turn/input.json | 7 + .../snapshots/text-turn/session.golden.txt | 489 ++++++ .../tests/snapshots/text-turn/session.jsonl | 35 + .../snapshots/text-turn/stdout.golden.txt | 342 ++++ .../tests/snapshots/tool-call-turn/input.json | 7 + .../tool-call-turn/session.golden.txt | 1469 +++++++++++++++++ .../snapshots/tool-call-turn/session.jsonl | 100 ++ .../tool-call-turn/stdout.golden.txt | 723 ++++++++ 24 files changed, 5173 insertions(+), 9 deletions(-) create mode 100644 examples/acp-agent/tests/snapshots/cancel/input.json create mode 100644 examples/acp-agent/tests/snapshots/cancel/replay.override.json create mode 100644 examples/acp-agent/tests/snapshots/cancel/session.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/cancel/session.jsonl create mode 100644 examples/acp-agent/tests/snapshots/cancel/stdout.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/error-finish/input.json create mode 100644 examples/acp-agent/tests/snapshots/error-finish/replay.override.json create mode 100644 examples/acp-agent/tests/snapshots/error-finish/session.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/error-finish/session.jsonl create mode 100644 examples/acp-agent/tests/snapshots/error-finish/stdout.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/multi-turn/input.json create mode 100644 examples/acp-agent/tests/snapshots/multi-turn/session.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/multi-turn/session.jsonl create mode 100644 examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/text-turn/input.json create mode 100644 examples/acp-agent/tests/snapshots/text-turn/session.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/text-turn/session.jsonl create mode 100644 examples/acp-agent/tests/snapshots/text-turn/stdout.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/tool-call-turn/input.json create mode 100644 examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl create mode 100644 examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.txt diff --git a/examples/acp-agent/tests/acp.snapshot.ts b/examples/acp-agent/tests/acp.snapshot.ts index a2422d4395..8aa4a6309b 100644 --- a/examples/acp-agent/tests/acp.snapshot.ts +++ b/examples/acp-agent/tests/acp.snapshot.ts @@ -20,20 +20,35 @@ import { type NormalizeContext, normalizeSessionLog, normalizeStdout } from './s const SNAPSHOTS_DIR = join(dirname(fileURLToPath(import.meta.url)), 'snapshots') const RECORDING = process.env.DSH_SNAPSHOT === 'record' -/** A scenario and whether it makes any model call (→ has a behavioral JSONL golden). */ +/** A snapshot scenario and how its fixtures are produced. */ interface Scenario { name: string /** Whether the scenario drives at least one model turn (so a JSONL golden applies). */ hasModelTurn: boolean + /** + * Whether `test:snapshot:record` regenerates this scenario's `session.jsonl` + * from the LIVE API. `recorded` scenarios are model-driven and reproducible; + * `authored` scenarios (a hand-written `replay.override.json` sidecar drives + * replay — e.g. a provider error or a cancel, which the live API can't be + * coaxed into deterministically) are NEVER re-recorded. + */ + recorded: boolean } const SCENARIOS: Scenario[] = [ - { name: 'handshake', hasModelTurn: false }, + { name: 'handshake', hasModelTurn: false, recorded: false }, + { name: 'text-turn', hasModelTurn: true, recorded: true }, + { name: 'tool-call-turn', hasModelTurn: true, recorded: true }, + { name: 'multi-turn', hasModelTurn: true, recorded: true }, + { name: 'error-finish', hasModelTurn: true, recorded: false }, + { name: 'cancel', hasModelTurn: true, recorded: false }, ] for (const scenario of SCENARIOS) { describe(`snapshot: ${scenario.name}`, () => { - it('matches the stdout transcript golden', async () => { + // In RECORD mode, only re-run the `recorded` (live-API) scenarios; the + // `authored` ones (sidecar-driven errors/cancel) are never re-recorded. + it.skipIf(RECORDING && !scenario.recorded)('matches the goldens', async () => { const dir = join(SNAPSHOTS_DIR, scenario.name) const input = JSON.parse(await readFile(join(dir, 'input.json'), 'utf8')) as InputScript const overrideFile = join(dir, 'replay.override.json') @@ -48,10 +63,10 @@ for (const scenario of SCENARIOS) { cwd: result.cwd, } - // RECORD mode: persist the freshly-harvested log back to the scenario's - // session.jsonl fixture (a model scenario must produce one). `--update` - // refreshes the Vitest goldens but NOT this fixture, so write it here. - if (RECORDING && scenario.hasModelTurn) { + // RECORD mode (recorded scenarios only): persist the freshly-harvested log + // back to the scenario's session.jsonl fixture. `--update` refreshes the + // Vitest goldens but NOT this fixture, so write it here. + if (RECORDING && scenario.recorded && scenario.hasModelTurn) { expect(result.sessionLog, 'record produced no session log to harvest').toBeDefined() await writeFile(join(dir, 'session.jsonl'), result.sessionLog as string) } diff --git a/examples/acp-agent/tests/snapshot-harness.ts b/examples/acp-agent/tests/snapshot-harness.ts index 7fb7eec21d..a13cb3a5a5 100644 --- a/examples/acp-agent/tests/snapshot-harness.ts +++ b/examples/acp-agent/tests/snapshot-harness.ts @@ -44,11 +44,19 @@ const repoTsconfig = fileURLToPath(new URL('../../../tsconfig.json', import.meta * harness interprets these in order. `newSession` captures the server-issued * (random) session id into a `{{sessionId}}` variable that later steps * reference, since a committed file cannot know the id in advance. + * + * `promptAndCancel` sends a prompt WITHOUT awaiting its response, waits until + * the client observes the first streamed `agent_message_chunk` (so the emitted + * frames deterministically precede the cancellation), then cancels the turn — + * the only way to exercise a cancel deterministically (a plain `prompt` step + * awaits the response, which a cancel/hang scenario would block on forever). */ type InputStep = | { op: 'initialize'; terminalOutput?: boolean } | { op: 'newSession' } | { op: 'prompt'; text: string } + | { op: 'promptExpectError'; text: string } + | { op: 'promptAndCancel'; text: string } | { op: 'cancel' } /** A scenario's `input.json`: an ordered list of input steps. */ @@ -122,8 +130,23 @@ export async function runScenario(input: InputScript, opts: RunOptions): Promise Writable.toWeb(child.stdin) as WritableStream, Readable.toWeb(passthrough) as ReadableStream, ) + // Watcher so a step can block until the client OBSERVES a particular + // session/update — used by promptAndCancel to pin frame order (send cancel + // only after the streamed agent_message_chunk has arrived, so those frames + // deterministically precede the cancelled prompt response). + const updateWaiters: { match: (u: SessionNotification['update']) => boolean; resolve: () => void }[] = [] + const waitForUpdate = (match: (u: SessionNotification['update']) => boolean): Promise => + new Promise(resolve => updateWaiters.push({ match, resolve })) + const makeClient = (_agent: AcpAgent): Client => ({ - sessionUpdate(_params: SessionNotification): Promise { + sessionUpdate(params: SessionNotification): Promise { + for (let i = updateWaiters.length - 1; i >= 0; i--) { + const waiter = updateWaiters[i] + if (waiter !== undefined && waiter.match(params.update)) { + updateWaiters.splice(i, 1) + waiter.resolve() + } + } return Promise.resolve() }, requestPermission(_params: RequestPermissionRequest): Promise { @@ -136,7 +159,7 @@ export async function runScenario(input: InputScript, opts: RunOptions): Promise let sessionLog: string | undefined try { for (const step of input.steps) { - await runStep(client, step, cwd, () => sessionId, (id) => { sessionId = id }) + await runStep(client, step, cwd, waitForUpdate, () => sessionId, (id) => { sessionId = id }) } // Done driving: close stdin so the server disposes gracefully (flushing // persistence) and exits. Then await exit so the harvested log is complete. @@ -170,6 +193,7 @@ async function runStep( client: ClientSideConnection, step: InputStep, cwd: string, + waitForUpdate: (match: (u: SessionNotification['update']) => boolean) => Promise, getSessionId: () => string | undefined, setSessionId: (id: string) => void, ): Promise { @@ -191,6 +215,34 @@ async function runStep( await client.prompt({ sessionId, prompt: [{ type: 'text', text: step.text }] }) return } + case 'promptExpectError': { + const sessionId = getSessionId() + if (sessionId === undefined) throw new Error('snapshot-harness: promptExpectError before newSession') + // The model fails this turn (a recorded provider error), so the bridge + // answers the prompt with a JSON-RPC error and the SDK rejects. That + // rejection IS the expected editor experience — swallow it so the run + // completes and the stdout transcript (the error frame) is captured. + await client.prompt({ sessionId, prompt: [{ type: 'text', text: step.text }] }) + .then(() => { throw new Error('snapshot-harness: expected the prompt to fail but it succeeded') }, + () => { /* expected: the turn failed and the bridge returned an error */ }) + return + } + case 'promptAndCancel': { + const sessionId = getSessionId() + if (sessionId === undefined) throw new Error('snapshot-harness: promptAndCancel before newSession') + // Dispatch the prompt WITHOUT awaiting (a hang fixture never resolves on + // its own). To pin frame order deterministically, wait until the client + // has OBSERVED the hang's streamed agent_message_chunk before cancelling — + // so those update frames always precede the cancelled prompt response in + // the transcript (without this, the late chunk and the response race; see + // the Codex review of commit 5). Then cancel and await the prompt, which + // the bridge settles as `cancelled` once the abort propagates. + const promptDone = client.prompt({ sessionId, prompt: [{ type: 'text', text: step.text }] }) + await waitForUpdate(u => u.sessionUpdate === 'agent_message_chunk') + await client.cancel({ sessionId }) + await promptDone + return + } case 'cancel': { const sessionId = getSessionId() if (sessionId === undefined) throw new Error('snapshot-harness: cancel before newSession') diff --git a/examples/acp-agent/tests/snapshots/cancel/input.json b/examples/acp-agent/tests/snapshots/cancel/input.json new file mode 100644 index 0000000000..0bc989ed10 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/cancel/input.json @@ -0,0 +1,7 @@ +{ + "steps": [ + { "op": "initialize" }, + { "op": "newSession" }, + { "op": "promptAndCancel", "text": "Start a long task; this turn will be cancelled mid-stream." } + ] +} diff --git a/examples/acp-agent/tests/snapshots/cancel/replay.override.json b/examples/acp-agent/tests/snapshots/cancel/replay.override.json new file mode 100644 index 0000000000..8436b9ca06 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/cancel/replay.override.json @@ -0,0 +1,3 @@ +[ + { "kind": "hang" } +] diff --git a/examples/acp-agent/tests/snapshots/cancel/session.golden.txt b/examples/acp-agent/tests/snapshots/cancel/session.golden.txt new file mode 100644 index 0000000000..c928bf58f3 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/cancel/session.golden.txt @@ -0,0 +1,95 @@ +{ + "type": "session", + "version": 1, + "id": "{{sessionId}}", + "createdAt": 0, + "cwd": "{{cwd}}" +} +{ + "type": "turn/start", + "seq": 0, + "time": 0, + "data": { + "turn": 1, + "trigger": { + "kind": "message", + "source": { + "kind": "user" + } + } + } +} +{ + "type": "user/message", + "seq": 1, + "time": 0, + "data": { + "content": [ + { + "type": "text", + "text": "Start a long task; this turn will be cancelled mid-stream." + } + ], + "source": { + "kind": "user" + } + } +} +{ + "type": "step/start", + "seq": 2, + "time": 0, + "data": { + "turn": 1, + "step": 1 + } +} +{ + "type": "assistant/chunk", + "seq": 3, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-start", + "index": 0, + "blockType": "text" + } + } +} +{ + "type": "assistant/chunk", + "seq": 4, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "text-delta", + "index": 0, + "text": "partial" + } + } +} +{ + "type": "step/end", + "seq": 5, + "time": 0, + "data": { + "turn": 1, + "step": 1 + } +} +{ + "type": "turn/end", + "seq": 6, + "time": 0, + "data": { + "turn": 1, + "reason": { + "kind": "aborted", + "reason": "session/cancel" + } + } +} diff --git a/examples/acp-agent/tests/snapshots/cancel/session.jsonl b/examples/acp-agent/tests/snapshots/cancel/session.jsonl new file mode 100644 index 0000000000..ab44090be6 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/cancel/session.jsonl @@ -0,0 +1 @@ +{"type":"session","version":1,"id":"00000000-0000-0000-0000-000000000000","createdAt":0} diff --git a/examples/acp-agent/tests/snapshots/cancel/stdout.golden.txt b/examples/acp-agent/tests/snapshots/cancel/stdout.golden.txt new file mode 100644 index 0000000000..42cb46e45c --- /dev/null +++ b/examples/acp-agent/tests/snapshots/cancel/stdout.golden.txt @@ -0,0 +1,62 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "protocolVersion": 1, + "agentInfo": { + "name": "deepseek-harness-acp", + "version": "0.0.1" + }, + "agentCapabilities": { + "loadSession": true, + "promptCapabilities": { + "image": false, + "audio": false, + "embeddedContext": false + } + }, + "authMethods": [] + } +} +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "sessionId": "{{sessionId}}" + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "user_message_chunk", + "content": { + "type": "text", + "text": "Start a long task; this turn will be cancelled mid-stream." + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_message_chunk", + "content": { + "type": "text", + "text": "partial" + } + } + } +} +{ + "jsonrpc": "2.0", + "id": 3, + "result": { + "stopReason": "cancelled" + } +} diff --git a/examples/acp-agent/tests/snapshots/error-finish/input.json b/examples/acp-agent/tests/snapshots/error-finish/input.json new file mode 100644 index 0000000000..29079a89a3 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/error-finish/input.json @@ -0,0 +1,7 @@ +{ + "steps": [ + { "op": "initialize" }, + { "op": "newSession" }, + { "op": "promptExpectError", "text": "This prompt triggers a recorded provider error." } + ] +} diff --git a/examples/acp-agent/tests/snapshots/error-finish/replay.override.json b/examples/acp-agent/tests/snapshots/error-finish/replay.override.json new file mode 100644 index 0000000000..eea32f25ca --- /dev/null +++ b/examples/acp-agent/tests/snapshots/error-finish/replay.override.json @@ -0,0 +1,3 @@ +[ + { "kind": "throw", "chunks": [], "message": "simulated provider error (HTTP 401)", "code": "AUTH", "status": 401 } +] diff --git a/examples/acp-agent/tests/snapshots/error-finish/session.golden.txt b/examples/acp-agent/tests/snapshots/error-finish/session.golden.txt new file mode 100644 index 0000000000..ae8b1914c3 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/error-finish/session.golden.txt @@ -0,0 +1,79 @@ +{ + "type": "session", + "version": 1, + "id": "{{sessionId}}", + "createdAt": 0, + "cwd": "{{cwd}}" +} +{ + "type": "turn/start", + "seq": 0, + "time": 0, + "data": { + "turn": 1, + "trigger": { + "kind": "message", + "source": { + "kind": "user" + } + } + } +} +{ + "type": "user/message", + "seq": 1, + "time": 0, + "data": { + "content": [ + { + "type": "text", + "text": "This prompt triggers a recorded provider error." + } + ], + "source": { + "kind": "user" + } + } +} +{ + "type": "step/start", + "seq": 2, + "time": 0, + "data": { + "turn": 1, + "step": 1 + } +} +{ + "type": "step/end", + "seq": 3, + "time": 0, + "data": { + "turn": 1, + "step": 1 + } +} +{ + "type": "error", + "seq": 4, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "message": "simulated provider error (HTTP 401)", + "code": "AUTH" + } +} +{ + "type": "turn/end", + "seq": 5, + "time": 0, + "data": { + "turn": 1, + "reason": { + "kind": "error", + "message": "simulated provider error (HTTP 401)", + "code": "AUTH" + } + } +} diff --git a/examples/acp-agent/tests/snapshots/error-finish/session.jsonl b/examples/acp-agent/tests/snapshots/error-finish/session.jsonl new file mode 100644 index 0000000000..ab44090be6 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/error-finish/session.jsonl @@ -0,0 +1 @@ +{"type":"session","version":1,"id":"00000000-0000-0000-0000-000000000000","createdAt":0} diff --git a/examples/acp-agent/tests/snapshots/error-finish/stdout.golden.txt b/examples/acp-agent/tests/snapshots/error-finish/stdout.golden.txt new file mode 100644 index 0000000000..8babe5e15b --- /dev/null +++ b/examples/acp-agent/tests/snapshots/error-finish/stdout.golden.txt @@ -0,0 +1,49 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "protocolVersion": 1, + "agentInfo": { + "name": "deepseek-harness-acp", + "version": "0.0.1" + }, + "agentCapabilities": { + "loadSession": true, + "promptCapabilities": { + "image": false, + "audio": false, + "embeddedContext": false + } + }, + "authMethods": [] + } +} +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "sessionId": "{{sessionId}}" + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "user_message_chunk", + "content": { + "type": "text", + "text": "This prompt triggers a recorded provider error." + } + } + } +} +{ + "jsonrpc": "2.0", + "id": 3, + "error": { + "code": -32603, + "message": "Internal error: turn failed: simulated provider error (HTTP 401)" + } +} diff --git a/examples/acp-agent/tests/snapshots/multi-turn/input.json b/examples/acp-agent/tests/snapshots/multi-turn/input.json new file mode 100644 index 0000000000..40cf159a46 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/multi-turn/input.json @@ -0,0 +1,8 @@ +{ + "steps": [ + { "op": "initialize" }, + { "op": "newSession" }, + { "op": "prompt", "text": "Reply with exactly the word: ONE. No tools." }, + { "op": "prompt", "text": "Reply with exactly the word: TWO. No tools." } + ] +} diff --git a/examples/acp-agent/tests/snapshots/multi-turn/session.golden.txt b/examples/acp-agent/tests/snapshots/multi-turn/session.golden.txt new file mode 100644 index 0000000000..fd80eb9713 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/multi-turn/session.golden.txt @@ -0,0 +1,929 @@ +{ + "type": "session", + "version": 1, + "id": "{{sessionId}}", + "createdAt": 0, + "cwd": "{{cwd}}" +} +{ + "type": "turn/start", + "seq": 0, + "time": 0, + "data": { + "turn": 1, + "trigger": { + "kind": "message", + "source": { + "kind": "user" + } + } + } +} +{ + "type": "user/message", + "seq": 1, + "time": 0, + "data": { + "content": [ + { + "type": "text", + "text": "Reply with exactly the word: ONE. No tools." + } + ], + "source": { + "kind": "user" + } + } +} +{ + "type": "step/start", + "seq": 2, + "time": 0, + "data": { + "turn": 1, + "step": 1 + } +} +{ + "type": "assistant/chunk", + "seq": 3, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-start", + "index": 0, + "blockType": "reasoning" + } + } +} +{ + "type": "assistant/chunk", + "seq": 4, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "The" + } + } +} +{ + "type": "assistant/chunk", + "seq": 5, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " user" + } + } +} +{ + "type": "assistant/chunk", + "seq": 6, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " wants" + } + } +} +{ + "type": "assistant/chunk", + "seq": 7, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " me" + } + } +} +{ + "type": "assistant/chunk", + "seq": 8, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " to" + } + } +} +{ + "type": "assistant/chunk", + "seq": 9, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " reply" + } + } +} +{ + "type": "assistant/chunk", + "seq": 10, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " with" + } + } +} +{ + "type": "assistant/chunk", + "seq": 11, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " exactly" + } + } +} +{ + "type": "assistant/chunk", + "seq": 12, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " the" + } + } +} +{ + "type": "assistant/chunk", + "seq": 13, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " word" + } + } +} +{ + "type": "assistant/chunk", + "seq": 14, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 15, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "ONE" + } + } +} +{ + "type": "assistant/chunk", + "seq": 16, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "\"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 17, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " and" + } + } +} +{ + "type": "assistant/chunk", + "seq": 18, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " no" + } + } +} +{ + "type": "assistant/chunk", + "seq": 19, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " tools" + } + } +} +{ + "type": "assistant/chunk", + "seq": 20, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "." + } + } +} +{ + "type": "assistant/chunk", + "seq": 21, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-start", + "index": 1, + "blockType": "text" + } + } +} +{ + "type": "assistant/chunk", + "seq": 22, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "text-delta", + "index": 1, + "text": "ONE" + } + } +} +{ + "type": "assistant/chunk", + "seq": 23, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-end", + "index": 0, + "block": { + "type": "reasoning", + "text": "The user wants me to reply with exactly the word \"ONE\" and no tools." + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 24, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-end", + "index": 1, + "block": { + "type": "text", + "text": "ONE" + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 25, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "usage", + "usage": { + "inputTokens": 113, + "outputTokens": 19, + "cacheReadTokens": 768, + "reasoningTokens": 17 + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 26, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "finish", + "reason": { + "kind": "stop" + } + } + } +} +{ + "type": "assistant/message", + "seq": 27, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "content": [ + { + "type": "reasoning", + "text": "The user wants me to reply with exactly the word \"ONE\" and no tools." + }, + { + "type": "text", + "text": "ONE" + } + ] + } +} +{ + "type": "usage", + "seq": 28, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "usage": { + "inputTokens": 113, + "outputTokens": 19, + "cacheReadTokens": 768, + "reasoningTokens": 17 + } + } +} +{ + "type": "step/end", + "seq": 29, + "time": 0, + "data": { + "turn": 1, + "step": 1 + } +} +{ + "type": "turn/end", + "seq": 30, + "time": 0, + "data": { + "turn": 1, + "reason": { + "kind": "completed" + } + } +} +{ + "type": "turn/start", + "seq": 31, + "time": 0, + "data": { + "turn": 2, + "trigger": { + "kind": "message", + "source": { + "kind": "user" + } + } + } +} +{ + "type": "user/message", + "seq": 32, + "time": 0, + "data": { + "content": [ + { + "type": "text", + "text": "Reply with exactly the word: TWO. No tools." + } + ], + "source": { + "kind": "user" + } + } +} +{ + "type": "step/start", + "seq": 33, + "time": 0, + "data": { + "turn": 2, + "step": 1 + } +} +{ + "type": "assistant/chunk", + "seq": 34, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "block-start", + "index": 0, + "blockType": "reasoning" + } + } +} +{ + "type": "assistant/chunk", + "seq": 35, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "The" + } + } +} +{ + "type": "assistant/chunk", + "seq": 36, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " user" + } + } +} +{ + "type": "assistant/chunk", + "seq": 37, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " wants" + } + } +} +{ + "type": "assistant/chunk", + "seq": 38, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " me" + } + } +} +{ + "type": "assistant/chunk", + "seq": 39, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " to" + } + } +} +{ + "type": "assistant/chunk", + "seq": 40, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " reply" + } + } +} +{ + "type": "assistant/chunk", + "seq": 41, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " with" + } + } +} +{ + "type": "assistant/chunk", + "seq": 42, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " exactly" + } + } +} +{ + "type": "assistant/chunk", + "seq": 43, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " the" + } + } +} +{ + "type": "assistant/chunk", + "seq": 44, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " word" + } + } +} +{ + "type": "assistant/chunk", + "seq": 45, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 46, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "T" + } + } +} +{ + "type": "assistant/chunk", + "seq": 47, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "WO" + } + } +} +{ + "type": "assistant/chunk", + "seq": 48, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "\"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 49, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " and" + } + } +} +{ + "type": "assistant/chunk", + "seq": 50, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " use" + } + } +} +{ + "type": "assistant/chunk", + "seq": 51, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " no" + } + } +} +{ + "type": "assistant/chunk", + "seq": 52, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " tools" + } + } +} +{ + "type": "assistant/chunk", + "seq": 53, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "." + } + } +} +{ + "type": "assistant/chunk", + "seq": 54, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "block-start", + "index": 1, + "blockType": "text" + } + } +} +{ + "type": "assistant/chunk", + "seq": 55, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "text-delta", + "index": 1, + "text": "T" + } + } +} +{ + "type": "assistant/chunk", + "seq": 56, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "text-delta", + "index": 1, + "text": "WO" + } + } +} +{ + "type": "assistant/chunk", + "seq": 57, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "block-end", + "index": 0, + "block": { + "type": "reasoning", + "text": "The user wants me to reply with exactly the word \"TWO\" and use no tools." + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 58, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "block-end", + "index": 1, + "block": { + "type": "text", + "text": "TWO" + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 59, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "usage", + "usage": { + "inputTokens": 129, + "outputTokens": 22, + "cacheReadTokens": 768, + "reasoningTokens": 19 + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 60, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "chunk": { + "type": "finish", + "reason": { + "kind": "stop" + } + } + } +} +{ + "type": "assistant/message", + "seq": 61, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "content": [ + { + "type": "reasoning", + "text": "The user wants me to reply with exactly the word \"TWO\" and use no tools." + }, + { + "type": "text", + "text": "TWO" + } + ] + } +} +{ + "type": "usage", + "seq": 62, + "time": 0, + "data": { + "turn": 2, + "step": 1, + "usage": { + "inputTokens": 129, + "outputTokens": 22, + "cacheReadTokens": 768, + "reasoningTokens": 19 + } + } +} +{ + "type": "step/end", + "seq": 63, + "time": 0, + "data": { + "turn": 2, + "step": 1 + } +} +{ + "type": "turn/end", + "seq": 64, + "time": 0, + "data": { + "turn": 2, + "reason": { + "kind": "completed" + } + } +} diff --git a/examples/acp-agent/tests/snapshots/multi-turn/session.jsonl b/examples/acp-agent/tests/snapshots/multi-turn/session.jsonl new file mode 100644 index 0000000000..5222165530 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/multi-turn/session.jsonl @@ -0,0 +1,66 @@ +{"type":"session","version":1,"id":"c4893a53-19cb-4c09-81d2-e702a13c5123","createdAt":1781811971684,"cwd":"/tmp/acp-snap-cwd-zBZiqs"} +{"type":"turn/start","seq":0,"time":1781811971687,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}} +{"type":"user/message","seq":1,"time":1781811971688,"data":{"content":[{"type":"text","text":"Reply with exactly the word: ONE. No tools."}],"source":{"kind":"user"}}} +{"type":"step/start","seq":2,"time":1781811971688,"data":{"turn":1,"step":1}} +{"type":"assistant/chunk","seq":3,"time":1781811972281,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":4,"time":1781811972281,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":5,"time":1781811972455,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}} +{"type":"assistant/chunk","seq":6,"time":1781811972501,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" wants"}}} +{"type":"assistant/chunk","seq":7,"time":1781811972502,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":8,"time":1781811972502,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":9,"time":1781811972503,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":10,"time":1781811972503,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":11,"time":1781811972523,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" exactly"}}} +{"type":"assistant/chunk","seq":12,"time":1781811972523,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":13,"time":1781811972523,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" word"}}} +{"type":"assistant/chunk","seq":14,"time":1781811972523,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":15,"time":1781811972524,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":16,"time":1781811972524,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":17,"time":1781811972557,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":18,"time":1781811972558,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" no"}}} +{"type":"assistant/chunk","seq":19,"time":1781811972558,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" tools"}}} +{"type":"assistant/chunk","seq":20,"time":1781811972558,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":21,"time":1781811972594,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":22,"time":1781811972595,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} +{"type":"assistant/chunk","seq":23,"time":1781811972595,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to reply with exactly the word \"ONE\" and no tools."}}}} +{"type":"assistant/chunk","seq":24,"time":1781811972595,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"ONE"}}}} +{"type":"assistant/chunk","seq":25,"time":1781811972595,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":113,"outputTokens":19,"cacheReadTokens":768,"reasoningTokens":17}}}} +{"type":"assistant/chunk","seq":26,"time":1781811972595,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":27,"time":1781811972597,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"ONE\" and no tools."},{"type":"text","text":"ONE"}]}} +{"type":"usage","seq":28,"time":1781811972597,"data":{"turn":1,"step":1,"usage":{"inputTokens":113,"outputTokens":19,"cacheReadTokens":768,"reasoningTokens":17}}} +{"type":"step/end","seq":29,"time":1781811972597,"data":{"turn":1,"step":1}} +{"type":"turn/end","seq":30,"time":1781811972597,"data":{"turn":1,"reason":{"kind":"completed"}}} +{"type":"turn/start","seq":31,"time":1781811972603,"data":{"turn":2,"trigger":{"kind":"message","source":{"kind":"user"}}}} +{"type":"user/message","seq":32,"time":1781811972604,"data":{"content":[{"type":"text","text":"Reply with exactly the word: TWO. No tools."}],"source":{"kind":"user"}}} +{"type":"step/start","seq":33,"time":1781811972604,"data":{"turn":2,"step":1}} +{"type":"assistant/chunk","seq":34,"time":1781811973140,"data":{"turn":2,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":35,"time":1781811973140,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":36,"time":1781811973337,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}} +{"type":"assistant/chunk","seq":37,"time":1781811973371,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" wants"}}} +{"type":"assistant/chunk","seq":38,"time":1781811973371,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":39,"time":1781811973371,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":40,"time":1781811973372,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":41,"time":1781811973405,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":42,"time":1781811973406,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" exactly"}}} +{"type":"assistant/chunk","seq":43,"time":1781811973406,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":44,"time":1781811973406,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" word"}}} +{"type":"assistant/chunk","seq":45,"time":1781811973406,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":46,"time":1781811973406,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"T"}}} +{"type":"assistant/chunk","seq":47,"time":1781811973439,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WO"}}} +{"type":"assistant/chunk","seq":48,"time":1781811973439,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":49,"time":1781811973473,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":50,"time":1781811973473,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" use"}}} +{"type":"assistant/chunk","seq":51,"time":1781811973507,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" no"}}} +{"type":"assistant/chunk","seq":52,"time":1781811973507,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" tools"}}} +{"type":"assistant/chunk","seq":53,"time":1781811973507,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":54,"time":1781811973507,"data":{"turn":2,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":55,"time":1781811973508,"data":{"turn":2,"step":1,"chunk":{"type":"text-delta","index":1,"text":"T"}}} +{"type":"assistant/chunk","seq":56,"time":1781811973542,"data":{"turn":2,"step":1,"chunk":{"type":"text-delta","index":1,"text":"WO"}}} +{"type":"assistant/chunk","seq":57,"time":1781811973543,"data":{"turn":2,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to reply with exactly the word \"TWO\" and use no tools."}}}} +{"type":"assistant/chunk","seq":58,"time":1781811973543,"data":{"turn":2,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"TWO"}}}} +{"type":"assistant/chunk","seq":59,"time":1781811973543,"data":{"turn":2,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":129,"outputTokens":22,"cacheReadTokens":768,"reasoningTokens":19}}}} +{"type":"assistant/chunk","seq":60,"time":1781811973543,"data":{"turn":2,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":61,"time":1781811973543,"data":{"turn":2,"step":1,"content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"TWO\" and use no tools."},{"type":"text","text":"TWO"}]}} +{"type":"usage","seq":62,"time":1781811973543,"data":{"turn":2,"step":1,"usage":{"inputTokens":129,"outputTokens":22,"cacheReadTokens":768,"reasoningTokens":19}}} +{"type":"step/end","seq":63,"time":1781811973543,"data":{"turn":2,"step":1}} +{"type":"turn/end","seq":64,"time":1781811973543,"data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.txt b/examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.txt new file mode 100644 index 0000000000..80a6f71aef --- /dev/null +++ b/examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.txt @@ -0,0 +1,615 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "protocolVersion": 1, + "agentInfo": { + "name": "deepseek-harness-acp", + "version": "0.0.1" + }, + "agentCapabilities": { + "loadSession": true, + "promptCapabilities": { + "image": false, + "audio": false, + "embeddedContext": false + } + }, + "authMethods": [] + } +} +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "sessionId": "{{sessionId}}" + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "user_message_chunk", + "content": { + "type": "text", + "text": "Reply with exactly the word: ONE. No tools." + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "The" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " user" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " wants" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " me" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " to" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " reply" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " with" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " exactly" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " the" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " word" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " \"" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "ONE" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "\"" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " and" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " no" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " tools" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "." + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_message_chunk", + "content": { + "type": "text", + "text": "ONE" + } + } + } +} +{ + "jsonrpc": "2.0", + "id": 3, + "result": { + "stopReason": "end_turn" + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "user_message_chunk", + "content": { + "type": "text", + "text": "Reply with exactly the word: TWO. No tools." + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "The" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " user" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " wants" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " me" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " to" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " reply" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " with" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " exactly" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " the" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " word" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " \"" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "T" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "WO" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "\"" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " and" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " use" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " no" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " tools" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "." + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_message_chunk", + "content": { + "type": "text", + "text": "T" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_message_chunk", + "content": { + "type": "text", + "text": "WO" + } + } + } +} +{ + "jsonrpc": "2.0", + "id": 4, + "result": { + "stopReason": "end_turn" + } +} diff --git a/examples/acp-agent/tests/snapshots/text-turn/input.json b/examples/acp-agent/tests/snapshots/text-turn/input.json new file mode 100644 index 0000000000..5fe0259a4e --- /dev/null +++ b/examples/acp-agent/tests/snapshots/text-turn/input.json @@ -0,0 +1,7 @@ +{ + "steps": [ + { "op": "initialize" }, + { "op": "newSession" }, + { "op": "prompt", "text": "Reply with exactly the word: PONG. Do not use any tools." } + ] +} diff --git a/examples/acp-agent/tests/snapshots/text-turn/session.golden.txt b/examples/acp-agent/tests/snapshots/text-turn/session.golden.txt new file mode 100644 index 0000000000..c61e27694e --- /dev/null +++ b/examples/acp-agent/tests/snapshots/text-turn/session.golden.txt @@ -0,0 +1,489 @@ +{ + "type": "session", + "version": 1, + "id": "{{sessionId}}", + "createdAt": 0, + "cwd": "{{cwd}}" +} +{ + "type": "turn/start", + "seq": 0, + "time": 0, + "data": { + "turn": 1, + "trigger": { + "kind": "message", + "source": { + "kind": "user" + } + } + } +} +{ + "type": "user/message", + "seq": 1, + "time": 0, + "data": { + "content": [ + { + "type": "text", + "text": "Reply with exactly the word: PONG. Do not use any tools." + } + ], + "source": { + "kind": "user" + } + } +} +{ + "type": "step/start", + "seq": 2, + "time": 0, + "data": { + "turn": 1, + "step": 1 + } +} +{ + "type": "assistant/chunk", + "seq": 3, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-start", + "index": 0, + "blockType": "reasoning" + } + } +} +{ + "type": "assistant/chunk", + "seq": 4, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "The" + } + } +} +{ + "type": "assistant/chunk", + "seq": 5, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " user" + } + } +} +{ + "type": "assistant/chunk", + "seq": 6, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " wants" + } + } +} +{ + "type": "assistant/chunk", + "seq": 7, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " me" + } + } +} +{ + "type": "assistant/chunk", + "seq": 8, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " to" + } + } +} +{ + "type": "assistant/chunk", + "seq": 9, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " reply" + } + } +} +{ + "type": "assistant/chunk", + "seq": 10, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " with" + } + } +} +{ + "type": "assistant/chunk", + "seq": 11, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " exactly" + } + } +} +{ + "type": "assistant/chunk", + "seq": 12, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " the" + } + } +} +{ + "type": "assistant/chunk", + "seq": 13, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " word" + } + } +} +{ + "type": "assistant/chunk", + "seq": 14, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 15, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "P" + } + } +} +{ + "type": "assistant/chunk", + "seq": 16, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "ONG" + } + } +} +{ + "type": "assistant/chunk", + "seq": 17, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "\"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 18, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " without" + } + } +} +{ + "type": "assistant/chunk", + "seq": 19, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " using" + } + } +} +{ + "type": "assistant/chunk", + "seq": 20, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " any" + } + } +} +{ + "type": "assistant/chunk", + "seq": 21, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " tools" + } + } +} +{ + "type": "assistant/chunk", + "seq": 22, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "." + } + } +} +{ + "type": "assistant/chunk", + "seq": 23, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-start", + "index": 1, + "blockType": "text" + } + } +} +{ + "type": "assistant/chunk", + "seq": 24, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "text-delta", + "index": 1, + "text": "P" + } + } +} +{ + "type": "assistant/chunk", + "seq": 25, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "text-delta", + "index": 1, + "text": "ONG" + } + } +} +{ + "type": "assistant/chunk", + "seq": 26, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-end", + "index": 0, + "block": { + "type": "reasoning", + "text": "The user wants me to reply with exactly the word \"PONG\" without using any tools." + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 27, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-end", + "index": 1, + "block": { + "type": "text", + "text": "PONG" + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 28, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "usage", + "usage": { + "inputTokens": 117, + "outputTokens": 22, + "cacheReadTokens": 768, + "reasoningTokens": 19 + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 29, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "finish", + "reason": { + "kind": "stop" + } + } + } +} +{ + "type": "assistant/message", + "seq": 30, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "content": [ + { + "type": "reasoning", + "text": "The user wants me to reply with exactly the word \"PONG\" without using any tools." + }, + { + "type": "text", + "text": "PONG" + } + ] + } +} +{ + "type": "usage", + "seq": 31, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "usage": { + "inputTokens": 117, + "outputTokens": 22, + "cacheReadTokens": 768, + "reasoningTokens": 19 + } + } +} +{ + "type": "step/end", + "seq": 32, + "time": 0, + "data": { + "turn": 1, + "step": 1 + } +} +{ + "type": "turn/end", + "seq": 33, + "time": 0, + "data": { + "turn": 1, + "reason": { + "kind": "completed" + } + } +} diff --git a/examples/acp-agent/tests/snapshots/text-turn/session.jsonl b/examples/acp-agent/tests/snapshots/text-turn/session.jsonl new file mode 100644 index 0000000000..ed970cbcd1 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/text-turn/session.jsonl @@ -0,0 +1,35 @@ +{"type":"session","version":1,"id":"dc42ad0b-4188-44c6-8d56-fd6f9cabe44f","createdAt":1781811940516,"cwd":"/tmp/acp-snap-cwd-9lipaP"} +{"type":"turn/start","seq":0,"time":1781811940519,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}} +{"type":"user/message","seq":1,"time":1781811940519,"data":{"content":[{"type":"text","text":"Reply with exactly the word: PONG. Do not use any tools."}],"source":{"kind":"user"}}} +{"type":"step/start","seq":2,"time":1781811940520,"data":{"turn":1,"step":1}} +{"type":"assistant/chunk","seq":3,"time":1781811940960,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":4,"time":1781811940960,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":5,"time":1781811941102,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}} +{"type":"assistant/chunk","seq":6,"time":1781811941133,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" wants"}}} +{"type":"assistant/chunk","seq":7,"time":1781811941134,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":8,"time":1781811941134,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":9,"time":1781811941134,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":10,"time":1781811941134,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":11,"time":1781811941134,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" exactly"}}} +{"type":"assistant/chunk","seq":12,"time":1781811941166,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":13,"time":1781811941167,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" word"}}} +{"type":"assistant/chunk","seq":14,"time":1781811941167,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":15,"time":1781811941167,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"P"}}} +{"type":"assistant/chunk","seq":16,"time":1781811941167,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"ONG"}}} +{"type":"assistant/chunk","seq":17,"time":1781811941167,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":18,"time":1781811941199,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" without"}}} +{"type":"assistant/chunk","seq":19,"time":1781811941200,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" using"}}} +{"type":"assistant/chunk","seq":20,"time":1781811941200,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" any"}}} +{"type":"assistant/chunk","seq":21,"time":1781811941200,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" tools"}}} +{"type":"assistant/chunk","seq":22,"time":1781811941200,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":23,"time":1781811941233,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":24,"time":1781811941233,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":1,"text":"P"}}} +{"type":"assistant/chunk","seq":25,"time":1781811941234,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":1,"text":"ONG"}}} +{"type":"assistant/chunk","seq":26,"time":1781811941234,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to reply with exactly the word \"PONG\" without using any tools."}}}} +{"type":"assistant/chunk","seq":27,"time":1781811941234,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PONG"}}}} +{"type":"assistant/chunk","seq":28,"time":1781811941234,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":117,"outputTokens":22,"cacheReadTokens":768,"reasoningTokens":19}}}} +{"type":"assistant/chunk","seq":29,"time":1781811941234,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":30,"time":1781811941236,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"PONG\" without using any tools."},{"type":"text","text":"PONG"}]}} +{"type":"usage","seq":31,"time":1781811941236,"data":{"turn":1,"step":1,"usage":{"inputTokens":117,"outputTokens":22,"cacheReadTokens":768,"reasoningTokens":19}}} +{"type":"step/end","seq":32,"time":1781811941236,"data":{"turn":1,"step":1}} +{"type":"turn/end","seq":33,"time":1781811941236,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/examples/acp-agent/tests/snapshots/text-turn/stdout.golden.txt b/examples/acp-agent/tests/snapshots/text-turn/stdout.golden.txt new file mode 100644 index 0000000000..be961bc8c9 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/text-turn/stdout.golden.txt @@ -0,0 +1,342 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "protocolVersion": 1, + "agentInfo": { + "name": "deepseek-harness-acp", + "version": "0.0.1" + }, + "agentCapabilities": { + "loadSession": true, + "promptCapabilities": { + "image": false, + "audio": false, + "embeddedContext": false + } + }, + "authMethods": [] + } +} +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "sessionId": "{{sessionId}}" + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "user_message_chunk", + "content": { + "type": "text", + "text": "Reply with exactly the word: PONG. Do not use any tools." + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "The" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " user" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " wants" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " me" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " to" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " reply" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " with" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " exactly" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " the" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " word" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " \"" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "P" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "ONG" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "\"" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " without" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " using" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " any" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " tools" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "." + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_message_chunk", + "content": { + "type": "text", + "text": "P" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_message_chunk", + "content": { + "type": "text", + "text": "ONG" + } + } + } +} +{ + "jsonrpc": "2.0", + "id": 3, + "result": { + "stopReason": "end_turn" + } +} diff --git a/examples/acp-agent/tests/snapshots/tool-call-turn/input.json b/examples/acp-agent/tests/snapshots/tool-call-turn/input.json new file mode 100644 index 0000000000..92da4668af --- /dev/null +++ b/examples/acp-agent/tests/snapshots/tool-call-turn/input.json @@ -0,0 +1,7 @@ +{ + "steps": [ + { "op": "initialize" }, + { "op": "newSession" }, + { "op": "prompt", "text": "Use the bash tool to run exactly: echo SNAPSHOT_OK. Then reply with the single word DONE and stop." } + ] +} diff --git a/examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.txt b/examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.txt new file mode 100644 index 0000000000..87ee87fcc8 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.txt @@ -0,0 +1,1469 @@ +{ + "type": "session", + "version": 1, + "id": "{{sessionId}}", + "createdAt": 0, + "cwd": "{{cwd}}" +} +{ + "type": "turn/start", + "seq": 0, + "time": 0, + "data": { + "turn": 1, + "trigger": { + "kind": "message", + "source": { + "kind": "user" + } + } + } +} +{ + "type": "user/message", + "seq": 1, + "time": 0, + "data": { + "content": [ + { + "type": "text", + "text": "Use the bash tool to run exactly: echo SNAPSHOT_OK. Then reply with the single word DONE and stop." + } + ], + "source": { + "kind": "user" + } + } +} +{ + "type": "step/start", + "seq": 2, + "time": 0, + "data": { + "turn": 1, + "step": 1 + } +} +{ + "type": "assistant/chunk", + "seq": 3, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-start", + "index": 0, + "blockType": "reasoning" + } + } +} +{ + "type": "assistant/chunk", + "seq": 4, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "The" + } + } +} +{ + "type": "assistant/chunk", + "seq": 5, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " user" + } + } +} +{ + "type": "assistant/chunk", + "seq": 6, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " wants" + } + } +} +{ + "type": "assistant/chunk", + "seq": 7, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " me" + } + } +} +{ + "type": "assistant/chunk", + "seq": 8, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " to" + } + } +} +{ + "type": "assistant/chunk", + "seq": 9, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " run" + } + } +} +{ + "type": "assistant/chunk", + "seq": 10, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " a" + } + } +} +{ + "type": "assistant/chunk", + "seq": 11, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " specific" + } + } +} +{ + "type": "assistant/chunk", + "seq": 12, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " command" + } + } +} +{ + "type": "assistant/chunk", + "seq": 13, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " and" + } + } +} +{ + "type": "assistant/chunk", + "seq": 14, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " then" + } + } +} +{ + "type": "assistant/chunk", + "seq": 15, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " reply" + } + } +} +{ + "type": "assistant/chunk", + "seq": 16, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " with" + } + } +} +{ + "type": "assistant/chunk", + "seq": 17, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " D" + } + } +} +{ + "type": "assistant/chunk", + "seq": 18, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "ONE" + } + } +} +{ + "type": "assistant/chunk", + "seq": 19, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "." + } + } +} +{ + "type": "assistant/chunk", + "seq": 20, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-start", + "index": 1, + "blockType": "tool-call" + } + } +} +{ + "type": "assistant/chunk", + "seq": 21, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "" + } + } +} +{ + "type": "assistant/chunk", + "seq": 22, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "{" + } + } +} +{ + "type": "assistant/chunk", + "seq": 23, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "\"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 24, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "command" + } + } +} +{ + "type": "assistant/chunk", + "seq": 25, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "\"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 26, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": ": " + } + } +} +{ + "type": "assistant/chunk", + "seq": 27, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "\"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 28, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "echo" + } + } +} +{ + "type": "assistant/chunk", + "seq": 29, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": " S" + } + } +} +{ + "type": "assistant/chunk", + "seq": 30, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "NA" + } + } +} +{ + "type": "assistant/chunk", + "seq": 31, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "PS" + } + } +} +{ + "type": "assistant/chunk", + "seq": 32, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "H" + } + } +} +{ + "type": "assistant/chunk", + "seq": 33, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "OT" + } + } +} +{ + "type": "assistant/chunk", + "seq": 34, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "_OK" + } + } +} +{ + "type": "assistant/chunk", + "seq": 35, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "\"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 36, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": ", " + } + } +} +{ + "type": "assistant/chunk", + "seq": 37, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "\"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 38, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "description" + } + } +} +{ + "type": "assistant/chunk", + "seq": 39, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "\"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 40, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": ": " + } + } +} +{ + "type": "assistant/chunk", + "seq": 41, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "\"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 42, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "Run" + } + } +} +{ + "type": "assistant/chunk", + "seq": 43, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": " the" + } + } +} +{ + "type": "assistant/chunk", + "seq": 44, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": " exact" + } + } +} +{ + "type": "assistant/chunk", + "seq": 45, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": " echo" + } + } +} +{ + "type": "assistant/chunk", + "seq": 46, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": " command" + } + } +} +{ + "type": "assistant/chunk", + "seq": 47, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": " requested" + } + } +} +{ + "type": "assistant/chunk", + "seq": 48, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "\"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 49, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "tool-call-delta", + "index": 1, + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "argumentsDelta": "}" + } + } +} +{ + "type": "assistant/chunk", + "seq": 50, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-end", + "index": 0, + "block": { + "type": "reasoning", + "text": "The user wants me to run a specific command and then reply with DONE." + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 51, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "block-end", + "index": 1, + "block": { + "type": "tool-call", + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "arguments": "{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run the exact echo command requested\"}" + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 52, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "usage", + "usage": { + "inputTokens": 129, + "outputTokens": 86, + "cacheReadTokens": 768, + "reasoningTokens": 16 + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 53, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "chunk": { + "type": "finish", + "reason": { + "kind": "tool-calls" + } + } + } +} +{ + "type": "assistant/message", + "seq": 54, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "content": [ + { + "type": "reasoning", + "text": "The user wants me to run a specific command and then reply with DONE." + }, + { + "type": "tool-call", + "id": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "arguments": "{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run the exact echo command requested\"}" + } + ] + } +} +{ + "type": "usage", + "seq": 55, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "usage": { + "inputTokens": 129, + "outputTokens": 86, + "cacheReadTokens": 768, + "reasoningTokens": 16 + } + } +} +{ + "type": "tool/call", + "seq": 56, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "callId": "call_00_waDnb5eZcD1dBV49O7F39256", + "name": "bash", + "arguments": "{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run the exact echo command requested\"}" + } +} +{ + "type": "tool/result", + "seq": 57, + "time": 0, + "data": { + "turn": 1, + "step": 1, + "callId": "call_00_waDnb5eZcD1dBV49O7F39256", + "content": [ + { + "type": "text", + "text": "SNAPSHOT_OK\n" + } + ], + "isError": false + } +} +{ + "type": "step/end", + "seq": 58, + "time": 0, + "data": { + "turn": 1, + "step": 1 + } +} +{ + "type": "step/start", + "seq": 59, + "time": 0, + "data": { + "turn": 1, + "step": 2 + } +} +{ + "type": "assistant/chunk", + "seq": 60, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "block-start", + "index": 0, + "blockType": "reasoning" + } + } +} +{ + "type": "assistant/chunk", + "seq": 61, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "The" + } + } +} +{ + "type": "assistant/chunk", + "seq": 62, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " command" + } + } +} +{ + "type": "assistant/chunk", + "seq": 63, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " ran" + } + } +} +{ + "type": "assistant/chunk", + "seq": 64, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " successfully" + } + } +} +{ + "type": "assistant/chunk", + "seq": 65, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " and" + } + } +} +{ + "type": "assistant/chunk", + "seq": 66, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " output" + } + } +} +{ + "type": "assistant/chunk", + "seq": 67, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 68, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "S" + } + } +} +{ + "type": "assistant/chunk", + "seq": 69, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "NA" + } + } +} +{ + "type": "assistant/chunk", + "seq": 70, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "PS" + } + } +} +{ + "type": "assistant/chunk", + "seq": 71, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "H" + } + } +} +{ + "type": "assistant/chunk", + "seq": 72, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "OT" + } + } +} +{ + "type": "assistant/chunk", + "seq": 73, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "_OK" + } + } +} +{ + "type": "assistant/chunk", + "seq": 74, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "\"." + } + } +} +{ + "type": "assistant/chunk", + "seq": 75, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " Now" + } + } +} +{ + "type": "assistant/chunk", + "seq": 76, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " I" + } + } +} +{ + "type": "assistant/chunk", + "seq": 77, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " need" + } + } +} +{ + "type": "assistant/chunk", + "seq": 78, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " to" + } + } +} +{ + "type": "assistant/chunk", + "seq": 79, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " reply" + } + } +} +{ + "type": "assistant/chunk", + "seq": 80, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " with" + } + } +} +{ + "type": "assistant/chunk", + "seq": 81, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " the" + } + } +} +{ + "type": "assistant/chunk", + "seq": 82, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " single" + } + } +} +{ + "type": "assistant/chunk", + "seq": 83, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " word" + } + } +} +{ + "type": "assistant/chunk", + "seq": 84, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": " \"" + } + } +} +{ + "type": "assistant/chunk", + "seq": 85, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "D" + } + } +} +{ + "type": "assistant/chunk", + "seq": 86, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "ONE" + } + } +} +{ + "type": "assistant/chunk", + "seq": 87, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "reasoning-delta", + "index": 0, + "text": "\"." + } + } +} +{ + "type": "assistant/chunk", + "seq": 88, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "block-start", + "index": 1, + "blockType": "text" + } + } +} +{ + "type": "assistant/chunk", + "seq": 89, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "text-delta", + "index": 1, + "text": "D" + } + } +} +{ + "type": "assistant/chunk", + "seq": 90, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "text-delta", + "index": 1, + "text": "ONE" + } + } +} +{ + "type": "assistant/chunk", + "seq": 91, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "block-end", + "index": 0, + "block": { + "type": "reasoning", + "text": "The command ran successfully and output \"SNAPSHOT_OK\". Now I need to reply with the single word \"DONE\"." + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 92, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "block-end", + "index": 1, + "block": { + "type": "text", + "text": "DONE" + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 93, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "usage", + "usage": { + "inputTokens": 105, + "outputTokens": 30, + "cacheReadTokens": 896, + "reasoningTokens": 27 + } + } + } +} +{ + "type": "assistant/chunk", + "seq": 94, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "chunk": { + "type": "finish", + "reason": { + "kind": "stop" + } + } + } +} +{ + "type": "assistant/message", + "seq": 95, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "content": [ + { + "type": "reasoning", + "text": "The command ran successfully and output \"SNAPSHOT_OK\". Now I need to reply with the single word \"DONE\"." + }, + { + "type": "text", + "text": "DONE" + } + ] + } +} +{ + "type": "usage", + "seq": 96, + "time": 0, + "data": { + "turn": 1, + "step": 2, + "usage": { + "inputTokens": 105, + "outputTokens": 30, + "cacheReadTokens": 896, + "reasoningTokens": 27 + } + } +} +{ + "type": "step/end", + "seq": 97, + "time": 0, + "data": { + "turn": 1, + "step": 2 + } +} +{ + "type": "turn/end", + "seq": 98, + "time": 0, + "data": { + "turn": 1, + "reason": { + "kind": "completed" + } + } +} diff --git a/examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl b/examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl new file mode 100644 index 0000000000..f465404419 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl @@ -0,0 +1,100 @@ +{"type":"session","version":1,"id":"8c1d42ba-5f00-44bb-aaa1-0832fae5c24a","createdAt":1781811967162,"cwd":"/tmp/acp-snap-cwd-rdktn3"} +{"type":"turn/start","seq":0,"time":1781811967165,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}} +{"type":"user/message","seq":1,"time":1781811967165,"data":{"content":[{"type":"text","text":"Use the bash tool to run exactly: echo SNAPSHOT_OK. Then reply with the single word DONE and stop."}],"source":{"kind":"user"}}} +{"type":"step/start","seq":2,"time":1781811967165,"data":{"turn":1,"step":1}} +{"type":"assistant/chunk","seq":3,"time":1781811967719,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":4,"time":1781811967720,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":5,"time":1781811967849,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}} +{"type":"assistant/chunk","seq":6,"time":1781811967883,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" wants"}}} +{"type":"assistant/chunk","seq":7,"time":1781811967883,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":8,"time":1781811967883,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":9,"time":1781811967884,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" run"}}} +{"type":"assistant/chunk","seq":10,"time":1781811967884,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":11,"time":1781811967916,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" specific"}}} +{"type":"assistant/chunk","seq":12,"time":1781811967917,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" command"}}} +{"type":"assistant/chunk","seq":13,"time":1781811967950,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":14,"time":1781811967950,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" then"}}} +{"type":"assistant/chunk","seq":15,"time":1781811967951,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":16,"time":1781811967984,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":17,"time":1781811967984,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" D"}}} +{"type":"assistant/chunk","seq":18,"time":1781811967984,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":19,"time":1781811967985,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":20,"time":1781811968085,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":21,"time":1781811968086,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":22,"time":1781811968120,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":23,"time":1781811968121,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":24,"time":1781811968121,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":25,"time":1781811968121,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":26,"time":1781811968121,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":27,"time":1781811968153,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":28,"time":1781811968153,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"echo"}}} +{"type":"assistant/chunk","seq":29,"time":1781811968153,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":" S"}}} +{"type":"assistant/chunk","seq":30,"time":1781811968153,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"NA"}}} +{"type":"assistant/chunk","seq":31,"time":1781811968187,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"PS"}}} +{"type":"assistant/chunk","seq":32,"time":1781811968188,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"H"}}} +{"type":"assistant/chunk","seq":33,"time":1781811968188,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"OT"}}} +{"type":"assistant/chunk","seq":34,"time":1781811968188,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"_OK"}}} +{"type":"assistant/chunk","seq":35,"time":1781811968188,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":36,"time":1781811968254,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":37,"time":1781811968255,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":38,"time":1781811968255,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":39,"time":1781811968255,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":40,"time":1781811968255,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":41,"time":1781811968289,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":42,"time":1781811968289,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"Run"}}} +{"type":"assistant/chunk","seq":43,"time":1781811968289,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":" the"}}} +{"type":"assistant/chunk","seq":44,"time":1781811968289,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":" exact"}}} +{"type":"assistant/chunk","seq":45,"time":1781811968323,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":" echo"}}} +{"type":"assistant/chunk","seq":46,"time":1781811968356,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":" command"}}} +{"type":"assistant/chunk","seq":47,"time":1781811968356,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":" requested"}}} +{"type":"assistant/chunk","seq":48,"time":1781811968390,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":49,"time":1781811968390,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":50,"time":1781811968477,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to run a specific command and then reply with DONE."}}}} +{"type":"assistant/chunk","seq":51,"time":1781811968477,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","arguments":"{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run the exact echo command requested\"}"}}}} +{"type":"assistant/chunk","seq":52,"time":1781811968477,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":129,"outputTokens":86,"cacheReadTokens":768,"reasoningTokens":16}}}} +{"type":"assistant/chunk","seq":53,"time":1781811968477,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":54,"time":1781811968479,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to run a specific command and then reply with DONE."},{"type":"tool-call","id":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","arguments":"{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run the exact echo command requested\"}"}]}} +{"type":"usage","seq":55,"time":1781811968479,"data":{"turn":1,"step":1,"usage":{"inputTokens":129,"outputTokens":86,"cacheReadTokens":768,"reasoningTokens":16}}} +{"type":"tool/call","seq":56,"time":1781811968479,"data":{"turn":1,"step":1,"callId":"call_00_waDnb5eZcD1dBV49O7F39256","name":"bash","arguments":"{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run the exact echo command requested\"}"}} +{"type":"tool/result","seq":57,"time":1781811968493,"data":{"turn":1,"step":1,"callId":"call_00_waDnb5eZcD1dBV49O7F39256","content":[{"type":"text","text":"SNAPSHOT_OK\n"}],"isError":false}} +{"type":"step/end","seq":58,"time":1781811968494,"data":{"turn":1,"step":1}} +{"type":"step/start","seq":59,"time":1781811968494,"data":{"turn":1,"step":2}} +{"type":"assistant/chunk","seq":60,"time":1781811969060,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":61,"time":1781811969060,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":62,"time":1781811969175,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" command"}}} +{"type":"assistant/chunk","seq":63,"time":1781811969209,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" ran"}}} +{"type":"assistant/chunk","seq":64,"time":1781811969244,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" successfully"}}} +{"type":"assistant/chunk","seq":65,"time":1781811969244,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":66,"time":1781811969244,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" output"}}} +{"type":"assistant/chunk","seq":67,"time":1781811969244,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":68,"time":1781811969278,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"S"}}} +{"type":"assistant/chunk","seq":69,"time":1781811969278,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"NA"}}} +{"type":"assistant/chunk","seq":70,"time":1781811969278,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"PS"}}} +{"type":"assistant/chunk","seq":71,"time":1781811969279,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"H"}}} +{"type":"assistant/chunk","seq":72,"time":1781811969279,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"OT"}}} +{"type":"assistant/chunk","seq":73,"time":1781811969279,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"_OK"}}} +{"type":"assistant/chunk","seq":74,"time":1781811969313,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":75,"time":1781811969313,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" Now"}}} +{"type":"assistant/chunk","seq":76,"time":1781811969313,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":77,"time":1781811969314,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" need"}}} +{"type":"assistant/chunk","seq":78,"time":1781811969314,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":79,"time":1781811969314,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":80,"time":1781811969347,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":81,"time":1781811969348,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":82,"time":1781811969348,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}} +{"type":"assistant/chunk","seq":83,"time":1781811969420,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" word"}}} +{"type":"assistant/chunk","seq":84,"time":1781811969421,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":85,"time":1781811969421,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"D"}}} +{"type":"assistant/chunk","seq":86,"time":1781811969421,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":87,"time":1781811969421,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":88,"time":1781811969421,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":89,"time":1781811969422,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":1,"text":"D"}}} +{"type":"assistant/chunk","seq":90,"time":1781811969422,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} +{"type":"assistant/chunk","seq":91,"time":1781811969422,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The command ran successfully and output \"SNAPSHOT_OK\". Now I need to reply with the single word \"DONE\"."}}}} +{"type":"assistant/chunk","seq":92,"time":1781811969422,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}}} +{"type":"assistant/chunk","seq":93,"time":1781811969422,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":105,"outputTokens":30,"cacheReadTokens":896,"reasoningTokens":27}}}} +{"type":"assistant/chunk","seq":94,"time":1781811969422,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":95,"time":1781811969422,"data":{"turn":1,"step":2,"content":[{"type":"reasoning","text":"The command ran successfully and output \"SNAPSHOT_OK\". Now I need to reply with the single word \"DONE\"."},{"type":"text","text":"DONE"}]}} +{"type":"usage","seq":96,"time":1781811969422,"data":{"turn":1,"step":2,"usage":{"inputTokens":105,"outputTokens":30,"cacheReadTokens":896,"reasoningTokens":27}}} +{"type":"step/end","seq":97,"time":1781811969422,"data":{"turn":1,"step":2}} +{"type":"turn/end","seq":98,"time":1781811969423,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.txt b/examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.txt new file mode 100644 index 0000000000..f5b5cdb3f1 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.txt @@ -0,0 +1,723 @@ +{ + "jsonrpc": "2.0", + "id": 1, + "result": { + "protocolVersion": 1, + "agentInfo": { + "name": "deepseek-harness-acp", + "version": "0.0.1" + }, + "agentCapabilities": { + "loadSession": true, + "promptCapabilities": { + "image": false, + "audio": false, + "embeddedContext": false + } + }, + "authMethods": [] + } +} +{ + "jsonrpc": "2.0", + "id": 2, + "result": { + "sessionId": "{{sessionId}}" + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "user_message_chunk", + "content": { + "type": "text", + "text": "Use the bash tool to run exactly: echo SNAPSHOT_OK. Then reply with the single word DONE and stop." + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "The" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " user" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " wants" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " me" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " to" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " run" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " a" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " specific" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " command" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " and" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " then" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " reply" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " with" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " D" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "ONE" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "." + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "tool_call", + "toolCallId": "call_00_waDnb5eZcD1dBV49O7F39256", + "title": "echo SNAPSHOT_OK", + "kind": "execute", + "status": "in_progress", + "rawInput": "echo SNAPSHOT_OK", + "content": [ + { + "type": "content", + "content": { + "type": "text", + "text": "Run the exact echo command requested" + } + } + ] + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "tool_call_update", + "toolCallId": "call_00_waDnb5eZcD1dBV49O7F39256", + "status": "completed", + "content": [ + { + "type": "content", + "content": { + "type": "text", + "text": "```console\nSNAPSHOT_OK\n```" + } + } + ] + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "The" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " command" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " ran" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " successfully" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " and" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " output" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " \"" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "S" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "NA" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "PS" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "H" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "OT" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "_OK" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "\"." + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " Now" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " I" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " need" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " to" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " reply" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " with" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " the" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " single" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " word" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": " \"" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "D" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "ONE" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_thought_chunk", + "content": { + "type": "text", + "text": "\"." + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_message_chunk", + "content": { + "type": "text", + "text": "D" + } + } + } +} +{ + "jsonrpc": "2.0", + "method": "session/update", + "params": { + "sessionId": "{{sessionId}}", + "update": { + "sessionUpdate": "agent_message_chunk", + "content": { + "type": "text", + "text": "ONE" + } + } + } +} +{ + "jsonrpc": "2.0", + "id": 3, + "result": { + "stopReason": "end_turn" + } +}