From bef93865914d4c655bf21aee73ca6b19ad8c6209 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 00:19:54 +0800 Subject: [PATCH 01/13] docs(rfc): add ACP snapshot tests RFC (record-once / replay-deterministic) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Records the decision to add a third test tier: snapshot tests that boot the real acp-agent subprocess over ACP stdio, record the LLM's streamed responses once against the real API, then replay them deterministically so the full stdout transcript can be diffed against a committed golden — keyless in CI. Captures the design choices hardened in a Codex (xhigh) review: record at the provider-neutral llm/stream waterfall; a discriminated fixture entry schema (chunks/throw/hang) that honors both LLM failure branches; positional replay with a one-in-flight-stream constraint; per-stream atomic fixture flush (the subprocess is SIGKILLed, so dispose-time flush would never run); a providerless replay config; normalize-then-snapshot parsed frames; normalization over an OS sandbox now with the rootless bwrap/sandbox-exec tier reserved via the BashExecutor capability seam. Cross-links the proposed determinism RFC (complementary: internal history invariant vs external protocol contract). --- docs/rfc/README.md | 1 + .../2026-06-19-acp-snapshot-tests.md | 69 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md diff --git a/docs/rfc/README.md b/docs/rfc/README.md index bc56275477..9bb5448830 100644 --- a/docs/rfc/README.md +++ b/docs/rfc/README.md @@ -56,6 +56,7 @@ Do NOT write one for a mechanical or local choice (a variable name, a one-file r | [Every session event is enclosed in a turn](implemented/2026-06-15-turn-enclosure-invariant.md) | 2026-06-15 | | [pnpm as the package manager instead of Yarn 4](implemented/2026-06-16-pnpm-over-yarn.md) | 2026-06-16 | | [Rich ACP bash rendering — the terminal card (`_meta`) and command classification](implemented/2026-06-18-acp-terminal-and-tool-rendering.md) | 2026-06-18 | +| [ACP snapshot tests — record-once / replay-deterministic](implemented/2026-06-19-acp-snapshot-tests.md) | 2026-06-19 | ## Rejected diff --git a/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md b/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md new file mode 100644 index 0000000000..900f9a9cd8 --- /dev/null +++ b/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md @@ -0,0 +1,69 @@ +# RFC: ACP snapshot tests — record-once / replay-deterministic + +Status: implemented (accepted 2026-06-19) + + + +## Context + +The harness has two test tiers: keyless unit `.spec.ts` (the 100%-per-file coverage gate) and real-API `.e2e.ts` (key-gated, self-skipping in CI). Neither continuously verifies the **complete output transcript** an ACP editor (Zed) sees on its stdin/stdout. The existing ACP e2e ([examples/acp-agent/tests/acp.e2e.ts](../../../examples/acp-agent/tests/acp.e2e.ts)) is the closest end-to-end check, but it is key-gated and asserts on a handful of *structured fields* (`stopReason`, a `tool_call` title), not the byte-for-byte stream of `session/update` frames. That leaves the "green units, broken product" gap: every unit test can pass while the actual editor-facing protocol output regresses — the same class of failure that shipped the inject bug ([docs/postmortem/0001](../../postmortem/0001-acp-default-export-drops-inject.md)), where 178 hand-mounted tests stayed green while a real Zed session crashed instantly. + +The blocker for a full-transcript test is the model: the agent's output is driven by a non-deterministic LLM, and a key-gated test that hits the real API on every run is neither deterministic nor CI-runnable. We want the fidelity of a real run with the determinism of a fixture. + +This RFC records the decision to add a third test tier — **snapshot tests** — and the design choices that make it deterministic, keyless-in-CI, and cheap to maintain. + +## Decision + +A snapshot test boots the **real** `examples/acp-agent` subprocess, drives it over real ACP stdio with a deterministic input script, and diffs its (normalized) stdout transcript against a committed golden file. The model is made deterministic by **recording its streamed responses once** against the real API and **replaying them** on every subsequent run. + +### Record/replay at the `llm/stream` waterfall + +The record/replay seam is the provider-agnostic `llm/stream` waterfall ([packages/llm/src/index.ts](../../../packages/llm/src/index.ts)), not an HTTP-record library and not an adapter swap. The agent loop calls `ctx.llm.stream()` for every model call (and `generate()` also drains `stream()` internally), so a single waterfall listener intercepts every model interaction regardless of which adapter (deepseek, pi-ai) is installed. The recorded unit is the parsed `StreamChunk` — provider-neutral, JSON-serializable, and already the unit the loop treats as "the replay record" ([packages/agent-loop/src/loop.ts](../../../packages/agent-loop/src/loop.ts)). + +A byte-level HTTP-record library (Polly/nock/MSW) was rejected: it would be adapter-specific (the two adapters share only the `StreamChunk` contract, not transport internals), it handles streaming SSE awkwardly, and it records at a lower level than the thing under test. Recording parsed chunks is simpler, robust, and human-reviewable. + +### Fixture entry schema honors the full LLM contract + +The LLM contract ([packages/llm/src/types.ts](../../../packages/llm/src/types.ts)) allows an adapter to report failure two ways: *throw from `stream()`*, or *end the stream with a `finish {kind:'error'|'aborted'}` chunk*. A fixture of bare `StreamChunk[]` could only replay the second. So each `llm.json` entry is a discriminated record: + +``` +{ kind: 'chunks', chunks: StreamChunk[] } +| { kind: 'throw', message: string, code: string, status?: number } +| { kind: 'hang' } +``` + +`throw` replays the thrown-error branch (e.g. a provider 401), and `hang` (one chunk, then wait for abort) replays cancellation — mirroring the `hang` marker in the existing [MockAdapter](../../../packages/agent-loop/tests/mock-adapter.ts). This keeps both contract branches exercised through the real consumer, per the "honor cross-seam contracts on BOTH sides" defensive pattern. + +### Positional replay, one in-flight stream + +Replay is positional: the Nth `stream()` call in a scenario returns the Nth recorded entry (a cursor with `shift()` semantics, like MockAdapter). This is deterministic **only when at most one model stream is in flight at a time**. The first cut runs one ACP session per scenario, which guarantees that. Multi-session concurrency (the bridge multiplexes N sessions, which can prompt concurrently) would let scheduling decide which model call consumes which entry — so concurrent-session snapshots are explicitly out of scope until fixture entries are keyed by request rather than position. A scenario whose control flow changes the number/order of model calls must be re-recorded; the cursor **fails loud on overrun** rather than silently reusing or skipping an entry. + +### Record flushes per-stream, not on dispose + +The example subprocess is terminated with `SIGKILL` by the test teardown, and `start.ts` has no disposal path, so a `ctx.effect` disposer that flushed `llm.json` at teardown would never run. Record mode therefore flushes the fixture **atomically after each completed stream** (write-temp-then-rename). A minimal graceful-shutdown path (SIGTERM / stdin-end → `await ctx.dispose()`) is added for cleanliness, but fixture durability does not depend on it. + +### Keyless replay needs a providerless config + +`examples/base.yml` always loads `@deepseek-ai/dsh-llm-deepseek`, whose `apply` throws when no API key is present ([packages/llm-deepseek/src/index.ts](../../../packages/llm-deepseek/src/index.ts)). So replay cannot reuse the normal config — it uses a dedicated `examples/acp-agent/cordis.snapshot.yml` that omits `llm-deepseek` and installs the replay plugin in its place. Record mode loads the real adapter *and* the replay plugin (which tees it). In replay mode `start.ts` also skips `.env` loading so a stray key cannot trigger a live call. + +### Normalize, then snapshot parsed frames + +The transcript contains non-deterministic values: `randomUUID()` session ids, the temp `mkdtemp` cwd (which appears in terminal-card `_meta`), JSON-RPC ids, and timing. A pure normalization function replaces these with stable tokens (`{{sessionId}}`, `{{cwd}}`, sequenced ids; volatile numerics dropped/rounded) **before** the snapshot. The golden holds normalized, stable-stringified frames (not opaque bytes) for clean, line-diffable PRs; a separate raw-purity assertion keeps the existing guarantee that every stdout line parses as JSON (no logger leak onto the protocol channel). Vitest's `toMatchFileSnapshot` provides the golden store and the `-u`/`--update` "accept the diff" workflow. + +### Isolation: normalization now, sandbox later + +Determinism of the tool environment comes from a per-test `mkdtemp` cwd, the executor's existing secret-scrubbing env (`/KEY|SECRET|TOKEN/i`), the fresh non-login `bash -c` per call, and the normalization pass — **not** from an OS sandbox. A real rootless sandbox (bwrap on Linux, sandbox-exec/Seatbelt on macOS) is the established cross-platform pattern (Claude Code, Codex), but it is per-OS, fragile on newer kernels (Ubuntu 24.04+ AppArmor blocks unprivileged user namespaces), and unnecessary for transcript determinism. It is reserved as a future tier via the documented `BashExecutor` capability seam ([a sandboxing executor replaces dsh-bash-local without touching a tool schema](2026-06-13-capability-seams.md)) — a new `bash-*` package, not a change here. Scenarios keep bash commands tightly constrained (no `date`/`env`/background/large-output) so the temp-dir tier suffices. + +### Example-local plugin, not a new package + +The replay plugin lives at `examples/acp-agent/src/llm-replay.ts`, referenced from the snapshot config by relative path — exactly how echo-agent wires its [mock-llm.ts](../../../examples/echo-agent/src/mock-llm.ts). It is test/example infrastructure with one consumer; the capability-seams rule says not to split into a published `packages/` trio preemptively. It is promoted to a package only when a second example needs it. + +### Two subcommands, replay in the default gate + +`pnpm run test:snapshot` runs replay (keyless) and is composed into the default `pnpm run test` gate so every PR gets the regression check (the main `vitest.config.ts` include stays narrow; the gate is `test && test:snapshot`). `pnpm run test:snapshot:record` requires `DEEPSEEK_API_KEY` (loaded from repo `.env` first), hits the real API, and `--update`s both `llm.json` and the golden in one pass. Both forward a scenario filter. A missing fixture in replay **fails loud** with a "record first" message rather than self-skipping (the e2e self-skip rule is a CI-secret accommodation, not appropriate here — a committed-fixture test that silently vanishes is a coverage hole). No-model scenarios commit `llm.json` as `[]` so fail-loud and the no-model case don't conflict. An orphan-fixture guard test fails on a golden/fixture not referenced by any scenario (Vitest does not prune orphaned raw goldens). + +## Consequences + +A new test tier and its fixtures to maintain: each scenario is a directory of `input.json` + `llm.json` + `stdout.golden.txt`, committed and reviewed. Re-recording when the model's phrasing changes churns the goldens — visible in review, which is the point of committing them. Bought: deterministic, keyless, full-transcript regression coverage that boots the real Loader (so it still guards the export-shape bug class), exercises the real bash executor, and gives a one-command accept-the-diff loop. The tier is ACP-first but the harness (subprocess + tee + input-DSL + normalization + record/replay waterfall) is example-agnostic and extends to other examples. + +This RFC relates to but does not supersede the [proposed determinism RFC](../proposed/2026-06-11-deterministic-and-stress-testing.md): that proposal's "universal replay fixture" re-derives session *message history* after every test (an internal-consistency invariant), whereas snapshot tests pin the *external protocol output*. They are complementary — one guards the event-sourcing invariant, the other guards the editor-facing contract. From 1a1ce734ba158d344c534d2e017eb0180ba99cd4 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 01:10:30 +0800 Subject: [PATCH 02/13] feat(acp-example): add record/replay llm/stream plugin for snapshot tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduces examples/acp-agent/src/llm-replay.ts, a function/namespace plugin that installs a single llm/stream waterfall listener. In record mode it tees the real model's StreamChunks into a per-scenario llm.json (flushed atomically after EACH stream, since the snapshot subprocess is SIGKILLed and start.ts has no disposal path). In replay mode it short-circuits the waterfall and serves recorded streams back positionally — the Nth stream() call gets the Nth entry — so a snapshot test can drive the real agent with no API key. Each fixture entry is a discriminated record {chunks|throw|hang} so it can replay BOTH branches of the LLM failure contract (throw from stream() vs a finish-error chunk) plus cancellation. A throw entry carries the prefix chunks emitted before the throw, replayed before the error, so a mid-stream failure (partial output then STREAM_CLOSED) reproduces what the loop saw live. Fail-loud on a missing or exhausted fixture (never a silent skip). Unit tests drive the real LlmService waterfall (record tee, ordered replay, the three entry kinds, partial-then-throw, fail-loud, event-driven abort, HMR-safety). Broadens the unit vitest include to examples/*/tests and registers the plugin + snapshot tests as knip entries. Per docs/rfc/implemented/2026-06-19. --- examples/acp-agent/README.md | 4 + examples/acp-agent/src/llm-replay.ts | 195 +++++++++++++++ examples/acp-agent/tests/llm-replay.spec.ts | 262 ++++++++++++++++++++ knip.json | 1 + vitest.config.ts | 2 +- 5 files changed, 463 insertions(+), 1 deletion(-) create mode 100644 examples/acp-agent/src/llm-replay.ts create mode 100644 examples/acp-agent/tests/llm-replay.spec.ts diff --git a/examples/acp-agent/README.md b/examples/acp-agent/README.md index 846e49fe78..31c81dccee 100644 --- a/examples/acp-agent/README.md +++ b/examples/acp-agent/README.md @@ -30,6 +30,10 @@ Add to your Zed `settings.json` under `agent_servers`: The editor sets each session's `cwd` to the project it opens; the agent's bash tools run there (see the per-session `cwd` note in `packages/acp`), so the server does not need to be launched in the workspace. +## Snapshot tests (record-once / replay-deterministic) + +This example is the home of the harness's **snapshot tests** — they boot this server as a real subprocess, drive it with a deterministic input script, and diff its normalized stdout transcript against a committed golden file. The model is made deterministic by `src/llm-replay.ts`, a function/namespace plugin that installs an `llm/stream` waterfall listener: in `record` mode it tees the real model's `StreamChunk`s into a per-scenario `llm.json` (flushed atomically after each call); in `replay` mode it short-circuits the waterfall and serves those chunks back, so replay needs no API key. Each fixture entry is a discriminated record — `{ kind: 'chunks' | 'throw' | 'hang' }` — so both LLM failure branches (throw vs. finish-error) and cancellation replay faithfully. See [docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md](../../docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md) for the full design. + ## MVP limitations The bridge supports N concurrent sessions per connection, each in its own workspace `cwd` (RFC 011). Remaining limits: text-only prompts, `additionalDirectories` rejected (a session operates in its single `cwd`), and the tool-permission gate is deferred (`TODO(rfc010-permission-gate)` — tools run with the executor's full authority). See `packages/acp/README.md` for the full contract. diff --git a/examples/acp-agent/src/llm-replay.ts b/examples/acp-agent/src/llm-replay.ts new file mode 100644 index 0000000000..ea1c13f186 --- /dev/null +++ b/examples/acp-agent/src/llm-replay.ts @@ -0,0 +1,195 @@ +/** + * Record/replay LLM plugin for snapshot tests. + * + * Installs a single `llm/stream` waterfall listener that, in `record` mode, + * tees the real model's streamed {@link StreamChunk}s into a fixture file, and + * in `replay` mode short-circuits the waterfall (never calls `next()`) to yield + * previously-recorded streams deterministically. This is the seam that lets a + * snapshot test boot the real agent against a fixed model transcript with no + * API key — see docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md. + * + * It lives in the example (not packages/) because it is example/test + * infrastructure with one consumer, exactly like echo-agent's `mock-llm.ts`; + * the capability-seams rule says not to split into a published package + * preemptively. + * + * Plugin export shape: named `name`/`inject`/`Config`/`apply`, NO default + * export (the cordis Loader's `unwrapExports` does `exports.default ?? exports`, + * so a stray default would drop the namespace — see docs/postmortem/0001). + */ + +import { existsSync, readFileSync, renameSync, writeFileSync } from 'node:fs' +import type { Context } from 'cordis' +import type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm' +import { LlmError, assertNever } from '@deepseek-ai/dsh-llm' + +/** + * One recorded model call. A discriminated union (not a bare `StreamChunk[]`) + * so it can faithfully replay BOTH branches of the documented LLM failure + * contract — an adapter may THROW from `stream()` or end with a `finish` error + * chunk — plus a `hang` marker for cancellation scenarios (mirrors the + * `MockAdapter` `hang` support in packages/agent-loop/tests). + * + * A `throw` entry carries any `chunks` the adapter emitted BEFORE it threw, so + * a mid-stream transport failure (partial output then `STREAM_CLOSED`) replays + * the partial chunks first and only then throws — exactly what the agent loop + * saw live (it may already have emitted partial assistant chunks). + */ +export type ReplayEntry = + | { kind: 'chunks'; chunks: StreamChunk[] } + | { kind: 'throw'; chunks: StreamChunk[]; message: string; code: string; status?: number } + | { kind: 'hang' } + +/** Resolved plugin configuration. */ +export interface ReplayConfig { + /** `record` tees the real model to `file`; `replay` serves `file` back. */ + mode: 'record' | 'replay' + /** Path to the per-scenario `llm.json` fixture. */ + file: string +} + +/** + * Read and validate a fixture file. Throws a clear, fail-loud error when the + * file is missing (the scenario was never recorded) or malformed — never + * silently returns an empty script, so a coverage hole can't masquerade as a + * passing replay. + */ +export function loadFixture(file: string): ReplayEntry[] { + if (!existsSync(file)) { + throw new Error(`llm-replay: fixture not found: ${file} — run \`pnpm run test:snapshot:record\` first`) + } + const parsed: unknown = JSON.parse(readFileSync(file, 'utf8')) + if (!Array.isArray(parsed)) { + throw new Error(`llm-replay: fixture is not a JSON array: ${file}`) + } + // The fixture round-trips StreamChunk through JSON; branded CallId fields + // deserialize as plain strings, which are structurally StreamChunk. We trust + // the file shape (it is committed and produced by record mode) rather than + // deep-validating every chunk. + return parsed as ReplayEntry[] +} + +/** Atomically write the recorded entries to `file` (temp write + rename). */ +function flushFixture(file: string, entries: ReplayEntry[]): void { + const tmp = `${file}.tmp-${process.pid}` + writeFileSync(tmp, `${JSON.stringify(entries, null, 2)}\n`, { encoding: 'utf8' }) + renameSync(tmp, file) +} + +/** Yield a recorded stream back, honoring abort like a real adapter. */ +async function* replayEntry(entry: ReplayEntry, signal: AbortSignal | undefined): AsyncIterable { + switch (entry.kind) { + case 'chunks': + for (const chunk of entry.chunks) { + if (signal?.aborted) throw new Error('aborted') + yield chunk + } + return + case 'throw': + // Replay the THROW branch of the LLM contract: emit whatever the adapter + // streamed before it threw (so the loop sees the same partial output it + // saw live), then throw the recorded error (e.g. a provider 401, or a + // mid-stream STREAM_CLOSED after partial chunks). + for (const chunk of entry.chunks) { + if (signal?.aborted) throw new Error('aborted') + yield chunk + } + throw new LlmError(entry.message, entry.code, entry.status) + case 'hang': + // Replay a stream that stalls until cancelled (mirrors MockAdapter): one + // chunk, then wait for abort and surface it as the consumer expects. + yield { type: 'block-start', index: 0, blockType: 'text' } + yield { type: 'text-delta', index: 0, text: 'partial' } + await new Promise((_resolve, reject) => { + if (signal?.aborted) { reject(new Error('aborted')); return } + signal?.addEventListener('abort', () => { reject(new Error('aborted')) }, { once: true }) + }) + return + default: + // Closed local union: an unknown kind means malformed (hand-edited or + // drifted) fixture data — fail loud with a runtime diagnostic. + return assertNever(entry, 'llm-replay fixture entry') + } +} + +/** + * Install the record/replay `llm/stream` listener on `ctx`. Returns the + * listener disposer (so a fiber dispose removes it — HMR safety). Exported + * separately from {@link apply} so unit tests can drive it without the Loader + * or env vars. + * + * Replay is POSITIONAL: the Nth `stream()` call serves the Nth fixture entry. + * This is deterministic only with at most one model stream in flight at a time; + * the snapshot harness runs one ACP session per scenario to guarantee that. The + * cursor is advanced synchronously at listener-invocation time (not lazily + * inside the generator) so call ORDER, not iteration order, fixes the mapping. + */ +export function installLlmReplay(ctx: Context, config: ReplayConfig): () => void { + if (config.mode === 'replay') { + const entries = loadFixture(config.file) + let cursor = 0 + return ctx.on('llm/stream', (_options: GenerateOptions, _next) => { + const index = cursor++ + const entry: ReplayEntry | undefined = entries[index] + return (async function* () { + if (entry === undefined) { + throw new Error( + `llm-replay: fixture exhausted — requested model call #${index + 1} but ${config.file} has only ${entries.length}; re-record the scenario`, + ) + } + yield* replayEntry(entry, _options.signal) + })() + }) + } + + // Record mode: delegate to the real adapter via next(), tee each chunk, and + // flush atomically after EACH completed stream — the subprocess is SIGKILLed + // by the test teardown and start.ts has no disposal path, so a dispose-time + // flush would never run (see the RFC). + const recorded: ReplayEntry[] = [] + return ctx.on('llm/stream', (_options: GenerateOptions, next) => { + const inner = next() + return (async function* () { + const chunks: StreamChunk[] = [] + try { + for await (const chunk of inner) { + chunks.push(chunk) + yield chunk + } + } catch (error) { + const code = error instanceof LlmError ? error.code : 'UNKNOWN' + const status = error instanceof LlmError ? error.status : undefined + const message = error instanceof Error ? error.message : String(error) + // Record the chunks emitted before the throw alongside the error, so + // replay reproduces the same partial output + failure. + const entry: ReplayEntry = status === undefined + ? { kind: 'throw', chunks, message, code } + : { kind: 'throw', chunks, message, code, status } + recorded.push(entry) + flushFixture(config.file, recorded) + throw error + } + recorded.push({ kind: 'chunks', chunks }) + flushFixture(config.file, recorded) + })() + }) +} + +export const name = 'llm-replay' +export const inject = ['llm'] + +export interface Config { + /** Override the mode; defaults to `$DSH_SNAPSHOT` (`record`) else `replay`. */ + mode?: 'record' | 'replay' + /** Override the fixture path; defaults to `$DSH_SNAPSHOT_FILE`. */ + file?: string +} + +export function apply(ctx: Context, config: Config = {}): void { + const mode = config.mode ?? (process.env.DSH_SNAPSHOT === 'record' ? 'record' : 'replay') + const file = config.file ?? process.env.DSH_SNAPSHOT_FILE + if (file === undefined || file.length === 0) { + throw new Error('llm-replay: a fixture path is required (Config.file or $DSH_SNAPSHOT_FILE)') + } + installLlmReplay(ctx, { mode, file }) +} diff --git a/examples/acp-agent/tests/llm-replay.spec.ts b/examples/acp-agent/tests/llm-replay.spec.ts new file mode 100644 index 0000000000..2da8981532 --- /dev/null +++ b/examples/acp-agent/tests/llm-replay.spec.ts @@ -0,0 +1,262 @@ +import { mkdtempSync, rmSync, writeFileSync } from 'node:fs' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { afterEach, beforeEach, describe, expect, it } from 'vitest' +import { Context } from 'cordis' +import LlmService, { GenerateOptions, LlmAdapter, LlmError, StreamChunk } from '@deepseek-ai/dsh-llm' +import { type ReplayEntry, installLlmReplay, loadFixture } from '../src/llm-replay.ts' + +/** + * Unit tests for the record/replay llm/stream plugin. These drive the listener + * through the REAL LlmService waterfall (not a hand-rolled stub) so they verify + * the actual seam the snapshot harness depends on. + */ + +const TEXT_SCRIPT: StreamChunk[] = [ + { type: 'block-start', index: 0, blockType: 'text' }, + { type: 'text-delta', index: 0, text: 'hi' }, + { type: 'block-end', index: 0, block: { type: 'text', text: 'hi' } }, + { type: 'usage', usage: { inputTokens: 1, outputTokens: 1 } }, + { type: 'finish', reason: { kind: 'stop' } }, +] + +/** A scripted adapter whose every call yields one of a list of scripts. */ +class MultiScriptAdapter extends LlmAdapter { + calls = 0 + constructor(private scripts: (StreamChunk[] | (() => never))[]) { + super() + } + + async * stream(_options: GenerateOptions): AsyncIterable { + const script = this.scripts[this.calls++] + if (script === undefined) throw new Error('MultiScriptAdapter: script exhausted') + if (typeof script === 'function') return script() // throws (returns never) + yield* script + } +} + +let dir: string +let file: string + +beforeEach(() => { + dir = mkdtempSync(join(tmpdir(), 'llm-replay-spec-')) + file = join(dir, 'llm.json') +}) + +afterEach(() => { + rmSync(dir, { recursive: true, force: true }) +}) + +async function drain(iter: AsyncIterable): Promise { + const out: StreamChunk[] = [] + for await (const chunk of iter) out.push(chunk) + return out +} + +describe('llm-replay record mode', () => { + it('tees the real stream unchanged and flushes one chunks-entry per call', async () => { + const ctx = new Context() + await ctx.plugin(LlmService) + ctx.llm.registerAdapter(['m'], new MultiScriptAdapter([TEXT_SCRIPT])) + installLlmReplay(ctx, { mode: 'record', file }) + + const seen = await drain(ctx.llm.stream({ model: 'm', messages: [] })) + expect(seen).toEqual(TEXT_SCRIPT) // consumer sees the real chunks unchanged + + const fixture = loadFixture(file) + expect(fixture).toEqual([{ kind: 'chunks', chunks: TEXT_SCRIPT }]) + }) + + it('flushes after EACH stream (durable without dispose)', async () => { + const ctx = new Context() + await ctx.plugin(LlmService) + ctx.llm.registerAdapter(['m'], new MultiScriptAdapter([TEXT_SCRIPT, TEXT_SCRIPT])) + installLlmReplay(ctx, { mode: 'record', file }) + + await drain(ctx.llm.stream({ model: 'm', messages: [] })) + expect(loadFixture(file)).toHaveLength(1) // already on disk, no dispose needed + await drain(ctx.llm.stream({ model: 'm', messages: [] })) + expect(loadFixture(file)).toHaveLength(2) + }) + + it('records a throw-entry then re-throws when the adapter throws', async () => { + const ctx = new Context() + await ctx.plugin(LlmService) + ctx.llm.registerAdapter(['m'], new MultiScriptAdapter([() => { throw new Error('boom') }])) + installLlmReplay(ctx, { mode: 'record', file }) + + await expect(drain(ctx.llm.stream({ model: 'm', messages: [] }))).rejects.toThrow('boom') + expect(loadFixture(file)).toEqual([{ kind: 'throw', chunks: [], message: 'boom', code: 'UNKNOWN' }]) + }) + + it('records the partial chunks emitted before a mid-stream throw', async () => { + const partial: StreamChunk[] = [ + { type: 'block-start', index: 0, blockType: 'text' }, + { type: 'text-delta', index: 0, text: 'par' }, + ] + function* chunkThenThrow(): Generator { + yield* partial + throw new LlmError('connection dropped', 'STREAM_CLOSED') + } + // An adapter that streams two chunks, then throws mid-stream. + class MidStreamThrowAdapter extends LlmAdapter { + async * stream(_options: GenerateOptions): AsyncIterable { + yield* chunkThenThrow() + } + } + const ctx = new Context() + await ctx.plugin(LlmService) + ctx.llm.registerAdapter(['m'], new MidStreamThrowAdapter()) + installLlmReplay(ctx, { mode: 'record', file }) + + const seen: StreamChunk[] = [] + await expect((async () => { + for await (const c of ctx.llm.stream({ model: 'm', messages: [] })) seen.push(c) + })()).rejects.toThrow('connection dropped') + expect(seen).toEqual(partial) // consumer saw the partial output before the throw + expect(loadFixture(file)).toEqual([ + { kind: 'throw', chunks: partial, message: 'connection dropped', code: 'STREAM_CLOSED' }, + ]) + }) +}) + +describe('llm-replay replay mode', () => { + function writeFixture(entries: ReplayEntry[]): void { + writeFileSync(file, JSON.stringify(entries), 'utf8') + } + + it('serves recorded chunks back in order, short-circuiting the adapter', async () => { + writeFixture([{ kind: 'chunks', chunks: TEXT_SCRIPT }]) + const ctx = new Context() + await ctx.plugin(LlmService) + // No adapter registered for 'm' — replay must not reach it. + installLlmReplay(ctx, { mode: 'replay', file }) + + const seen = await drain(ctx.llm.stream({ model: 'm', messages: [] })) + expect(seen).toEqual(TEXT_SCRIPT) + }) + + it('serves the Nth call the Nth entry (positional)', async () => { + const second: StreamChunk[] = [ + { type: 'block-start', index: 0, blockType: 'text' }, + { type: 'text-delta', index: 0, text: 'two' }, + { type: 'finish', reason: { kind: 'stop' } }, + ] + writeFixture([{ kind: 'chunks', chunks: TEXT_SCRIPT }, { kind: 'chunks', chunks: second }]) + const ctx = new Context() + await ctx.plugin(LlmService) + installLlmReplay(ctx, { mode: 'replay', file }) + + expect(await drain(ctx.llm.stream({ model: 'm', messages: [] }))).toEqual(TEXT_SCRIPT) + expect(await drain(ctx.llm.stream({ model: 'm', messages: [] }))).toEqual(second) + }) + + it('replays a throw-entry as an LlmError with the recorded code/status', async () => { + writeFixture([{ kind: 'throw', chunks: [], message: 'unauthorized', code: 'AUTH', status: 401 }]) + const ctx = new Context() + await ctx.plugin(LlmService) + installLlmReplay(ctx, { mode: 'replay', file }) + + await expect(drain(ctx.llm.stream({ model: 'm', messages: [] }))).rejects.toMatchObject({ + message: 'unauthorized', + code: 'AUTH', + status: 401, + }) + }) + + it('replays a throw-entry preceded by its partial chunks', async () => { + const partial: StreamChunk[] = [ + { type: 'block-start', index: 0, blockType: 'text' }, + { type: 'text-delta', index: 0, text: 'par' }, + ] + writeFixture([{ kind: 'throw', chunks: partial, message: 'dropped', code: 'STREAM_CLOSED' }]) + const ctx = new Context() + await ctx.plugin(LlmService) + installLlmReplay(ctx, { mode: 'replay', file }) + + const seen: StreamChunk[] = [] + await expect((async () => { + for await (const c of ctx.llm.stream({ model: 'm', messages: [] })) seen.push(c) + })()).rejects.toThrow('dropped') + expect(seen).toEqual(partial) // partial output replayed before the throw + }) + + it('replays a hang-entry that surfaces abort when the signal fires', async () => { + writeFixture([{ kind: 'hang' }]) + const ctx = new Context() + await ctx.plugin(LlmService) + installLlmReplay(ctx, { mode: 'replay', file }) + + const controller = new AbortController() + const iterator = ctx.llm.stream({ model: 'm', messages: [], signal: controller.signal })[Symbol.asyncIterator]() + // Deterministically consume the two pre-hang chunks (no sleep), then abort + // and assert the next pull rejects — event-driven, per the no-sleeps rule. + expect((await iterator.next()).value).toMatchObject({ type: 'block-start' }) + expect((await iterator.next()).value).toMatchObject({ type: 'text-delta' }) + controller.abort() + await expect(iterator.next()).rejects.toThrow('aborted') + }) + + it('fails loud when the fixture is missing', () => { + const ctx = new Context() + expect(() => installLlmReplay(ctx, { mode: 'replay', file: join(dir, 'absent.json') })) + .toThrow(/fixture not found/) + }) + + it('fails loud when the fixture is exhausted', async () => { + writeFixture([{ kind: 'chunks', chunks: TEXT_SCRIPT }]) + const ctx = new Context() + await ctx.plugin(LlmService) + installLlmReplay(ctx, { mode: 'replay', file }) + + await drain(ctx.llm.stream({ model: 'm', messages: [] })) + await expect(drain(ctx.llm.stream({ model: 'm', messages: [] }))).rejects.toThrow(/exhausted/) + }) + + it('aborts mid-replay when the signal is already set', async () => { + writeFixture([{ kind: 'chunks', chunks: TEXT_SCRIPT }]) + const ctx = new Context() + await ctx.plugin(LlmService) + installLlmReplay(ctx, { mode: 'replay', file }) + + const controller = new AbortController() + controller.abort() + await expect(drain(ctx.llm.stream({ model: 'm', messages: [], signal: controller.signal }))) + .rejects.toThrow('aborted') + }) +}) + +describe('llm-replay HMR safety', () => { + it('removes the waterfall listener when the owning fiber is disposed', async () => { + writeFileSync(file, JSON.stringify([{ kind: 'chunks', chunks: TEXT_SCRIPT }]), 'utf8') + const ctx = new Context() + await ctx.plugin(LlmService) + ctx.llm.registerAdapter(['m'], new MultiScriptAdapter([TEXT_SCRIPT, TEXT_SCRIPT])) + + const fiber = await ctx.plugin(Object.assign((inner: Context) => { + installLlmReplay(inner, { mode: 'replay', file }) + }, { inject: ['llm'] })) + + // While installed, replay short-circuits to the fixture ('hi'). + expect(await drain(ctx.llm.stream({ model: 'm', messages: [] }))).toEqual(TEXT_SCRIPT) + + await fiber.dispose() + // After dispose, the listener is gone and the call reaches the real adapter + // (also TEXT_SCRIPT here) — proving the waterfall no longer intercepts. + const afterDispose = await drain(ctx.llm.stream({ model: 'm', messages: [] })) + expect(afterDispose).toEqual(TEXT_SCRIPT) + }) +}) + +describe('loadFixture', () => { + it('throws on a non-array JSON fixture', () => { + writeFileSync(file, '{"not":"an array"}', 'utf8') + expect(() => loadFixture(file)).toThrow(/not a JSON array/) + }) + + it('reads back what was written', () => { + const entries: ReplayEntry[] = [{ kind: 'chunks', chunks: TEXT_SCRIPT }] + writeFileSync(file, JSON.stringify(entries), 'utf8') + expect(loadFixture(file)).toEqual(entries) + }) +}) diff --git a/knip.json b/knip.json index 189da8d695..0693f71c02 100644 --- a/knip.json +++ b/knip.json @@ -7,6 +7,7 @@ "entry": [ "examples/echo-agent/src/*.ts", "examples/coding-agent/src/*.ts", + "examples/acp-agent/src/*.ts", "examples/acp-agent/tests/**/*.e2e.ts" ], "project": ["scripts/**/*.ts", "examples/**/*.ts"] diff --git a/vitest.config.ts b/vitest.config.ts index e8eb5e204e..0878477fb4 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -19,7 +19,7 @@ export default defineConfig({ // instead applies the one root map to every importer. plugins: [tsconfigPaths({ projects: ['./tsconfig.test.json'] })], test: { - include: ['packages/*/tests/**/*.spec.ts'], + include: ['packages/*/tests/**/*.spec.ts', 'examples/*/tests/**/*.spec.ts'], coverage: { provider: 'v8', // Coverage measures OUR runtime source. Types-only files carry no From c182543dd51a196d4c021593624a5e4075550c71 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 02:44:33 +0800 Subject: [PATCH 03/13] refactor(acp-example): derive llm-replay script from the session JSONL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Per a design revision, the per-scenario snapshot fixture becomes EXACTLY the persisted session JSONL (/session.jsonl) rather than a hand-authored llm.json. The log already holds all LLM behavior (assistant/chunk carries every StreamChunk) AND all harness behavior (tool/call, tool/result, turn/*, usage), so one artifact drives replay and doubles as a behavioral golden. llm-replay becomes replay-only (the record-tee is removed; recording is now "run the real agent once and harvest the .jsonl", done by the harness in a later commit). deriveReplayScript(events) groups assistant/chunk by (turn,step) in log order — exact because the loop makes one ctx.llm.stream() call per step and tags each chunk with the current (turn,step). The two failure modes the log can't express (a thrown stream — no terminal finish; cancel/hang — timing) use an optional replay.override.json sidecar. Hardens against a Codex review finding: a derived group is only valid if it ends in a `finish` chunk. A group without one is the fingerprint of a thrown stream() and is NOT silently replayed as a clean stop — deriveReplayScript throws, naming the (turn,step), so a missing sidecar override fails loud. Updates the unit tests (parse/derive/load helpers, sidecar override, finish- terminated grouping, HMR), the example README, and the RFC prose to the JSONL format. Two goldens (stdout transcript + re-persisted JSONL) and the harness wiring land in the next commit. --- .../2026-06-19-acp-snapshot-tests.md | 44 ++- examples/acp-agent/README.md | 2 +- examples/acp-agent/src/llm-replay.ts | 221 ++++++----- examples/acp-agent/tests/llm-replay.spec.ts | 347 ++++++++++-------- 4 files changed, 352 insertions(+), 262 deletions(-) diff --git a/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md b/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md index 900f9a9cd8..db05031169 100644 --- a/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md +++ b/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md @@ -14,44 +14,54 @@ This RFC records the decision to add a third test tier — **snapshot tests** ## Decision -A snapshot test boots the **real** `examples/acp-agent` subprocess, drives it over real ACP stdio with a deterministic input script, and diffs its (normalized) stdout transcript against a committed golden file. The model is made deterministic by **recording its streamed responses once** against the real API and **replaying them** on every subsequent run. +A snapshot test boots the **real** `examples/acp-agent` subprocess, drives it over real ACP stdio with a deterministic input script, and diffs its (normalized) output against committed golden files. The model is made deterministic by **recording a real run's session log once** against the real API and **replaying it** on every subsequent run. The committed fixture IS the persisted session JSONL — the same append-only log the harness writes for any session. -### Record/replay at the `llm/stream` waterfall +### The fixture is the persisted session JSONL -The record/replay seam is the provider-agnostic `llm/stream` waterfall ([packages/llm/src/index.ts](../../../packages/llm/src/index.ts)), not an HTTP-record library and not an adapter swap. The agent loop calls `ctx.llm.stream()` for every model call (and `generate()` also drains `stream()` internally), so a single waterfall listener intercepts every model interaction regardless of which adapter (deepseek, pi-ai) is installed. The recorded unit is the parsed `StreamChunk` — provider-neutral, JSON-serializable, and already the unit the loop treats as "the replay record" ([packages/agent-loop/src/loop.ts](../../../packages/agent-loop/src/loop.ts)). +The per-scenario fixture is `/session.jsonl`: the exact log produced by running the scenario once against the real API (the snapshot harness harvests the file the JSONL persistence backend writes). This log already contains everything needed to reproduce the run deterministically: its `assistant/chunk` events carry every parsed `StreamChunk` (the LLM's behavior), and its `tool/call`/`tool/result`/`turn/*`/`assistant/message`/`usage` events carry the harness's behavior. One artifact captures both, and it is the format the codebase already treats as the authoritative replay record ([packages/session/src/types.ts](../../../packages/session/src/types.ts): "raw chunks are the replay record"). -A byte-level HTTP-record library (Polly/nock/MSW) was rejected: it would be adapter-specific (the two adapters share only the `StreamChunk` contract, not transport internals), it handles streaming SSE awkwardly, and it records at a lower level than the thing under test. Recording parsed chunks is simpler, robust, and human-reviewable. +An earlier draft used a hand-authored `llm.json` of model chunks; reusing the real session log instead means the fixture is a genuine product of the system (not a hand-built mock), and it doubles as a behavioral golden (see below). A byte-level HTTP-record library (Polly/nock/MSW) was rejected: adapter-specific, awkward with streaming SSE, and lower-level than the thing under test. -### Fixture entry schema honors the full LLM contract +### Replay derives the model script from the log -The LLM contract ([packages/llm/src/types.ts](../../../packages/llm/src/types.ts)) allows an adapter to report failure two ways: *throw from `stream()`*, or *end the stream with a `finish {kind:'error'|'aborted'}` chunk*. A fixture of bare `StreamChunk[]` could only replay the second. So each `llm.json` entry is a discriminated record: +The replay seam is the provider-agnostic `llm/stream` waterfall ([packages/llm/src/index.ts](../../../packages/llm/src/index.ts)) — a single listener intercepts every model call regardless of adapter (deepseek, pi-ai), because the loop routes all model calls through `ctx.llm.stream()`. The `llm-replay` plugin short-circuits that waterfall (never calls `next()`) and serves back streams reconstructed from the log: `deriveReplayScript(events)` groups `assistant/chunk` events by `(turn, step)` in log order, yielding one model stream per group. This grouping is exact because the agent loop makes **exactly one `ctx.llm.stream()` call per step** and tags every chunk with the current `(turn, step)` ([packages/agent-loop/src/loop.ts](../../../packages/agent-loop/src/loop.ts)): `step` increments once per loop iteration, so `(turn, step)` is unique per model call. A `finish {kind:'error'}` chunk is part of its group and replays naturally — no special-casing. + +### The in-memory replay entry honors the full LLM contract + +`deriveReplayScript` produces a list of `ReplayEntry`, the in-memory unit the replay listener serves positionally: ``` { kind: 'chunks', chunks: StreamChunk[] } -| { kind: 'throw', message: string, code: string, status?: number } +| { kind: 'throw', chunks: StreamChunk[], message: string, code: string, status?: number } | { kind: 'hang' } ``` -`throw` replays the thrown-error branch (e.g. a provider 401), and `hang` (one chunk, then wait for abort) replays cancellation — mirroring the `hang` marker in the existing [MockAdapter](../../../packages/agent-loop/tests/mock-adapter.ts). This keeps both contract branches exercised through the real consumer, per the "honor cross-seam contracts on BOTH sides" defensive pattern. +`chunks` is what the log derives. The other two cover the LLM contract's failure branches the log **cannot** reconstruct from `assistant/chunk` alone: a *pure throw before any chunk* (e.g. an HTTP 401 — the log holds only a `turn/end {error}`, no chunks) and a *cancel/hang* (a timing behavior, not chunk content). A scenario needing those supplies an optional `/replay.override.json` (a `ReplayEntry[]`) that **replaces** the derived script. The `throw` entry carries any prefix chunks so a mid-stream failure replays its partial output before throwing — the "honor cross-seam contracts on BOTH sides" defensive pattern. Synthesizing throw/cancel from the log's `turn/end {kind:error|aborted}` was rejected: it would couple `llm-replay` to loop-internal turn-closing semantics and the `turn/end` reason is lossy (it can't distinguish a thrown 401 from a finish-error). An explicit sidecar is the cleaner seam. ### Positional replay, one in-flight stream -Replay is positional: the Nth `stream()` call in a scenario returns the Nth recorded entry (a cursor with `shift()` semantics, like MockAdapter). This is deterministic **only when at most one model stream is in flight at a time**. The first cut runs one ACP session per scenario, which guarantees that. Multi-session concurrency (the bridge multiplexes N sessions, which can prompt concurrently) would let scheduling decide which model call consumes which entry — so concurrent-session snapshots are explicitly out of scope until fixture entries are keyed by request rather than position. A scenario whose control flow changes the number/order of model calls must be re-recorded; the cursor **fails loud on overrun** rather than silently reusing or skipping an entry. +Replay is positional: the Nth `stream()` call serves the Nth `ReplayEntry`. This is deterministic **only when at most one model stream is in flight at a time**. The first cut runs one ACP session per scenario, which guarantees that. Multi-session concurrency (the bridge multiplexes N sessions, which can prompt concurrently) would let scheduling decide which model call consumes which entry — so concurrent-session snapshots are out of scope until entries are keyed by request rather than position. A scenario whose control flow changes the number/order of model calls must be re-recorded; the cursor **fails loud on overrun** rather than silently reusing or skipping an entry. A missing `session.jsonl` in replay fails loud too ("record first") — never a silent skip. -### Record flushes per-stream, not on dispose +### Recording harvests the log; keyless replay needs a providerless config -The example subprocess is terminated with `SIGKILL` by the test teardown, and `start.ts` has no disposal path, so a `ctx.effect` disposer that flushed `llm.json` at teardown would never run. Record mode therefore flushes the fixture **atomically after each completed stream** (write-temp-then-rename). A minimal graceful-shutdown path (SIGTERM / stdin-end → `await ctx.dispose()`) is added for cleanliness, but fixture durability does not depend on it. +Recording runs the scenario with the real `llm-deepseek` adapter and the JSONL persistence backend, then copies the produced `.jsonl` into the scenario dir. Per-event appends are durable, but the harness shuts the subprocess down gracefully (close stdin → `await ctx.dispose()`) before harvesting so the final events are flushed. `llm-replay` itself does no recording — it is replay-only. -### Keyless replay needs a providerless config +`examples/base.yml` always loads `@deepseek-ai/dsh-llm-deepseek`, whose `apply` throws when no API key is present ([packages/llm-deepseek/src/index.ts](../../../packages/llm-deepseek/src/index.ts)). So replay cannot reuse the normal config — it uses a dedicated `examples/acp-agent/cordis.snapshot.yml` that omits `llm-deepseek` and installs `llm-replay` in its place. Recording uses a config that loads the real adapter (no `llm-replay`). In replay mode `start.ts` also skips `.env` loading so a stray key cannot trigger a live call. -`examples/base.yml` always loads `@deepseek-ai/dsh-llm-deepseek`, whose `apply` throws when no API key is present ([packages/llm-deepseek/src/index.ts](../../../packages/llm-deepseek/src/index.ts)). So replay cannot reuse the normal config — it uses a dedicated `examples/acp-agent/cordis.snapshot.yml` that omits `llm-deepseek` and installs the replay plugin in its place. Record mode loads the real adapter *and* the replay plugin (which tees it). In replay mode `start.ts` also skips `.env` loading so a stray key cannot trigger a live call. +### Two goldens: normalize, then snapshot -### Normalize, then snapshot parsed frames +A snapshot run asserts **two** normalized goldens, because the harness's external surfaces are distinct: -The transcript contains non-deterministic values: `randomUUID()` session ids, the temp `mkdtemp` cwd (which appears in terminal-card `_meta`), JSON-RPC ids, and timing. A pure normalization function replaces these with stable tokens (`{{sessionId}}`, `{{cwd}}`, sequenced ids; volatile numerics dropped/rounded) **before** the snapshot. The golden holds normalized, stable-stringified frames (not opaque bytes) for clean, line-diffable PRs; a separate raw-purity assertion keeps the existing guarantee that every stdout line parses as JSON (no logger leak onto the protocol channel). Vitest's `toMatchFileSnapshot` provides the golden store and the `-u`/`--update` "accept the diff" workflow. +1. The **stdout transcript** — the framed `session/update` JSON-RPC the editor sees. Catches regressions in the ACP bridge's event→update translation (`streamSessionEventUpdate`). +2. The **re-derived session JSONL** — the log the replay run itself persists, compared against the recorded fixture. Catches regressions in the loop, tool dispatch, and turn/step structure that never surface on stdout. + +The two are genuinely additive: stdout is the bridge's *lossy projection* of the log (it drops `usage`, `step/*`, exact `seq`/`time`, and renders tool I/O differently), so a loop/tool/turn-structure regression can change the JSONL while leaving the stdout projection identical, and a bridge-translation regression can change stdout while the JSONL is untouched. Asserting the JSONL equality also echoes the proposed [universal replay fixture](../proposed/2026-06-11-deterministic-and-stress-testing.md) idea. + +Both surfaces contain non-deterministic values that a pure normalization function scrubs **before** the snapshot: `randomUUID()` session ids → `{{sessionId}}`, the temp `mkdtemp` cwd → `{{cwd}}` (it appears in terminal-card `_meta` and the log header), JSON-RPC ids → a stable sequence, and the log's per-event `time` (epoch ms) + header `createdAt` dropped or zeroed. Real bash runs during replay, so the JSONL normalizer additionally stabilizes tool-output volatility (any embedded paths/pids/timestamps) — scenarios keep bash commands tightly constrained (`echo`, file writes; no `date`/`env`/background/large-output) so this surface is small. The goldens hold normalized, stable-stringified frames/events (not opaque bytes) for clean, line-diffable PRs; a separate raw-purity assertion keeps the guarantee that every stdout line parses as JSON (no logger leak onto the protocol channel). Vitest's `toMatchFileSnapshot` provides the golden store and the `-u`/`--update` "accept the diff" workflow. ### Isolation: normalization now, sandbox later + Determinism of the tool environment comes from a per-test `mkdtemp` cwd, the executor's existing secret-scrubbing env (`/KEY|SECRET|TOKEN/i`), the fresh non-login `bash -c` per call, and the normalization pass — **not** from an OS sandbox. A real rootless sandbox (bwrap on Linux, sandbox-exec/Seatbelt on macOS) is the established cross-platform pattern (Claude Code, Codex), but it is per-OS, fragile on newer kernels (Ubuntu 24.04+ AppArmor blocks unprivileged user namespaces), and unnecessary for transcript determinism. It is reserved as a future tier via the documented `BashExecutor` capability seam ([a sandboxing executor replaces dsh-bash-local without touching a tool schema](2026-06-13-capability-seams.md)) — a new `bash-*` package, not a change here. Scenarios keep bash commands tightly constrained (no `date`/`env`/background/large-output) so the temp-dir tier suffices. ### Example-local plugin, not a new package @@ -60,10 +70,10 @@ The replay plugin lives at `examples/acp-agent/src/llm-replay.ts`, referenced fr ### Two subcommands, replay in the default gate -`pnpm run test:snapshot` runs replay (keyless) and is composed into the default `pnpm run test` gate so every PR gets the regression check (the main `vitest.config.ts` include stays narrow; the gate is `test && test:snapshot`). `pnpm run test:snapshot:record` requires `DEEPSEEK_API_KEY` (loaded from repo `.env` first), hits the real API, and `--update`s both `llm.json` and the golden in one pass. Both forward a scenario filter. A missing fixture in replay **fails loud** with a "record first" message rather than self-skipping (the e2e self-skip rule is a CI-secret accommodation, not appropriate here — a committed-fixture test that silently vanishes is a coverage hole). No-model scenarios commit `llm.json` as `[]` so fail-loud and the no-model case don't conflict. An orphan-fixture guard test fails on a golden/fixture not referenced by any scenario (Vitest does not prune orphaned raw goldens). +`pnpm run test:snapshot` runs replay (keyless) and is composed into the default `pnpm run test` gate so every PR gets the regression check (the main `vitest.config.ts` include stays narrow; the gate is `test && test:snapshot`). `pnpm run test:snapshot:record` requires `DEEPSEEK_API_KEY` (loaded from repo `.env` first), hits the real API, harvests the produced `session.jsonl`, and `--update`s both goldens in one pass. Both forward a scenario filter. A missing fixture in replay **fails loud** with a "record first" message rather than self-skipping (the e2e self-skip rule is a CI-secret accommodation, not appropriate here — a committed-fixture test that silently vanishes is a coverage hole). A no-model scenario's `session.jsonl` simply has no `assistant/chunk` events (empty derived script); fail-loud still applies if a model call happens with no entry. An orphan-fixture guard test fails on a golden/fixture not referenced by any scenario (Vitest does not prune orphaned raw goldens). ## Consequences -A new test tier and its fixtures to maintain: each scenario is a directory of `input.json` + `llm.json` + `stdout.golden.txt`, committed and reviewed. Re-recording when the model's phrasing changes churns the goldens — visible in review, which is the point of committing them. Bought: deterministic, keyless, full-transcript regression coverage that boots the real Loader (so it still guards the export-shape bug class), exercises the real bash executor, and gives a one-command accept-the-diff loop. The tier is ACP-first but the harness (subprocess + tee + input-DSL + normalization + record/replay waterfall) is example-agnostic and extends to other examples. +A new test tier and its fixtures to maintain: each scenario is a directory of `input.json` (the client stdin script) + `session.jsonl` (the recorded log) + an optional `replay.override.json` + the two `*.golden` files, committed and reviewed. Re-recording when the model's phrasing changes churns the goldens — visible in review, which is the point of committing them. Bought: deterministic, keyless, full-transcript regression coverage that boots the real Loader (so it still guards the export-shape bug class), exercises the real bash executor, and gives a one-command accept-the-diff loop. The tier is ACP-first but the harness (subprocess + tee + input-DSL + normalization + JSONL-derived replay) is example-agnostic and extends to other examples. This RFC relates to but does not supersede the [proposed determinism RFC](../proposed/2026-06-11-deterministic-and-stress-testing.md): that proposal's "universal replay fixture" re-derives session *message history* after every test (an internal-consistency invariant), whereas snapshot tests pin the *external protocol output*. They are complementary — one guards the event-sourcing invariant, the other guards the editor-facing contract. diff --git a/examples/acp-agent/README.md b/examples/acp-agent/README.md index 31c81dccee..a2436dbf33 100644 --- a/examples/acp-agent/README.md +++ b/examples/acp-agent/README.md @@ -32,7 +32,7 @@ The editor sets each session's `cwd` to the project it opens; the agent's bash t ## Snapshot tests (record-once / replay-deterministic) -This example is the home of the harness's **snapshot tests** — they boot this server as a real subprocess, drive it with a deterministic input script, and diff its normalized stdout transcript against a committed golden file. The model is made deterministic by `src/llm-replay.ts`, a function/namespace plugin that installs an `llm/stream` waterfall listener: in `record` mode it tees the real model's `StreamChunk`s into a per-scenario `llm.json` (flushed atomically after each call); in `replay` mode it short-circuits the waterfall and serves those chunks back, so replay needs no API key. Each fixture entry is a discriminated record — `{ kind: 'chunks' | 'throw' | 'hang' }` — so both LLM failure branches (throw vs. finish-error) and cancellation replay faithfully. See [docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md](../../docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md) for the full design. +This example is the home of the harness's **snapshot tests** — they boot this server as a real subprocess, drive it with a deterministic input script, and diff its normalized output against committed golden files. The model is made deterministic by `src/llm-replay.ts`, a function/namespace plugin that installs an `llm/stream` waterfall listener and short-circuits it, serving model streams reconstructed from a recorded **session JSONL** fixture (`/session.jsonl`) — so replay needs no API key. The fixture IS the persisted session log: its `assistant/chunk` events carry every `StreamChunk`, so grouping them by `(turn, step)` reconstructs each `stream()` call (one model call per loop step). Recording is therefore "run the real agent once and harvest the `.jsonl`". The two failure modes not expressible as logged chunks — a pure throw before any chunk, and cancel/hang — use an optional `/replay.override.json` sidecar (a `ReplayEntry[]` that replaces the derived script). See [docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md](../../docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md) for the full design. ## MVP limitations diff --git a/examples/acp-agent/src/llm-replay.ts b/examples/acp-agent/src/llm-replay.ts index ea1c13f186..d24299b275 100644 --- a/examples/acp-agent/src/llm-replay.ts +++ b/examples/acp-agent/src/llm-replay.ts @@ -1,12 +1,25 @@ /** - * Record/replay LLM plugin for snapshot tests. + * Replay LLM plugin for snapshot tests. * - * Installs a single `llm/stream` waterfall listener that, in `record` mode, - * tees the real model's streamed {@link StreamChunk}s into a fixture file, and - * in `replay` mode short-circuits the waterfall (never calls `next()`) to yield - * previously-recorded streams deterministically. This is the seam that lets a - * snapshot test boot the real agent against a fixed model transcript with no - * API key — see docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md. + * Installs a single `llm/stream` waterfall listener that short-circuits the + * waterfall (never calls `next()`) and yields model streams reconstructed from + * a recorded **session JSONL** fixture — so a snapshot test can boot the real + * agent against a fixed model transcript with no API key. See + * docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md. + * + * The fixture IS the persisted session log (`/session.jsonl`): its + * `assistant/chunk` events carry every {@link StreamChunk}, so grouping them by + * `(turn, step)` reconstructs each `stream()` call's chunk sequence (one model + * call per loop step — see packages/agent-loop/src/loop.ts). Recording is + * therefore "run the real agent once and harvest the `.jsonl`", done by the + * snapshot harness — this plugin does not record. + * + * Two failure modes are NOT reconstructable from `assistant/chunk` alone — a + * pure throw before any chunk (e.g. an HTTP 401: the log holds only a + * `turn/end {error}`, no chunks) and a cancel/hang (timing, not chunk content). + * A scenario that needs those supplies an optional sidecar + * (`/replay.override.json`: a `ReplayEntry[]`) that REPLACES the + * derived script. * * It lives in the example (not packages/) because it is example/test * infrastructure with one consumer, exactly like echo-agent's `mock-llm.ts`; @@ -18,8 +31,9 @@ * so a stray default would drop the namespace — see docs/postmortem/0001). */ -import { existsSync, readFileSync, renameSync, writeFileSync } from 'node:fs' +import { existsSync, readFileSync } from 'node:fs' import type { Context } from 'cordis' +import type { SessionEvent } from '@deepseek-ai/dsh-session' import type { GenerateOptions, StreamChunk } from '@deepseek-ai/dsh-llm' import { LlmError, assertNever } from '@deepseek-ai/dsh-llm' @@ -34,6 +48,11 @@ import { LlmError, assertNever } from '@deepseek-ai/dsh-llm' * a mid-stream transport failure (partial output then `STREAM_CLOSED`) replays * the partial chunks first and only then throws — exactly what the agent loop * saw live (it may already have emitted partial assistant chunks). + * + * The normal/finish-terminated cases are DERIVED from the session JSONL + * ({@link deriveReplayScript}); only the throw and hang cases need a + * hand-authored sidecar entry (a thrown stream leaves no terminal `finish` in + * the log, so it cannot be derived as `chunks`). */ export type ReplayEntry = | { kind: 'chunks'; chunks: StreamChunk[] } @@ -42,38 +61,103 @@ export type ReplayEntry = /** Resolved plugin configuration. */ export interface ReplayConfig { - /** `record` tees the real model to `file`; `replay` serves `file` back. */ - mode: 'record' | 'replay' - /** Path to the per-scenario `llm.json` fixture. */ + /** Path to the per-scenario `session.jsonl` fixture (the recorded log). */ file: string + /** + * Optional path to a `ReplayEntry[]` sidecar that REPLACES the derived + * script. Used by the two scenarios not expressible as `assistant/chunk` + * (pure throw-before-chunk, cancel/hang). Absent for normal scenarios. + */ + overrideFile?: string } /** - * Read and validate a fixture file. Throws a clear, fail-loud error when the - * file is missing (the scenario was never recorded) or malformed — never + * Parse a session `.jsonl` buffer into its event list. Line 0 is the session + * header (a `{type:'session',…}` record), every subsequent non-empty line is a + * {@link SessionEvent}. The header is skipped; malformed lines fail loud. + */ +export function parseSessionLog(text: string): SessionEvent[] { + const lines = text.split('\n').filter(line => line.trim().length > 0) + const events: SessionEvent[] = [] + // Skip line 0 (the header). A reader distinguishes it by its `type:'session'` + // tag; we simply drop the first line, which the JSONL backend guarantees is + // the header. + for (let i = 1; i < lines.length; i++) { + const parsed: unknown = JSON.parse(lines[i] as string) + events.push(parsed as SessionEvent) + } + return events +} + +/** + * Reconstruct the per-`stream()` replay script from a recorded session log. + * + * The agent loop makes exactly one `ctx.llm.stream()` call per step and appends + * every chunk as an `assistant/chunk` event tagged with the current + * `(turn, step)`. Grouping those events by `(turn, step)` in log order + * therefore yields one `{kind:'chunks'}` entry per model call, in call order. + * + * A group is only valid if it ends in a `finish` chunk — the adapter contract + * guarantees a successful (or finish-error) stream terminates with `finish`, + * and the loop relies on it. A group WITHOUT a terminal `finish` is the + * fingerprint of a *thrown* `stream()` (the loop recorded the prefix chunks, + * then an `error`/`turn/end`, but no `finish`): such a stream cannot be + * faithfully replayed as `{kind:'chunks'}` (that would look like a clean stop), + * so deriving it is an error — the scenario must supply a `replay.override.json` + * sidecar with an explicit `throw` (or `hang`) entry instead. {@link + * deriveReplayScript} throws, naming the offending `(turn, step)`, so a missing + * override fails loud rather than silently replaying a thrown call as success. + */ +export function deriveReplayScript(events: SessionEvent[]): ReplayEntry[] { + const script: ReplayEntry[] = [] + let currentKey: string | undefined + let current: StreamChunk[] = [] + const close = (key: string | undefined, chunks: StreamChunk[]): void => { + if (chunks.length === 0) return + if (chunks[chunks.length - 1]?.type !== 'finish') { + throw new Error( + `llm-replay: model call ${key} ended without a finish chunk (a thrown stream); ` + + 'this scenario needs a replay.override.json sidecar', + ) + } + script.push({ kind: 'chunks', chunks }) + } + for (const event of events) { + if (event.type !== 'assistant/chunk') continue + const { turn, step, chunk } = event.data + const key = `${turn}/${step}` + if (key !== currentKey) { + // A new (turn, step) — i.e. a new stream() call. Close the previous one + // (skip the initial empty buffer before any chunk has been seen). + close(currentKey, current) + currentKey = key + current = [] + } + current.push(chunk) + } + close(currentKey, current) + return script +} + +/** + * Build the replay script for a scenario: the sidecar override if present, + * otherwise the script derived from the recorded session JSONL. Fail-loud if + * the JSONL fixture is missing (the scenario was never recorded) — never * silently returns an empty script, so a coverage hole can't masquerade as a * passing replay. */ -export function loadFixture(file: string): ReplayEntry[] { - if (!existsSync(file)) { - throw new Error(`llm-replay: fixture not found: ${file} — run \`pnpm run test:snapshot:record\` first`) +export function loadReplayScript(config: ReplayConfig): ReplayEntry[] { + if (config.overrideFile !== undefined && existsSync(config.overrideFile)) { + const parsed: unknown = JSON.parse(readFileSync(config.overrideFile, 'utf8')) + if (!Array.isArray(parsed)) { + throw new Error(`llm-replay: override is not a JSON array: ${config.overrideFile}`) + } + return parsed as ReplayEntry[] } - const parsed: unknown = JSON.parse(readFileSync(file, 'utf8')) - if (!Array.isArray(parsed)) { - throw new Error(`llm-replay: fixture is not a JSON array: ${file}`) + if (!existsSync(config.file)) { + throw new Error(`llm-replay: fixture not found: ${config.file} — run \`pnpm run test:snapshot:record\` first`) } - // The fixture round-trips StreamChunk through JSON; branded CallId fields - // deserialize as plain strings, which are structurally StreamChunk. We trust - // the file shape (it is committed and produced by record mode) rather than - // deep-validating every chunk. - return parsed as ReplayEntry[] -} - -/** Atomically write the recorded entries to `file` (temp write + rename). */ -function flushFixture(file: string, entries: ReplayEntry[]): void { - const tmp = `${file}.tmp-${process.pid}` - writeFileSync(tmp, `${JSON.stringify(entries, null, 2)}\n`, { encoding: 'utf8' }) - renameSync(tmp, file) + return deriveReplayScript(parseSessionLog(readFileSync(config.file, 'utf8'))) } /** Yield a recorded stream back, honoring abort like a real adapter. */ @@ -107,70 +191,35 @@ async function* replayEntry(entry: ReplayEntry, signal: AbortSignal | undefined) return default: // Closed local union: an unknown kind means malformed (hand-edited or - // drifted) fixture data — fail loud with a runtime diagnostic. - return assertNever(entry, 'llm-replay fixture entry') + // drifted) sidecar data — fail loud with a runtime diagnostic. + return assertNever(entry, 'llm-replay replay entry') } } /** - * Install the record/replay `llm/stream` listener on `ctx`. Returns the - * listener disposer (so a fiber dispose removes it — HMR safety). Exported - * separately from {@link apply} so unit tests can drive it without the Loader - * or env vars. + * Install the replay `llm/stream` listener on `ctx`. Returns the listener + * disposer (so a fiber dispose removes it — HMR safety). Exported separately + * from {@link apply} so unit tests can drive it without the Loader or env vars. * - * Replay is POSITIONAL: the Nth `stream()` call serves the Nth fixture entry. + * Replay is POSITIONAL: the Nth `stream()` call serves the Nth script entry. * This is deterministic only with at most one model stream in flight at a time; * the snapshot harness runs one ACP session per scenario to guarantee that. The * cursor is advanced synchronously at listener-invocation time (not lazily * inside the generator) so call ORDER, not iteration order, fixes the mapping. */ export function installLlmReplay(ctx: Context, config: ReplayConfig): () => void { - if (config.mode === 'replay') { - const entries = loadFixture(config.file) - let cursor = 0 - return ctx.on('llm/stream', (_options: GenerateOptions, _next) => { - const index = cursor++ - const entry: ReplayEntry | undefined = entries[index] - return (async function* () { - if (entry === undefined) { - throw new Error( - `llm-replay: fixture exhausted — requested model call #${index + 1} but ${config.file} has only ${entries.length}; re-record the scenario`, - ) - } - yield* replayEntry(entry, _options.signal) - })() - }) - } - - // Record mode: delegate to the real adapter via next(), tee each chunk, and - // flush atomically after EACH completed stream — the subprocess is SIGKILLed - // by the test teardown and start.ts has no disposal path, so a dispose-time - // flush would never run (see the RFC). - const recorded: ReplayEntry[] = [] - return ctx.on('llm/stream', (_options: GenerateOptions, next) => { - const inner = next() + const entries = loadReplayScript(config) + let cursor = 0 + return ctx.on('llm/stream', (options: GenerateOptions, _next) => { + const index = cursor++ + const entry: ReplayEntry | undefined = entries[index] return (async function* () { - const chunks: StreamChunk[] = [] - try { - for await (const chunk of inner) { - chunks.push(chunk) - yield chunk - } - } catch (error) { - const code = error instanceof LlmError ? error.code : 'UNKNOWN' - const status = error instanceof LlmError ? error.status : undefined - const message = error instanceof Error ? error.message : String(error) - // Record the chunks emitted before the throw alongside the error, so - // replay reproduces the same partial output + failure. - const entry: ReplayEntry = status === undefined - ? { kind: 'throw', chunks, message, code } - : { kind: 'throw', chunks, message, code, status } - recorded.push(entry) - flushFixture(config.file, recorded) - throw error + if (entry === undefined) { + throw new Error( + `llm-replay: script exhausted — requested model call #${index + 1} but the fixture has only ${entries.length}; re-record the scenario`, + ) } - recorded.push({ kind: 'chunks', chunks }) - flushFixture(config.file, recorded) + yield* replayEntry(entry, options.signal) })() }) } @@ -179,17 +228,17 @@ export const name = 'llm-replay' export const inject = ['llm'] export interface Config { - /** Override the mode; defaults to `$DSH_SNAPSHOT` (`record`) else `replay`. */ - mode?: 'record' | 'replay' /** Override the fixture path; defaults to `$DSH_SNAPSHOT_FILE`. */ file?: string + /** Override the sidecar path; defaults to `$DSH_SNAPSHOT_OVERRIDE`. */ + overrideFile?: string } export function apply(ctx: Context, config: Config = {}): void { - const mode = config.mode ?? (process.env.DSH_SNAPSHOT === 'record' ? 'record' : 'replay') const file = config.file ?? process.env.DSH_SNAPSHOT_FILE if (file === undefined || file.length === 0) { throw new Error('llm-replay: a fixture path is required (Config.file or $DSH_SNAPSHOT_FILE)') } - installLlmReplay(ctx, { mode, file }) + const overrideFile = config.overrideFile ?? process.env.DSH_SNAPSHOT_OVERRIDE + installLlmReplay(ctx, overrideFile === undefined || overrideFile.length === 0 ? { file } : { file, overrideFile }) } diff --git a/examples/acp-agent/tests/llm-replay.spec.ts b/examples/acp-agent/tests/llm-replay.spec.ts index 2da8981532..9dee417686 100644 --- a/examples/acp-agent/tests/llm-replay.spec.ts +++ b/examples/acp-agent/tests/llm-replay.spec.ts @@ -3,16 +3,24 @@ import { tmpdir } from 'node:os' import { join } from 'node:path' import { afterEach, beforeEach, describe, expect, it } from 'vitest' import { Context } from 'cordis' -import LlmService, { GenerateOptions, LlmAdapter, LlmError, StreamChunk } from '@deepseek-ai/dsh-llm' -import { type ReplayEntry, installLlmReplay, loadFixture } from '../src/llm-replay.ts' +import type { SessionEvent } from '@deepseek-ai/dsh-session' +import LlmService, { GenerateOptions, LlmAdapter, StreamChunk } from '@deepseek-ai/dsh-llm' +import { + type ReplayEntry, + deriveReplayScript, + installLlmReplay, + loadReplayScript, + parseSessionLog, +} from '../src/llm-replay.ts' /** - * Unit tests for the record/replay llm/stream plugin. These drive the listener - * through the REAL LlmService waterfall (not a hand-rolled stub) so they verify - * the actual seam the snapshot harness depends on. + * Unit tests for the replay llm/stream plugin. These drive the listener through + * the REAL LlmService waterfall (not a hand-rolled stub) so they verify the + * actual seam the snapshot harness depends on, plus the pure + * derive/parse/load helpers that turn a recorded session JSONL into a script. */ -const TEXT_SCRIPT: StreamChunk[] = [ +const TEXT_CHUNKS: StreamChunk[] = [ { type: 'block-start', index: 0, blockType: 'text' }, { type: 'text-delta', index: 0, text: 'hi' }, { type: 'block-end', index: 0, block: { type: 'text', text: 'hi' } }, @@ -20,19 +28,15 @@ const TEXT_SCRIPT: StreamChunk[] = [ { type: 'finish', reason: { kind: 'stop' } }, ] -/** A scripted adapter whose every call yields one of a list of scripts. */ -class MultiScriptAdapter extends LlmAdapter { - calls = 0 - constructor(private scripts: (StreamChunk[] | (() => never))[]) { - super() - } +/** Build a minimal session-JSONL string: a header line + the given events. */ +function sessionJsonl(events: SessionEvent[]): string { + const header = JSON.stringify({ type: 'session', version: 1, id: 's1', createdAt: 0 }) + return [header, ...events.map(e => JSON.stringify(e))].join('\n') + '\n' +} - async * stream(_options: GenerateOptions): AsyncIterable { - const script = this.scripts[this.calls++] - if (script === undefined) throw new Error('MultiScriptAdapter: script exhausted') - if (typeof script === 'function') return script() // throws (returns never) - yield* script - } +/** A SessionEvent of type assistant/chunk for (turn, step). */ +function chunkEvent(seq: number, turn: number, step: number, chunk: StreamChunk): SessionEvent { + return { type: 'assistant/chunk', seq, time: 0, data: { turn, step, chunk } } } let dir: string @@ -40,7 +44,7 @@ let file: string beforeEach(() => { dir = mkdtempSync(join(tmpdir(), 'llm-replay-spec-')) - file = join(dir, 'llm.json') + file = join(dir, 'session.jsonl') }) afterEach(() => { @@ -53,139 +57,183 @@ async function drain(iter: AsyncIterable): Promise { return out } -describe('llm-replay record mode', () => { - it('tees the real stream unchanged and flushes one chunks-entry per call', async () => { - const ctx = new Context() - await ctx.plugin(LlmService) - ctx.llm.registerAdapter(['m'], new MultiScriptAdapter([TEXT_SCRIPT])) - installLlmReplay(ctx, { mode: 'record', file }) - - const seen = await drain(ctx.llm.stream({ model: 'm', messages: [] })) - expect(seen).toEqual(TEXT_SCRIPT) // consumer sees the real chunks unchanged - - const fixture = loadFixture(file) - expect(fixture).toEqual([{ kind: 'chunks', chunks: TEXT_SCRIPT }]) +describe('parseSessionLog', () => { + it('skips the header line and parses each event', () => { + const events = [chunkEvent(1, 1, 1, TEXT_CHUNKS[0] as StreamChunk)] + expect(parseSessionLog(sessionJsonl(events))).toEqual(events) }) - it('flushes after EACH stream (durable without dispose)', async () => { - const ctx = new Context() - await ctx.plugin(LlmService) - ctx.llm.registerAdapter(['m'], new MultiScriptAdapter([TEXT_SCRIPT, TEXT_SCRIPT])) - installLlmReplay(ctx, { mode: 'record', file }) - - await drain(ctx.llm.stream({ model: 'm', messages: [] })) - expect(loadFixture(file)).toHaveLength(1) // already on disk, no dispose needed - await drain(ctx.llm.stream({ model: 'm', messages: [] })) - expect(loadFixture(file)).toHaveLength(2) - }) - - it('records a throw-entry then re-throws when the adapter throws', async () => { - const ctx = new Context() - await ctx.plugin(LlmService) - ctx.llm.registerAdapter(['m'], new MultiScriptAdapter([() => { throw new Error('boom') }])) - installLlmReplay(ctx, { mode: 'record', file }) - - await expect(drain(ctx.llm.stream({ model: 'm', messages: [] }))).rejects.toThrow('boom') - expect(loadFixture(file)).toEqual([{ kind: 'throw', chunks: [], message: 'boom', code: 'UNKNOWN' }]) - }) - - it('records the partial chunks emitted before a mid-stream throw', async () => { - const partial: StreamChunk[] = [ - { type: 'block-start', index: 0, blockType: 'text' }, - { type: 'text-delta', index: 0, text: 'par' }, - ] - function* chunkThenThrow(): Generator { - yield* partial - throw new LlmError('connection dropped', 'STREAM_CLOSED') - } - // An adapter that streams two chunks, then throws mid-stream. - class MidStreamThrowAdapter extends LlmAdapter { - async * stream(_options: GenerateOptions): AsyncIterable { - yield* chunkThenThrow() - } - } - const ctx = new Context() - await ctx.plugin(LlmService) - ctx.llm.registerAdapter(['m'], new MidStreamThrowAdapter()) - installLlmReplay(ctx, { mode: 'record', file }) - - const seen: StreamChunk[] = [] - await expect((async () => { - for await (const c of ctx.llm.stream({ model: 'm', messages: [] })) seen.push(c) - })()).rejects.toThrow('connection dropped') - expect(seen).toEqual(partial) // consumer saw the partial output before the throw - expect(loadFixture(file)).toEqual([ - { kind: 'throw', chunks: partial, message: 'connection dropped', code: 'STREAM_CLOSED' }, - ]) + it('ignores blank lines', () => { + const header = JSON.stringify({ type: 'session', version: 1, id: 's1', createdAt: 0 }) + const ev = chunkEvent(1, 1, 1, TEXT_CHUNKS[0] as StreamChunk) + expect(parseSessionLog(`${header}\n\n${JSON.stringify(ev)}\n\n`)).toEqual([ev]) }) }) -describe('llm-replay replay mode', () => { - function writeFixture(entries: ReplayEntry[]): void { - writeFileSync(file, JSON.stringify(entries), 'utf8') +describe('deriveReplayScript', () => { + it('groups assistant/chunk by (turn, step) into one entry per stream() call', () => { + const events: SessionEvent[] = TEXT_CHUNKS.map((c, i) => chunkEvent(i + 1, 1, 1, c)) + expect(deriveReplayScript(events)).toEqual([{ kind: 'chunks', chunks: TEXT_CHUNKS }]) + }) + + it('produces one entry per distinct (turn, step), in log order', () => { + const callA = TEXT_CHUNKS + const callB: StreamChunk[] = [ + { type: 'block-start', index: 0, blockType: 'text' }, + { type: 'text-delta', index: 0, text: 'two' }, + { type: 'finish', reason: { kind: 'stop' } }, + ] + let seq = 1 + const events: SessionEvent[] = [ + ...callA.map(c => chunkEvent(seq++, 1, 1, c)), + ...callB.map(c => chunkEvent(seq++, 1, 2, c)), // same turn, next step + ] + expect(deriveReplayScript(events)).toEqual([ + { kind: 'chunks', chunks: callA }, + { kind: 'chunks', chunks: callB }, + ]) + }) + + it('separates calls across turns too', () => { + let seq = 1 + const events: SessionEvent[] = [ + ...TEXT_CHUNKS.map(c => chunkEvent(seq++, 1, 1, c)), + ...TEXT_CHUNKS.map(c => chunkEvent(seq++, 2, 1, c)), // new turn, step resets to 1 + ] + expect(deriveReplayScript(events)).toHaveLength(2) + }) + + it('ignores non-assistant/chunk events', () => { + let seq = 1 + const events: SessionEvent[] = [ + { type: 'turn/start', seq: seq++, time: 0, data: { turn: 1, trigger: { kind: 'continuation' } } }, + ...TEXT_CHUNKS.map(c => chunkEvent(seq++, 1, 1, c)), + { type: 'turn/end', seq: seq++, time: 0, data: { turn: 1, reason: { kind: 'completed' } } }, + ] + expect(deriveReplayScript(events)).toEqual([{ kind: 'chunks', chunks: TEXT_CHUNKS }]) + }) + + it('returns an empty script for a log with no assistant/chunk events', () => { + expect(deriveReplayScript([])).toEqual([]) + }) + + it('keeps a finish-error chunk in the derived entry (replays naturally)', () => { + const errChunks: StreamChunk[] = [ + { type: 'block-start', index: 0, blockType: 'text' }, + { type: 'finish', reason: { kind: 'error', message: 'boom', code: 'X' } }, + ] + const events = errChunks.map((c, i) => chunkEvent(i + 1, 1, 1, c)) + expect(deriveReplayScript(events)).toEqual([{ kind: 'chunks', chunks: errChunks }]) + }) + + it('throws on a group that lacks a terminal finish chunk (a thrown stream)', () => { + // A thrown stream(): prefix chunks logged, then error/turn/end, NO finish. + const events: SessionEvent[] = [ + chunkEvent(1, 1, 1, { type: 'block-start', index: 0, blockType: 'text' }), + chunkEvent(2, 1, 1, { type: 'text-delta', index: 0, text: 'par' }), + { type: 'turn/end', seq: 3, time: 0, data: { turn: 1, reason: { kind: 'error', message: 'x' } } }, + ] + expect(() => deriveReplayScript(events)).toThrow(/without a finish chunk.*replay\.override\.json/s) + }) + + it('names the offending (turn, step) when a group is incomplete', () => { + const events: SessionEvent[] = [ + chunkEvent(1, 2, 3, { type: 'block-start', index: 0, blockType: 'text' }), + ] + expect(() => deriveReplayScript(events)).toThrow(/2\/3/) + }) +}) + +describe('loadReplayScript', () => { + it('derives from the session JSONL when no override is present', () => { + writeFileSync(file, sessionJsonl(TEXT_CHUNKS.map((c, i) => chunkEvent(i + 1, 1, 1, c))), 'utf8') + expect(loadReplayScript({ file })).toEqual([{ kind: 'chunks', chunks: TEXT_CHUNKS }]) + }) + + it('uses the sidecar override when present, ignoring the JSONL', () => { + writeFileSync(file, sessionJsonl([]), 'utf8') + const overrideFile = join(dir, 'replay.override.json') + const override: ReplayEntry[] = [{ kind: 'throw', chunks: [], message: '401', code: 'AUTH', status: 401 }] + writeFileSync(overrideFile, JSON.stringify(override), 'utf8') + expect(loadReplayScript({ file, overrideFile })).toEqual(override) + }) + + it('falls back to the JSONL when the override path is set but absent', () => { + writeFileSync(file, sessionJsonl(TEXT_CHUNKS.map((c, i) => chunkEvent(i + 1, 1, 1, c))), 'utf8') + expect(loadReplayScript({ file, overrideFile: join(dir, 'nope.json') })) + .toEqual([{ kind: 'chunks', chunks: TEXT_CHUNKS }]) + }) + + it('fails loud when the fixture is missing', () => { + expect(() => loadReplayScript({ file: join(dir, 'absent.jsonl') })).toThrow(/fixture not found/) + }) + + it('throws when the override is not a JSON array', () => { + writeFileSync(file, sessionJsonl([]), 'utf8') + const overrideFile = join(dir, 'replay.override.json') + writeFileSync(overrideFile, '{"not":"array"}', 'utf8') + expect(() => loadReplayScript({ file, overrideFile })).toThrow(/not a JSON array/) + }) +}) + +describe('installLlmReplay (through the real waterfall)', () => { + function writeLog(...calls: StreamChunk[][]): void { + let seq = 1 + const events: SessionEvent[] = [] + calls.forEach((chunks, step) => { + for (const c of chunks) events.push(chunkEvent(seq++, 1, step + 1, c)) + }) + writeFileSync(file, sessionJsonl(events), 'utf8') } - it('serves recorded chunks back in order, short-circuiting the adapter', async () => { - writeFixture([{ kind: 'chunks', chunks: TEXT_SCRIPT }]) + it('serves derived chunks back, short-circuiting the adapter', async () => { + writeLog(TEXT_CHUNKS) const ctx = new Context() await ctx.plugin(LlmService) // No adapter registered for 'm' — replay must not reach it. - installLlmReplay(ctx, { mode: 'replay', file }) - - const seen = await drain(ctx.llm.stream({ model: 'm', messages: [] })) - expect(seen).toEqual(TEXT_SCRIPT) + installLlmReplay(ctx, { file }) + expect(await drain(ctx.llm.stream({ model: 'm', messages: [] }))).toEqual(TEXT_CHUNKS) }) - it('serves the Nth call the Nth entry (positional)', async () => { + it('serves the Nth call the Nth derived entry (positional)', async () => { const second: StreamChunk[] = [ { type: 'block-start', index: 0, blockType: 'text' }, { type: 'text-delta', index: 0, text: 'two' }, { type: 'finish', reason: { kind: 'stop' } }, ] - writeFixture([{ kind: 'chunks', chunks: TEXT_SCRIPT }, { kind: 'chunks', chunks: second }]) + writeLog(TEXT_CHUNKS, second) const ctx = new Context() await ctx.plugin(LlmService) - installLlmReplay(ctx, { mode: 'replay', file }) - - expect(await drain(ctx.llm.stream({ model: 'm', messages: [] }))).toEqual(TEXT_SCRIPT) + installLlmReplay(ctx, { file }) + expect(await drain(ctx.llm.stream({ model: 'm', messages: [] }))).toEqual(TEXT_CHUNKS) expect(await drain(ctx.llm.stream({ model: 'm', messages: [] }))).toEqual(second) }) - it('replays a throw-entry as an LlmError with the recorded code/status', async () => { - writeFixture([{ kind: 'throw', chunks: [], message: 'unauthorized', code: 'AUTH', status: 401 }]) + it('replays a sidecar throw-entry as an LlmError with code/status, after its prefix chunks', async () => { + writeFileSync(file, sessionJsonl([]), 'utf8') + const overrideFile = join(dir, 'replay.override.json') + const partial: StreamChunk[] = [{ type: 'block-start', index: 0, blockType: 'text' }] + writeFileSync(overrideFile, JSON.stringify([ + { kind: 'throw', chunks: partial, message: 'unauthorized', code: 'AUTH', status: 401 }, + ]), 'utf8') const ctx = new Context() await ctx.plugin(LlmService) - installLlmReplay(ctx, { mode: 'replay', file }) - - await expect(drain(ctx.llm.stream({ model: 'm', messages: [] }))).rejects.toMatchObject({ - message: 'unauthorized', - code: 'AUTH', - status: 401, - }) - }) - - it('replays a throw-entry preceded by its partial chunks', async () => { - const partial: StreamChunk[] = [ - { type: 'block-start', index: 0, blockType: 'text' }, - { type: 'text-delta', index: 0, text: 'par' }, - ] - writeFixture([{ kind: 'throw', chunks: partial, message: 'dropped', code: 'STREAM_CLOSED' }]) - const ctx = new Context() - await ctx.plugin(LlmService) - installLlmReplay(ctx, { mode: 'replay', file }) + installLlmReplay(ctx, { file, overrideFile }) const seen: StreamChunk[] = [] await expect((async () => { for await (const c of ctx.llm.stream({ model: 'm', messages: [] })) seen.push(c) - })()).rejects.toThrow('dropped') - expect(seen).toEqual(partial) // partial output replayed before the throw + })()).rejects.toMatchObject({ message: 'unauthorized', code: 'AUTH', status: 401 }) + expect(seen).toEqual(partial) }) - it('replays a hang-entry that surfaces abort when the signal fires', async () => { - writeFixture([{ kind: 'hang' }]) + it('replays a sidecar hang-entry that surfaces abort when the signal fires', async () => { + writeFileSync(file, sessionJsonl([]), 'utf8') + const overrideFile = join(dir, 'replay.override.json') + writeFileSync(overrideFile, JSON.stringify([{ kind: 'hang' }]), 'utf8') const ctx = new Context() await ctx.plugin(LlmService) - installLlmReplay(ctx, { mode: 'replay', file }) + installLlmReplay(ctx, { file, overrideFile }) const controller = new AbortController() const iterator = ctx.llm.stream({ model: 'm', messages: [], signal: controller.signal })[Symbol.asyncIterator]() @@ -197,66 +245,49 @@ describe('llm-replay replay mode', () => { await expect(iterator.next()).rejects.toThrow('aborted') }) - it('fails loud when the fixture is missing', () => { - const ctx = new Context() - expect(() => installLlmReplay(ctx, { mode: 'replay', file: join(dir, 'absent.json') })) - .toThrow(/fixture not found/) - }) - - it('fails loud when the fixture is exhausted', async () => { - writeFixture([{ kind: 'chunks', chunks: TEXT_SCRIPT }]) + it('fails loud when the script is exhausted', async () => { + writeLog(TEXT_CHUNKS) const ctx = new Context() await ctx.plugin(LlmService) - installLlmReplay(ctx, { mode: 'replay', file }) - + installLlmReplay(ctx, { file }) await drain(ctx.llm.stream({ model: 'm', messages: [] })) await expect(drain(ctx.llm.stream({ model: 'm', messages: [] }))).rejects.toThrow(/exhausted/) }) it('aborts mid-replay when the signal is already set', async () => { - writeFixture([{ kind: 'chunks', chunks: TEXT_SCRIPT }]) + writeLog(TEXT_CHUNKS) const ctx = new Context() await ctx.plugin(LlmService) - installLlmReplay(ctx, { mode: 'replay', file }) - + installLlmReplay(ctx, { file }) const controller = new AbortController() controller.abort() await expect(drain(ctx.llm.stream({ model: 'm', messages: [], signal: controller.signal }))) .rejects.toThrow('aborted') }) -}) -describe('llm-replay HMR safety', () => { - it('removes the waterfall listener when the owning fiber is disposed', async () => { - writeFileSync(file, JSON.stringify([{ kind: 'chunks', chunks: TEXT_SCRIPT }]), 'utf8') + it('removes the waterfall listener when the owning fiber is disposed (HMR safety)', async () => { + writeLog(TEXT_CHUNKS, TEXT_CHUNKS) const ctx = new Context() await ctx.plugin(LlmService) - ctx.llm.registerAdapter(['m'], new MultiScriptAdapter([TEXT_SCRIPT, TEXT_SCRIPT])) + + // A real adapter to fall through to AFTER dispose, proving the listener is gone. + class FallthroughAdapter extends LlmAdapter { + async * stream(_options: GenerateOptions): AsyncIterable { + yield { type: 'finish', reason: { kind: 'stop' } } + } + } + ctx.llm.registerAdapter(['m'], new FallthroughAdapter()) const fiber = await ctx.plugin(Object.assign((inner: Context) => { - installLlmReplay(inner, { mode: 'replay', file }) + installLlmReplay(inner, { file }) }, { inject: ['llm'] })) - // While installed, replay short-circuits to the fixture ('hi'). - expect(await drain(ctx.llm.stream({ model: 'm', messages: [] }))).toEqual(TEXT_SCRIPT) + // While installed, replay short-circuits to the derived fixture ('hi'). + expect(await drain(ctx.llm.stream({ model: 'm', messages: [] }))).toEqual(TEXT_CHUNKS) await fiber.dispose() - // After dispose, the listener is gone and the call reaches the real adapter - // (also TEXT_SCRIPT here) — proving the waterfall no longer intercepts. - const afterDispose = await drain(ctx.llm.stream({ model: 'm', messages: [] })) - expect(afterDispose).toEqual(TEXT_SCRIPT) - }) -}) - -describe('loadFixture', () => { - it('throws on a non-array JSON fixture', () => { - writeFileSync(file, '{"not":"an array"}', 'utf8') - expect(() => loadFixture(file)).toThrow(/not a JSON array/) - }) - - it('reads back what was written', () => { - const entries: ReplayEntry[] = [{ kind: 'chunks', chunks: TEXT_SCRIPT }] - writeFileSync(file, JSON.stringify(entries), 'utf8') - expect(loadFixture(file)).toEqual(entries) + // After dispose the listener is gone; the call reaches the real adapter. + expect(await drain(ctx.llm.stream({ model: 'm', messages: [] }))) + .toEqual([{ type: 'finish', reason: { kind: 'stop' } }]) }) }) From 81d434896da39babaaeba16631531cbedef57f24 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 03:36:12 +0800 Subject: [PATCH 04/13] feat(acp-example): snapshot harness, normalizers, wiring, and handshake scenario MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds the snapshot-test harness and the keyless replay pipeline end-to-end. - snapshot-harness.ts: boots the real acp-agent subprocess via the cordis Loader (preserving TSX_TSCONFIG_PATH so unbuilt dsh-* imports resolve from a temp cwd), tees raw stdout into an SDK ClientSideConnection, interprets a per-scenario input.json DSL (initialize / newSession capturing the random sessionId / prompt / cancel), closes stdin to trigger graceful shutdown, and harvests the persisted session.jsonl. Failure-safe: a finally block SIGKILLs a live child, awaits its exit, and removes both temp dirs even on a thrown step or harvest. Raw bytes are buffered and decoded once (no multibyte split). - snapshot-normalize.ts (+ spec): two pure normalizers (stdout frames + session JSONL) scrub cwd, session ids / UUIDs, and JSON-RPC ids, and zero time / createdAt — but keep `seq` (deterministic by contract). normalizeStdout throws on a non-JSON line (the stdout-purity check). - start.ts: selects cordis.snapshot.yml (replay, providerless) or cordis.snapshot-record.yml (record, real adapter) from DSH_SNAPSHOT, skips .env in replay, and disposes the ctx on stdin end so persistence flushes before exit (harvest-after-flush, not on the prompt response). - acp.snapshot.ts: asserts the normalized stdout golden (and, for model scenarios, the re-persisted JSONL golden) via toMatchFileSnapshot; record mode writes the harvested log back to the scenario fixture; an orphan-fixture guard fails on an unregistered scenario dir. - handshake scenario: initialize + session/new (no model call; a header-only session.jsonl, since session/new persists no events). - vitest.snapshot.config.ts, test:snapshot / test:snapshot:record scripts, a pre-push snapshot job, and the knip entry. Incorporates Codex review: record-fixture writeback, failure-safe teardown, seq-not-scrubbed, harvest-after-flush. Per docs/rfc/implemented/2026-06-19. --- examples/acp-agent/cordis.snapshot-record.yml | 43 ++++ examples/acp-agent/cordis.snapshot.yml | 69 ++++++ examples/acp-agent/start.ts | 42 +++- examples/acp-agent/tests/acp.snapshot.ts | 90 +++++++ examples/acp-agent/tests/snapshot-harness.ts | 231 ++++++++++++++++++ .../tests/snapshot-normalize.spec.ts | 93 +++++++ .../acp-agent/tests/snapshot-normalize.ts | 102 ++++++++ .../tests/snapshots/handshake/input.json | 6 + .../tests/snapshots/handshake/session.jsonl | 1 + .../snapshots/handshake/stdout.golden.txt | 27 ++ knip.json | 3 +- lefthook.yml | 3 + package.json | 2 + vitest.snapshot.config.ts | 32 +++ 14 files changed, 736 insertions(+), 8 deletions(-) create mode 100644 examples/acp-agent/cordis.snapshot-record.yml create mode 100644 examples/acp-agent/cordis.snapshot.yml create mode 100644 examples/acp-agent/tests/acp.snapshot.ts create mode 100644 examples/acp-agent/tests/snapshot-harness.ts create mode 100644 examples/acp-agent/tests/snapshot-normalize.spec.ts create mode 100644 examples/acp-agent/tests/snapshot-normalize.ts create mode 100644 examples/acp-agent/tests/snapshots/handshake/input.json create mode 100644 examples/acp-agent/tests/snapshots/handshake/session.jsonl create mode 100644 examples/acp-agent/tests/snapshots/handshake/stdout.golden.txt create mode 100644 vitest.snapshot.config.ts diff --git a/examples/acp-agent/cordis.snapshot-record.yml b/examples/acp-agent/cordis.snapshot-record.yml new file mode 100644 index 0000000000..7a4a431f0a --- /dev/null +++ b/examples/acp-agent/cordis.snapshot-record.yml @@ -0,0 +1,43 @@ +# Snapshot-test RECORD config: a real run whose persisted session JSONL is +# harvested into a scenario fixture. Identical to cordis.yml (real llm-deepseek +# adapter + JSONL persistence) — recording must exercise the REAL model so the +# recorded log is a genuine product of the system. Needs DEEPSEEK_API_KEY. +# +# It is a separate file (rather than reusing cordis.yml) only so the snapshot +# harness selects it explicitly via $DSH_SNAPSHOT=record and so its persistence +# root can be pointed at the harness's harvest directory by the same env the +# replay path uses. The graceful-shutdown path in start.ts flushes persistence +# before exit so the harvested log is complete. + +- id: timer + name: '@cordisjs/plugin-timer' + +# Shared provider/tool core, INCLUDING the real llm-deepseek adapter. +- id: base + name: '@cordisjs/plugin-include' + config: + path: '../base.yml' + +- id: agent-loop + name: '@deepseek-ai/dsh-agent-loop' + config: + agents: [] + +- id: session-persistence + name: '@deepseek-ai/dsh-session-persistence-jsonl' + config: + root: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT + +- id: acp + name: '@deepseek-ai/dsh-acp' + config: + model: deepseek-v4-flash + systemPrompt: | + You are a coding assistant driven over the Agent Client Protocol. + + Your only tools are bash (plus bash_output/bash_kill for background + tasks). Do ALL file operations through bash: read with cat/sed/head, + search with grep, write with heredocs (cat <<'EOF' > file), edit with + sed or a rewrite. Each bash call runs in a fresh shell — pass workdir + instead of cd. Check the [exit code: N] marker; verify your work. Keep + answers brief and factual. diff --git a/examples/acp-agent/cordis.snapshot.yml b/examples/acp-agent/cordis.snapshot.yml new file mode 100644 index 0000000000..ed5690db18 --- /dev/null +++ b/examples/acp-agent/cordis.snapshot.yml @@ -0,0 +1,69 @@ +# Snapshot-test REPLAY config: the acp-agent plugin tree with the model replaced +# by llm-replay (serves a recorded session JSONL — no API key, no network). +# +# This does NOT include ../base.yml: base.yml always loads +# @deepseek-ai/dsh-llm-deepseek, whose apply() throws without DEEPSEEK_API_KEY, +# so a keyless replay run would die at boot. We inline the providerless core +# instead and install llm-replay where the adapter would be. +# +# stdout is reserved for the ACP JSON-RPC protocol — no stdout logger (see +# cordis.yml). The replay fixture path comes from $DSH_SNAPSHOT_FILE (and an +# optional $DSH_SNAPSHOT_OVERRIDE sidecar), set by the snapshot harness. + +- id: timer + name: '@cordisjs/plugin-timer' + +# Providerless core (everything base.yml has EXCEPT llm-deepseek). +- id: llm + name: '@deepseek-ai/dsh-llm' + +- id: sessions + name: '@deepseek-ai/dsh-session' + +- id: system-prompt + name: '@deepseek-ai/dsh-system-prompt' + +- id: tools + name: '@deepseek-ai/dsh-tools' + +- id: agents + name: '@deepseek-ai/dsh-agent' + +- id: invariants + name: '@deepseek-ai/dsh-invariants' + +- id: bash + name: '@deepseek-ai/dsh-bash-local' + config: + timeoutMs: 60000 + +- id: tool-bash + name: '@deepseek-ai/dsh-tool-bash' + +# The replay adapter: short-circuits llm/stream with the recorded log's chunks. +- id: llm-replay + name: './src/llm-replay.ts' + +- id: agent-loop + name: '@deepseek-ai/dsh-agent-loop' + config: + agents: [] + +- id: session-persistence + name: '@deepseek-ai/dsh-session-persistence-jsonl' + config: + root: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT + +- id: acp + name: '@deepseek-ai/dsh-acp' + config: + model: deepseek-v4-flash + systemPrompt: | + You are a coding assistant driven over the Agent Client Protocol. + + Your only tools are bash (plus bash_output/bash_kill for background + tasks). Do ALL file operations through bash: read with cat/sed/head, + search with grep, write with heredocs (cat <<'EOF' > file), edit with + sed or a rewrite. Each bash call runs in a fresh shell — pass workdir + instead of cd. Check the [exit code: N] marker; verify your work. Keep + answers brief and factual. diff --git a/examples/acp-agent/start.ts b/examples/acp-agent/start.ts index 1c97c0c8c0..01bcc32093 100644 --- a/examples/acp-agent/start.ts +++ b/examples/acp-agent/start.ts @@ -2,20 +2,36 @@ import { pathToFileURL } from 'node:url' import { Context } from 'cordis' import Loader from '@cordisjs/plugin-loader' +// Snapshot-test modes (set by the snapshot harness via env): +// DSH_SNAPSHOT=replay — load cordis.snapshot.yml (providerless; llm-replay +// serves a recorded session log). Skip .env so a stray +// key can never trigger a live model call. +// DSH_SNAPSHOT=record — load cordis.snapshot-record.yml (the real adapter + +// persistence) so a real run can be harvested. +// Absent — the normal demo (cordis.yml), driven by a real editor. +const snapshotMode = process.env.DSH_SNAPSHOT +const configPath = snapshotMode === 'replay' ? './cordis.snapshot.yml' + : snapshotMode === 'record' ? './cordis.snapshot-record.yml' + : './cordis.yml' + // Load DEEPSEEK_API_KEY / DEEPSEEK_BASE_URL from a gitignored repo-root .env // (Node native). Absent file is fine — the environment may already carry them. +// In REPLAY mode we deliberately skip this: replay must never reach the network, +// so we don't want a present .env to enable a live call. // // IMPORTANT: this server speaks ACP JSON-RPC on stdout. Do NOT add any // stdout logging here or in cordis.yml — it would corrupt the protocol frames. // A present-but-unreadable/malformed .env is a real misconfiguration: surface // it on STDERR (never stdout) rather than silently running with the wrong env. -try { - process.loadEnvFile(new URL('../../.env', import.meta.url).pathname) -} catch (error) { - if ((error as NodeJS.ErrnoException | null)?.code !== 'ENOENT') { - process.stderr.write(`acp-agent: failed to load .env: ${String(error)}\n`) +if (snapshotMode !== 'replay') { + try { + process.loadEnvFile(new URL('../../.env', import.meta.url).pathname) + } catch (error) { + if ((error as NodeJS.ErrnoException | null)?.code !== 'ENOENT') { + process.stderr.write(`acp-agent: failed to load .env: ${String(error)}\n`) + } + // ENOENT (no .env) is fine — rely on the ambient environment. } - // ENOENT (no .env) is fine — rely on the ambient environment. } const ctx = new Context() @@ -25,6 +41,18 @@ await ctx.plugin(Loader) await ctx.loader.create({ name: '@cordisjs/plugin-include', config: { - path: './cordis.yml', + path: configPath, }, }) + +// Graceful shutdown for snapshot RECORD runs: when the client closes our stdin +// (it is done driving the session), dispose the whole context. Disposal awaits +// the agent-loop teardown and the persistence backend's final `session/flush`, +// so the recorded `.jsonl` is fully written before the process exits and the +// harness harvests it. (In a normal editor session stdin stays open for the +// connection's lifetime; the editor kills the process, so this never fires.) +if (snapshotMode !== undefined) { + process.stdin.on('end', () => { + void ctx.fiber.dispose().then(() => { process.exit(0) }) + }) +} diff --git a/examples/acp-agent/tests/acp.snapshot.ts b/examples/acp-agent/tests/acp.snapshot.ts new file mode 100644 index 0000000000..a2422d4395 --- /dev/null +++ b/examples/acp-agent/tests/acp.snapshot.ts @@ -0,0 +1,90 @@ +import { readFile, readdir, writeFile } from 'node:fs/promises' +import { existsSync } from 'node:fs' +import { fileURLToPath } from 'node:url' +import { dirname, join } from 'node:path' +import { describe, expect, it } from 'vitest' +import { type InputScript, runScenario } from './snapshot-harness.ts' +import { type NormalizeContext, normalizeSessionLog, normalizeStdout } from './snapshot-normalize.ts' + +/** + * ACP snapshot tests (REPLAY by default, keyless). Each scenario under + * `snapshots//` ships an `input.json` (the client stdin script) and a + * recorded `session.jsonl` fixture; replay boots the real acp-agent subprocess, + * drives it, and diffs the normalized stdout transcript (and, for model + * scenarios, the re-persisted session log) against committed goldens. + * + * `pnpm run test:snapshot:record` (DSH_SNAPSHOT=record + -u) re-records the + * fixtures against the real API and refreshes the goldens in one pass. + */ + +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). */ +interface Scenario { + name: string + /** Whether the scenario drives at least one model turn (so a JSONL golden applies). */ + hasModelTurn: boolean +} + +const SCENARIOS: Scenario[] = [ + { name: 'handshake', hasModelTurn: false }, +] + +for (const scenario of SCENARIOS) { + describe(`snapshot: ${scenario.name}`, () => { + it('matches the stdout transcript golden', 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') + const result = await runScenario(input, { + mode: RECORDING ? 'record' : 'replay', + fixtureFile: join(dir, 'session.jsonl'), + ...existsSync(overrideFile) ? { overrideFile } : {}, + }) + + const ctx: NormalizeContext = { + sessionIds: result.sessionId !== undefined ? [result.sessionId] : [], + 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) { + expect(result.sessionLog, 'record produced no session log to harvest').toBeDefined() + await writeFile(join(dir, 'session.jsonl'), result.sessionLog as string) + } + + await expect(normalizeStdout(result.rawStdout, ctx)) + .toMatchFileSnapshot(join(dir, 'stdout.golden.txt')) + + if (scenario.hasModelTurn) { + expect(result.sessionLog, 'a model scenario must persist a session log').toBeDefined() + await expect(normalizeSessionLog(result.sessionLog as string, ctx)) + .toMatchFileSnapshot(join(dir, 'session.golden.txt')) + } + }) + }) +} + +describe('snapshot fixtures', () => { + it('every scenario directory is registered (no orphans)', async () => { + // toMatchFileSnapshot does not prune orphaned golden/fixture files, so a + // renamed/removed scenario could leave a stale dir that nothing exercises. + // Fail loud on any snapshots/ not present in SCENARIOS. + const entries = await readdir(SNAPSHOTS_DIR, { withFileTypes: true }) + const onDisk = entries.filter(e => e.isDirectory()).map(e => e.name).sort() + const registered = SCENARIOS.map(s => s.name).sort() + expect(onDisk).toEqual(registered) + }) + + it('every registered scenario has its required fixture files', async () => { + for (const { name } of SCENARIOS) { + const dir = join(SNAPSHOTS_DIR, name) + expect(existsSync(join(dir, 'input.json')), `${name}/input.json`).toBe(true) + expect(existsSync(join(dir, 'session.jsonl')), `${name}/session.jsonl`).toBe(true) + expect(existsSync(join(dir, 'stdout.golden.txt')), `${name}/stdout.golden.txt`).toBe(true) + } + }) +}) diff --git a/examples/acp-agent/tests/snapshot-harness.ts b/examples/acp-agent/tests/snapshot-harness.ts new file mode 100644 index 0000000000..7fb7eec21d --- /dev/null +++ b/examples/acp-agent/tests/snapshot-harness.ts @@ -0,0 +1,231 @@ +/** + * Shared harness for the ACP snapshot tests. A plain module (NOT a *.spec.ts / + * *.snapshot.ts) so importing it never re-registers another file's tests. + * + * It boots the REAL examples/acp-agent subprocess via the cordis Loader (so the + * export-shape bug class stays guarded — see docs/postmortem/0001), drives it + * over real ACP JSON-RPC stdio with a deterministic input script, tees raw + * stdout (for the golden + a purity check) into an SDK `ClientSideConnection`, + * and — in record mode — harvests the persisted session JSONL after a graceful + * shutdown flush. Two pure normalizers turn the captured stdout frames and the + * session-log events into stable, snapshot-able text. + * + * See docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md. + */ + +import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process' +import { mkdtemp, readFile, readdir, rm } from 'node:fs/promises' +import { tmpdir } from 'node:os' +import { join } from 'node:path' +import { fileURLToPath } from 'node:url' +import { Readable, Writable } from 'node:stream' +import { + ClientSideConnection, + ndJsonStream, + PROTOCOL_VERSION, + type Agent as AcpAgent, + type Client, + type RequestPermissionRequest, + type RequestPermissionResponse, + type SessionNotification, +} from '@agentclientprotocol/sdk' + +const startScript = fileURLToPath(new URL('../start.ts', import.meta.url)) +const tsxLoader = fileURLToPath(import.meta.resolve('tsx')) +// The repo-root tsconfig: dev/test run UNBUILT and the `@deepseek-ai/dsh-*` +// imports resolve through its `paths` map. The child's cwd is a temp dir +// OUTSIDE the repo, so tsx's upward search would miss it — point tsx at the +// repo tsconfig explicitly (same fix the e2e harness uses). Repo root is four +// levels up from this file (examples/acp-agent/tests). +const repoTsconfig = fileURLToPath(new URL('../../../tsconfig.json', import.meta.url)) + +/** + * One step of a scenario's deterministic input script (`input.json`). The + * 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. + */ +type InputStep = + | { op: 'initialize'; terminalOutput?: boolean } + | { op: 'newSession' } + | { op: 'prompt'; text: string } + | { op: 'cancel' } + +/** A scenario's `input.json`: an ordered list of input steps. */ +export interface InputScript { + steps: InputStep[] +} + +/** The result of running a scenario: raw stdout + the harvested session log. */ +export interface RunResult { + /** Raw stdout bytes (decoded utf8), every newline-delimited JSON-RPC frame. */ + rawStdout: string + /** stderr (for diagnostics on failure). */ + stderr: string + /** The session id the server issued (undefined if no session was created). */ + sessionId?: string + /** The temp cwd the session ran in (the bash workspace). */ + cwd: string + /** The persisted session log's content, if one was produced. */ + sessionLog?: string +} + +interface RunOptions { + /** `replay` (default, keyless) or `record` (real API, harvests the log). */ + mode: 'replay' | 'record' + /** The recorded session JSONL fixture path (replay reads it; record writes near it). */ + fixtureFile: string + /** Optional sidecar override path (replay). */ + overrideFile?: string +} + +/** + * Run a scenario end-to-end against a freshly-spawned subprocess. Owns the + * child and its temp dirs; always tears them down. Returns the captured stdout + * and (record mode) the harvested session-log path. + */ +export async function runScenario(input: InputScript, opts: RunOptions): Promise { + const cwd = await mkdtemp(join(tmpdir(), 'acp-snap-cwd-')) + const sessionsRoot = await mkdtemp(join(tmpdir(), 'acp-snap-sessions-')) + const env: NodeJS.ProcessEnv = { + ...process.env, + TSX_TSCONFIG_PATH: repoTsconfig, + DSH_SNAPSHOT: opts.mode, + DSH_SNAPSHOT_FILE: opts.fixtureFile, + DSH_SNAPSHOT_SESSIONS_ROOT: sessionsRoot, + ...opts.overrideFile !== undefined ? { DSH_SNAPSHOT_OVERRIDE: opts.overrideFile } : {}, + } + + const child: ChildProcessWithoutNullStreams = spawn( + process.execPath, + ['--import', tsxLoader, startScript], + { cwd, env, stdio: ['pipe', 'pipe', 'pipe'] }, + ) + + const rawBuffers: Buffer[] = [] + const stderrChunks: string[] = [] + child.stderr.setEncoding('utf8') + child.stderr.on('data', (c: string) => stderrChunks.push(c)) + + // Tee raw stdout: accumulate the bytes for the golden + purity check, and ALSO + // feed the same bytes to the SDK client through a passthrough. Buffer the raw + // bytes (not per-chunk utf8 strings) and decode once at the end, so a + // multibyte sequence split across two 'data' events can't corrupt the golden. + const passthrough = new Readable({ read() {} }) + child.stdout.on('data', (buf: Buffer) => { + rawBuffers.push(buf) + passthrough.push(buf) + }) + child.stdout.on('end', () => passthrough.push(null)) + + const stream = ndJsonStream( + Writable.toWeb(child.stdin) as WritableStream, + Readable.toWeb(passthrough) as ReadableStream, + ) + const makeClient = (_agent: AcpAgent): Client => ({ + sessionUpdate(_params: SessionNotification): Promise { + return Promise.resolve() + }, + requestPermission(_params: RequestPermissionRequest): Promise { + return Promise.resolve({ outcome: { outcome: 'cancelled' } }) + }, + }) + const client = new ClientSideConnection(makeClient, stream) + + let sessionId: string | undefined + let sessionLog: string | undefined + try { + for (const step of input.steps) { + await runStep(client, step, cwd, () => 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. + child.stdin.end() + await waitForExit(child) + // Harvest the persisted log (if any) while the temp dirs still exist. + const sessionLogPath = await findSessionLog(sessionsRoot) + if (sessionLogPath !== undefined) sessionLog = await readFile(sessionLogPath, 'utf8') + } finally { + // Failure-safe teardown: kill a still-running child and drop the temp dirs + // even if a step/harvest threw, so a flaky run never leaks a process or dir. + if (child.exitCode === null && child.signalCode === null) { + child.kill('SIGKILL') + await waitForExit(child) + } + await rm(cwd, { recursive: true, force: true }) + await rm(sessionsRoot, { recursive: true, force: true }) + } + + return { + rawStdout: Buffer.concat(rawBuffers).toString('utf8'), + stderr: stderrChunks.join(''), + cwd, + ...sessionId !== undefined ? { sessionId } : {}, + ...sessionLog !== undefined ? { sessionLog } : {}, + } +} + +/** Drive one input step over the client connection. */ +async function runStep( + client: ClientSideConnection, + step: InputStep, + cwd: string, + getSessionId: () => string | undefined, + setSessionId: (id: string) => void, +): Promise { + switch (step.op) { + case 'initialize': + await client.initialize({ + protocolVersion: PROTOCOL_VERSION, + clientCapabilities: step.terminalOutput === true ? { _meta: { terminal_output: true } } : {}, + }) + return + case 'newSession': { + const { sessionId } = await client.newSession({ cwd, mcpServers: [] }) + setSessionId(sessionId) + return + } + case 'prompt': { + const sessionId = getSessionId() + if (sessionId === undefined) throw new Error('snapshot-harness: prompt before newSession') + await client.prompt({ sessionId, prompt: [{ type: 'text', text: step.text }] }) + return + } + case 'cancel': { + const sessionId = getSessionId() + if (sessionId === undefined) throw new Error('snapshot-harness: cancel before newSession') + await client.cancel({ sessionId }) + return + } + default: + throw new Error(`snapshot-harness: unknown input op ${JSON.stringify(step)}`) + } +} + +/** Resolve once the child process exits (any code/signal). */ +function waitForExit(child: ChildProcessWithoutNullStreams): Promise { + if (child.exitCode !== null || child.signalCode !== null) return Promise.resolve() + return new Promise(resolve => child.once('exit', () => { resolve() })) +} + +/** Find the single produced `.jsonl` session log under a sessions root, if any. */ +async function findSessionLog(root: string): Promise { + let cwdDirs: string[] + try { + cwdDirs = await readdir(root) + } catch { + return undefined + } + for (const dir of cwdDirs) { + const sub = join(root, dir) + let files: string[] + try { + files = await readdir(sub) + } catch { + continue + } + const jsonl = files.find(f => f.endsWith('.jsonl')) + if (jsonl !== undefined) return join(sub, jsonl) + } + return undefined +} diff --git a/examples/acp-agent/tests/snapshot-normalize.spec.ts b/examples/acp-agent/tests/snapshot-normalize.spec.ts new file mode 100644 index 0000000000..339cb8493f --- /dev/null +++ b/examples/acp-agent/tests/snapshot-normalize.spec.ts @@ -0,0 +1,93 @@ +import { describe, expect, it } from 'vitest' +import { type NormalizeContext, normalizeSessionLog, normalizeStdout } from '../tests/snapshot-normalize.ts' + +/** + * Unit tests for the pure snapshot normalizers. Live as a *.spec.ts (runs in + * the default unit gate) and import the harness-side normalizers directly. + */ + +const ctx: NormalizeContext = { + sessionIds: ['11111111-2222-3333-4444-555555555555'], + cwd: '/tmp/acp-snap-cwd-abc123', +} + +describe('normalizeStdout', () => { + it('rewrites JSON-RPC ids to a stable first-seen sequence', () => { + const raw = [ + JSON.stringify({ jsonrpc: '2.0', id: 42, method: 'initialize' }), + JSON.stringify({ jsonrpc: '2.0', id: 42, result: {} }), + JSON.stringify({ jsonrpc: '2.0', id: 99, method: 'session/new' }), + ].join('\n') + const out = normalizeStdout(raw, ctx) + expect(out).toContain('"id": 1') + expect(out).toContain('"id": 2') + expect(out).not.toContain('42') + expect(out).not.toContain('99') + }) + + it('scrubs the cwd and session id anywhere they appear', () => { + const raw = JSON.stringify({ + jsonrpc: '2.0', method: 'session/update', + params: { sessionId: ctx.sessionIds[0], cwd: ctx.cwd, note: `at ${ctx.cwd}/x` }, + }) + const out = normalizeStdout(raw, ctx) + expect(out).toContain('{{sessionId}}') + expect(out).toContain('{{cwd}}') + expect(out).not.toContain(ctx.cwd) + expect(out).not.toContain(ctx.sessionIds[0] as string) + }) + + it('scrubs a stray UUID not in the known list', () => { + const raw = JSON.stringify({ jsonrpc: '2.0', method: 'x', params: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' } }) + expect(normalizeStdout(raw, ctx)).toContain('{{sessionId}}') + }) + + it('leaves notification frames without an id untouched in id-space', () => { + const raw = JSON.stringify({ jsonrpc: '2.0', method: 'session/update', params: {} }) + const out = normalizeStdout(raw, ctx) + expect(out).not.toContain('"id"') + }) + + it('throws on a non-JSON stdout line (the purity check)', () => { + const raw = `${JSON.stringify({ jsonrpc: '2.0', id: 1 })}\noops a log leaked\n` + expect(() => normalizeStdout(raw, ctx)).toThrow() + }) + + it('ignores blank lines', () => { + const raw = `\n${JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'm' })}\n\n` + expect(() => normalizeStdout(raw, ctx)).not.toThrow() + }) +}) + +describe('normalizeSessionLog', () => { + const header = (over: object) => JSON.stringify({ type: 'session', version: 1, id: 's', createdAt: 123, ...over }) + const event = (over: object) => JSON.stringify({ type: 'turn/start', seq: 1, time: 999, data: { turn: 1 }, ...over }) + + it('zeroes the header createdAt', () => { + const out = normalizeSessionLog(`${header({})}\n`, ctx) + expect(out).toContain('"createdAt": 0') + expect(out).not.toContain('123') + }) + + it('zeroes each event time but keeps seq', () => { + const out = normalizeSessionLog(`${header({})}\n${event({ seq: 7, time: 999 })}\n`, ctx) + expect(out).toContain('"time": 0') + expect(out).toContain('"seq": 7') // seq is deterministic — NOT scrubbed + expect(out).not.toContain('999') + }) + + it('scrubs cwd and session id deep inside event data', () => { + const ev = JSON.stringify({ + type: 'tool/result', seq: 2, time: 5, + data: { content: [{ type: 'text', text: `wrote ${ctx.cwd}/proof.txt` }] }, + }) + const out = normalizeSessionLog(`${header({ cwd: ctx.cwd })}\n${ev}\n`, ctx) + expect(out).toContain('{{cwd}}') + expect(out).not.toContain(ctx.cwd) + }) + + it('scrubs the session id in the header', () => { + const out = normalizeSessionLog(`${header({ id: ctx.sessionIds[0] })}\n`, ctx) + expect(out).toContain('{{sessionId}}') + }) +}) diff --git a/examples/acp-agent/tests/snapshot-normalize.ts b/examples/acp-agent/tests/snapshot-normalize.ts new file mode 100644 index 0000000000..c729c429b8 --- /dev/null +++ b/examples/acp-agent/tests/snapshot-normalize.ts @@ -0,0 +1,102 @@ +/** + * Pure normalizers for the ACP snapshot goldens. They replace the + * non-deterministic values in the two captured surfaces — the stdout JSON-RPC + * transcript and the persisted session JSONL — with stable tokens, so a golden + * compare reflects behavior, not run-to-run noise. Kept dependency-free and + * side-effect-free so they unit-test trivially. + * + * Scrubbed: `randomUUID()` session ids → `{{sessionId}}`; the temp `mkdtemp` + * cwd → `{{cwd}}` (it appears in terminal-card `_meta` and the log header); + * JSON-RPC request `id` → a stable per-transcript sequence; the log's per-event + * `time` (epoch ms) and header `createdAt` → 0. NOT scrubbed: the log's `seq` + * (deterministic — `seq = log.length`, part of the event-log contract). + * + * See docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md. + */ + +const SESSION_ID = '{{sessionId}}' +const CWD = '{{cwd}}' + +/** A UUID v4 string, the shape `randomUUID()` produces for session ids. */ +const UUID_RE = /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi + +/** Inputs the normalizers need to recognize a run's volatile values. */ +export interface NormalizeContext { + /** The session id(s) the run issued — replaced with `{{sessionId}}`. */ + sessionIds: string[] + /** The temp cwd the run used — replaced with `{{cwd}}`. */ + cwd: string +} + +/** Replace cwd, session ids, and any stray UUID with stable tokens in a string. */ +function scrubString(value: string, ctx: NormalizeContext): string { + let out = value + // cwd first (longest, most specific), then explicit session ids, then any + // residual UUID (covers ids that appear in places we didn't enumerate). + out = out.split(ctx.cwd).join(CWD) + for (const id of ctx.sessionIds) out = out.split(id).join(SESSION_ID) + out = out.replace(UUID_RE, SESSION_ID) + return out +} + +/** Recursively scrub a parsed JSON value (strings replaced; structure kept). */ +function scrubValue(value: unknown, ctx: NormalizeContext): unknown { + if (typeof value === 'string') return scrubString(value, ctx) + if (Array.isArray(value)) return value.map(v => scrubValue(v, ctx)) + if (value !== null && typeof value === 'object') { + const out: Record = {} + for (const [k, v] of Object.entries(value)) out[k] = scrubValue(v, ctx) + return out + } + return value +} + +/** + * Normalize a raw stdout transcript (newline-delimited JSON-RPC frames) into a + * stable, line-diffable golden: one pretty-printed frame per block, with the + * JSON-RPC `id` rewritten to a per-transcript sequence (1, 2, 3, …) and all + * volatile strings scrubbed. Throws if any non-empty line is not valid JSON — + * that doubles as the stdout-purity check (no logger leaked onto the protocol). + */ +export function normalizeStdout(rawStdout: string, ctx: NormalizeContext): string { + const lines = rawStdout.split('\n').filter(line => line.trim().length > 0) + // Map each distinct JSON-RPC id (request/response correlate by id) to a stable + // sequence number, in first-seen order, so id churn doesn't perturb the golden. + const idSeq = new Map() + const stableId = (id: unknown): number => { + const key = JSON.stringify(id) + let n = idSeq.get(key) + if (n === undefined) { n = idSeq.size + 1; idSeq.set(key, n) } + return n + } + const frames = lines.map((line) => { + const frame = JSON.parse(line) as Record + if ('id' in frame && frame.id !== undefined && frame.id !== null) { + frame.id = stableId(frame.id) + } + return scrubValue(frame, ctx) as Record + }) + return frames.map(f => JSON.stringify(f, null, 2)).join('\n') + '\n' +} + +/** + * Normalize a session JSONL log into a stable golden: the header line's + * volatile fields (`createdAt`, `id`, `cwd`) and every event's `time` are + * zeroed/scrubbed, all volatile strings scrubbed, and `seq` is LEFT INTACT + * (deterministic by contract). One pretty-printed record per block. + */ +export function normalizeSessionLog(rawLog: string, ctx: NormalizeContext): string { + const lines = rawLog.split('\n').filter(line => line.trim().length > 0) + const records = lines.map((line) => { + const record = JSON.parse(line) as Record + // Header line: { type: 'session', createdAt, id, cwd, … }. + if (record.type === 'session') { + if ('createdAt' in record) record.createdAt = 0 + } else if ('time' in record) { + // Event line: zero the epoch-ms timestamp; keep seq (deterministic). + record.time = 0 + } + return scrubValue(record, ctx) as Record + }) + return records.map(r => JSON.stringify(r, null, 2)).join('\n') + '\n' +} diff --git a/examples/acp-agent/tests/snapshots/handshake/input.json b/examples/acp-agent/tests/snapshots/handshake/input.json new file mode 100644 index 0000000000..e1e84be919 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/handshake/input.json @@ -0,0 +1,6 @@ +{ + "steps": [ + { "op": "initialize" }, + { "op": "newSession" } + ] +} diff --git a/examples/acp-agent/tests/snapshots/handshake/session.jsonl b/examples/acp-agent/tests/snapshots/handshake/session.jsonl new file mode 100644 index 0000000000..ab44090be6 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/handshake/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/handshake/stdout.golden.txt b/examples/acp-agent/tests/snapshots/handshake/stdout.golden.txt new file mode 100644 index 0000000000..ec34bb7f4a --- /dev/null +++ b/examples/acp-agent/tests/snapshots/handshake/stdout.golden.txt @@ -0,0 +1,27 @@ +{ + "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}}" + } +} diff --git a/knip.json b/knip.json index 0693f71c02..cb836485f1 100644 --- a/knip.json +++ b/knip.json @@ -8,7 +8,8 @@ "examples/echo-agent/src/*.ts", "examples/coding-agent/src/*.ts", "examples/acp-agent/src/*.ts", - "examples/acp-agent/tests/**/*.e2e.ts" + "examples/acp-agent/tests/**/*.e2e.ts", + "examples/acp-agent/tests/**/*.snapshot.ts" ], "project": ["scripts/**/*.ts", "examples/**/*.ts"] }, diff --git a/lefthook.yml b/lefthook.yml index 24600e4985..2a255424fa 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -25,6 +25,9 @@ pre-push: - name: test run: pnpm run test + - name: snapshot + run: pnpm run test:snapshot + - name: hygiene run: pnpm run hygiene diff --git a/package.json b/package.json index fc8bce92c4..b892288a0e 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,8 @@ "test": "vitest run", "test:coverage": "vitest run --coverage", "test:e2e": "vitest run --config vitest.e2e.config.ts", + "test:snapshot": "vitest run --config vitest.snapshot.config.ts", + "test:snapshot:record": "DSH_SNAPSHOT=record vitest run --config vitest.snapshot.config.ts --update", "knip": "knip", "publint": "tsx scripts/publint-all.ts", "doc-typecheck": "tsx scripts/doc-typecheck.ts", diff --git a/vitest.snapshot.config.ts b/vitest.snapshot.config.ts new file mode 100644 index 0000000000..1fb7ee48a4 --- /dev/null +++ b/vitest.snapshot.config.ts @@ -0,0 +1,32 @@ +import tsconfigPaths from 'vite-tsconfig-paths' +import { defineConfig } from 'vitest/config' + +// Snapshot tests: `pnpm run test:snapshot`, file pattern *.snapshot.ts. +// REPLAY by default — they boot the real acp-agent subprocess against a +// recorded session JSONL fixture (no API key, no network) and diff the +// normalized stdout transcript + re-persisted log against committed goldens. +// `pnpm run test:snapshot:record` (DSH_SNAPSHOT=record + -u) re-records the +// fixtures against the real API and refreshes the goldens. +// +// Replay loads no .env; record reads DEEPSEEK_API_KEY from the env or a +// gitignored repo-root .env (loaded here, mirroring the e2e config), so a +// contributor with a key only in .env can still record. +try { + process.loadEnvFile(new URL('.env', import.meta.url).pathname) +} catch { + // No .env — fine; replay needs no key and record reads it from the env. +} + +export default defineConfig({ + // Same resolution note as vitest.config.ts: bare workspace names resolve + // through the root tsconfig paths map; the native option cannot do this. + plugins: [tsconfigPaths({ projects: ['./tsconfig.test.json'] })], + test: { + include: ['examples/*/tests/**/*.snapshot.ts'], + // Each test boots a subprocess; give it room, and run files one at a time + // (a record run hits the live API, and replay subprocess boot is heavy). + testTimeout: 120_000, + hookTimeout: 30_000, + fileParallelism: false, + }, +}) 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 05/13] 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" + } +} From f09cc81c03e62b8f48b921a050bbbc0d7b821c0c Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 04:14:22 +0800 Subject: [PATCH 06/13] docs: require a snapshot test for transcript/UX-affecting changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Documents the snapshot tier and makes its use a convention. AGENTS.md gains the test:snapshot / test:snapshot:record commands (and corrects the now-stale `pnpm run test` include comment — the unit suite picks up examples/*/tests too), plus a Conventions bullet: a change affecting the editor-facing transcript or end-to-end agent UX needs a snapshot test (or an explicit note why none applies); a pure internal refactor is exempt. The dsh-code-review skill gains a matching reviewer-only check — review the golden diff itself, since a changed *.golden is a behavior change in disguise. --- .agents/skills/dsh-code-review/SKILL.md | 1 + AGENTS.md | 11 ++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.agents/skills/dsh-code-review/SKILL.md b/.agents/skills/dsh-code-review/SKILL.md index 7d4dcd6cd0..8d0792624c 100644 --- a/.agents/skills/dsh-code-review/SKILL.md +++ b/.agents/skills/dsh-code-review/SKILL.md @@ -43,6 +43,7 @@ Where your independent reasoning earns its keep. Start here, then keep going acr - **Plugin export shape + real-loader coverage.** A new/changed `cordis.yml`-loaded plugin: is it a function/namespace plugin (`name`/`inject`/`Config`/`apply` named exports) with NO `export default`? A stray default export makes the Loader's `unwrapExports` drop `inject` and the plugin crashes at load with `cannot get property … without inject` — invisible to hand-built `ctx.plugin({...})` tests and to line coverage. Confirm there's a test driving it through the REAL loader path (the no-key subprocess e2e for ACP is the model). And any opportunistic read of a service NOT in `static inject` should use `ctx.get(name)`, not `ctx.` (the property proxy throws through a foreign shadow). See [packages/AGENTS.md](../../../packages/AGENTS.md) and [docs/postmortem/0001](../../../docs/postmortem/0001-acp-default-export-drops-inject.md). - **Seam discipline.** New swappable capability? Check it's split per the capability-seams RFC (interface / impl / consumer), and that the consumer injects the interface key, never an implementation type. - **Test quality.** A test that passes but asserts the wrong thing is worse than none. Check that new tests would actually fail if the behavior regressed, and that they exercise the contract (events fired, disposal reached) rather than restating the implementation. +- **Snapshot coverage for transcript/UX changes.** If the PR changes the editor-facing transcript or end-to-end agent UX — the ACP bridge's event→update translation, the agent loop's observable output, tool presentation, or anything an editor renders — it must add or update a snapshot scenario (`examples/*/tests/**/*.snapshot.ts`, goldens under `examples/acp-agent/tests/snapshots/`) or note explicitly why none applies (AGENTS.md § Conventions). Review the golden diff itself: a changed `stdout.golden.txt` / `session.golden.txt` is a behavior change in disguise — confirm it's intended, not an accidental regression someone re-recorded away. A pure internal refactor with no observable-output change is exempt, but the PR should say so. See [docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md](../../../docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md). - **Intent and contracts.** Does the change do what the PR says, and honor the documented contract on *both* sides of every seam it touches (see AGENTS.md "Honor cross-seam contracts on BOTH sides")? ## How to respond diff --git a/AGENTS.md b/AGENTS.md index d4b8474865..96861b93ec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -60,10 +60,18 @@ scripts/ repo maintenance scripts (vendor-manifest guard, publint runner). ```sh pnpm install # pnpm workspaces, node >= 24 -pnpm run test # vitest run (packages/*/tests/**/*.spec.ts) +pnpm run test # vitest run (packages|examples/*/tests/**/*.spec.ts) pnpm run test:coverage # vitest run --coverage (per-file 100% gate on packages/*/src) pnpm run test:e2e # real-API tests (packages|examples/*/tests/**/*.e2e.ts); # self-skips without DEEPSEEK_API_KEY — see Secrets below +pnpm run test:snapshot # ACP snapshot tests (examples/*/tests/**/*.snapshot.ts): + # boot the real acp-agent subprocess, replay a recorded + # session JSONL, diff the normalized stdout + re-persisted + # log against committed goldens. KEYLESS — runs in the + # default gate. Filter one: `pnpm run test:snapshot -- -t `. +pnpm run test:snapshot:record # re-record fixtures + goldens against the real + # API (needs DEEPSEEK_API_KEY); accept-the-diff = re-record + # (or `pnpm run test:snapshot -- -u` to refresh goldens only) pnpm run typecheck # tsc -b tsconfig.build.json (declarations) + tsc -p # tsconfig.typecheck.json (tests/examples typecheck too) pnpm run lint # eslint . @@ -122,6 +130,7 @@ Dev/test/demo run **unbuilt** via tsx + the `paths` map in the root `tsconfig.js - **TODO markers**: use `FIXME`/`TODO`/`XXX` to flag known issues by urgency — see [docs/development.md](docs/development.md) for the semantics of each. - **Tests**: vitest, colocated under `packages//tests/*.spec.ts`. Every registry needs an HMR-safety test (dispose the contributing fiber, assert cleanup). **Excessive tests are welcome** — when in doubt, write the test; err on the side of covering edge cases, error paths, event ordering, and concurrency races even if they seem unlikely. Review findings get regression tests (see `packages/agent-loop/tests/review-fixes.spec.ts`). The same generosity applies to **real-API (with-key) e2e tests — inference is cheap here (we are DeepSeek), so do not ration them**: cover the agent's real flows (a real prompt that writes a file, multi-turn, tool use, cancellation) and run them frequently while developing, especially cheap **smoke tests** that boot the real example and check the world. A green mock/no-key suite proves the plumbing, not the product — the with-key smoke test is what catches "green units, broken product". See § Secrets / .env for the with-key policy and why self-skip is a CI accommodation, not a verdict that real-API tests are expensive. - **Prefer the REAL implementation over a mock/stand-in in tests.** When the genuine collaborator is available in the repo, wire it up instead of hand-rolling a fake — a test that registers an inline `defineTool({ name: 'bash', … })` to stand in for `dsh-tool-bash` proves the *bridge* moves bytes but not that the *shipping tool* renders the way the test asserts; the two drift and the test passes while the product is wrong. Mock only the genuinely expensive/non-deterministic boundary (the LLM adapter, the network, the clock) and keep everything downstream real: a bridge tool-call test runs the scripted mock MODEL but the REAL tool + REAL executor (e.g. `makeBridgeHarness({ withBash: true })` plugs `dsh-bash-local` + `dsh-tool-bash` and runs an actual `echo`), so it verifies the actual `presentCall`/`presentResult` an editor sees. This is the unit-test echo of "verify the world, not a synthetic stand-in" (see § Defensive patterns) — a fake you wrote will agree with whatever you assumed; the real thing won't. +- **A change that affects the editor-facing transcript or end-to-end agent UX needs a snapshot test (or an explicit note in the PR why none applies).** The snapshot tier (`examples/*/tests/**/*.snapshot.ts`, `pnpm run test:snapshot`) boots the real example subprocess, replays a recorded session JSONL deterministically (keyless), and diffs the normalized stdout transcript + re-persisted session log against committed goldens — the full-transcript regression net that mock-level unit tests structurally cannot be (it is what catches a bridge-translation or loop-structure regression that leaves every unit green). When you change the ACP bridge, the agent loop's observable output, tool presentation, or anything an editor renders, add or update a scenario under `examples/acp-agent/tests/snapshots/` and re-record with `pnpm run test:snapshot:record`. Reviewing the golden diff is part of the review. The rule is scoped to transcript/UX-affecting changes — a pure internal refactor with no observable-output change does not need one, but say so. See [docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md](docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md). ## Defensive patterns (hard-won) From 9a5a3835c83b88fd829ea922adacf2c6d49b238e Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 04:28:09 +0800 Subject: [PATCH 07/13] ci+fix: run snapshot tests in CI and load .env only when recording MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Holistic-review fixes for integration gaps the per-commit reviews missed: - CI now runs `pnpm run test:snapshot` (a step after the coverage gate). It was wired into pre-push but not .github/workflows/ci.yml, so the RFC/AGENTS claim that snapshot replay runs in the default PR gate was only half-true — CI is the real gate. - vitest.snapshot.config.ts loads the repo .env ONLY when DSH_SNAPSHOT=record. Loading it unconditionally contradicted the replay safety story (replay must never reach the network), and runScenario forwards process.env to the child. Non-ENOENT load errors now surface instead of being swallowed. - start.ts: the graceful-shutdown comment said "RECORD runs" but the path applies to both snapshot modes (replay also closes stdin → dispose → exit). - docs/development.md: list the new pre-push snapshot job and the CI snapshot gate. --- .github/workflows/ci.yml | 9 +++++++++ docs/development.md | 3 ++- examples/acp-agent/start.ts | 14 ++++++++------ vitest.snapshot.config.ts | 18 +++++++++++------- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f07f01b9ec..5b9a9fca4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,6 +60,15 @@ jobs: - name: Tests with coverage gate (per-file 100%) run: pnpm run test:coverage + # ACP snapshot tests (acp-snapshot-tests RFC): boot the real acp-agent + # subprocess and replay recorded session-log fixtures, diffing the + # normalized stdout transcript + re-persisted log against committed + # goldens. KEYLESS by design — the same `test:snapshot` script the pre-push + # hook runs (one source of truth), so the full-transcript regression net + # is part of every PR gate, not just local pre-push. + - name: Snapshot tests (ACP transcript replay) + run: pnpm run test:snapshot + # Before hygiene: publint validates the packed artifacts (lib/index.js), # which only the tsdown bundling step emits. - name: Build (tsc -b + tsdown bundles) diff --git a/docs/development.md b/docs/development.md index 144860a4ff..546be5dc86 100644 --- a/docs/development.md +++ b/docs/development.md @@ -57,7 +57,7 @@ DEEPSEEK_BASE_URL=https://... # optional lefthook is configured in `lefthook.yml` as an early local checkpoint before review: - `pre-commit` runs staged-file ESLint fixes, `pnpm run typecheck`, and the vendor manifest guard. -- `pre-push` runs `pnpm run test`, `pnpm run hygiene`, `pnpm run doc-sync`, and `pnpm run verify-module-graph`. +- `pre-push` runs `pnpm run test`, `pnpm run test:snapshot`, `pnpm run hygiene`, `pnpm run doc-sync`, and `pnpm run verify-module-graph`. The vendor manifest guard checks that changes under `vendor/*/src` are staged with the matching `vendor/README.md` manifest update. See `vendor/README.md` before editing vendored code. @@ -74,6 +74,7 @@ The GitHub workflow runs these gates on each pull request: - `pnpm run doc-sync` - `pnpm run verify-module-graph` - `pnpm run test:coverage` +- `pnpm run test:snapshot` - `pnpm run build` - `pnpm run knip && pnpm run publint` - an echo-agent smoke test that checks the demo's tool call, tool result, and JSONL output diff --git a/examples/acp-agent/start.ts b/examples/acp-agent/start.ts index 01bcc32093..028308cb4a 100644 --- a/examples/acp-agent/start.ts +++ b/examples/acp-agent/start.ts @@ -45,12 +45,14 @@ await ctx.loader.create({ }, }) -// Graceful shutdown for snapshot RECORD runs: when the client closes our stdin -// (it is done driving the session), dispose the whole context. Disposal awaits -// the agent-loop teardown and the persistence backend's final `session/flush`, -// so the recorded `.jsonl` is fully written before the process exits and the -// harness harvests it. (In a normal editor session stdin stays open for the -// connection's lifetime; the editor kills the process, so this never fires.) +// Graceful shutdown for snapshot runs (both replay and record): when the client +// closes our stdin (it is done driving the session), dispose the whole context. +// Disposal awaits the agent-loop teardown and the persistence backend's final +// `session/flush`, so the session `.jsonl` is fully written before the process +// exits and the harness harvests it (and the subprocess exits cleanly so the +// harness's waitForExit resolves). (In a normal editor session stdin stays open +// for the connection's lifetime; the editor kills the process, so this never +// fires.) if (snapshotMode !== undefined) { process.stdin.on('end', () => { void ctx.fiber.dispose().then(() => { process.exit(0) }) diff --git a/vitest.snapshot.config.ts b/vitest.snapshot.config.ts index 1fb7ee48a4..6dc4144044 100644 --- a/vitest.snapshot.config.ts +++ b/vitest.snapshot.config.ts @@ -8,13 +8,17 @@ import { defineConfig } from 'vitest/config' // `pnpm run test:snapshot:record` (DSH_SNAPSHOT=record + -u) re-records the // fixtures against the real API and refreshes the goldens. // -// Replay loads no .env; record reads DEEPSEEK_API_KEY from the env or a -// gitignored repo-root .env (loaded here, mirroring the e2e config), so a -// contributor with a key only in .env can still record. -try { - process.loadEnvFile(new URL('.env', import.meta.url).pathname) -} catch { - // No .env — fine; replay needs no key and record reads it from the env. +// Replay loads no .env (it must never reach the network — a recorded fixture +// drives the model). Record reads DEEPSEEK_API_KEY from the env or a gitignored +// repo-root .env, so a contributor with a key only in .env can still record. +if (process.env.DSH_SNAPSHOT === 'record') { + try { + process.loadEnvFile(new URL('.env', import.meta.url).pathname) + } catch (error) { + // ENOENT (no .env) is fine — the key may already be in the environment. + // Surface any other failure rather than silently recording with wrong env. + if ((error as NodeJS.ErrnoException | null)?.code !== 'ENOENT') throw error + } } export default defineConfig({ From b3caabb05dc89c0d1ae0610bac910c1f630e5d86 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 09:20:26 +0800 Subject: [PATCH 08/13] docs: fix snapshot-filter syntax (no `--`, which vitest reads as a file filter) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `pnpm run test:snapshot -- -t ` silently runs ALL scenarios: pnpm forwards `--` literally and vitest treats everything after it as positional filename filters, so `-t` is ignored. The working form drops the separator — `pnpm run test:snapshot -t ` (and `-u` likewise). --- AGENTS.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 96861b93ec..8e5fb22a29 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -68,10 +68,12 @@ pnpm run test:snapshot # ACP snapshot tests (examples/*/tests/**/*.snapshot.ts) # boot the real acp-agent subprocess, replay a recorded # session JSONL, diff the normalized stdout + re-persisted # log against committed goldens. KEYLESS — runs in the - # default gate. Filter one: `pnpm run test:snapshot -- -t `. + # default gate. Filter one by scenario name (no `--`, which + # vitest treats as a positional file filter): `pnpm run + # test:snapshot -t `. pnpm run test:snapshot:record # re-record fixtures + goldens against the real # API (needs DEEPSEEK_API_KEY); accept-the-diff = re-record - # (or `pnpm run test:snapshot -- -u` to refresh goldens only) + # (or `pnpm run test:snapshot -u` to refresh goldens only) pnpm run typecheck # tsc -b tsconfig.build.json (declarations) + tsc -p # tsconfig.typecheck.json (tests/examples typecheck too) pnpm run lint # eslint . From ec73e11c9b6c702b5394c2db4e39a4d3602952af Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 09:29:41 +0800 Subject: [PATCH 09/13] refactor(acp-example): snapshot goldens are JSONL, not pretty-printed .txt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The goldens now mirror the shape of the surfaces they capture — one compact JSON record per line — matching the wire (NDJSON stdout) and disk (JSONL session log) formats, renamed *.golden.jsonl. They stay grep/jq-able and faithful to what the agent emits, where the prior pretty-printed .txt was a reformatted representation. Both normalizers drop the 2-space indent; the normalizer spec asserts the compact form. All 11 goldens regenerated; replay remains deterministic (8/8 across runs). --- .../2026-06-19-acp-snapshot-tests.md | 2 +- examples/acp-agent/tests/acp.snapshot.ts | 6 +- .../tests/snapshot-normalize.spec.ts | 10 +- .../acp-agent/tests/snapshot-normalize.ts | 16 +- .../snapshots/cancel/session.golden.jsonl | 8 + .../tests/snapshots/cancel/session.golden.txt | 95 -- .../snapshots/cancel/stdout.golden.jsonl | 5 + .../tests/snapshots/cancel/stdout.golden.txt | 62 - .../error-finish/session.golden.jsonl | 7 + .../snapshots/error-finish/session.golden.txt | 79 - .../error-finish/stdout.golden.jsonl | 4 + .../snapshots/error-finish/stdout.golden.txt | 49 - .../snapshots/handshake/stdout.golden.jsonl | 2 + .../snapshots/handshake/stdout.golden.txt | 27 - .../snapshots/multi-turn/session.golden.jsonl | 66 + .../snapshots/multi-turn/session.golden.txt | 929 ----------- .../snapshots/multi-turn/stdout.golden.jsonl | 45 + .../snapshots/multi-turn/stdout.golden.txt | 615 ------- .../snapshots/text-turn/session.golden.jsonl | 35 + .../snapshots/text-turn/session.golden.txt | 489 ------ .../snapshots/text-turn/stdout.golden.jsonl | 25 + .../snapshots/text-turn/stdout.golden.txt | 342 ---- .../tool-call-turn/session.golden.jsonl | 100 ++ .../tool-call-turn/session.golden.txt | 1469 ----------------- .../tool-call-turn/stdout.golden.jsonl | 51 + .../tool-call-turn/stdout.golden.txt | 723 -------- 26 files changed, 366 insertions(+), 4895 deletions(-) create mode 100644 examples/acp-agent/tests/snapshots/cancel/session.golden.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/cancel/session.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/cancel/stdout.golden.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/cancel/stdout.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/error-finish/session.golden.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/error-finish/session.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/error-finish/stdout.golden.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/error-finish/stdout.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/handshake/stdout.golden.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/handshake/stdout.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/multi-turn/session.golden.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/multi-turn/session.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/text-turn/session.golden.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/text-turn/session.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/text-turn/stdout.golden.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/text-turn/stdout.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.txt create mode 100644 examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.jsonl delete mode 100644 examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.txt diff --git a/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md b/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md index db05031169..470e1baf74 100644 --- a/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md +++ b/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md @@ -57,7 +57,7 @@ A snapshot run asserts **two** normalized goldens, because the harness's externa The two are genuinely additive: stdout is the bridge's *lossy projection* of the log (it drops `usage`, `step/*`, exact `seq`/`time`, and renders tool I/O differently), so a loop/tool/turn-structure regression can change the JSONL while leaving the stdout projection identical, and a bridge-translation regression can change stdout while the JSONL is untouched. Asserting the JSONL equality also echoes the proposed [universal replay fixture](../proposed/2026-06-11-deterministic-and-stress-testing.md) idea. -Both surfaces contain non-deterministic values that a pure normalization function scrubs **before** the snapshot: `randomUUID()` session ids → `{{sessionId}}`, the temp `mkdtemp` cwd → `{{cwd}}` (it appears in terminal-card `_meta` and the log header), JSON-RPC ids → a stable sequence, and the log's per-event `time` (epoch ms) + header `createdAt` dropped or zeroed. Real bash runs during replay, so the JSONL normalizer additionally stabilizes tool-output volatility (any embedded paths/pids/timestamps) — scenarios keep bash commands tightly constrained (`echo`, file writes; no `date`/`env`/background/large-output) so this surface is small. The goldens hold normalized, stable-stringified frames/events (not opaque bytes) for clean, line-diffable PRs; a separate raw-purity assertion keeps the guarantee that every stdout line parses as JSON (no logger leak onto the protocol channel). Vitest's `toMatchFileSnapshot` provides the golden store and the `-u`/`--update` "accept the diff" workflow. +Both surfaces contain non-deterministic values that a pure normalization function scrubs **before** the snapshot: `randomUUID()` session ids → `{{sessionId}}`, the temp `mkdtemp` cwd → `{{cwd}}` (it appears in terminal-card `_meta` and the log header), JSON-RPC ids → a stable sequence, and the log's per-event `time` (epoch ms) + header `createdAt` dropped or zeroed (the log's `seq` is left intact — it is deterministic by contract, `seq = log.length`). Real bash runs during replay, so the JSONL normalizer additionally stabilizes tool-output volatility (any embedded paths/pids/timestamps) — scenarios keep bash commands tightly constrained (`echo`, file writes; no `date`/`env`/background/large-output) so this surface is small. The goldens are themselves **JSONL** — one compact, normalized record per line, in the same shape as the surfaces they mirror (NDJSON on the wire, JSONL on disk: `stdout.golden.jsonl`, `session.golden.jsonl`), so they stay `grep`/`jq`-able and faithful to what the agent actually emits. A separate raw-purity assertion keeps the guarantee that every stdout line parses as JSON (no logger leak onto the protocol channel). Vitest's `toMatchFileSnapshot` provides the golden store and the `-u`/`--update` "accept the diff" workflow. ### Isolation: normalization now, sandbox later diff --git a/examples/acp-agent/tests/acp.snapshot.ts b/examples/acp-agent/tests/acp.snapshot.ts index 8aa4a6309b..08a3f5ccc0 100644 --- a/examples/acp-agent/tests/acp.snapshot.ts +++ b/examples/acp-agent/tests/acp.snapshot.ts @@ -72,12 +72,12 @@ for (const scenario of SCENARIOS) { } await expect(normalizeStdout(result.rawStdout, ctx)) - .toMatchFileSnapshot(join(dir, 'stdout.golden.txt')) + .toMatchFileSnapshot(join(dir, 'stdout.golden.jsonl')) if (scenario.hasModelTurn) { expect(result.sessionLog, 'a model scenario must persist a session log').toBeDefined() await expect(normalizeSessionLog(result.sessionLog as string, ctx)) - .toMatchFileSnapshot(join(dir, 'session.golden.txt')) + .toMatchFileSnapshot(join(dir, 'session.golden.jsonl')) } }) }) @@ -99,7 +99,7 @@ describe('snapshot fixtures', () => { const dir = join(SNAPSHOTS_DIR, name) expect(existsSync(join(dir, 'input.json')), `${name}/input.json`).toBe(true) expect(existsSync(join(dir, 'session.jsonl')), `${name}/session.jsonl`).toBe(true) - expect(existsSync(join(dir, 'stdout.golden.txt')), `${name}/stdout.golden.txt`).toBe(true) + expect(existsSync(join(dir, 'stdout.golden.jsonl')), `${name}/stdout.golden.jsonl`).toBe(true) } }) }) diff --git a/examples/acp-agent/tests/snapshot-normalize.spec.ts b/examples/acp-agent/tests/snapshot-normalize.spec.ts index 339cb8493f..bfdeab5dc8 100644 --- a/examples/acp-agent/tests/snapshot-normalize.spec.ts +++ b/examples/acp-agent/tests/snapshot-normalize.spec.ts @@ -19,8 +19,8 @@ describe('normalizeStdout', () => { JSON.stringify({ jsonrpc: '2.0', id: 99, method: 'session/new' }), ].join('\n') const out = normalizeStdout(raw, ctx) - expect(out).toContain('"id": 1') - expect(out).toContain('"id": 2') + expect(out).toContain('"id":1') + expect(out).toContain('"id":2') expect(out).not.toContain('42') expect(out).not.toContain('99') }) @@ -65,14 +65,14 @@ describe('normalizeSessionLog', () => { it('zeroes the header createdAt', () => { const out = normalizeSessionLog(`${header({})}\n`, ctx) - expect(out).toContain('"createdAt": 0') + expect(out).toContain('"createdAt":0') expect(out).not.toContain('123') }) it('zeroes each event time but keeps seq', () => { const out = normalizeSessionLog(`${header({})}\n${event({ seq: 7, time: 999 })}\n`, ctx) - expect(out).toContain('"time": 0') - expect(out).toContain('"seq": 7') // seq is deterministic — NOT scrubbed + expect(out).toContain('"time":0') + expect(out).toContain('"seq":7') // seq is deterministic — NOT scrubbed expect(out).not.toContain('999') }) diff --git a/examples/acp-agent/tests/snapshot-normalize.ts b/examples/acp-agent/tests/snapshot-normalize.ts index c729c429b8..f863913591 100644 --- a/examples/acp-agent/tests/snapshot-normalize.ts +++ b/examples/acp-agent/tests/snapshot-normalize.ts @@ -53,10 +53,11 @@ function scrubValue(value: unknown, ctx: NormalizeContext): unknown { /** * Normalize a raw stdout transcript (newline-delimited JSON-RPC frames) into a - * stable, line-diffable golden: one pretty-printed frame per block, with the - * JSON-RPC `id` rewritten to a per-transcript sequence (1, 2, 3, …) and all - * volatile strings scrubbed. Throws if any non-empty line is not valid JSON — - * that doubles as the stdout-purity check (no logger leaked onto the protocol). + * stable golden in the SAME shape as the wire: one compact JSON frame per line + * (NDJSON), with the JSON-RPC `id` rewritten to a per-transcript sequence + * (1, 2, 3, …) and all volatile strings scrubbed. Throws if any non-empty line + * is not valid JSON — that doubles as the stdout-purity check (no logger leaked + * onto the protocol). */ export function normalizeStdout(rawStdout: string, ctx: NormalizeContext): string { const lines = rawStdout.split('\n').filter(line => line.trim().length > 0) @@ -76,14 +77,15 @@ export function normalizeStdout(rawStdout: string, ctx: NormalizeContext): strin } return scrubValue(frame, ctx) as Record }) - return frames.map(f => JSON.stringify(f, null, 2)).join('\n') + '\n' + return frames.map(f => JSON.stringify(f)).join('\n') + '\n' } /** * Normalize a session JSONL log into a stable golden: the header line's * volatile fields (`createdAt`, `id`, `cwd`) and every event's `time` are * zeroed/scrubbed, all volatile strings scrubbed, and `seq` is LEFT INTACT - * (deterministic by contract). One pretty-printed record per block. + * (deterministic by contract). Output is JSONL in the same shape as the input — + * one compact record per line. */ export function normalizeSessionLog(rawLog: string, ctx: NormalizeContext): string { const lines = rawLog.split('\n').filter(line => line.trim().length > 0) @@ -98,5 +100,5 @@ export function normalizeSessionLog(rawLog: string, ctx: NormalizeContext): stri } return scrubValue(record, ctx) as Record }) - return records.map(r => JSON.stringify(r, null, 2)).join('\n') + '\n' + return records.map(r => JSON.stringify(r)).join('\n') + '\n' } diff --git a/examples/acp-agent/tests/snapshots/cancel/session.golden.jsonl b/examples/acp-agent/tests/snapshots/cancel/session.golden.jsonl new file mode 100644 index 0000000000..ecb5155beb --- /dev/null +++ b/examples/acp-agent/tests/snapshots/cancel/session.golden.jsonl @@ -0,0 +1,8 @@ +{"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.golden.txt b/examples/acp-agent/tests/snapshots/cancel/session.golden.txt deleted file mode 100644 index c928bf58f3..0000000000 --- a/examples/acp-agent/tests/snapshots/cancel/session.golden.txt +++ /dev/null @@ -1,95 +0,0 @@ -{ - "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/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/cancel/stdout.golden.jsonl new file mode 100644 index 0000000000..86ac88d0f4 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/cancel/stdout.golden.jsonl @@ -0,0 +1,5 @@ +{"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/cancel/stdout.golden.txt b/examples/acp-agent/tests/snapshots/cancel/stdout.golden.txt deleted file mode 100644 index 42cb46e45c..0000000000 --- a/examples/acp-agent/tests/snapshots/cancel/stdout.golden.txt +++ /dev/null @@ -1,62 +0,0 @@ -{ - "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/session.golden.jsonl b/examples/acp-agent/tests/snapshots/error-finish/session.golden.jsonl new file mode 100644 index 0000000000..fcf2cde49f --- /dev/null +++ b/examples/acp-agent/tests/snapshots/error-finish/session.golden.jsonl @@ -0,0 +1,7 @@ +{"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.golden.txt b/examples/acp-agent/tests/snapshots/error-finish/session.golden.txt deleted file mode 100644 index ae8b1914c3..0000000000 --- a/examples/acp-agent/tests/snapshots/error-finish/session.golden.txt +++ /dev/null @@ -1,79 +0,0 @@ -{ - "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/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/error-finish/stdout.golden.jsonl new file mode 100644 index 0000000000..e978f8969b --- /dev/null +++ b/examples/acp-agent/tests/snapshots/error-finish/stdout.golden.jsonl @@ -0,0 +1,4 @@ +{"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/error-finish/stdout.golden.txt b/examples/acp-agent/tests/snapshots/error-finish/stdout.golden.txt deleted file mode 100644 index 8babe5e15b..0000000000 --- a/examples/acp-agent/tests/snapshots/error-finish/stdout.golden.txt +++ /dev/null @@ -1,49 +0,0 @@ -{ - "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/handshake/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/handshake/stdout.golden.jsonl new file mode 100644 index 0000000000..ad3f94a046 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/handshake/stdout.golden.jsonl @@ -0,0 +1,2 @@ +{"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}}"}} diff --git a/examples/acp-agent/tests/snapshots/handshake/stdout.golden.txt b/examples/acp-agent/tests/snapshots/handshake/stdout.golden.txt deleted file mode 100644 index ec34bb7f4a..0000000000 --- a/examples/acp-agent/tests/snapshots/handshake/stdout.golden.txt +++ /dev/null @@ -1,27 +0,0 @@ -{ - "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}}" - } -} diff --git a/examples/acp-agent/tests/snapshots/multi-turn/session.golden.jsonl b/examples/acp-agent/tests/snapshots/multi-turn/session.golden.jsonl new file mode 100644 index 0000000000..4623cc674d --- /dev/null +++ b/examples/acp-agent/tests/snapshots/multi-turn/session.golden.jsonl @@ -0,0 +1,66 @@ +{"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.golden.txt b/examples/acp-agent/tests/snapshots/multi-turn/session.golden.txt deleted file mode 100644 index fd80eb9713..0000000000 --- a/examples/acp-agent/tests/snapshots/multi-turn/session.golden.txt +++ /dev/null @@ -1,929 +0,0 @@ -{ - "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/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.jsonl new file mode 100644 index 0000000000..d0c1644cfc --- /dev/null +++ b/examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.jsonl @@ -0,0 +1,45 @@ +{"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/multi-turn/stdout.golden.txt b/examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.txt deleted file mode 100644 index 80a6f71aef..0000000000 --- a/examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.txt +++ /dev/null @@ -1,615 +0,0 @@ -{ - "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/session.golden.jsonl b/examples/acp-agent/tests/snapshots/text-turn/session.golden.jsonl new file mode 100644 index 0000000000..a25f008246 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/text-turn/session.golden.jsonl @@ -0,0 +1,35 @@ +{"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.golden.txt b/examples/acp-agent/tests/snapshots/text-turn/session.golden.txt deleted file mode 100644 index c61e27694e..0000000000 --- a/examples/acp-agent/tests/snapshots/text-turn/session.golden.txt +++ /dev/null @@ -1,489 +0,0 @@ -{ - "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/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/text-turn/stdout.golden.jsonl new file mode 100644 index 0000000000..61d0e31953 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/text-turn/stdout.golden.jsonl @@ -0,0 +1,25 @@ +{"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/text-turn/stdout.golden.txt b/examples/acp-agent/tests/snapshots/text-turn/stdout.golden.txt deleted file mode 100644 index be961bc8c9..0000000000 --- a/examples/acp-agent/tests/snapshots/text-turn/stdout.golden.txt +++ /dev/null @@ -1,342 +0,0 @@ -{ - "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/session.golden.jsonl b/examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.jsonl new file mode 100644 index 0000000000..2608bc8f95 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.jsonl @@ -0,0 +1,100 @@ +{"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.golden.txt b/examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.txt deleted file mode 100644 index 87ee87fcc8..0000000000 --- a/examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.txt +++ /dev/null @@ -1,1469 +0,0 @@ -{ - "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/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.jsonl new file mode 100644 index 0000000000..c7169a8d7c --- /dev/null +++ b/examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.jsonl @@ -0,0 +1,51 @@ +{"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"}} 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 deleted file mode 100644 index f5b5cdb3f1..0000000000 --- a/examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.txt +++ /dev/null @@ -1,723 +0,0 @@ -{ - "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" - } -} From 679aaacfc493708694bf28f966bebd15bb082960 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 09:41:10 +0800 Subject: [PATCH 10/13] refactor(examples): DRY the acp-agent configs via base-core.yml + acp-tail.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The snapshot replay config duplicated most of base.yml + the acp tail just to swap llm-deepseek → llm-replay. Factor the shared pieces: - examples/base-core.yml: the providerless provider/tool core (llm, sessions, system-prompt, tools, agents, invariants, bash-local, tool-bash). base.yml is now base-core + the llm-deepseek adapter; the snapshot replay config is base-core + llm-replay. The replay config no longer hand-copies the core. - examples/acp-agent/acp-tail.yml: agent-loop (no pre-created agents) + persistence + the ACP bridge/system-prompt, shared by cordis.yml and the replay config so the three acp-agent configs can't drift. Its persistence root is `$DSH_SNAPSHOT_SESSIONS_ROOT ?? ./.sessions`. - Deleted cordis.snapshot-record.yml: recording now reuses the normal cordis.yml (real adapter), with the harness redirecting the persistence root via env. start.ts maps DSH_SNAPSHOT=record → cordis.yml. Verified: snapshot replay 8/8 keyless; record path works through cordis.yml; ACP e2e no-key boot green through the doubly-nested include (cordis.yml → base.yml → base-core.yml); coding-agent boots clean; all gates pass. --- AGENTS.md | 4 +- .../2026-06-19-acp-snapshot-tests.md | 2 +- examples/acp-agent/acp-tail.yml | 33 +++++++++ examples/acp-agent/cordis.snapshot-record.yml | 43 ------------ examples/acp-agent/cordis.snapshot.yml | 67 +++++-------------- examples/acp-agent/cordis.yml | 41 +++--------- examples/acp-agent/start.ts | 9 ++- examples/base-core.yml | 37 ++++++++++ examples/base.yml | 45 ++++--------- 9 files changed, 117 insertions(+), 164 deletions(-) create mode 100644 examples/acp-agent/acp-tail.yml delete mode 100644 examples/acp-agent/cordis.snapshot-record.yml create mode 100644 examples/base-core.yml diff --git a/AGENTS.md b/AGENTS.md index 8e5fb22a29..84d4297b12 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -41,7 +41,9 @@ examples/ Runnable demos (not workspaces). echo-agent = mock model + echo (pnpm run demo:coding, needs DEEPSEEK_API_KEY). acp-agent = the coding agent exposed as an ACP server over JSON-RPC stdio (pnpm run demo:acp, needs DEEPSEEK_API_KEY). - base.yml = shared provider/tool core both real demos include. + base.yml = shared provider/tool core both real demos include + (= base-core.yml, the providerless core, + the llm-deepseek adapter; + base-core.yml is reused by the acp-agent snapshot-replay config). docs/ architecture.md — the design doc. module-graph.md — generated inter-package dependency graph (Mermaid; `pnpm run gen-module-graph`). rfc/ — design decisions and proposals, one kind of doc grouped by diff --git a/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md b/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md index 470e1baf74..8433e131f2 100644 --- a/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md +++ b/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md @@ -46,7 +46,7 @@ Replay is positional: the Nth `stream()` call serves the Nth `ReplayEntry`. This Recording runs the scenario with the real `llm-deepseek` adapter and the JSONL persistence backend, then copies the produced `.jsonl` into the scenario dir. Per-event appends are durable, but the harness shuts the subprocess down gracefully (close stdin → `await ctx.dispose()`) before harvesting so the final events are flushed. `llm-replay` itself does no recording — it is replay-only. -`examples/base.yml` always loads `@deepseek-ai/dsh-llm-deepseek`, whose `apply` throws when no API key is present ([packages/llm-deepseek/src/index.ts](../../../packages/llm-deepseek/src/index.ts)). So replay cannot reuse the normal config — it uses a dedicated `examples/acp-agent/cordis.snapshot.yml` that omits `llm-deepseek` and installs `llm-replay` in its place. Recording uses a config that loads the real adapter (no `llm-replay`). In replay mode `start.ts` also skips `.env` loading so a stray key cannot trigger a live call. +`examples/base.yml` always loads `@deepseek-ai/dsh-llm-deepseek`, whose `apply` throws when no API key is present ([packages/llm-deepseek/src/index.ts](../../../packages/llm-deepseek/src/index.ts)). So replay cannot reuse the normal config — it uses a dedicated `examples/acp-agent/cordis.snapshot.yml` that installs `llm-replay` in place of the adapter. To avoid duplicating the rest of the tree, the providerless core is factored into `examples/base-core.yml` (shared by `base.yml = base-core + llm-deepseek` and the replay config = `base-core + llm-replay`), and the agent-loop/persistence/ACP-bridge tail into `examples/acp-agent/acp-tail.yml` (shared by `cordis.yml` and the replay config). Recording reuses the normal `cordis.yml` (real adapter) — its persistence root reads `$DSH_SNAPSHOT_SESSIONS_ROOT` when the harness sets it — so there is no separate record config. In replay mode `start.ts` skips `.env` loading so a stray key cannot trigger a live call. ### Two goldens: normalize, then snapshot diff --git a/examples/acp-agent/acp-tail.yml b/examples/acp-agent/acp-tail.yml new file mode 100644 index 0000000000..ce58343add --- /dev/null +++ b/examples/acp-agent/acp-tail.yml @@ -0,0 +1,33 @@ +# The acp-agent "tail" shared by every acp-agent config (the normal demo, the +# snapshot RECORD path which reuses cordis.yml, and the snapshot REPLAY config): +# agent-loop (no pre-created agents — ACP session/new creates them on demand), +# JSONL session persistence, and the ACP bridge with its system prompt. The +# providerless core + an LLM adapter are included BEFORE this tail by each +# config; nothing here loads an adapter, so the tail is provider-agnostic. +# +# Persistence root: $DSH_SNAPSHOT_SESSIONS_ROOT when the snapshot harness sets +# it (so it can harvest / isolate the log), else ./.sessions for the demo. + +- id: agent-loop + name: '@deepseek-ai/dsh-agent-loop' + config: + agents: [] + +- id: session-persistence + name: '@deepseek-ai/dsh-session-persistence-jsonl' + config: + root: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT ?? './.sessions' + +- id: acp + name: '@deepseek-ai/dsh-acp' + config: + model: deepseek-v4-flash + systemPrompt: | + You are a coding assistant driven over the Agent Client Protocol. + + Your only tools are bash (plus bash_output/bash_kill for background + tasks). Do ALL file operations through bash: read with cat/sed/head, + search with grep, write with heredocs (cat <<'EOF' > file), edit with + sed or a rewrite. Each bash call runs in a fresh shell — pass workdir + instead of cd. Check the [exit code: N] marker; verify your work. Keep + answers brief and factual. diff --git a/examples/acp-agent/cordis.snapshot-record.yml b/examples/acp-agent/cordis.snapshot-record.yml deleted file mode 100644 index 7a4a431f0a..0000000000 --- a/examples/acp-agent/cordis.snapshot-record.yml +++ /dev/null @@ -1,43 +0,0 @@ -# Snapshot-test RECORD config: a real run whose persisted session JSONL is -# harvested into a scenario fixture. Identical to cordis.yml (real llm-deepseek -# adapter + JSONL persistence) — recording must exercise the REAL model so the -# recorded log is a genuine product of the system. Needs DEEPSEEK_API_KEY. -# -# It is a separate file (rather than reusing cordis.yml) only so the snapshot -# harness selects it explicitly via $DSH_SNAPSHOT=record and so its persistence -# root can be pointed at the harness's harvest directory by the same env the -# replay path uses. The graceful-shutdown path in start.ts flushes persistence -# before exit so the harvested log is complete. - -- id: timer - name: '@cordisjs/plugin-timer' - -# Shared provider/tool core, INCLUDING the real llm-deepseek adapter. -- id: base - name: '@cordisjs/plugin-include' - config: - path: '../base.yml' - -- id: agent-loop - name: '@deepseek-ai/dsh-agent-loop' - config: - agents: [] - -- id: session-persistence - name: '@deepseek-ai/dsh-session-persistence-jsonl' - config: - root: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT - -- id: acp - name: '@deepseek-ai/dsh-acp' - config: - model: deepseek-v4-flash - systemPrompt: | - You are a coding assistant driven over the Agent Client Protocol. - - Your only tools are bash (plus bash_output/bash_kill for background - tasks). Do ALL file operations through bash: read with cat/sed/head, - search with grep, write with heredocs (cat <<'EOF' > file), edit with - sed or a rewrite. Each bash call runs in a fresh shell — pass workdir - instead of cd. Check the [exit code: N] marker; verify your work. Keep - answers brief and factual. diff --git a/examples/acp-agent/cordis.snapshot.yml b/examples/acp-agent/cordis.snapshot.yml index ed5690db18..2dadd066c4 100644 --- a/examples/acp-agent/cordis.snapshot.yml +++ b/examples/acp-agent/cordis.snapshot.yml @@ -1,10 +1,11 @@ # Snapshot-test REPLAY config: the acp-agent plugin tree with the model replaced # by llm-replay (serves a recorded session JSONL — no API key, no network). # -# This does NOT include ../base.yml: base.yml always loads -# @deepseek-ai/dsh-llm-deepseek, whose apply() throws without DEEPSEEK_API_KEY, -# so a keyless replay run would die at boot. We inline the providerless core -# instead and install llm-replay where the adapter would be. +# It reuses ../base-core.yml (the providerless core) + ./acp-tail.yml (agent- +# loop + persistence + the ACP bridge), the SAME pieces cordis.yml shares — only +# the LLM adapter differs: llm-replay here, llm-deepseek there. It can't reuse +# ../base.yml because that loads llm-deepseek, whose apply() throws without +# DEEPSEEK_API_KEY, killing a keyless replay run at boot. # # stdout is reserved for the ACP JSON-RPC protocol — no stdout logger (see # cordis.yml). The replay fixture path comes from $DSH_SNAPSHOT_FILE (and an @@ -13,57 +14,19 @@ - id: timer name: '@cordisjs/plugin-timer' -# Providerless core (everything base.yml has EXCEPT llm-deepseek). -- id: llm - name: '@deepseek-ai/dsh-llm' - -- id: sessions - name: '@deepseek-ai/dsh-session' - -- id: system-prompt - name: '@deepseek-ai/dsh-system-prompt' - -- id: tools - name: '@deepseek-ai/dsh-tools' - -- id: agents - name: '@deepseek-ai/dsh-agent' - -- id: invariants - name: '@deepseek-ai/dsh-invariants' - -- id: bash - name: '@deepseek-ai/dsh-bash-local' +# Providerless core (everything base.yml has EXCEPT the llm-deepseek adapter). +- id: base-core + name: '@cordisjs/plugin-include' config: - timeoutMs: 60000 + path: '../base-core.yml' -- id: tool-bash - name: '@deepseek-ai/dsh-tool-bash' - -# The replay adapter: short-circuits llm/stream with the recorded log's chunks. +# The replay adapter: short-circuits llm/stream with the recorded log's chunks, +# in place of llm-deepseek. - id: llm-replay name: './src/llm-replay.ts' -- id: agent-loop - name: '@deepseek-ai/dsh-agent-loop' +# agent-loop + persistence + the ACP bridge — shared with cordis.yml. +- id: acp-tail + name: '@cordisjs/plugin-include' config: - agents: [] - -- id: session-persistence - name: '@deepseek-ai/dsh-session-persistence-jsonl' - config: - root: !!js process.env.DSH_SNAPSHOT_SESSIONS_ROOT - -- id: acp - name: '@deepseek-ai/dsh-acp' - config: - model: deepseek-v4-flash - systemPrompt: | - You are a coding assistant driven over the Agent Client Protocol. - - Your only tools are bash (plus bash_output/bash_kill for background - tasks). Do ALL file operations through bash: read with cat/sed/head, - search with grep, write with heredocs (cat <<'EOF' > file), edit with - sed or a rewrite. Each bash call runs in a fresh shell — pass workdir - instead of cd. Check the [exit code: N] marker; verify your work. Keep - answers brief and factual. + path: './acp-tail.yml' diff --git a/examples/acp-agent/cordis.yml b/examples/acp-agent/cordis.yml index b21b661851..384330cc9d 100644 --- a/examples/acp-agent/cordis.yml +++ b/examples/acp-agent/cordis.yml @@ -1,4 +1,6 @@ -# The acp-agent plugin tree, loaded via @cordisjs/plugin-include. +# The acp-agent plugin tree, loaded via @cordisjs/plugin-include. Also the +# snapshot RECORD config (start.ts selects it for DSH_SNAPSHOT=record): a real +# llm-deepseek run whose persisted log the snapshot harness harvests. # # CRITICAL: this example loads NO stdout logger (no @cordisjs/plugin-logger- # console, no stdio-chat). stdout is reserved for the ACP JSON-RPC protocol — @@ -12,38 +14,17 @@ - id: timer name: '@cordisjs/plugin-timer' -# Shared provider/tool core (llm, sessions, system-prompt, tools, agents, -# invariants, llm-deepseek, bash-local, tool-bash). Nested include resolved -# relative to THIS file's directory. +# Shared provider/tool core, INCLUDING the real llm-deepseek adapter. Nested +# include resolved relative to THIS file's directory. - id: base name: '@cordisjs/plugin-include' config: path: '../base.yml' -# agent-loop with NO pre-created agents: ACP `session/new` creates them on -# demand (unlike coding-agent, which pre-creates `main`). -- id: agent-loop - name: '@deepseek-ai/dsh-agent-loop' +# agent-loop (no pre-created agents) + JSONL persistence + the ACP bridge. +# Shared with the snapshot REPLAY config (cordis.snapshot.yml) so the three +# acp-agent configs don't drift. +- id: acp-tail + name: '@cordisjs/plugin-include' config: - agents: [] - -# Durable session persistence — required by the ACP bridge for `session/load`. -- id: session-persistence - name: '@deepseek-ai/dsh-session-persistence-jsonl' - config: - root: './.sessions' - -# The ACP bridge: wires AgentSideConnection to stdin/stdout. -- id: acp - name: '@deepseek-ai/dsh-acp' - config: - model: deepseek-v4-flash - systemPrompt: | - You are a coding assistant driven over the Agent Client Protocol. - - Your only tools are bash (plus bash_output/bash_kill for background - tasks). Do ALL file operations through bash: read with cat/sed/head, - search with grep, write with heredocs (cat <<'EOF' > file), edit with - sed or a rewrite. Each bash call runs in a fresh shell — pass workdir - instead of cd. Check the [exit code: N] marker; verify your work. Keep - answers brief and factual. + path: './acp-tail.yml' diff --git a/examples/acp-agent/start.ts b/examples/acp-agent/start.ts index 028308cb4a..f2ae6f60ba 100644 --- a/examples/acp-agent/start.ts +++ b/examples/acp-agent/start.ts @@ -6,13 +6,12 @@ import Loader from '@cordisjs/plugin-loader' // DSH_SNAPSHOT=replay — load cordis.snapshot.yml (providerless; llm-replay // serves a recorded session log). Skip .env so a stray // key can never trigger a live model call. -// DSH_SNAPSHOT=record — load cordis.snapshot-record.yml (the real adapter + -// persistence) so a real run can be harvested. +// DSH_SNAPSHOT=record — load the normal cordis.yml (the real llm-deepseek +// adapter + persistence) so a real run can be harvested +// (the persistence root is redirected by env). // Absent — the normal demo (cordis.yml), driven by a real editor. const snapshotMode = process.env.DSH_SNAPSHOT -const configPath = snapshotMode === 'replay' ? './cordis.snapshot.yml' - : snapshotMode === 'record' ? './cordis.snapshot-record.yml' - : './cordis.yml' +const configPath = snapshotMode === 'replay' ? './cordis.snapshot.yml' : './cordis.yml' // Load DEEPSEEK_API_KEY / DEEPSEEK_BASE_URL from a gitignored repo-root .env // (Node native). Absent file is fine — the environment may already carry them. diff --git a/examples/base-core.yml b/examples/base-core.yml new file mode 100644 index 0000000000..15282c8ff6 --- /dev/null +++ b/examples/base-core.yml @@ -0,0 +1,37 @@ +# Providerless provider/tool core — everything the model and tools need EXCEPT +# an LLM adapter. Split out of base.yml so two consumers can share it: +# - base.yml = base-core.yml + the real llm-deepseek adapter (the demos). +# - acp-agent/cordis.snapshot.yml = base-core.yml + llm-replay (keyless +# snapshot replay — base.yml can't be reused there because llm-deepseek's +# apply() throws without DEEPSEEK_API_KEY). +# +# Plugin entries use package names (resolved from node_modules), so they are +# insensitive to the baseUrl reset that plugin-include performs per file. + +- id: llm + name: '@deepseek-ai/dsh-llm' + +- id: sessions + name: '@deepseek-ai/dsh-session' + +- id: system-prompt + name: '@deepseek-ai/dsh-system-prompt' + +- id: tools + name: '@deepseek-ai/dsh-tools' + +- id: agents + name: '@deepseek-ai/dsh-agent' + +# Dev-mode event-contract assertions + session-log freeze (off in prod). +- id: invariants + name: '@deepseek-ai/dsh-invariants' + +# Bash execution: the local executor implementation + the tool schemas. +- id: bash + name: '@deepseek-ai/dsh-bash-local' + config: + timeoutMs: 60000 + +- id: tool-bash + name: '@deepseek-ai/dsh-tool-bash' diff --git a/examples/base.yml b/examples/base.yml index 992f6a2c8b..897cef725d 100644 --- a/examples/base.yml +++ b/examples/base.yml @@ -1,7 +1,12 @@ # Shared provider/tool core for the example agents, loaded via a nested -# @cordisjs/plugin-include from each example's cordis.yml. Contains everything -# the model and tools need; each example adds its own infra (logger/timer/hmr), -# its agent-loop config (the examples disagree — see below), and its UI plugin. +# @cordisjs/plugin-include from each example's cordis.yml. This is +# base-core.yml (the providerless core: llm, sessions, system-prompt, tools, +# agents, invariants, bash-local, tool-bash) PLUS the real llm-deepseek adapter. +# +# The providerless core lives in base-core.yml so the keyless snapshot-replay +# config (acp-agent/cordis.snapshot.yml) can reuse it with llm-replay in place +# of the adapter — it can't reuse THIS file, because llm-deepseek's apply() +# throws without DEEPSEEK_API_KEY. # # Deliberately EXCLUDES: # - the console logger: it writes to stdout, which the acp-agent reserves for @@ -12,28 +17,13 @@ # pre-create NONE (ACP session/new creates agents on demand). So each example # declares agent-loop with its own `agents` list. # -# Plugin entries here use package names (resolved from node_modules), so they -# are insensitive to the baseUrl reset that plugin-include performs per file. # Requires DEEPSEEK_API_KEY (and optionally DEEPSEEK_BASE_URL) in the env. -- id: llm - name: '@deepseek-ai/dsh-llm' - -- id: sessions - name: '@deepseek-ai/dsh-session' - -- id: system-prompt - name: '@deepseek-ai/dsh-system-prompt' - -- id: tools - name: '@deepseek-ai/dsh-tools' - -- id: agents - name: '@deepseek-ai/dsh-agent' - -# Dev-mode event-contract assertions + session-log freeze (off in prod). -- id: invariants - name: '@deepseek-ai/dsh-invariants' +# The providerless core (resolved relative to THIS file's directory). +- id: base-core + name: '@cordisjs/plugin-include' + config: + path: './base-core.yml' # The DeepSeek adapter. Swap to '@deepseek-ai/dsh-llm-pi-ai' for the pi-ai-backed # twin (same config shape; `reasoning: high` replaces thinking/reasoningEffort). @@ -45,12 +35,3 @@ models: - deepseek-v4-flash - deepseek-v4-pro - -# Bash execution: the local executor implementation + the tool schemas. -- id: bash - name: '@deepseek-ai/dsh-bash-local' - config: - timeoutMs: 60000 - -- id: tool-bash - name: '@deepseek-ai/dsh-tool-bash' From 76fceae5b361a198af222374eedcbdb26670a474 Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 10:01:42 +0800 Subject: [PATCH 11/13] feat(acp-example): per-scenario workspace/ seeding + a real file-edit scenario MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Establishes the standard way to give a snapshot scenario a non-empty starting workspace: an optional `/workspace/` directory whose contents the harness copies into the temp cwd before the run (for both record and replay), so the agent's bash tools see the seeded files. The cwd is normalized in the goldens, so seeded paths stay stable. The new `workspace-edit` scenario demonstrates the full read→write→verify cycle on a seeded file: it ships `workspace/greeting.txt` ("hello"), prompts the agent to append a WORLD line and cat it back. The recorded log captures the real bash edits (`echo WORLD >> greeting.txt`, then `cat` showing `hello\nWORLD`), and it replays deterministically with no key. Also hardens runScenario teardown (Codex review): workspace seeding and spawn now run inside the try whose finally removes both temp dirs, so a seeding/spawn failure can't leak them. Documents the convention in the RFC + example README. --- .../2026-06-19-acp-snapshot-tests.md | 2 +- examples/acp-agent/README.md | 2 +- examples/acp-agent/tests/acp.snapshot.ts | 3 + examples/acp-agent/tests/snapshot-harness.ts | 145 ++++---- .../tests/snapshots/workspace-edit/input.json | 7 + .../workspace-edit/session.golden.jsonl | 331 ++++++++++++++++++ .../snapshots/workspace-edit/session.jsonl | 331 ++++++++++++++++++ .../workspace-edit/stdout.golden.jsonl | 215 ++++++++++++ .../workspace-edit/workspace/greeting.txt | 1 + 9 files changed, 972 insertions(+), 65 deletions(-) create mode 100644 examples/acp-agent/tests/snapshots/workspace-edit/input.json create mode 100644 examples/acp-agent/tests/snapshots/workspace-edit/session.golden.jsonl create mode 100644 examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl create mode 100644 examples/acp-agent/tests/snapshots/workspace-edit/stdout.golden.jsonl create mode 100644 examples/acp-agent/tests/snapshots/workspace-edit/workspace/greeting.txt diff --git a/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md b/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md index 8433e131f2..5a0bdac0b2 100644 --- a/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md +++ b/docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md @@ -74,6 +74,6 @@ The replay plugin lives at `examples/acp-agent/src/llm-replay.ts`, referenced fr ## Consequences -A new test tier and its fixtures to maintain: each scenario is a directory of `input.json` (the client stdin script) + `session.jsonl` (the recorded log) + an optional `replay.override.json` + the two `*.golden` files, committed and reviewed. Re-recording when the model's phrasing changes churns the goldens — visible in review, which is the point of committing them. Bought: deterministic, keyless, full-transcript regression coverage that boots the real Loader (so it still guards the export-shape bug class), exercises the real bash executor, and gives a one-command accept-the-diff loop. The tier is ACP-first but the harness (subprocess + tee + input-DSL + normalization + JSONL-derived replay) is example-agnostic and extends to other examples. +A new test tier and its fixtures to maintain: each scenario is a directory of `input.json` (the client stdin script) + `session.jsonl` (the recorded log) + an optional `replay.override.json` + an optional `workspace/` seed dir + the two `*.golden.jsonl` files, committed and reviewed. A scenario that needs the agent to operate on existing files (read, edit, grep) ships a `/workspace/` directory; the harness copies its contents into the temp cwd before the run, so the seeded files are present for both record and replay (the cwd is normalized in the goldens, so the seeded paths stay stable). Re-recording when the model's phrasing changes churns the goldens — visible in review, which is the point of committing them. Bought: deterministic, keyless, full-transcript regression coverage that boots the real Loader (so it still guards the export-shape bug class), exercises the real bash executor, and gives a one-command accept-the-diff loop. The tier is ACP-first but the harness (subprocess + tee + input-DSL + workspace seeding + normalization + JSONL-derived replay) is example-agnostic and extends to other examples. This RFC relates to but does not supersede the [proposed determinism RFC](../proposed/2026-06-11-deterministic-and-stress-testing.md): that proposal's "universal replay fixture" re-derives session *message history* after every test (an internal-consistency invariant), whereas snapshot tests pin the *external protocol output*. They are complementary — one guards the event-sourcing invariant, the other guards the editor-facing contract. diff --git a/examples/acp-agent/README.md b/examples/acp-agent/README.md index a2436dbf33..51d3f22414 100644 --- a/examples/acp-agent/README.md +++ b/examples/acp-agent/README.md @@ -32,7 +32,7 @@ The editor sets each session's `cwd` to the project it opens; the agent's bash t ## Snapshot tests (record-once / replay-deterministic) -This example is the home of the harness's **snapshot tests** — they boot this server as a real subprocess, drive it with a deterministic input script, and diff its normalized output against committed golden files. The model is made deterministic by `src/llm-replay.ts`, a function/namespace plugin that installs an `llm/stream` waterfall listener and short-circuits it, serving model streams reconstructed from a recorded **session JSONL** fixture (`/session.jsonl`) — so replay needs no API key. The fixture IS the persisted session log: its `assistant/chunk` events carry every `StreamChunk`, so grouping them by `(turn, step)` reconstructs each `stream()` call (one model call per loop step). Recording is therefore "run the real agent once and harvest the `.jsonl`". The two failure modes not expressible as logged chunks — a pure throw before any chunk, and cancel/hang — use an optional `/replay.override.json` sidecar (a `ReplayEntry[]` that replaces the derived script). See [docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md](../../docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md) for the full design. +This example is the home of the harness's **snapshot tests** — they boot this server as a real subprocess, drive it with a deterministic input script, and diff its normalized output against committed golden files. The model is made deterministic by `src/llm-replay.ts`, a function/namespace plugin that installs an `llm/stream` waterfall listener and short-circuits it, serving model streams reconstructed from a recorded **session JSONL** fixture (`/session.jsonl`) — so replay needs no API key. The fixture IS the persisted session log: its `assistant/chunk` events carry every `StreamChunk`, so grouping them by `(turn, step)` reconstructs each `stream()` call (one model call per loop step). Recording is therefore "run the real agent once and harvest the `.jsonl`". The two failure modes not expressible as logged chunks — a pure throw before any chunk, and cancel/hang — use an optional `/replay.override.json` sidecar (a `ReplayEntry[]` that replaces the derived script). A scenario that needs the agent to operate on existing files ships an optional `/workspace/` directory — the harness copies its contents into the temp cwd before the run (see `workspace-edit`). See [docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md](../../docs/rfc/implemented/2026-06-19-acp-snapshot-tests.md) for the full design. ## MVP limitations diff --git a/examples/acp-agent/tests/acp.snapshot.ts b/examples/acp-agent/tests/acp.snapshot.ts index 08a3f5ccc0..582df37b82 100644 --- a/examples/acp-agent/tests/acp.snapshot.ts +++ b/examples/acp-agent/tests/acp.snapshot.ts @@ -39,6 +39,7 @@ const SCENARIOS: Scenario[] = [ { name: 'handshake', hasModelTurn: false, recorded: false }, { name: 'text-turn', hasModelTurn: true, recorded: true }, { name: 'tool-call-turn', hasModelTurn: true, recorded: true }, + { name: 'workspace-edit', hasModelTurn: true, recorded: true }, { name: 'multi-turn', hasModelTurn: true, recorded: true }, { name: 'error-finish', hasModelTurn: true, recorded: false }, { name: 'cancel', hasModelTurn: true, recorded: false }, @@ -52,10 +53,12 @@ for (const scenario of SCENARIOS) { 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') + const workspaceDir = join(dir, 'workspace') const result = await runScenario(input, { mode: RECORDING ? 'record' : 'replay', fixtureFile: join(dir, 'session.jsonl'), ...existsSync(overrideFile) ? { overrideFile } : {}, + ...existsSync(workspaceDir) ? { workspaceDir } : {}, }) const ctx: NormalizeContext = { diff --git a/examples/acp-agent/tests/snapshot-harness.ts b/examples/acp-agent/tests/snapshot-harness.ts index a13cb3a5a5..de05c8ca98 100644 --- a/examples/acp-agent/tests/snapshot-harness.ts +++ b/examples/acp-agent/tests/snapshot-harness.ts @@ -14,7 +14,8 @@ */ import { spawn, type ChildProcessWithoutNullStreams } from 'node:child_process' -import { mkdtemp, readFile, readdir, rm } from 'node:fs/promises' +import { cp, mkdtemp, readFile, readdir, rm } from 'node:fs/promises' +import { existsSync } from 'node:fs' import { tmpdir } from 'node:os' import { join } from 'node:path' import { fileURLToPath } from 'node:url' @@ -85,6 +86,13 @@ interface RunOptions { fixtureFile: string /** Optional sidecar override path (replay). */ overrideFile?: string + /** + * Optional `/workspace/` directory whose contents are copied into + * the temp cwd BEFORE the run — the standard way to seed files the agent + * operates on (a file to read, edit, or grep). Absent for scenarios that + * start from an empty workspace. + */ + workspaceDir?: string } /** @@ -95,69 +103,79 @@ interface RunOptions { export async function runScenario(input: InputScript, opts: RunOptions): Promise { const cwd = await mkdtemp(join(tmpdir(), 'acp-snap-cwd-')) const sessionsRoot = await mkdtemp(join(tmpdir(), 'acp-snap-sessions-')) - const env: NodeJS.ProcessEnv = { - ...process.env, - TSX_TSCONFIG_PATH: repoTsconfig, - DSH_SNAPSHOT: opts.mode, - DSH_SNAPSHOT_FILE: opts.fixtureFile, - DSH_SNAPSHOT_SESSIONS_ROOT: sessionsRoot, - ...opts.overrideFile !== undefined ? { DSH_SNAPSHOT_OVERRIDE: opts.overrideFile } : {}, - } - - const child: ChildProcessWithoutNullStreams = spawn( - process.execPath, - ['--import', tsxLoader, startScript], - { cwd, env, stdio: ['pipe', 'pipe', 'pipe'] }, - ) - - const rawBuffers: Buffer[] = [] - const stderrChunks: string[] = [] - child.stderr.setEncoding('utf8') - child.stderr.on('data', (c: string) => stderrChunks.push(c)) - - // Tee raw stdout: accumulate the bytes for the golden + purity check, and ALSO - // feed the same bytes to the SDK client through a passthrough. Buffer the raw - // bytes (not per-chunk utf8 strings) and decode once at the end, so a - // multibyte sequence split across two 'data' events can't corrupt the golden. - const passthrough = new Readable({ read() {} }) - child.stdout.on('data', (buf: Buffer) => { - rawBuffers.push(buf) - passthrough.push(buf) - }) - child.stdout.on('end', () => passthrough.push(null)) - - const stream = ndJsonStream( - 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 { - 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 { - return Promise.resolve({ outcome: { outcome: 'cancelled' } }) - }, - }) - const client = new ClientSideConnection(makeClient, stream) - + // Everything past the temp-dir creation runs under a try/finally that always + // removes both dirs — so a failure in workspace seeding, spawn, or any step + // never leaks them (the "e2e tests own their resources" rule). + let child: ChildProcessWithoutNullStreams | undefined let sessionId: string | undefined let sessionLog: string | undefined + const rawBuffers: Buffer[] = [] + const stderrChunks: string[] = [] try { + // Seed the workspace if the scenario ships one (a file the agent reads/edits). + // Copied into the temp cwd so the agent's bash tools see it; the goldens + // normalize the cwd, so the seeded paths stay stable across runs. + if (opts.workspaceDir !== undefined && existsSync(opts.workspaceDir)) { + await cp(opts.workspaceDir, cwd, { recursive: true }) + } + const env: NodeJS.ProcessEnv = { + ...process.env, + TSX_TSCONFIG_PATH: repoTsconfig, + DSH_SNAPSHOT: opts.mode, + DSH_SNAPSHOT_FILE: opts.fixtureFile, + DSH_SNAPSHOT_SESSIONS_ROOT: sessionsRoot, + ...opts.overrideFile !== undefined ? { DSH_SNAPSHOT_OVERRIDE: opts.overrideFile } : {}, + } + + child = spawn( + process.execPath, + ['--import', tsxLoader, startScript], + { cwd, env, stdio: ['pipe', 'pipe', 'pipe'] }, + ) + + child.stderr.setEncoding('utf8') + child.stderr.on('data', (c: string) => stderrChunks.push(c)) + + // Tee raw stdout: accumulate the bytes for the golden + purity check, and ALSO + // feed the same bytes to the SDK client through a passthrough. Buffer the raw + // bytes (not per-chunk utf8 strings) and decode once at the end, so a + // multibyte sequence split across two 'data' events can't corrupt the golden. + const passthrough = new Readable({ read() {} }) + child.stdout.on('data', (buf: Buffer) => { + rawBuffers.push(buf) + passthrough.push(buf) + }) + child.stdout.on('end', () => passthrough.push(null)) + + const stream = ndJsonStream( + 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 { + 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 { + return Promise.resolve({ outcome: { outcome: 'cancelled' } }) + }, + }) + const client = new ClientSideConnection(makeClient, stream) + for (const step of input.steps) { await runStep(client, step, cwd, waitForUpdate, () => sessionId, (id) => { sessionId = id }) } @@ -170,8 +188,9 @@ export async function runScenario(input: InputScript, opts: RunOptions): Promise if (sessionLogPath !== undefined) sessionLog = await readFile(sessionLogPath, 'utf8') } finally { // Failure-safe teardown: kill a still-running child and drop the temp dirs - // even if a step/harvest threw, so a flaky run never leaks a process or dir. - if (child.exitCode === null && child.signalCode === null) { + // even if seeding/spawn/a step/harvest threw, so a flaky run never leaks a + // process or dir. `child` is undefined only if spawn itself threw. + if (child !== undefined && child.exitCode === null && child.signalCode === null) { child.kill('SIGKILL') await waitForExit(child) } diff --git a/examples/acp-agent/tests/snapshots/workspace-edit/input.json b/examples/acp-agent/tests/snapshots/workspace-edit/input.json new file mode 100644 index 0000000000..30d61b908a --- /dev/null +++ b/examples/acp-agent/tests/snapshots/workspace-edit/input.json @@ -0,0 +1,7 @@ +{ + "steps": [ + { "op": "initialize" }, + { "op": "newSession" }, + { "op": "prompt", "text": "A file named greeting.txt in the current directory contains one word. Use the bash tool to append a second line containing the word WORLD to it (so it has two lines), then read the file back with `cat greeting.txt` to confirm, and reply with the single word DONE. Use a single bash call per action." } + ] +} diff --git a/examples/acp-agent/tests/snapshots/workspace-edit/session.golden.jsonl b/examples/acp-agent/tests/snapshots/workspace-edit/session.golden.jsonl new file mode 100644 index 0000000000..013df575dc --- /dev/null +++ b/examples/acp-agent/tests/snapshots/workspace-edit/session.golden.jsonl @@ -0,0 +1,331 @@ +{"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":"A file named greeting.txt in the current directory contains one word. Use the bash tool to append a second line containing the word WORLD to it (so it has two lines), then read the file back with `cat greeting.txt` to confirm, and reply with the single word DONE. Use a single bash call per action."}],"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":"Let"}}} +{"type":"assistant/chunk","seq":5,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":6,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" break"}}} +{"type":"assistant/chunk","seq":7,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" this"}}} +{"type":"assistant/chunk","seq":8,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" down"}}} +{"type":"assistant/chunk","seq":9,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" into"}}} +{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" steps"}}} +{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":\n"}}} +{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"1"}}} +{"type":"assistant/chunk","seq":13,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":14,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" First"}}} +{"type":"assistant/chunk","seq":15,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} +{"type":"assistant/chunk","seq":16,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} +{"type":"assistant/chunk","seq":17,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":18,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":19,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":20,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" see"}}} +{"type":"assistant/chunk","seq":21,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" what"}}} +{"type":"assistant/chunk","seq":22,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"'s"}}} +{"type":"assistant/chunk","seq":23,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" in"}}} +{"type":"assistant/chunk","seq":24,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} +{"type":"assistant/chunk","seq":25,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":26,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"2"}}} +{"type":"assistant/chunk","seq":27,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":28,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Then"}}} +{"type":"assistant/chunk","seq":29,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} +{"type":"assistant/chunk","seq":30,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":31,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} +{"type":"assistant/chunk","seq":32,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} +{"type":"assistant/chunk","seq":33,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":34,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" as"}}} +{"type":"assistant/chunk","seq":35,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":36,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" second"}}} +{"type":"assistant/chunk","seq":37,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" line"}}} +{"type":"assistant/chunk","seq":38,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":39,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"3"}}} +{"type":"assistant/chunk","seq":40,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":41,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Then"}}} +{"type":"assistant/chunk","seq":42,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} +{"type":"assistant/chunk","seq":43,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} +{"type":"assistant/chunk","seq":44,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" back"}}} +{"type":"assistant/chunk","seq":45,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":46,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} +{"type":"assistant/chunk","seq":47,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n\n"}}} +{"type":"assistant/chunk","seq":48,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Wait"}}} +{"type":"assistant/chunk","seq":49,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} +{"type":"assistant/chunk","seq":50,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":51,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" instruction"}}} +{"type":"assistant/chunk","seq":52,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" says"}}} +{"type":"assistant/chunk","seq":53,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":54,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Use"}}} +{"type":"assistant/chunk","seq":55,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":56,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}} +{"type":"assistant/chunk","seq":57,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":58,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":59,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" per"}}} +{"type":"assistant/chunk","seq":60,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} +{"type":"assistant/chunk","seq":61,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":62,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" -"}}} +{"type":"assistant/chunk","seq":63,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" but"}}} +{"type":"assistant/chunk","seq":64,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":65,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" need"}}} +{"type":"assistant/chunk","seq":66,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":67,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} +{"type":"assistant/chunk","seq":68,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" multiple"}}} +{"type":"assistant/chunk","seq":69,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" actions"}}} +{"type":"assistant/chunk","seq":70,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":71,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Let"}}} +{"type":"assistant/chunk","seq":72,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":73,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" re"}}} +{"type":"assistant/chunk","seq":74,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"-read"}}} +{"type":"assistant/chunk","seq":75,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".\n\n"}}} +{"type":"assistant/chunk","seq":76,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":77,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Use"}}} +{"type":"assistant/chunk","seq":78,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":79,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}} +{"type":"assistant/chunk","seq":80,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":81,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":82,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" per"}}} +{"type":"assistant/chunk","seq":83,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} +{"type":"assistant/chunk","seq":84,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":85,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" -"}}} +{"type":"assistant/chunk","seq":86,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":87,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" think"}}} +{"type":"assistant/chunk","seq":88,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" this"}}} +{"type":"assistant/chunk","seq":89,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" means"}}} +{"type":"assistant/chunk","seq":90,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" each"}}} +{"type":"assistant/chunk","seq":91,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} +{"type":"assistant/chunk","seq":92,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" should"}}} +{"type":"assistant/chunk","seq":93,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" be"}}} +{"type":"assistant/chunk","seq":94,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":95,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" separate"}}} +{"type":"assistant/chunk","seq":96,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":97,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":98,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} +{"type":"assistant/chunk","seq":99,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" not"}}} +{"type":"assistant/chunk","seq":100,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" one"}}} +{"type":"assistant/chunk","seq":101,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" big"}}} +{"type":"assistant/chunk","seq":102,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":103,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":104,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".\n\n"}}} +{"type":"assistant/chunk","seq":105,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Let"}}} +{"type":"assistant/chunk","seq":106,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":107,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} +{"type":"assistant/chunk","seq":108,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":\n"}}} +{"type":"assistant/chunk","seq":109,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"1"}}} +{"type":"assistant/chunk","seq":110,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":111,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" First"}}} +{"type":"assistant/chunk","seq":112,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":113,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":114,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} +{"type":"assistant/chunk","seq":115,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} +{"type":"assistant/chunk","seq":116,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":117,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":118,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":119,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" see"}}} +{"type":"assistant/chunk","seq":120,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":121,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" current"}}} +{"type":"assistant/chunk","seq":122,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" content"}}} +{"type":"assistant/chunk","seq":123,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":124,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"2"}}} +{"type":"assistant/chunk","seq":125,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":126,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Second"}}} +{"type":"assistant/chunk","seq":127,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":128,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":129,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} +{"type":"assistant/chunk","seq":130,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} +{"type":"assistant/chunk","seq":131,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":132,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} +{"type":"assistant/chunk","seq":133,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} +{"type":"assistant/chunk","seq":134,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":135,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":136,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":137,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":138,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":139,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"3"}}} +{"type":"assistant/chunk","seq":140,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":141,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Third"}}} +{"type":"assistant/chunk","seq":142,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":143,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":144,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} +{"type":"assistant/chunk","seq":145,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} +{"type":"assistant/chunk","seq":146,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":147,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":148,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":149,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" confirm"}}} +{"type":"assistant/chunk","seq":150,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n\n"}}} +{"type":"assistant/chunk","seq":151,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Actually"}}} +{"type":"assistant/chunk","seq":152,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} +{"type":"assistant/chunk","seq":153,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" let"}}} +{"type":"assistant/chunk","seq":154,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":155,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" just"}}} +{"type":"assistant/chunk","seq":156,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} +{"type":"assistant/chunk","seq":157,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} +{"type":"assistant/chunk","seq":158,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" step"}}} +{"type":"assistant/chunk","seq":159,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" by"}}} +{"type":"assistant/chunk","seq":160,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" step"}}} +{"type":"assistant/chunk","seq":161,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":162,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":163,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":164,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":165,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":166,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":167,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":168,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":169,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":170,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"cat"}}} +{"type":"assistant/chunk","seq":171,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":172,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":173,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":174,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":175,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":176,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":177,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":178,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":179,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":180,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"Read"}}} +{"type":"assistant/chunk","seq":181,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" current"}}} +{"type":"assistant/chunk","seq":182,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" content"}}} +{"type":"assistant/chunk","seq":183,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" of"}}} +{"type":"assistant/chunk","seq":184,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":185,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":186,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":187,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":188,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Let me break this down into steps:\n1. First, read the file to see what's in it\n2. Then append \"WORLD\" as a second line\n3. Then read it back with cat\n\nWait, the instruction says \"Use a single bash call per action\" - but I need to do multiple actions. Let me re-read.\n\n\"Use a single bash call per action\" - I think this means each action should be a separate bash call, not one big bash call.\n\nLet me do:\n1. First bash call: read the file to see the current content\n2. Second bash call: append \"WORLD\" to the file\n3. Third bash call: cat the file to confirm\n\nActually, let me just do it step by step."}}}} +{"type":"assistant/chunk","seq":189,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}}}} +{"type":"assistant/chunk","seq":190,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":168,"outputTokens":224,"cacheReadTokens":768,"reasoningTokens":158}}}} +{"type":"assistant/chunk","seq":191,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":192,"time":0,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"Let me break this down into steps:\n1. First, read the file to see what's in it\n2. Then append \"WORLD\" as a second line\n3. Then read it back with cat\n\nWait, the instruction says \"Use a single bash call per action\" - but I need to do multiple actions. Let me re-read.\n\n\"Use a single bash call per action\" - I think this means each action should be a separate bash call, not one big bash call.\n\nLet me do:\n1. First bash call: read the file to see the current content\n2. Second bash call: append \"WORLD\" to the file\n3. Third bash call: cat the file to confirm\n\nActually, let me just do it step by step."},{"type":"tool-call","id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}]}} +{"type":"usage","seq":193,"time":0,"data":{"turn":1,"step":1,"usage":{"inputTokens":168,"outputTokens":224,"cacheReadTokens":768,"reasoningTokens":158}}} +{"type":"tool/call","seq":194,"time":0,"data":{"turn":1,"step":1,"callId":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}} +{"type":"tool/result","seq":195,"time":0,"data":{"turn":1,"step":1,"callId":"call_00_J7zkTYNbCxhU7s0fIfIq4165","content":[{"type":"text","text":"hello\n"}],"isError":false}} +{"type":"step/end","seq":196,"time":0,"data":{"turn":1,"step":1}} +{"type":"step/start","seq":197,"time":0,"data":{"turn":1,"step":2}} +{"type":"assistant/chunk","seq":198,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":199,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":200,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":201,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" contains"}}} +{"type":"assistant/chunk","seq":202,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":203,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"hello"}}} +{"type":"assistant/chunk","seq":204,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":205,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" Now"}}} +{"type":"assistant/chunk","seq":206,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":207,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" need"}}} +{"type":"assistant/chunk","seq":208,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":209,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} +{"type":"assistant/chunk","seq":210,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":211,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} +{"type":"assistant/chunk","seq":212,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} +{"type":"assistant/chunk","seq":213,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":214,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" as"}}} +{"type":"assistant/chunk","seq":215,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":216,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" second"}}} +{"type":"assistant/chunk","seq":217,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" line"}}} +{"type":"assistant/chunk","seq":218,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":219,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":220,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":221,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":222,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":223,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":224,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":225,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":226,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":227,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"App"}}} +{"type":"assistant/chunk","seq":228,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"end"}}} +{"type":"assistant/chunk","seq":229,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" WORLD"}}} +{"type":"assistant/chunk","seq":230,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" as"}}} +{"type":"assistant/chunk","seq":231,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" second"}}} +{"type":"assistant/chunk","seq":232,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" line"}}} +{"type":"assistant/chunk","seq":233,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":234,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":235,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":236,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":237,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":238,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":239,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":240,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"echo"}}} +{"type":"assistant/chunk","seq":241,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" WORLD"}}} +{"type":"assistant/chunk","seq":242,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" >>"}}} +{"type":"assistant/chunk","seq":243,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":244,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":245,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":246,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":247,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The file contains \"hello\". Now I need to append \"WORLD\" as a second line."}}}} +{"type":"assistant/chunk","seq":248,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}}}} +{"type":"assistant/chunk","seq":249,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":278,"outputTokens":88,"cacheReadTokens":896,"reasoningTokens":20}}}} +{"type":"assistant/chunk","seq":250,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":251,"time":0,"data":{"turn":1,"step":2,"content":[{"type":"reasoning","text":"The file contains \"hello\". Now I need to append \"WORLD\" as a second line."},{"type":"tool-call","id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}]}} +{"type":"usage","seq":252,"time":0,"data":{"turn":1,"step":2,"usage":{"inputTokens":278,"outputTokens":88,"cacheReadTokens":896,"reasoningTokens":20}}} +{"type":"tool/call","seq":253,"time":0,"data":{"turn":1,"step":2,"callId":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}} +{"type":"tool/result","seq":254,"time":0,"data":{"turn":1,"step":2,"callId":"call_00_r6yugViLOxPuocpIvXrQ5342","content":[{"type":"text","text":"(no output)"}],"isError":false}} +{"type":"step/end","seq":255,"time":0,"data":{"turn":1,"step":2}} +{"type":"step/start","seq":256,"time":0,"data":{"turn":1,"step":3}} +{"type":"assistant/chunk","seq":257,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":258,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"Now"}}} +{"type":"assistant/chunk","seq":259,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" confirm"}}} +{"type":"assistant/chunk","seq":260,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":261,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} +{"type":"assistant/chunk","seq":262,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":263,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":264,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":265,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":266,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":267,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":268,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":269,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":270,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":271,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"Confirm"}}} +{"type":"assistant/chunk","seq":272,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" file"}}} +{"type":"assistant/chunk","seq":273,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" content"}}} +{"type":"assistant/chunk","seq":274,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" with"}}} +{"type":"assistant/chunk","seq":275,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" cat"}}} +{"type":"assistant/chunk","seq":276,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":277,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":278,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":279,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":280,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":281,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":282,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":283,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"cat"}}} +{"type":"assistant/chunk","seq":284,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":285,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":286,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":287,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":288,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Now confirm with cat."}}}} +{"type":"assistant/chunk","seq":289,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}}}} +{"type":"assistant/chunk","seq":290,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":124,"outputTokens":70,"cacheReadTokens":1152,"reasoningTokens":5}}}} +{"type":"assistant/chunk","seq":291,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":292,"time":0,"data":{"turn":1,"step":3,"content":[{"type":"reasoning","text":"Now confirm with cat."},{"type":"tool-call","id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}]}} +{"type":"usage","seq":293,"time":0,"data":{"turn":1,"step":3,"usage":{"inputTokens":124,"outputTokens":70,"cacheReadTokens":1152,"reasoningTokens":5}}} +{"type":"tool/call","seq":294,"time":0,"data":{"turn":1,"step":3,"callId":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}} +{"type":"tool/result","seq":295,"time":0,"data":{"turn":1,"step":3,"callId":"call_00_SC1arlNU29Vn38HnR4Kp9691","content":[{"type":"text","text":"hello\nWORLD\n"}],"isError":false}} +{"type":"step/end","seq":296,"time":0,"data":{"turn":1,"step":3}} +{"type":"step/start","seq":297,"time":0,"data":{"turn":1,"step":4}} +{"type":"assistant/chunk","seq":298,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":299,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":300,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":301,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" now"}}} +{"type":"assistant/chunk","seq":302,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" has"}}} +{"type":"assistant/chunk","seq":303,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" two"}}} +{"type":"assistant/chunk","seq":304,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" lines"}}} +{"type":"assistant/chunk","seq":305,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} +{"type":"assistant/chunk","seq":306,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":307,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"hello"}}} +{"type":"assistant/chunk","seq":308,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":309,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":310,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":311,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} +{"type":"assistant/chunk","seq":312,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} +{"type":"assistant/chunk","seq":313,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":314,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" The"}}} +{"type":"assistant/chunk","seq":315,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" task"}}} +{"type":"assistant/chunk","seq":316,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" is"}}} +{"type":"assistant/chunk","seq":317,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" complete"}}} +{"type":"assistant/chunk","seq":318,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":319,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":320,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"text-delta","index":1,"text":"D"}}} +{"type":"assistant/chunk","seq":321,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} +{"type":"assistant/chunk","seq":322,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The file now has two lines: \"hello\" and \"WORLD\". The task is complete."}}}} +{"type":"assistant/chunk","seq":323,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}}} +{"type":"assistant/chunk","seq":324,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"usage","usage":{"inputTokens":211,"outputTokens":23,"cacheReadTokens":1152,"reasoningTokens":20}}}} +{"type":"assistant/chunk","seq":325,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":326,"time":0,"data":{"turn":1,"step":4,"content":[{"type":"reasoning","text":"The file now has two lines: \"hello\" and \"WORLD\". The task is complete."},{"type":"text","text":"DONE"}]}} +{"type":"usage","seq":327,"time":0,"data":{"turn":1,"step":4,"usage":{"inputTokens":211,"outputTokens":23,"cacheReadTokens":1152,"reasoningTokens":20}}} +{"type":"step/end","seq":328,"time":0,"data":{"turn":1,"step":4}} +{"type":"turn/end","seq":329,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl b/examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl new file mode 100644 index 0000000000..0062a9e77c --- /dev/null +++ b/examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl @@ -0,0 +1,331 @@ +{"type":"session","version":1,"id":"9beaf658-0308-440c-b83e-51a82666d594","createdAt":1781834404758,"cwd":"/tmp/acp-snap-cwd-rRY3xl"} +{"type":"turn/start","seq":0,"time":1781834404760,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}} +{"type":"user/message","seq":1,"time":1781834404761,"data":{"content":[{"type":"text","text":"A file named greeting.txt in the current directory contains one word. Use the bash tool to append a second line containing the word WORLD to it (so it has two lines), then read the file back with `cat greeting.txt` to confirm, and reply with the single word DONE. Use a single bash call per action."}],"source":{"kind":"user"}}} +{"type":"step/start","seq":2,"time":1781834404761,"data":{"turn":1,"step":1}} +{"type":"assistant/chunk","seq":3,"time":1781834405182,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":4,"time":1781834405182,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Let"}}} +{"type":"assistant/chunk","seq":5,"time":1781834405277,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":6,"time":1781834405305,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" break"}}} +{"type":"assistant/chunk","seq":7,"time":1781834405305,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" this"}}} +{"type":"assistant/chunk","seq":8,"time":1781834405305,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" down"}}} +{"type":"assistant/chunk","seq":9,"time":1781834405333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" into"}}} +{"type":"assistant/chunk","seq":10,"time":1781834405334,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" steps"}}} +{"type":"assistant/chunk","seq":11,"time":1781834405362,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":\n"}}} +{"type":"assistant/chunk","seq":12,"time":1781834405362,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"1"}}} +{"type":"assistant/chunk","seq":13,"time":1781834405362,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":14,"time":1781834405363,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" First"}}} +{"type":"assistant/chunk","seq":15,"time":1781834405363,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} +{"type":"assistant/chunk","seq":16,"time":1781834405396,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} +{"type":"assistant/chunk","seq":17,"time":1781834405419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":18,"time":1781834405419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":19,"time":1781834405419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":20,"time":1781834405419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" see"}}} +{"type":"assistant/chunk","seq":21,"time":1781834405447,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" what"}}} +{"type":"assistant/chunk","seq":22,"time":1781834405448,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"'s"}}} +{"type":"assistant/chunk","seq":23,"time":1781834405448,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" in"}}} +{"type":"assistant/chunk","seq":24,"time":1781834405448,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} +{"type":"assistant/chunk","seq":25,"time":1781834405477,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":26,"time":1781834405477,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"2"}}} +{"type":"assistant/chunk","seq":27,"time":1781834405478,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":28,"time":1781834405478,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Then"}}} +{"type":"assistant/chunk","seq":29,"time":1781834405505,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} +{"type":"assistant/chunk","seq":30,"time":1781834405506,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":31,"time":1781834405534,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} +{"type":"assistant/chunk","seq":32,"time":1781834405535,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} +{"type":"assistant/chunk","seq":33,"time":1781834405535,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":34,"time":1781834405535,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" as"}}} +{"type":"assistant/chunk","seq":35,"time":1781834405562,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":36,"time":1781834405563,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" second"}}} +{"type":"assistant/chunk","seq":37,"time":1781834405591,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" line"}}} +{"type":"assistant/chunk","seq":38,"time":1781834405591,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":39,"time":1781834405592,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"3"}}} +{"type":"assistant/chunk","seq":40,"time":1781834405592,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":41,"time":1781834405592,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Then"}}} +{"type":"assistant/chunk","seq":42,"time":1781834405623,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} +{"type":"assistant/chunk","seq":43,"time":1781834405623,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} +{"type":"assistant/chunk","seq":44,"time":1781834405624,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" back"}}} +{"type":"assistant/chunk","seq":45,"time":1781834405624,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":46,"time":1781834405648,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} +{"type":"assistant/chunk","seq":47,"time":1781834405649,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n\n"}}} +{"type":"assistant/chunk","seq":48,"time":1781834405649,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Wait"}}} +{"type":"assistant/chunk","seq":49,"time":1781834405649,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} +{"type":"assistant/chunk","seq":50,"time":1781834405649,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":51,"time":1781834405676,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" instruction"}}} +{"type":"assistant/chunk","seq":52,"time":1781834405677,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" says"}}} +{"type":"assistant/chunk","seq":53,"time":1781834405677,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":54,"time":1781834405677,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Use"}}} +{"type":"assistant/chunk","seq":55,"time":1781834405677,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":56,"time":1781834405677,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}} +{"type":"assistant/chunk","seq":57,"time":1781834405705,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":58,"time":1781834405705,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":59,"time":1781834405705,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" per"}}} +{"type":"assistant/chunk","seq":60,"time":1781834405705,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} +{"type":"assistant/chunk","seq":61,"time":1781834405705,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":62,"time":1781834405706,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" -"}}} +{"type":"assistant/chunk","seq":63,"time":1781834405734,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" but"}}} +{"type":"assistant/chunk","seq":64,"time":1781834405735,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":65,"time":1781834405735,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" need"}}} +{"type":"assistant/chunk","seq":66,"time":1781834405735,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":67,"time":1781834405735,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} +{"type":"assistant/chunk","seq":68,"time":1781834405762,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" multiple"}}} +{"type":"assistant/chunk","seq":69,"time":1781834405800,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" actions"}}} +{"type":"assistant/chunk","seq":70,"time":1781834405800,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":71,"time":1781834405801,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Let"}}} +{"type":"assistant/chunk","seq":72,"time":1781834405801,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":73,"time":1781834405801,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" re"}}} +{"type":"assistant/chunk","seq":74,"time":1781834405819,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"-read"}}} +{"type":"assistant/chunk","seq":75,"time":1781834405820,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".\n\n"}}} +{"type":"assistant/chunk","seq":76,"time":1781834405820,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":77,"time":1781834405820,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Use"}}} +{"type":"assistant/chunk","seq":78,"time":1781834405820,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":79,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}} +{"type":"assistant/chunk","seq":80,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":81,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":82,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" per"}}} +{"type":"assistant/chunk","seq":83,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} +{"type":"assistant/chunk","seq":84,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":85,"time":1781834405876,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" -"}}} +{"type":"assistant/chunk","seq":86,"time":1781834405877,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":87,"time":1781834405877,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" think"}}} +{"type":"assistant/chunk","seq":88,"time":1781834405877,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" this"}}} +{"type":"assistant/chunk","seq":89,"time":1781834405905,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" means"}}} +{"type":"assistant/chunk","seq":90,"time":1781834405906,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" each"}}} +{"type":"assistant/chunk","seq":91,"time":1781834405906,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} +{"type":"assistant/chunk","seq":92,"time":1781834405906,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" should"}}} +{"type":"assistant/chunk","seq":93,"time":1781834405933,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" be"}}} +{"type":"assistant/chunk","seq":94,"time":1781834405934,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":95,"time":1781834405962,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" separate"}}} +{"type":"assistant/chunk","seq":96,"time":1781834405962,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":97,"time":1781834405962,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":98,"time":1781834405962,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} +{"type":"assistant/chunk","seq":99,"time":1781834405963,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" not"}}} +{"type":"assistant/chunk","seq":100,"time":1781834405990,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" one"}}} +{"type":"assistant/chunk","seq":101,"time":1781834406018,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" big"}}} +{"type":"assistant/chunk","seq":102,"time":1781834406047,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":103,"time":1781834406048,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":104,"time":1781834406075,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".\n\n"}}} +{"type":"assistant/chunk","seq":105,"time":1781834406076,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Let"}}} +{"type":"assistant/chunk","seq":106,"time":1781834406076,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":107,"time":1781834406076,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} +{"type":"assistant/chunk","seq":108,"time":1781834406103,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":\n"}}} +{"type":"assistant/chunk","seq":109,"time":1781834406104,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"1"}}} +{"type":"assistant/chunk","seq":110,"time":1781834406104,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":111,"time":1781834406104,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" First"}}} +{"type":"assistant/chunk","seq":112,"time":1781834406132,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":113,"time":1781834406133,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":114,"time":1781834406160,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} +{"type":"assistant/chunk","seq":115,"time":1781834406161,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} +{"type":"assistant/chunk","seq":116,"time":1781834406161,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":117,"time":1781834406190,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":118,"time":1781834406191,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":119,"time":1781834406218,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" see"}}} +{"type":"assistant/chunk","seq":120,"time":1781834406219,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":121,"time":1781834406219,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" current"}}} +{"type":"assistant/chunk","seq":122,"time":1781834406219,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" content"}}} +{"type":"assistant/chunk","seq":123,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":124,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"2"}}} +{"type":"assistant/chunk","seq":125,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":126,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Second"}}} +{"type":"assistant/chunk","seq":127,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":128,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":129,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} +{"type":"assistant/chunk","seq":130,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} +{"type":"assistant/chunk","seq":131,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":132,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} +{"type":"assistant/chunk","seq":133,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} +{"type":"assistant/chunk","seq":134,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":135,"time":1781834406305,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":136,"time":1781834406306,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":137,"time":1781834406306,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":138,"time":1781834406332,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":139,"time":1781834406333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"3"}}} +{"type":"assistant/chunk","seq":140,"time":1781834406333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":141,"time":1781834406333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Third"}}} +{"type":"assistant/chunk","seq":142,"time":1781834406333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":143,"time":1781834406333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":144,"time":1781834406361,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} +{"type":"assistant/chunk","seq":145,"time":1781834406362,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} +{"type":"assistant/chunk","seq":146,"time":1781834406390,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":147,"time":1781834406390,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":148,"time":1781834406390,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":149,"time":1781834406418,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" confirm"}}} +{"type":"assistant/chunk","seq":150,"time":1781834406419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n\n"}}} +{"type":"assistant/chunk","seq":151,"time":1781834406419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Actually"}}} +{"type":"assistant/chunk","seq":152,"time":1781834406419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} +{"type":"assistant/chunk","seq":153,"time":1781834406419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" let"}}} +{"type":"assistant/chunk","seq":154,"time":1781834406446,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":155,"time":1781834406447,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" just"}}} +{"type":"assistant/chunk","seq":156,"time":1781834406447,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} +{"type":"assistant/chunk","seq":157,"time":1781834406447,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} +{"type":"assistant/chunk","seq":158,"time":1781834406476,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" step"}}} +{"type":"assistant/chunk","seq":159,"time":1781834406476,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" by"}}} +{"type":"assistant/chunk","seq":160,"time":1781834406477,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" step"}}} +{"type":"assistant/chunk","seq":161,"time":1781834406477,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":162,"time":1781834406562,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":163,"time":1781834406562,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":164,"time":1781834406589,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":165,"time":1781834406590,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":166,"time":1781834406590,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":167,"time":1781834406590,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":168,"time":1781834406590,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":169,"time":1781834406618,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":170,"time":1781834406619,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"cat"}}} +{"type":"assistant/chunk","seq":171,"time":1781834406619,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":172,"time":1781834406619,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":173,"time":1781834406647,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":174,"time":1781834406675,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":175,"time":1781834406676,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":176,"time":1781834406676,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":177,"time":1781834406676,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":178,"time":1781834406676,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":179,"time":1781834406705,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":180,"time":1781834406705,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"Read"}}} +{"type":"assistant/chunk","seq":181,"time":1781834406705,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" current"}}} +{"type":"assistant/chunk","seq":182,"time":1781834406705,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" content"}}} +{"type":"assistant/chunk","seq":183,"time":1781834406733,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" of"}}} +{"type":"assistant/chunk","seq":184,"time":1781834406733,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":185,"time":1781834406733,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":186,"time":1781834406733,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":187,"time":1781834406761,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":188,"time":1781834406823,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Let me break this down into steps:\n1. First, read the file to see what's in it\n2. Then append \"WORLD\" as a second line\n3. Then read it back with cat\n\nWait, the instruction says \"Use a single bash call per action\" - but I need to do multiple actions. Let me re-read.\n\n\"Use a single bash call per action\" - I think this means each action should be a separate bash call, not one big bash call.\n\nLet me do:\n1. First bash call: read the file to see the current content\n2. Second bash call: append \"WORLD\" to the file\n3. Third bash call: cat the file to confirm\n\nActually, let me just do it step by step."}}}} +{"type":"assistant/chunk","seq":189,"time":1781834406824,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}}}} +{"type":"assistant/chunk","seq":190,"time":1781834406824,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":168,"outputTokens":224,"cacheReadTokens":768,"reasoningTokens":158}}}} +{"type":"assistant/chunk","seq":191,"time":1781834406824,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":192,"time":1781834406825,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"Let me break this down into steps:\n1. First, read the file to see what's in it\n2. Then append \"WORLD\" as a second line\n3. Then read it back with cat\n\nWait, the instruction says \"Use a single bash call per action\" - but I need to do multiple actions. Let me re-read.\n\n\"Use a single bash call per action\" - I think this means each action should be a separate bash call, not one big bash call.\n\nLet me do:\n1. First bash call: read the file to see the current content\n2. Second bash call: append \"WORLD\" to the file\n3. Third bash call: cat the file to confirm\n\nActually, let me just do it step by step."},{"type":"tool-call","id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}]}} +{"type":"usage","seq":193,"time":1781834406826,"data":{"turn":1,"step":1,"usage":{"inputTokens":168,"outputTokens":224,"cacheReadTokens":768,"reasoningTokens":158}}} +{"type":"tool/call","seq":194,"time":1781834406826,"data":{"turn":1,"step":1,"callId":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}} +{"type":"tool/result","seq":195,"time":1781834406858,"data":{"turn":1,"step":1,"callId":"call_00_J7zkTYNbCxhU7s0fIfIq4165","content":[{"type":"text","text":"hello\n"}],"isError":false}} +{"type":"step/end","seq":196,"time":1781834406859,"data":{"turn":1,"step":1}} +{"type":"step/start","seq":197,"time":1781834406859,"data":{"turn":1,"step":2}} +{"type":"assistant/chunk","seq":198,"time":1781834407670,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":199,"time":1781834407670,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":200,"time":1781834407822,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":201,"time":1781834407851,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" contains"}}} +{"type":"assistant/chunk","seq":202,"time":1781834407851,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":203,"time":1781834407851,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"hello"}}} +{"type":"assistant/chunk","seq":204,"time":1781834407851,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":205,"time":1781834407851,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" Now"}}} +{"type":"assistant/chunk","seq":206,"time":1781834407852,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":207,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" need"}}} +{"type":"assistant/chunk","seq":208,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":209,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} +{"type":"assistant/chunk","seq":210,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":211,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} +{"type":"assistant/chunk","seq":212,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} +{"type":"assistant/chunk","seq":213,"time":1781834407908,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":214,"time":1781834407908,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" as"}}} +{"type":"assistant/chunk","seq":215,"time":1781834407908,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":216,"time":1781834407908,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" second"}}} +{"type":"assistant/chunk","seq":217,"time":1781834407908,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" line"}}} +{"type":"assistant/chunk","seq":218,"time":1781834407909,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":219,"time":1781834407994,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":220,"time":1781834407994,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":221,"time":1781834408022,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":222,"time":1781834408023,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":223,"time":1781834408023,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":224,"time":1781834408051,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":225,"time":1781834408051,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":226,"time":1781834408051,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":227,"time":1781834408051,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"App"}}} +{"type":"assistant/chunk","seq":228,"time":1781834408079,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"end"}}} +{"type":"assistant/chunk","seq":229,"time":1781834408080,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" WORLD"}}} +{"type":"assistant/chunk","seq":230,"time":1781834408080,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" as"}}} +{"type":"assistant/chunk","seq":231,"time":1781834408080,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" second"}}} +{"type":"assistant/chunk","seq":232,"time":1781834408080,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" line"}}} +{"type":"assistant/chunk","seq":233,"time":1781834408137,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":234,"time":1781834408165,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":235,"time":1781834408165,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":236,"time":1781834408165,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":237,"time":1781834408165,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":238,"time":1781834408165,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":239,"time":1781834408193,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":240,"time":1781834408193,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"echo"}}} +{"type":"assistant/chunk","seq":241,"time":1781834408194,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" WORLD"}}} +{"type":"assistant/chunk","seq":242,"time":1781834408222,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" >>"}}} +{"type":"assistant/chunk","seq":243,"time":1781834408222,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":244,"time":1781834408222,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":245,"time":1781834408222,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":246,"time":1781834408255,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":247,"time":1781834408309,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The file contains \"hello\". Now I need to append \"WORLD\" as a second line."}}}} +{"type":"assistant/chunk","seq":248,"time":1781834408309,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}}}} +{"type":"assistant/chunk","seq":249,"time":1781834408309,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":278,"outputTokens":88,"cacheReadTokens":896,"reasoningTokens":20}}}} +{"type":"assistant/chunk","seq":250,"time":1781834408309,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":251,"time":1781834408310,"data":{"turn":1,"step":2,"content":[{"type":"reasoning","text":"The file contains \"hello\". Now I need to append \"WORLD\" as a second line."},{"type":"tool-call","id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}]}} +{"type":"usage","seq":252,"time":1781834408310,"data":{"turn":1,"step":2,"usage":{"inputTokens":278,"outputTokens":88,"cacheReadTokens":896,"reasoningTokens":20}}} +{"type":"tool/call","seq":253,"time":1781834408310,"data":{"turn":1,"step":2,"callId":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}} +{"type":"tool/result","seq":254,"time":1781834408321,"data":{"turn":1,"step":2,"callId":"call_00_r6yugViLOxPuocpIvXrQ5342","content":[{"type":"text","text":"(no output)"}],"isError":false}} +{"type":"step/end","seq":255,"time":1781834408321,"data":{"turn":1,"step":2}} +{"type":"step/start","seq":256,"time":1781834408321,"data":{"turn":1,"step":3}} +{"type":"assistant/chunk","seq":257,"time":1781834408885,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":258,"time":1781834408885,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"Now"}}} +{"type":"assistant/chunk","seq":259,"time":1781834409001,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" confirm"}}} +{"type":"assistant/chunk","seq":260,"time":1781834409032,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":261,"time":1781834409033,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} +{"type":"assistant/chunk","seq":262,"time":1781834409033,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":263,"time":1781834409113,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":264,"time":1781834409113,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":265,"time":1781834409142,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":266,"time":1781834409142,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":267,"time":1781834409142,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":268,"time":1781834409142,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":269,"time":1781834409142,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":270,"time":1781834409170,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":271,"time":1781834409171,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"Confirm"}}} +{"type":"assistant/chunk","seq":272,"time":1781834409171,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" file"}}} +{"type":"assistant/chunk","seq":273,"time":1781834409199,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" content"}}} +{"type":"assistant/chunk","seq":274,"time":1781834409199,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" with"}}} +{"type":"assistant/chunk","seq":275,"time":1781834409199,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" cat"}}} +{"type":"assistant/chunk","seq":276,"time":1781834409229,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":277,"time":1781834409261,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":278,"time":1781834409261,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":279,"time":1781834409261,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":280,"time":1781834409261,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":281,"time":1781834409261,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":282,"time":1781834409289,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":283,"time":1781834409289,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"cat"}}} +{"type":"assistant/chunk","seq":284,"time":1781834409289,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":285,"time":1781834409289,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":286,"time":1781834409317,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":287,"time":1781834409317,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":288,"time":1781834409374,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Now confirm with cat."}}}} +{"type":"assistant/chunk","seq":289,"time":1781834409374,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}}}} +{"type":"assistant/chunk","seq":290,"time":1781834409374,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":124,"outputTokens":70,"cacheReadTokens":1152,"reasoningTokens":5}}}} +{"type":"assistant/chunk","seq":291,"time":1781834409374,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":292,"time":1781834409375,"data":{"turn":1,"step":3,"content":[{"type":"reasoning","text":"Now confirm with cat."},{"type":"tool-call","id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}]}} +{"type":"usage","seq":293,"time":1781834409375,"data":{"turn":1,"step":3,"usage":{"inputTokens":124,"outputTokens":70,"cacheReadTokens":1152,"reasoningTokens":5}}} +{"type":"tool/call","seq":294,"time":1781834409375,"data":{"turn":1,"step":3,"callId":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}} +{"type":"tool/result","seq":295,"time":1781834409389,"data":{"turn":1,"step":3,"callId":"call_00_SC1arlNU29Vn38HnR4Kp9691","content":[{"type":"text","text":"hello\nWORLD\n"}],"isError":false}} +{"type":"step/end","seq":296,"time":1781834409389,"data":{"turn":1,"step":3}} +{"type":"step/start","seq":297,"time":1781834409389,"data":{"turn":1,"step":4}} +{"type":"assistant/chunk","seq":298,"time":1781834410109,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":299,"time":1781834410109,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":300,"time":1781834410216,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":301,"time":1781834410245,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" now"}}} +{"type":"assistant/chunk","seq":302,"time":1781834410245,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" has"}}} +{"type":"assistant/chunk","seq":303,"time":1781834410245,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" two"}}} +{"type":"assistant/chunk","seq":304,"time":1781834410245,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" lines"}}} +{"type":"assistant/chunk","seq":305,"time":1781834410274,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} +{"type":"assistant/chunk","seq":306,"time":1781834410274,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":307,"time":1781834410274,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"hello"}}} +{"type":"assistant/chunk","seq":308,"time":1781834410274,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":309,"time":1781834410274,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":310,"time":1781834410275,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":311,"time":1781834410302,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} +{"type":"assistant/chunk","seq":312,"time":1781834410302,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} +{"type":"assistant/chunk","seq":313,"time":1781834410302,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":314,"time":1781834410302,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" The"}}} +{"type":"assistant/chunk","seq":315,"time":1781834410302,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" task"}}} +{"type":"assistant/chunk","seq":316,"time":1781834410330,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" is"}}} +{"type":"assistant/chunk","seq":317,"time":1781834410331,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" complete"}}} +{"type":"assistant/chunk","seq":318,"time":1781834410331,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":319,"time":1781834410331,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":320,"time":1781834410331,"data":{"turn":1,"step":4,"chunk":{"type":"text-delta","index":1,"text":"D"}}} +{"type":"assistant/chunk","seq":321,"time":1781834410331,"data":{"turn":1,"step":4,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} +{"type":"assistant/chunk","seq":322,"time":1781834410359,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The file now has two lines: \"hello\" and \"WORLD\". The task is complete."}}}} +{"type":"assistant/chunk","seq":323,"time":1781834410360,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}}} +{"type":"assistant/chunk","seq":324,"time":1781834410360,"data":{"turn":1,"step":4,"chunk":{"type":"usage","usage":{"inputTokens":211,"outputTokens":23,"cacheReadTokens":1152,"reasoningTokens":20}}}} +{"type":"assistant/chunk","seq":325,"time":1781834410360,"data":{"turn":1,"step":4,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":326,"time":1781834410360,"data":{"turn":1,"step":4,"content":[{"type":"reasoning","text":"The file now has two lines: \"hello\" and \"WORLD\". The task is complete."},{"type":"text","text":"DONE"}]}} +{"type":"usage","seq":327,"time":1781834410360,"data":{"turn":1,"step":4,"usage":{"inputTokens":211,"outputTokens":23,"cacheReadTokens":1152,"reasoningTokens":20}}} +{"type":"step/end","seq":328,"time":1781834410360,"data":{"turn":1,"step":4}} +{"type":"turn/end","seq":329,"time":1781834410360,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/examples/acp-agent/tests/snapshots/workspace-edit/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/workspace-edit/stdout.golden.jsonl new file mode 100644 index 0000000000..1f7c191c9d --- /dev/null +++ b/examples/acp-agent/tests/snapshots/workspace-edit/stdout.golden.jsonl @@ -0,0 +1,215 @@ +{"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":"A file named greeting.txt in the current directory contains one word. Use the bash tool to append a second line containing the word WORLD to it (so it has two lines), then read the file back with `cat greeting.txt` to confirm, and reply with the single word DONE. Use a single bash call per action."}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"Let"}}}} +{"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":" break"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" this"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" down"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" into"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" steps"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":":\n"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"1"}}}} +{"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":" First"}}}} +{"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":" read"}}}} +{"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":" file"}}}} +{"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":" see"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" what"}}}} +{"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":" in"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" it"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"2"}}}} +{"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":" Then"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" append"}}}} +{"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":"WOR"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"LD"}}}} +{"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":" as"}}}} +{"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":" second"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" line"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"3"}}}} +{"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":" Then"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" read"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" it"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" back"}}}} +{"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":" cat"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n\n"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"Wait"}}}} +{"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":" the"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" instruction"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" says"}}}} +{"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":"Use"}}}} +{"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":" single"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" per"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" action"}}}} +{"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":" -"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" but"}}}} +{"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":" do"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" multiple"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" actions"}}}} +{"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":" Let"}}}} +{"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":" re"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"-read"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":".\n\n"}}}} +{"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":"Use"}}}} +{"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":" single"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" per"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" action"}}}} +{"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":" -"}}}} +{"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":" think"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" this"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" means"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" each"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" action"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" should"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" be"}}}} +{"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":" separate"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} +{"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":" not"}}}} +{"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":" big"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":".\n\n"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"Let"}}}} +{"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":" do"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":":\n"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"1"}}}} +{"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":" First"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} +{"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":" read"}}}} +{"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":" file"}}}} +{"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":" see"}}}} +{"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":" current"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" content"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"2"}}}} +{"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":" Second"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} +{"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":" append"}}}} +{"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":"WOR"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"LD"}}}} +{"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":" to"}}}} +{"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":" file"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"3"}}}} +{"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":" Third"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} +{"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":" cat"}}}} +{"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":" file"}}}} +{"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":" confirm"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n\n"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"Actually"}}}} +{"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":" let"}}}} +{"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":" just"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" do"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" it"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" step"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" by"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" step"}}}} +{"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_J7zkTYNbCxhU7s0fIfIq4165","title":"cat greeting.txt","kind":"execute","status":"in_progress","rawInput":"cat greeting.txt","content":[{"type":"content","content":{"type":"text","text":"Read current content of greeting.txt"}}]}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_00_J7zkTYNbCxhU7s0fIfIq4165","status":"completed","content":[{"type":"content","content":{"type":"text","text":"```console\nhello\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":" file"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" contains"}}}} +{"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":"hello"}}}} +{"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":" append"}}}} +{"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":"WOR"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"LD"}}}} +{"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":" as"}}}} +{"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":" second"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" line"}}}} +{"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_r6yugViLOxPuocpIvXrQ5342","title":"echo WORLD >> greeting.txt","kind":"execute","status":"in_progress","rawInput":"echo WORLD >> greeting.txt","content":[{"type":"content","content":{"type":"text","text":"Append WORLD as second line"}}]}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_00_r6yugViLOxPuocpIvXrQ5342","status":"completed","content":[{"type":"content","content":{"type":"text","text":"```console\n(no output)\n```"}}]}}} +{"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":" confirm"}}}} +{"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":" cat"}}}} +{"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_SC1arlNU29Vn38HnR4Kp9691","title":"cat greeting.txt","kind":"execute","status":"in_progress","rawInput":"cat greeting.txt","content":[{"type":"content","content":{"type":"text","text":"Confirm file content with cat"}}]}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_00_SC1arlNU29Vn38HnR4Kp9691","status":"completed","content":[{"type":"content","content":{"type":"text","text":"```console\nhello\nWORLD\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":" file"}}}} +{"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":" has"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" two"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" lines"}}}} +{"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":" \""}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"hello"}}}} +{"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":" \""}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"WOR"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"LD"}}}} +{"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":" The"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" task"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" is"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" complete"}}}} +{"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"}} diff --git a/examples/acp-agent/tests/snapshots/workspace-edit/workspace/greeting.txt b/examples/acp-agent/tests/snapshots/workspace-edit/workspace/greeting.txt new file mode 100644 index 0000000000..ce01362503 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/workspace-edit/workspace/greeting.txt @@ -0,0 +1 @@ +hello From 72df4d2e168140ea7a109b8586e07f5ae79aba3b Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 10:07:06 +0800 Subject: [PATCH 12/13] test(acp-example): re-record snapshot goldens after merging master MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Master's "fix(acp): align prompt and workspace contracts" changed the editor- facing transcript — `user/message` → `user_message_chunk` is now emitted during session/load replay ONLY, not live streaming, so a live prompt no longer echoes the user message back. The snapshot tier caught this (6 goldens shifted); this re-records the four recorded scenarios against the API and re-accepts the two authored goldens so they reflect the merged behavior. Full suite green and deterministic; this is the tier working as designed. --- .../snapshots/cancel/stdout.golden.jsonl | 1 - .../error-finish/stdout.golden.jsonl | 1 - .../snapshots/multi-turn/session.golden.jsonl | 74 +-- .../tests/snapshots/multi-turn/session.jsonl | 132 ++--- .../snapshots/multi-turn/stdout.golden.jsonl | 4 +- .../snapshots/text-turn/session.golden.jsonl | 4 +- .../tests/snapshots/text-turn/session.jsonl | 70 +-- .../snapshots/text-turn/stdout.golden.jsonl | 1 - .../tool-call-turn/session.golden.jsonl | 185 ++++--- .../snapshots/tool-call-turn/session.jsonl | 207 +++---- .../tool-call-turn/stdout.golden.jsonl | 26 +- .../workspace-edit/session.golden.jsonl | 513 +++++++---------- .../snapshots/workspace-edit/session.jsonl | 523 +++++++----------- .../workspace-edit/stdout.golden.jsonl | 253 +++------ 14 files changed, 810 insertions(+), 1184 deletions(-) diff --git a/examples/acp-agent/tests/snapshots/cancel/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/cancel/stdout.golden.jsonl index 86ac88d0f4..3400223f4d 100644 --- a/examples/acp-agent/tests/snapshots/cancel/stdout.golden.jsonl +++ b/examples/acp-agent/tests/snapshots/cancel/stdout.golden.jsonl @@ -1,5 +1,4 @@ {"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/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/error-finish/stdout.golden.jsonl index e978f8969b..8515dacf5a 100644 --- a/examples/acp-agent/tests/snapshots/error-finish/stdout.golden.jsonl +++ b/examples/acp-agent/tests/snapshots/error-finish/stdout.golden.jsonl @@ -1,4 +1,3 @@ {"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/session.golden.jsonl b/examples/acp-agent/tests/snapshots/multi-turn/session.golden.jsonl index 4623cc674d..20fe3a727b 100644 --- a/examples/acp-agent/tests/snapshots/multi-turn/session.golden.jsonl +++ b/examples/acp-agent/tests/snapshots/multi-turn/session.golden.jsonl @@ -17,50 +17,50 @@ {"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":18,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" use"}}} +{"type":"assistant/chunk","seq":19,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" no"}}} +{"type":"assistant/chunk","seq":20,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" tools"}}} +{"type":"assistant/chunk","seq":21,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":22,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":23,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} +{"type":"assistant/chunk","seq":24,"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 use no tools."}}}} +{"type":"assistant/chunk","seq":25,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"ONE"}}}} +{"type":"assistant/chunk","seq":26,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":106,"outputTokens":20,"cacheReadTokens":768,"reasoningTokens":18}}}} +{"type":"assistant/chunk","seq":27,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":28,"time":0,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"ONE\" and use no tools."},{"type":"text","text":"ONE"}]}} +{"type":"usage","seq":29,"time":0,"data":{"turn":1,"step":1,"usage":{"inputTokens":106,"outputTokens":20,"cacheReadTokens":768,"reasoningTokens":18}}} +{"type":"step/end","seq":30,"time":0,"data":{"turn":1,"step":1}} +{"type":"turn/end","seq":31,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}} +{"type":"turn/start","seq":32,"time":0,"data":{"turn":2,"trigger":{"kind":"message","source":{"kind":"user"}}}} +{"type":"user/message","seq":33,"time":0,"data":{"content":[{"type":"text","text":"Reply with exactly the word: TWO. No tools."}],"source":{"kind":"user"}}} +{"type":"step/start","seq":34,"time":0,"data":{"turn":2,"step":1}} +{"type":"assistant/chunk","seq":35,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":36,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":37,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}} +{"type":"assistant/chunk","seq":38,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" wants"}}} +{"type":"assistant/chunk","seq":39,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":40,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":41,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":42,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":43,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" exactly"}}} +{"type":"assistant/chunk","seq":44,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":45,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" word"}}} +{"type":"assistant/chunk","seq":46,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":47,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"T"}}} +{"type":"assistant/chunk","seq":48,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WO"}}} +{"type":"assistant/chunk","seq":49,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":50,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} {"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":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 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":59,"time":0,"data":{"turn":2,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":122,"outputTokens":21,"cacheReadTokens":768,"reasoningTokens":18}}}} {"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":"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 no tools."},{"type":"text","text":"TWO"}]}} +{"type":"usage","seq":62,"time":0,"data":{"turn":2,"step":1,"usage":{"inputTokens":122,"outputTokens":21,"cacheReadTokens":768,"reasoningTokens":18}}} {"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 index 5222165530..c490a17f38 100644 --- a/examples/acp-agent/tests/snapshots/multi-turn/session.jsonl +++ b/examples/acp-agent/tests/snapshots/multi-turn/session.jsonl @@ -1,66 +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"}}} +{"type":"session","version":1,"id":"803f0752-a3db-4394-9c93-3b6fcd410664","createdAt":1781834688308,"cwd":"/tmp/acp-snap-cwd-QVaaKH"} +{"type":"turn/start","seq":0,"time":1781834688311,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}} +{"type":"user/message","seq":1,"time":1781834688312,"data":{"content":[{"type":"text","text":"Reply with exactly the word: ONE. No tools."}],"source":{"kind":"user"}}} +{"type":"step/start","seq":2,"time":1781834688312,"data":{"turn":1,"step":1}} +{"type":"assistant/chunk","seq":3,"time":1781834688735,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":4,"time":1781834688735,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":5,"time":1781834688864,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}} +{"type":"assistant/chunk","seq":6,"time":1781834688889,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" wants"}}} +{"type":"assistant/chunk","seq":7,"time":1781834688890,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":8,"time":1781834688890,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":9,"time":1781834688890,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":10,"time":1781834688890,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":11,"time":1781834688920,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" exactly"}}} +{"type":"assistant/chunk","seq":12,"time":1781834688920,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":13,"time":1781834688921,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" word"}}} +{"type":"assistant/chunk","seq":14,"time":1781834688921,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":15,"time":1781834688921,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":16,"time":1781834688921,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":17,"time":1781834688948,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":18,"time":1781834688948,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" use"}}} +{"type":"assistant/chunk","seq":19,"time":1781834688979,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" no"}}} +{"type":"assistant/chunk","seq":20,"time":1781834688979,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" tools"}}} +{"type":"assistant/chunk","seq":21,"time":1781834688979,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":22,"time":1781834689007,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":23,"time":1781834689007,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} +{"type":"assistant/chunk","seq":24,"time":1781834689008,"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 use no tools."}}}} +{"type":"assistant/chunk","seq":25,"time":1781834689008,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"ONE"}}}} +{"type":"assistant/chunk","seq":26,"time":1781834689008,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":106,"outputTokens":20,"cacheReadTokens":768,"reasoningTokens":18}}}} +{"type":"assistant/chunk","seq":27,"time":1781834689008,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":28,"time":1781834689009,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"ONE\" and use no tools."},{"type":"text","text":"ONE"}]}} +{"type":"usage","seq":29,"time":1781834689010,"data":{"turn":1,"step":1,"usage":{"inputTokens":106,"outputTokens":20,"cacheReadTokens":768,"reasoningTokens":18}}} +{"type":"step/end","seq":30,"time":1781834689010,"data":{"turn":1,"step":1}} +{"type":"turn/end","seq":31,"time":1781834689010,"data":{"turn":1,"reason":{"kind":"completed"}}} +{"type":"turn/start","seq":32,"time":1781834689017,"data":{"turn":2,"trigger":{"kind":"message","source":{"kind":"user"}}}} +{"type":"user/message","seq":33,"time":1781834689017,"data":{"content":[{"type":"text","text":"Reply with exactly the word: TWO. No tools."}],"source":{"kind":"user"}}} +{"type":"step/start","seq":34,"time":1781834689017,"data":{"turn":2,"step":1}} +{"type":"assistant/chunk","seq":35,"time":1781834689551,"data":{"turn":2,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":36,"time":1781834689551,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":37,"time":1781834689643,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}} +{"type":"assistant/chunk","seq":38,"time":1781834689676,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" wants"}}} +{"type":"assistant/chunk","seq":39,"time":1781834689676,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":40,"time":1781834689676,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":41,"time":1781834689676,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":42,"time":1781834689676,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":43,"time":1781834689702,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" exactly"}}} +{"type":"assistant/chunk","seq":44,"time":1781834689702,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":45,"time":1781834689702,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" word"}}} +{"type":"assistant/chunk","seq":46,"time":1781834689702,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":47,"time":1781834689702,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"T"}}} +{"type":"assistant/chunk","seq":48,"time":1781834689703,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WO"}}} +{"type":"assistant/chunk","seq":49,"time":1781834689731,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":50,"time":1781834689731,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":51,"time":1781834689732,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" no"}}} +{"type":"assistant/chunk","seq":52,"time":1781834689759,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" tools"}}} +{"type":"assistant/chunk","seq":53,"time":1781834689759,"data":{"turn":2,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":54,"time":1781834689759,"data":{"turn":2,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":55,"time":1781834689759,"data":{"turn":2,"step":1,"chunk":{"type":"text-delta","index":1,"text":"T"}}} +{"type":"assistant/chunk","seq":56,"time":1781834689760,"data":{"turn":2,"step":1,"chunk":{"type":"text-delta","index":1,"text":"WO"}}} +{"type":"assistant/chunk","seq":57,"time":1781834689788,"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 no tools."}}}} +{"type":"assistant/chunk","seq":58,"time":1781834689788,"data":{"turn":2,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"TWO"}}}} +{"type":"assistant/chunk","seq":59,"time":1781834689788,"data":{"turn":2,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":122,"outputTokens":21,"cacheReadTokens":768,"reasoningTokens":18}}}} +{"type":"assistant/chunk","seq":60,"time":1781834689788,"data":{"turn":2,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":61,"time":1781834689789,"data":{"turn":2,"step":1,"content":[{"type":"reasoning","text":"The user wants me to reply with exactly the word \"TWO\" and no tools."},{"type":"text","text":"TWO"}]}} +{"type":"usage","seq":62,"time":1781834689789,"data":{"turn":2,"step":1,"usage":{"inputTokens":122,"outputTokens":21,"cacheReadTokens":768,"reasoningTokens":18}}} +{"type":"step/end","seq":63,"time":1781834689789,"data":{"turn":2,"step":1}} +{"type":"turn/end","seq":64,"time":1781834689789,"data":{"turn":2,"reason":{"kind":"completed"}}} diff --git a/examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.jsonl index d0c1644cfc..22bb6757fd 100644 --- a/examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.jsonl +++ b/examples/acp-agent/tests/snapshots/multi-turn/stdout.golden.jsonl @@ -1,6 +1,5 @@ {"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"}}}} @@ -15,12 +14,12 @@ {"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":" 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":"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"}}}} @@ -36,7 +35,6 @@ {"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":"."}}}} diff --git a/examples/acp-agent/tests/snapshots/text-turn/session.golden.jsonl b/examples/acp-agent/tests/snapshots/text-turn/session.golden.jsonl index a25f008246..ad4e11841e 100644 --- a/examples/acp-agent/tests/snapshots/text-turn/session.golden.jsonl +++ b/examples/acp-agent/tests/snapshots/text-turn/session.golden.jsonl @@ -27,9 +27,9 @@ {"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":28,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":878,"outputTokens":22,"cacheReadTokens":0,"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":"usage","seq":31,"time":0,"data":{"turn":1,"step":1,"usage":{"inputTokens":878,"outputTokens":22,"cacheReadTokens":0,"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 index ed970cbcd1..8306f3d4de 100644 --- a/examples/acp-agent/tests/snapshots/text-turn/session.jsonl +++ b/examples/acp-agent/tests/snapshots/text-turn/session.jsonl @@ -1,35 +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"}}} +{"type":"session","version":1,"id":"b8c052fd-b33f-475a-8a0c-bc3b75527602","createdAt":1781834679270,"cwd":"/tmp/acp-snap-cwd-TJst85"} +{"type":"turn/start","seq":0,"time":1781834679273,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}} +{"type":"user/message","seq":1,"time":1781834679273,"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":1781834679273,"data":{"turn":1,"step":1}} +{"type":"assistant/chunk","seq":3,"time":1781834680004,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":4,"time":1781834680004,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":5,"time":1781834680079,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}} +{"type":"assistant/chunk","seq":6,"time":1781834680113,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" wants"}}} +{"type":"assistant/chunk","seq":7,"time":1781834680114,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":8,"time":1781834680114,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":9,"time":1781834680114,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":10,"time":1781834680114,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":11,"time":1781834680137,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" exactly"}}} +{"type":"assistant/chunk","seq":12,"time":1781834680138,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":13,"time":1781834680138,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" word"}}} +{"type":"assistant/chunk","seq":14,"time":1781834680138,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":15,"time":1781834680138,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"P"}}} +{"type":"assistant/chunk","seq":16,"time":1781834680138,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"ONG"}}} +{"type":"assistant/chunk","seq":17,"time":1781834680167,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":18,"time":1781834680167,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" without"}}} +{"type":"assistant/chunk","seq":19,"time":1781834680167,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" using"}}} +{"type":"assistant/chunk","seq":20,"time":1781834680196,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" any"}}} +{"type":"assistant/chunk","seq":21,"time":1781834680196,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" tools"}}} +{"type":"assistant/chunk","seq":22,"time":1781834680196,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":23,"time":1781834680196,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":24,"time":1781834680196,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":1,"text":"P"}}} +{"type":"assistant/chunk","seq":25,"time":1781834680225,"data":{"turn":1,"step":1,"chunk":{"type":"text-delta","index":1,"text":"ONG"}}} +{"type":"assistant/chunk","seq":26,"time":1781834680226,"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":1781834680226,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"PONG"}}}} +{"type":"assistant/chunk","seq":28,"time":1781834680226,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":878,"outputTokens":22,"cacheReadTokens":0,"reasoningTokens":19}}}} +{"type":"assistant/chunk","seq":29,"time":1781834680226,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":30,"time":1781834680227,"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":1781834680227,"data":{"turn":1,"step":1,"usage":{"inputTokens":878,"outputTokens":22,"cacheReadTokens":0,"reasoningTokens":19}}} +{"type":"step/end","seq":32,"time":1781834680228,"data":{"turn":1,"step":1}} +{"type":"turn/end","seq":33,"time":1781834680228,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/examples/acp-agent/tests/snapshots/text-turn/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/text-turn/stdout.golden.jsonl index 61d0e31953..e35715ccad 100644 --- a/examples/acp-agent/tests/snapshots/text-turn/stdout.golden.jsonl +++ b/examples/acp-agent/tests/snapshots/text-turn/stdout.golden.jsonl @@ -1,6 +1,5 @@ {"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"}}}} diff --git a/examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.jsonl b/examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.jsonl index 2608bc8f95..a3ddac0862 100644 --- a/examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.jsonl +++ b/examples/acp-agent/tests/snapshots/tool-call-turn/session.golden.jsonl @@ -9,92 +9,99 @@ {"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"}}} +{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" `"}}} +{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"echo"}}} +{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" S"}}} +{"type":"assistant/chunk","seq":13,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"NA"}}} +{"type":"assistant/chunk","seq":14,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"PS"}}} +{"type":"assistant/chunk","seq":15,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"H"}}} +{"type":"assistant/chunk","seq":16,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"OT"}}} +{"type":"assistant/chunk","seq":17,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"_OK"}}} +{"type":"assistant/chunk","seq":18,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"`"}}} +{"type":"assistant/chunk","seq":19,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":20,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" then"}}} +{"type":"assistant/chunk","seq":21,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":22,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":23,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":24,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"D"}}} +{"type":"assistant/chunk","seq":25,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":26,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":27,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":28,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":29,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":30,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":31,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":32,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":33,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":34,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":35,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"echo"}}} +{"type":"assistant/chunk","seq":36,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":" S"}}} +{"type":"assistant/chunk","seq":37,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"NA"}}} +{"type":"assistant/chunk","seq":38,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"PS"}}} +{"type":"assistant/chunk","seq":39,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"H"}}} +{"type":"assistant/chunk","seq":40,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"OT"}}} +{"type":"assistant/chunk","seq":41,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"_OK"}}} +{"type":"assistant/chunk","seq":42,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":43,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":44,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":45,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":46,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":47,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":48,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","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_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"Run"}}} +{"type":"assistant/chunk","seq":50,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":" echo"}}} +{"type":"assistant/chunk","seq":51,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":" S"}}} +{"type":"assistant/chunk","seq":52,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"NA"}}} +{"type":"assistant/chunk","seq":53,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"PS"}}} +{"type":"assistant/chunk","seq":54,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"H"}}} +{"type":"assistant/chunk","seq":55,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"OT"}}} +{"type":"assistant/chunk","seq":56,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"_OK"}}} +{"type":"assistant/chunk","seq":57,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":58,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":59,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to run `echo SNAPSHOT_OK` and then reply with \"DONE\"."}}}} +{"type":"assistant/chunk","seq":60,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","arguments":"{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run echo SNAPSHOT_OK\"}"}}}} +{"type":"assistant/chunk","seq":61,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":122,"outputTokens":95,"cacheReadTokens":768,"reasoningTokens":23}}}} +{"type":"assistant/chunk","seq":62,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":63,"time":0,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to run `echo SNAPSHOT_OK` and then reply with \"DONE\"."},{"type":"tool-call","id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","arguments":"{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run echo SNAPSHOT_OK\"}"}]}} +{"type":"usage","seq":64,"time":0,"data":{"turn":1,"step":1,"usage":{"inputTokens":122,"outputTokens":95,"cacheReadTokens":768,"reasoningTokens":23}}} +{"type":"tool/call","seq":65,"time":0,"data":{"turn":1,"step":1,"callId":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","arguments":"{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run echo SNAPSHOT_OK\"}"}} +{"type":"tool/result","seq":66,"time":0,"data":{"turn":1,"step":1,"callId":"call_00_7bmU1TAadx8ADiZJ3BqC9330","content":[{"type":"text","text":"SNAPSHOT_OK\n"}],"isError":false}} +{"type":"step/end","seq":67,"time":0,"data":{"turn":1,"step":1}} +{"type":"step/start","seq":68,"time":0,"data":{"turn":1,"step":2}} +{"type":"assistant/chunk","seq":69,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":70,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":71,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" command"}}} +{"type":"assistant/chunk","seq":72,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" ran"}}} +{"type":"assistant/chunk","seq":73,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" successfully"}}} +{"type":"assistant/chunk","seq":74,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":75,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" output"}}} +{"type":"assistant/chunk","seq":76,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":77,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"S"}}} +{"type":"assistant/chunk","seq":78,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"NA"}}} +{"type":"assistant/chunk","seq":79,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"PS"}}} +{"type":"assistant/chunk","seq":80,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"H"}}} +{"type":"assistant/chunk","seq":81,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"OT"}}} +{"type":"assistant/chunk","seq":82,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"_OK"}}} +{"type":"assistant/chunk","seq":83,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":84,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" Now"}}} +{"type":"assistant/chunk","seq":85,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":86,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" need"}}} +{"type":"assistant/chunk","seq":87,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":88,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":89,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":90,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" just"}}} +{"type":"assistant/chunk","seq":91,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":92,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"D"}}} +{"type":"assistant/chunk","seq":93,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":94,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":95,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":96,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":1,"text":"D"}}} +{"type":"assistant/chunk","seq":97,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} +{"type":"assistant/chunk","seq":98,"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 just \"DONE\"."}}}} +{"type":"assistant/chunk","seq":99,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}}} +{"type":"assistant/chunk","seq":100,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":235,"outputTokens":28,"cacheReadTokens":768,"reasoningTokens":25}}}} +{"type":"assistant/chunk","seq":101,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":102,"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 just \"DONE\"."},{"type":"text","text":"DONE"}]}} +{"type":"usage","seq":103,"time":0,"data":{"turn":1,"step":2,"usage":{"inputTokens":235,"outputTokens":28,"cacheReadTokens":768,"reasoningTokens":25}}} +{"type":"step/end","seq":104,"time":0,"data":{"turn":1,"step":2}} +{"type":"turn/end","seq":105,"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 index f465404419..411c05fdc4 100644 --- a/examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl +++ b/examples/acp-agent/tests/snapshots/tool-call-turn/session.jsonl @@ -1,100 +1,107 @@ -{"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"}}} +{"type":"session","version":1,"id":"0e5b2fc1-d220-4a81-b48b-939c14dea057","createdAt":1781834681068,"cwd":"/tmp/acp-snap-cwd-5F2H38"} +{"type":"turn/start","seq":0,"time":1781834681072,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}} +{"type":"user/message","seq":1,"time":1781834681073,"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":1781834681073,"data":{"turn":1,"step":1}} +{"type":"assistant/chunk","seq":3,"time":1781834681472,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":4,"time":1781834681472,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":5,"time":1781834681566,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}} +{"type":"assistant/chunk","seq":6,"time":1781834681597,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" wants"}}} +{"type":"assistant/chunk","seq":7,"time":1781834681598,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":8,"time":1781834681598,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":9,"time":1781834681598,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" run"}}} +{"type":"assistant/chunk","seq":10,"time":1781834681598,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" `"}}} +{"type":"assistant/chunk","seq":11,"time":1781834681599,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"echo"}}} +{"type":"assistant/chunk","seq":12,"time":1781834681629,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" S"}}} +{"type":"assistant/chunk","seq":13,"time":1781834681630,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"NA"}}} +{"type":"assistant/chunk","seq":14,"time":1781834681630,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"PS"}}} +{"type":"assistant/chunk","seq":15,"time":1781834681630,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"H"}}} +{"type":"assistant/chunk","seq":16,"time":1781834681630,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"OT"}}} +{"type":"assistant/chunk","seq":17,"time":1781834681630,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"_OK"}}} +{"type":"assistant/chunk","seq":18,"time":1781834681661,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"`"}}} +{"type":"assistant/chunk","seq":19,"time":1781834681661,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":20,"time":1781834681662,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" then"}}} +{"type":"assistant/chunk","seq":21,"time":1781834681662,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":22,"time":1781834681695,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":23,"time":1781834681696,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":24,"time":1781834681696,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"D"}}} +{"type":"assistant/chunk","seq":25,"time":1781834681696,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":26,"time":1781834681696,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":27,"time":1781834681790,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":28,"time":1781834681790,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":29,"time":1781834681823,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":30,"time":1781834681824,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":31,"time":1781834681824,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":32,"time":1781834681824,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":33,"time":1781834681824,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":34,"time":1781834681856,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":35,"time":1781834681856,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"echo"}}} +{"type":"assistant/chunk","seq":36,"time":1781834681856,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":" S"}}} +{"type":"assistant/chunk","seq":37,"time":1781834681856,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"NA"}}} +{"type":"assistant/chunk","seq":38,"time":1781834681856,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"PS"}}} +{"type":"assistant/chunk","seq":39,"time":1781834681894,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"H"}}} +{"type":"assistant/chunk","seq":40,"time":1781834681895,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"OT"}}} +{"type":"assistant/chunk","seq":41,"time":1781834681895,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"_OK"}}} +{"type":"assistant/chunk","seq":42,"time":1781834681895,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":43,"time":1781834681923,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":44,"time":1781834681923,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":45,"time":1781834681955,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":46,"time":1781834681956,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":47,"time":1781834681956,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":48,"time":1781834681956,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":49,"time":1781834681989,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"Run"}}} +{"type":"assistant/chunk","seq":50,"time":1781834681989,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":" echo"}}} +{"type":"assistant/chunk","seq":51,"time":1781834681989,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":" S"}}} +{"type":"assistant/chunk","seq":52,"time":1781834682020,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"NA"}}} +{"type":"assistant/chunk","seq":53,"time":1781834682020,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"PS"}}} +{"type":"assistant/chunk","seq":54,"time":1781834682020,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"H"}}} +{"type":"assistant/chunk","seq":55,"time":1781834682020,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"OT"}}} +{"type":"assistant/chunk","seq":56,"time":1781834682020,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"_OK"}}} +{"type":"assistant/chunk","seq":57,"time":1781834682052,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":58,"time":1781834682053,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":59,"time":1781834682119,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to run `echo SNAPSHOT_OK` and then reply with \"DONE\"."}}}} +{"type":"assistant/chunk","seq":60,"time":1781834682119,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","arguments":"{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run echo SNAPSHOT_OK\"}"}}}} +{"type":"assistant/chunk","seq":61,"time":1781834682119,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":122,"outputTokens":95,"cacheReadTokens":768,"reasoningTokens":23}}}} +{"type":"assistant/chunk","seq":62,"time":1781834682119,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":63,"time":1781834682121,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to run `echo SNAPSHOT_OK` and then reply with \"DONE\"."},{"type":"tool-call","id":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","arguments":"{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run echo SNAPSHOT_OK\"}"}]}} +{"type":"usage","seq":64,"time":1781834682121,"data":{"turn":1,"step":1,"usage":{"inputTokens":122,"outputTokens":95,"cacheReadTokens":768,"reasoningTokens":23}}} +{"type":"tool/call","seq":65,"time":1781834682121,"data":{"turn":1,"step":1,"callId":"call_00_7bmU1TAadx8ADiZJ3BqC9330","name":"bash","arguments":"{\"command\": \"echo SNAPSHOT_OK\", \"description\": \"Run echo SNAPSHOT_OK\"}"}} +{"type":"tool/result","seq":66,"time":1781834682136,"data":{"turn":1,"step":1,"callId":"call_00_7bmU1TAadx8ADiZJ3BqC9330","content":[{"type":"text","text":"SNAPSHOT_OK\n"}],"isError":false}} +{"type":"step/end","seq":67,"time":1781834682137,"data":{"turn":1,"step":1}} +{"type":"step/start","seq":68,"time":1781834682137,"data":{"turn":1,"step":2}} +{"type":"assistant/chunk","seq":69,"time":1781834682760,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":70,"time":1781834682761,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":71,"time":1781834682826,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" command"}}} +{"type":"assistant/chunk","seq":72,"time":1781834682855,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" ran"}}} +{"type":"assistant/chunk","seq":73,"time":1781834682885,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" successfully"}}} +{"type":"assistant/chunk","seq":74,"time":1781834682886,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} +{"type":"assistant/chunk","seq":75,"time":1781834682886,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" output"}}} +{"type":"assistant/chunk","seq":76,"time":1781834682915,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":77,"time":1781834682915,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"S"}}} +{"type":"assistant/chunk","seq":78,"time":1781834682915,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"NA"}}} +{"type":"assistant/chunk","seq":79,"time":1781834682915,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"PS"}}} +{"type":"assistant/chunk","seq":80,"time":1781834682915,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"H"}}} +{"type":"assistant/chunk","seq":81,"time":1781834682916,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"OT"}}} +{"type":"assistant/chunk","seq":82,"time":1781834682946,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"_OK"}}} +{"type":"assistant/chunk","seq":83,"time":1781834682947,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":84,"time":1781834682947,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" Now"}}} +{"type":"assistant/chunk","seq":85,"time":1781834682947,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":86,"time":1781834682947,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" need"}}} +{"type":"assistant/chunk","seq":87,"time":1781834682947,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":88,"time":1781834682976,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":89,"time":1781834682977,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":90,"time":1781834682977,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" just"}}} +{"type":"assistant/chunk","seq":91,"time":1781834682977,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":92,"time":1781834682977,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"D"}}} +{"type":"assistant/chunk","seq":93,"time":1781834683007,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":94,"time":1781834683007,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} +{"type":"assistant/chunk","seq":95,"time":1781834683007,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":96,"time":1781834683007,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":1,"text":"D"}}} +{"type":"assistant/chunk","seq":97,"time":1781834683007,"data":{"turn":1,"step":2,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} +{"type":"assistant/chunk","seq":98,"time":1781834683008,"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 just \"DONE\"."}}}} +{"type":"assistant/chunk","seq":99,"time":1781834683008,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}}} +{"type":"assistant/chunk","seq":100,"time":1781834683008,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":235,"outputTokens":28,"cacheReadTokens":768,"reasoningTokens":25}}}} +{"type":"assistant/chunk","seq":101,"time":1781834683008,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":102,"time":1781834683008,"data":{"turn":1,"step":2,"content":[{"type":"reasoning","text":"The command ran successfully and output \"SNAPSHOT_OK\". Now I need to reply with just \"DONE\"."},{"type":"text","text":"DONE"}]}} +{"type":"usage","seq":103,"time":1781834683008,"data":{"turn":1,"step":2,"usage":{"inputTokens":235,"outputTokens":28,"cacheReadTokens":768,"reasoningTokens":25}}} +{"type":"step/end","seq":104,"time":1781834683008,"data":{"turn":1,"step":2}} +{"type":"turn/end","seq":105,"time":1781834683008,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.jsonl index c7169a8d7c..dff67d8e3a 100644 --- a/examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.jsonl +++ b/examples/acp-agent/tests/snapshots/tool-call-turn/stdout.golden.jsonl @@ -1,24 +1,30 @@ {"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":" `"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"echo"}}}} +{"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":" 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":" \""}}}} +{"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":"\"."}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call","toolCallId":"call_00_7bmU1TAadx8ADiZJ3BqC9330","title":"echo SNAPSHOT_OK","kind":"execute","status":"in_progress","rawInput":"echo SNAPSHOT_OK","content":[{"type":"content","content":{"type":"text","text":"Run echo SNAPSHOT_OK"}}]}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_00_7bmU1TAadx8ADiZJ3BqC9330","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"}}}} @@ -39,9 +45,7 @@ {"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":" just"}}}} {"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"}}}} diff --git a/examples/acp-agent/tests/snapshots/workspace-edit/session.golden.jsonl b/examples/acp-agent/tests/snapshots/workspace-edit/session.golden.jsonl index 013df575dc..4d84da80f0 100644 --- a/examples/acp-agent/tests/snapshots/workspace-edit/session.golden.jsonl +++ b/examples/acp-agent/tests/snapshots/workspace-edit/session.golden.jsonl @@ -3,329 +3,190 @@ {"type":"user/message","seq":1,"time":0,"data":{"content":[{"type":"text","text":"A file named greeting.txt in the current directory contains one word. Use the bash tool to append a second line containing the word WORLD to it (so it has two lines), then read the file back with `cat greeting.txt` to confirm, and reply with the single word DONE. Use a single bash call per action."}],"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":"Let"}}} -{"type":"assistant/chunk","seq":5,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} -{"type":"assistant/chunk","seq":6,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" break"}}} -{"type":"assistant/chunk","seq":7,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" this"}}} -{"type":"assistant/chunk","seq":8,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" down"}}} -{"type":"assistant/chunk","seq":9,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" into"}}} -{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" steps"}}} -{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":\n"}}} -{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"1"}}} -{"type":"assistant/chunk","seq":13,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":14,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" First"}}} -{"type":"assistant/chunk","seq":15,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} -{"type":"assistant/chunk","seq":16,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} -{"type":"assistant/chunk","seq":17,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":18,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":19,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":20,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" see"}}} -{"type":"assistant/chunk","seq":21,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" what"}}} -{"type":"assistant/chunk","seq":22,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"'s"}}} -{"type":"assistant/chunk","seq":23,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" in"}}} -{"type":"assistant/chunk","seq":24,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} -{"type":"assistant/chunk","seq":25,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} -{"type":"assistant/chunk","seq":26,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"2"}}} -{"type":"assistant/chunk","seq":27,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":28,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Then"}}} -{"type":"assistant/chunk","seq":29,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} -{"type":"assistant/chunk","seq":30,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":31,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} -{"type":"assistant/chunk","seq":32,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} -{"type":"assistant/chunk","seq":33,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":34,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" as"}}} -{"type":"assistant/chunk","seq":35,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} -{"type":"assistant/chunk","seq":36,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" second"}}} -{"type":"assistant/chunk","seq":37,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" line"}}} -{"type":"assistant/chunk","seq":38,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} -{"type":"assistant/chunk","seq":39,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"3"}}} -{"type":"assistant/chunk","seq":40,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":41,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Then"}}} -{"type":"assistant/chunk","seq":42,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} -{"type":"assistant/chunk","seq":43,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} -{"type":"assistant/chunk","seq":44,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" back"}}} -{"type":"assistant/chunk","seq":45,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} -{"type":"assistant/chunk","seq":46,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} -{"type":"assistant/chunk","seq":47,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n\n"}}} -{"type":"assistant/chunk","seq":48,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Wait"}}} -{"type":"assistant/chunk","seq":49,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} -{"type":"assistant/chunk","seq":50,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":51,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" instruction"}}} -{"type":"assistant/chunk","seq":52,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" says"}}} -{"type":"assistant/chunk","seq":53,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":54,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Use"}}} -{"type":"assistant/chunk","seq":55,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} -{"type":"assistant/chunk","seq":56,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}} -{"type":"assistant/chunk","seq":57,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":58,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":59,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" per"}}} -{"type":"assistant/chunk","seq":60,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} -{"type":"assistant/chunk","seq":61,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":62,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" -"}}} -{"type":"assistant/chunk","seq":63,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" but"}}} -{"type":"assistant/chunk","seq":64,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} -{"type":"assistant/chunk","seq":65,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" need"}}} -{"type":"assistant/chunk","seq":66,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":67,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} -{"type":"assistant/chunk","seq":68,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" multiple"}}} -{"type":"assistant/chunk","seq":69,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" actions"}}} -{"type":"assistant/chunk","seq":70,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":71,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Let"}}} -{"type":"assistant/chunk","seq":72,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} -{"type":"assistant/chunk","seq":73,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" re"}}} -{"type":"assistant/chunk","seq":74,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"-read"}}} -{"type":"assistant/chunk","seq":75,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".\n\n"}}} -{"type":"assistant/chunk","seq":76,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":77,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Use"}}} -{"type":"assistant/chunk","seq":78,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} -{"type":"assistant/chunk","seq":79,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}} -{"type":"assistant/chunk","seq":80,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":81,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":82,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" per"}}} -{"type":"assistant/chunk","seq":83,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} -{"type":"assistant/chunk","seq":84,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":85,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" -"}}} -{"type":"assistant/chunk","seq":86,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} -{"type":"assistant/chunk","seq":87,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" think"}}} -{"type":"assistant/chunk","seq":88,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" this"}}} -{"type":"assistant/chunk","seq":89,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" means"}}} -{"type":"assistant/chunk","seq":90,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" each"}}} -{"type":"assistant/chunk","seq":91,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} -{"type":"assistant/chunk","seq":92,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" should"}}} -{"type":"assistant/chunk","seq":93,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" be"}}} -{"type":"assistant/chunk","seq":94,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} -{"type":"assistant/chunk","seq":95,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" separate"}}} -{"type":"assistant/chunk","seq":96,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":97,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":98,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} -{"type":"assistant/chunk","seq":99,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" not"}}} -{"type":"assistant/chunk","seq":100,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" one"}}} -{"type":"assistant/chunk","seq":101,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" big"}}} -{"type":"assistant/chunk","seq":102,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":103,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":104,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".\n\n"}}} -{"type":"assistant/chunk","seq":105,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Let"}}} -{"type":"assistant/chunk","seq":106,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} -{"type":"assistant/chunk","seq":107,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} -{"type":"assistant/chunk","seq":108,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":\n"}}} -{"type":"assistant/chunk","seq":109,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"1"}}} -{"type":"assistant/chunk","seq":110,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":111,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" First"}}} -{"type":"assistant/chunk","seq":112,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":113,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":114,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} -{"type":"assistant/chunk","seq":115,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} -{"type":"assistant/chunk","seq":116,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":117,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":118,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":119,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" see"}}} -{"type":"assistant/chunk","seq":120,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":121,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" current"}}} -{"type":"assistant/chunk","seq":122,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" content"}}} -{"type":"assistant/chunk","seq":123,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} -{"type":"assistant/chunk","seq":124,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"2"}}} -{"type":"assistant/chunk","seq":125,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":126,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Second"}}} -{"type":"assistant/chunk","seq":127,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":128,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":129,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} -{"type":"assistant/chunk","seq":130,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} -{"type":"assistant/chunk","seq":131,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":132,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} -{"type":"assistant/chunk","seq":133,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} -{"type":"assistant/chunk","seq":134,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":135,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":136,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":137,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":138,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} -{"type":"assistant/chunk","seq":139,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"3"}}} -{"type":"assistant/chunk","seq":140,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":141,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Third"}}} -{"type":"assistant/chunk","seq":142,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":143,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":144,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} -{"type":"assistant/chunk","seq":145,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} -{"type":"assistant/chunk","seq":146,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":147,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":148,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":149,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" confirm"}}} -{"type":"assistant/chunk","seq":150,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n\n"}}} -{"type":"assistant/chunk","seq":151,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Actually"}}} -{"type":"assistant/chunk","seq":152,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} -{"type":"assistant/chunk","seq":153,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" let"}}} -{"type":"assistant/chunk","seq":154,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} -{"type":"assistant/chunk","seq":155,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" just"}}} -{"type":"assistant/chunk","seq":156,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} -{"type":"assistant/chunk","seq":157,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} -{"type":"assistant/chunk","seq":158,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" step"}}} -{"type":"assistant/chunk","seq":159,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" by"}}} -{"type":"assistant/chunk","seq":160,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" step"}}} -{"type":"assistant/chunk","seq":161,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":162,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":163,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":""}}} -{"type":"assistant/chunk","seq":164,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"{"}}} -{"type":"assistant/chunk","seq":165,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":166,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"command"}}} -{"type":"assistant/chunk","seq":167,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":168,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":169,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":170,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"cat"}}} -{"type":"assistant/chunk","seq":171,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" greeting"}}} -{"type":"assistant/chunk","seq":172,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":".txt"}}} -{"type":"assistant/chunk","seq":173,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":174,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":", "}}} -{"type":"assistant/chunk","seq":175,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":176,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"description"}}} -{"type":"assistant/chunk","seq":177,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":178,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":179,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":180,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"Read"}}} -{"type":"assistant/chunk","seq":181,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" current"}}} -{"type":"assistant/chunk","seq":182,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" content"}}} -{"type":"assistant/chunk","seq":183,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" of"}}} -{"type":"assistant/chunk","seq":184,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" greeting"}}} -{"type":"assistant/chunk","seq":185,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":".txt"}}} -{"type":"assistant/chunk","seq":186,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":187,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"}"}}} -{"type":"assistant/chunk","seq":188,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Let me break this down into steps:\n1. First, read the file to see what's in it\n2. Then append \"WORLD\" as a second line\n3. Then read it back with cat\n\nWait, the instruction says \"Use a single bash call per action\" - but I need to do multiple actions. Let me re-read.\n\n\"Use a single bash call per action\" - I think this means each action should be a separate bash call, not one big bash call.\n\nLet me do:\n1. First bash call: read the file to see the current content\n2. Second bash call: append \"WORLD\" to the file\n3. Third bash call: cat the file to confirm\n\nActually, let me just do it step by step."}}}} -{"type":"assistant/chunk","seq":189,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}}}} -{"type":"assistant/chunk","seq":190,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":168,"outputTokens":224,"cacheReadTokens":768,"reasoningTokens":158}}}} -{"type":"assistant/chunk","seq":191,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":192,"time":0,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"Let me break this down into steps:\n1. First, read the file to see what's in it\n2. Then append \"WORLD\" as a second line\n3. Then read it back with cat\n\nWait, the instruction says \"Use a single bash call per action\" - but I need to do multiple actions. Let me re-read.\n\n\"Use a single bash call per action\" - I think this means each action should be a separate bash call, not one big bash call.\n\nLet me do:\n1. First bash call: read the file to see the current content\n2. Second bash call: append \"WORLD\" to the file\n3. Third bash call: cat the file to confirm\n\nActually, let me just do it step by step."},{"type":"tool-call","id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}]}} -{"type":"usage","seq":193,"time":0,"data":{"turn":1,"step":1,"usage":{"inputTokens":168,"outputTokens":224,"cacheReadTokens":768,"reasoningTokens":158}}} -{"type":"tool/call","seq":194,"time":0,"data":{"turn":1,"step":1,"callId":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}} -{"type":"tool/result","seq":195,"time":0,"data":{"turn":1,"step":1,"callId":"call_00_J7zkTYNbCxhU7s0fIfIq4165","content":[{"type":"text","text":"hello\n"}],"isError":false}} -{"type":"step/end","seq":196,"time":0,"data":{"turn":1,"step":1}} -{"type":"step/start","seq":197,"time":0,"data":{"turn":1,"step":2}} -{"type":"assistant/chunk","seq":198,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} -{"type":"assistant/chunk","seq":199,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} -{"type":"assistant/chunk","seq":200,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":201,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" contains"}}} -{"type":"assistant/chunk","seq":202,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":203,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"hello"}}} -{"type":"assistant/chunk","seq":204,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} -{"type":"assistant/chunk","seq":205,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" Now"}}} -{"type":"assistant/chunk","seq":206,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} -{"type":"assistant/chunk","seq":207,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" need"}}} -{"type":"assistant/chunk","seq":208,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":209,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} -{"type":"assistant/chunk","seq":210,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":211,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} -{"type":"assistant/chunk","seq":212,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} -{"type":"assistant/chunk","seq":213,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":214,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" as"}}} -{"type":"assistant/chunk","seq":215,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} -{"type":"assistant/chunk","seq":216,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" second"}}} -{"type":"assistant/chunk","seq":217,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" line"}}} -{"type":"assistant/chunk","seq":218,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":219,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":220,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":""}}} -{"type":"assistant/chunk","seq":221,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"{"}}} -{"type":"assistant/chunk","seq":222,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":223,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"description"}}} -{"type":"assistant/chunk","seq":224,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":225,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":226,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":227,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"App"}}} -{"type":"assistant/chunk","seq":228,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"end"}}} -{"type":"assistant/chunk","seq":229,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" WORLD"}}} -{"type":"assistant/chunk","seq":230,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" as"}}} -{"type":"assistant/chunk","seq":231,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" second"}}} -{"type":"assistant/chunk","seq":232,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" line"}}} -{"type":"assistant/chunk","seq":233,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":234,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":", "}}} -{"type":"assistant/chunk","seq":235,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":236,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"command"}}} -{"type":"assistant/chunk","seq":237,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":238,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":239,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":240,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"echo"}}} -{"type":"assistant/chunk","seq":241,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" WORLD"}}} -{"type":"assistant/chunk","seq":242,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" >>"}}} -{"type":"assistant/chunk","seq":243,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" greeting"}}} -{"type":"assistant/chunk","seq":244,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":".txt"}}} -{"type":"assistant/chunk","seq":245,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":246,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"}"}}} -{"type":"assistant/chunk","seq":247,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The file contains \"hello\". Now I need to append \"WORLD\" as a second line."}}}} -{"type":"assistant/chunk","seq":248,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}}}} -{"type":"assistant/chunk","seq":249,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":278,"outputTokens":88,"cacheReadTokens":896,"reasoningTokens":20}}}} -{"type":"assistant/chunk","seq":250,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":251,"time":0,"data":{"turn":1,"step":2,"content":[{"type":"reasoning","text":"The file contains \"hello\". Now I need to append \"WORLD\" as a second line."},{"type":"tool-call","id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}]}} -{"type":"usage","seq":252,"time":0,"data":{"turn":1,"step":2,"usage":{"inputTokens":278,"outputTokens":88,"cacheReadTokens":896,"reasoningTokens":20}}} -{"type":"tool/call","seq":253,"time":0,"data":{"turn":1,"step":2,"callId":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}} -{"type":"tool/result","seq":254,"time":0,"data":{"turn":1,"step":2,"callId":"call_00_r6yugViLOxPuocpIvXrQ5342","content":[{"type":"text","text":"(no output)"}],"isError":false}} -{"type":"step/end","seq":255,"time":0,"data":{"turn":1,"step":2}} -{"type":"step/start","seq":256,"time":0,"data":{"turn":1,"step":3}} -{"type":"assistant/chunk","seq":257,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} -{"type":"assistant/chunk","seq":258,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"Now"}}} -{"type":"assistant/chunk","seq":259,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" confirm"}}} -{"type":"assistant/chunk","seq":260,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} -{"type":"assistant/chunk","seq":261,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} -{"type":"assistant/chunk","seq":262,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":263,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":264,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":""}}} -{"type":"assistant/chunk","seq":265,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"{"}}} -{"type":"assistant/chunk","seq":266,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":267,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"description"}}} -{"type":"assistant/chunk","seq":268,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":269,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":270,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":271,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"Confirm"}}} -{"type":"assistant/chunk","seq":272,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" file"}}} -{"type":"assistant/chunk","seq":273,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" content"}}} -{"type":"assistant/chunk","seq":274,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" with"}}} -{"type":"assistant/chunk","seq":275,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" cat"}}} -{"type":"assistant/chunk","seq":276,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":277,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":", "}}} -{"type":"assistant/chunk","seq":278,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":279,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"command"}}} -{"type":"assistant/chunk","seq":280,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":281,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":282,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":283,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"cat"}}} -{"type":"assistant/chunk","seq":284,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" greeting"}}} -{"type":"assistant/chunk","seq":285,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":".txt"}}} -{"type":"assistant/chunk","seq":286,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":287,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"}"}}} -{"type":"assistant/chunk","seq":288,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Now confirm with cat."}}}} -{"type":"assistant/chunk","seq":289,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}}}} -{"type":"assistant/chunk","seq":290,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":124,"outputTokens":70,"cacheReadTokens":1152,"reasoningTokens":5}}}} -{"type":"assistant/chunk","seq":291,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":292,"time":0,"data":{"turn":1,"step":3,"content":[{"type":"reasoning","text":"Now confirm with cat."},{"type":"tool-call","id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}]}} -{"type":"usage","seq":293,"time":0,"data":{"turn":1,"step":3,"usage":{"inputTokens":124,"outputTokens":70,"cacheReadTokens":1152,"reasoningTokens":5}}} -{"type":"tool/call","seq":294,"time":0,"data":{"turn":1,"step":3,"callId":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}} -{"type":"tool/result","seq":295,"time":0,"data":{"turn":1,"step":3,"callId":"call_00_SC1arlNU29Vn38HnR4Kp9691","content":[{"type":"text","text":"hello\nWORLD\n"}],"isError":false}} -{"type":"step/end","seq":296,"time":0,"data":{"turn":1,"step":3}} -{"type":"step/start","seq":297,"time":0,"data":{"turn":1,"step":4}} -{"type":"assistant/chunk","seq":298,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} -{"type":"assistant/chunk","seq":299,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} -{"type":"assistant/chunk","seq":300,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":301,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" now"}}} -{"type":"assistant/chunk","seq":302,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" has"}}} -{"type":"assistant/chunk","seq":303,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" two"}}} -{"type":"assistant/chunk","seq":304,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" lines"}}} -{"type":"assistant/chunk","seq":305,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} -{"type":"assistant/chunk","seq":306,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":307,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"hello"}}} -{"type":"assistant/chunk","seq":308,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":309,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} -{"type":"assistant/chunk","seq":310,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":311,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} -{"type":"assistant/chunk","seq":312,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} -{"type":"assistant/chunk","seq":313,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} -{"type":"assistant/chunk","seq":314,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" The"}}} -{"type":"assistant/chunk","seq":315,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" task"}}} -{"type":"assistant/chunk","seq":316,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" is"}}} -{"type":"assistant/chunk","seq":317,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" complete"}}} -{"type":"assistant/chunk","seq":318,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":319,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} -{"type":"assistant/chunk","seq":320,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"text-delta","index":1,"text":"D"}}} -{"type":"assistant/chunk","seq":321,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} -{"type":"assistant/chunk","seq":322,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The file now has two lines: \"hello\" and \"WORLD\". The task is complete."}}}} -{"type":"assistant/chunk","seq":323,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}}} -{"type":"assistant/chunk","seq":324,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"usage","usage":{"inputTokens":211,"outputTokens":23,"cacheReadTokens":1152,"reasoningTokens":20}}}} -{"type":"assistant/chunk","seq":325,"time":0,"data":{"turn":1,"step":4,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} -{"type":"assistant/message","seq":326,"time":0,"data":{"turn":1,"step":4,"content":[{"type":"reasoning","text":"The file now has two lines: \"hello\" and \"WORLD\". The task is complete."},{"type":"text","text":"DONE"}]}} -{"type":"usage","seq":327,"time":0,"data":{"turn":1,"step":4,"usage":{"inputTokens":211,"outputTokens":23,"cacheReadTokens":1152,"reasoningTokens":20}}} -{"type":"step/end","seq":328,"time":0,"data":{"turn":1,"step":4}} -{"type":"turn/end","seq":329,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}} +{"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":":\n"}}} +{"type":"assistant/chunk","seq":10,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"1"}}} +{"type":"assistant/chunk","seq":11,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":12,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Append"}}} +{"type":"assistant/chunk","seq":13,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":14,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" second"}}} +{"type":"assistant/chunk","seq":15,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" line"}}} +{"type":"assistant/chunk","seq":16,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" containing"}}} +{"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":"WOR"}}} +{"type":"assistant/chunk","seq":19,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} +{"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":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":22,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" greeting"}}} +{"type":"assistant/chunk","seq":23,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".txt"}}} +{"type":"assistant/chunk","seq":24,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":25,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"2"}}} +{"type":"assistant/chunk","seq":26,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":27,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Read"}}} +{"type":"assistant/chunk","seq":28,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":29,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":30,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" back"}}} +{"type":"assistant/chunk","seq":31,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":32,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" `"}}} +{"type":"assistant/chunk","seq":33,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"cat"}}} +{"type":"assistant/chunk","seq":34,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" greeting"}}} +{"type":"assistant/chunk","seq":35,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".txt"}}} +{"type":"assistant/chunk","seq":36,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"`"}}} +{"type":"assistant/chunk","seq":37,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":38,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" confirm"}}} +{"type":"assistant/chunk","seq":39,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":40,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"3"}}} +{"type":"assistant/chunk","seq":41,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":42,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Reply"}}} +{"type":"assistant/chunk","seq":43,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":44,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":45,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"D"}}} +{"type":"assistant/chunk","seq":46,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":47,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\"\n\n"}}} +{"type":"assistant/chunk","seq":48,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"But"}}} +{"type":"assistant/chunk","seq":49,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" they"}}} +{"type":"assistant/chunk","seq":50,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" want"}}} +{"type":"assistant/chunk","seq":51,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":52,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"a"}}} +{"type":"assistant/chunk","seq":53,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}} +{"type":"assistant/chunk","seq":54,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":55,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":56,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" per"}}} +{"type":"assistant/chunk","seq":57,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} +{"type":"assistant/chunk","seq":58,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":59,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" -"}}} +{"type":"assistant/chunk","seq":60,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" so"}}} +{"type":"assistant/chunk","seq":61,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":62,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"'ll"}}} +{"type":"assistant/chunk","seq":63,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} +{"type":"assistant/chunk","seq":64,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" two"}}} +{"type":"assistant/chunk","seq":65,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" separate"}}} +{"type":"assistant/chunk","seq":66,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":67,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" calls"}}} +{"type":"assistant/chunk","seq":68,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} +{"type":"assistant/chunk","seq":69,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" one"}}} +{"type":"assistant/chunk","seq":70,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" for"}}} +{"type":"assistant/chunk","seq":71,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" app"}}} +{"type":"assistant/chunk","seq":72,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"ending"}}} +{"type":"assistant/chunk","seq":73,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} +{"type":"assistant/chunk","seq":74,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" one"}}} +{"type":"assistant/chunk","seq":75,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" for"}}} +{"type":"assistant/chunk","seq":76,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reading"}}} +{"type":"assistant/chunk","seq":77,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":78,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":79,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":80,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":81,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":82,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":83,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":84,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":85,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":86,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"echo"}}} +{"type":"assistant/chunk","seq":87,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" '"}}} +{"type":"assistant/chunk","seq":88,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"WOR"}}} +{"type":"assistant/chunk","seq":89,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"LD"}}} +{"type":"assistant/chunk","seq":90,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"'"}}} +{"type":"assistant/chunk","seq":91,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" >>"}}} +{"type":"assistant/chunk","seq":92,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":93,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":94,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":95,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":96,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":97,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":98,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":99,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":100,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":101,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"App"}}} +{"type":"assistant/chunk","seq":102,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"end"}}} +{"type":"assistant/chunk","seq":103,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" WORLD"}}} +{"type":"assistant/chunk","seq":104,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" line"}}} +{"type":"assistant/chunk","seq":105,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" to"}}} +{"type":"assistant/chunk","seq":106,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":107,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":108,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":109,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":110,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Append a second line containing \"WORLD\" to greeting.txt\n2. Read the file back with `cat greeting.txt` to confirm\n3. Reply with \"DONE\"\n\nBut they want \"a single bash call per action\" - so I'll do two separate bash calls: one for appending, one for reading."}}}} +{"type":"assistant/chunk","seq":111,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","arguments":"{\"command\": \"echo 'WORLD' >> greeting.txt\", \"description\": \"Append WORLD line to greeting.txt\"}"}}}} +{"type":"assistant/chunk","seq":112,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":161,"outputTokens":146,"cacheReadTokens":768,"reasoningTokens":74}}}} +{"type":"assistant/chunk","seq":113,"time":0,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":114,"time":0,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to:\n1. Append a second line containing \"WORLD\" to greeting.txt\n2. Read the file back with `cat greeting.txt` to confirm\n3. Reply with \"DONE\"\n\nBut they want \"a single bash call per action\" - so I'll do two separate bash calls: one for appending, one for reading."},{"type":"tool-call","id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","arguments":"{\"command\": \"echo 'WORLD' >> greeting.txt\", \"description\": \"Append WORLD line to greeting.txt\"}"}]}} +{"type":"usage","seq":115,"time":0,"data":{"turn":1,"step":1,"usage":{"inputTokens":161,"outputTokens":146,"cacheReadTokens":768,"reasoningTokens":74}}} +{"type":"tool/call","seq":116,"time":0,"data":{"turn":1,"step":1,"callId":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","arguments":"{\"command\": \"echo 'WORLD' >> greeting.txt\", \"description\": \"Append WORLD line to greeting.txt\"}"}} +{"type":"tool/result","seq":117,"time":0,"data":{"turn":1,"step":1,"callId":"call_00_r3tvHl3fD0tmV0GKQt032338","content":[{"type":"text","text":"(no output)"}],"isError":false}} +{"type":"step/end","seq":118,"time":0,"data":{"turn":1,"step":1}} +{"type":"step/start","seq":119,"time":0,"data":{"turn":1,"step":2}} +{"type":"assistant/chunk","seq":120,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":121,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"App"}}} +{"type":"assistant/chunk","seq":122,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"ended"}}} +{"type":"assistant/chunk","seq":123,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" successfully"}}} +{"type":"assistant/chunk","seq":124,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":125,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" Now"}}} +{"type":"assistant/chunk","seq":126,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} +{"type":"assistant/chunk","seq":127,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":128,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":129,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":130,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":131,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":132,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":133,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":134,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":135,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":136,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":137,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":138,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"cat"}}} +{"type":"assistant/chunk","seq":139,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":140,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":141,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":142,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":143,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":144,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":145,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":146,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":147,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":148,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"Read"}}} +{"type":"assistant/chunk","seq":149,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":150,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":151,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":" to"}}} +{"type":"assistant/chunk","seq":152,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":" confirm"}}} +{"type":"assistant/chunk","seq":153,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":154,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":155,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Appended successfully. Now read the file."}}}} +{"type":"assistant/chunk","seq":156,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read greeting.txt to confirm\"}"}}}} +{"type":"assistant/chunk","seq":157,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":193,"outputTokens":74,"cacheReadTokens":896,"reasoningTokens":9}}}} +{"type":"assistant/chunk","seq":158,"time":0,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":159,"time":0,"data":{"turn":1,"step":2,"content":[{"type":"reasoning","text":"Appended successfully. Now read the file."},{"type":"tool-call","id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read greeting.txt to confirm\"}"}]}} +{"type":"usage","seq":160,"time":0,"data":{"turn":1,"step":2,"usage":{"inputTokens":193,"outputTokens":74,"cacheReadTokens":896,"reasoningTokens":9}}} +{"type":"tool/call","seq":161,"time":0,"data":{"turn":1,"step":2,"callId":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read greeting.txt to confirm\"}"}} +{"type":"tool/result","seq":162,"time":0,"data":{"turn":1,"step":2,"callId":"call_00_SkCP8dgN8aCbLiZDcYa68316","content":[{"type":"text","text":"hello\nWORLD\n"}],"isError":false}} +{"type":"step/end","seq":163,"time":0,"data":{"turn":1,"step":2}} +{"type":"step/start","seq":164,"time":0,"data":{"turn":1,"step":3}} +{"type":"assistant/chunk","seq":165,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":166,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":167,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":168,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" now"}}} +{"type":"assistant/chunk","seq":169,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" has"}}} +{"type":"assistant/chunk","seq":170,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" two"}}} +{"type":"assistant/chunk","seq":171,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" lines"}}} +{"type":"assistant/chunk","seq":172,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":173,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":174,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"'ll"}}} +{"type":"assistant/chunk","seq":175,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":176,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":177,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" D"}}} +{"type":"assistant/chunk","seq":178,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":179,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":180,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":181,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"text-delta","index":1,"text":"D"}}} +{"type":"assistant/chunk","seq":182,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} +{"type":"assistant/chunk","seq":183,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The file now has two lines. I'll reply with DONE."}}}} +{"type":"assistant/chunk","seq":184,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}}} +{"type":"assistant/chunk","seq":185,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":156,"outputTokens":17,"cacheReadTokens":1024,"reasoningTokens":14}}}} +{"type":"assistant/chunk","seq":186,"time":0,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":187,"time":0,"data":{"turn":1,"step":3,"content":[{"type":"reasoning","text":"The file now has two lines. I'll reply with DONE."},{"type":"text","text":"DONE"}]}} +{"type":"usage","seq":188,"time":0,"data":{"turn":1,"step":3,"usage":{"inputTokens":156,"outputTokens":17,"cacheReadTokens":1024,"reasoningTokens":14}}} +{"type":"step/end","seq":189,"time":0,"data":{"turn":1,"step":3}} +{"type":"turn/end","seq":190,"time":0,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl b/examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl index 0062a9e77c..3baefe4e86 100644 --- a/examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl +++ b/examples/acp-agent/tests/snapshots/workspace-edit/session.jsonl @@ -1,331 +1,192 @@ -{"type":"session","version":1,"id":"9beaf658-0308-440c-b83e-51a82666d594","createdAt":1781834404758,"cwd":"/tmp/acp-snap-cwd-rRY3xl"} -{"type":"turn/start","seq":0,"time":1781834404760,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}} -{"type":"user/message","seq":1,"time":1781834404761,"data":{"content":[{"type":"text","text":"A file named greeting.txt in the current directory contains one word. Use the bash tool to append a second line containing the word WORLD to it (so it has two lines), then read the file back with `cat greeting.txt` to confirm, and reply with the single word DONE. Use a single bash call per action."}],"source":{"kind":"user"}}} -{"type":"step/start","seq":2,"time":1781834404761,"data":{"turn":1,"step":1}} -{"type":"assistant/chunk","seq":3,"time":1781834405182,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} -{"type":"assistant/chunk","seq":4,"time":1781834405182,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Let"}}} -{"type":"assistant/chunk","seq":5,"time":1781834405277,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} -{"type":"assistant/chunk","seq":6,"time":1781834405305,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" break"}}} -{"type":"assistant/chunk","seq":7,"time":1781834405305,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" this"}}} -{"type":"assistant/chunk","seq":8,"time":1781834405305,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" down"}}} -{"type":"assistant/chunk","seq":9,"time":1781834405333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" into"}}} -{"type":"assistant/chunk","seq":10,"time":1781834405334,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" steps"}}} -{"type":"assistant/chunk","seq":11,"time":1781834405362,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":\n"}}} -{"type":"assistant/chunk","seq":12,"time":1781834405362,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"1"}}} -{"type":"assistant/chunk","seq":13,"time":1781834405362,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":14,"time":1781834405363,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" First"}}} -{"type":"assistant/chunk","seq":15,"time":1781834405363,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} -{"type":"assistant/chunk","seq":16,"time":1781834405396,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} -{"type":"assistant/chunk","seq":17,"time":1781834405419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":18,"time":1781834405419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":19,"time":1781834405419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":20,"time":1781834405419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" see"}}} -{"type":"assistant/chunk","seq":21,"time":1781834405447,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" what"}}} -{"type":"assistant/chunk","seq":22,"time":1781834405448,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"'s"}}} -{"type":"assistant/chunk","seq":23,"time":1781834405448,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" in"}}} -{"type":"assistant/chunk","seq":24,"time":1781834405448,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} -{"type":"assistant/chunk","seq":25,"time":1781834405477,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} -{"type":"assistant/chunk","seq":26,"time":1781834405477,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"2"}}} -{"type":"assistant/chunk","seq":27,"time":1781834405478,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":28,"time":1781834405478,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Then"}}} -{"type":"assistant/chunk","seq":29,"time":1781834405505,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} -{"type":"assistant/chunk","seq":30,"time":1781834405506,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":31,"time":1781834405534,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} -{"type":"assistant/chunk","seq":32,"time":1781834405535,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} -{"type":"assistant/chunk","seq":33,"time":1781834405535,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":34,"time":1781834405535,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" as"}}} -{"type":"assistant/chunk","seq":35,"time":1781834405562,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} -{"type":"assistant/chunk","seq":36,"time":1781834405563,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" second"}}} -{"type":"assistant/chunk","seq":37,"time":1781834405591,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" line"}}} -{"type":"assistant/chunk","seq":38,"time":1781834405591,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} -{"type":"assistant/chunk","seq":39,"time":1781834405592,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"3"}}} -{"type":"assistant/chunk","seq":40,"time":1781834405592,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":41,"time":1781834405592,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Then"}}} -{"type":"assistant/chunk","seq":42,"time":1781834405623,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} -{"type":"assistant/chunk","seq":43,"time":1781834405623,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} -{"type":"assistant/chunk","seq":44,"time":1781834405624,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" back"}}} -{"type":"assistant/chunk","seq":45,"time":1781834405624,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} -{"type":"assistant/chunk","seq":46,"time":1781834405648,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} -{"type":"assistant/chunk","seq":47,"time":1781834405649,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n\n"}}} -{"type":"assistant/chunk","seq":48,"time":1781834405649,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Wait"}}} -{"type":"assistant/chunk","seq":49,"time":1781834405649,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} -{"type":"assistant/chunk","seq":50,"time":1781834405649,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":51,"time":1781834405676,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" instruction"}}} -{"type":"assistant/chunk","seq":52,"time":1781834405677,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" says"}}} -{"type":"assistant/chunk","seq":53,"time":1781834405677,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":54,"time":1781834405677,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Use"}}} -{"type":"assistant/chunk","seq":55,"time":1781834405677,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} -{"type":"assistant/chunk","seq":56,"time":1781834405677,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}} -{"type":"assistant/chunk","seq":57,"time":1781834405705,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":58,"time":1781834405705,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":59,"time":1781834405705,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" per"}}} -{"type":"assistant/chunk","seq":60,"time":1781834405705,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} -{"type":"assistant/chunk","seq":61,"time":1781834405705,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":62,"time":1781834405706,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" -"}}} -{"type":"assistant/chunk","seq":63,"time":1781834405734,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" but"}}} -{"type":"assistant/chunk","seq":64,"time":1781834405735,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} -{"type":"assistant/chunk","seq":65,"time":1781834405735,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" need"}}} -{"type":"assistant/chunk","seq":66,"time":1781834405735,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":67,"time":1781834405735,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} -{"type":"assistant/chunk","seq":68,"time":1781834405762,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" multiple"}}} -{"type":"assistant/chunk","seq":69,"time":1781834405800,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" actions"}}} -{"type":"assistant/chunk","seq":70,"time":1781834405800,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":71,"time":1781834405801,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Let"}}} -{"type":"assistant/chunk","seq":72,"time":1781834405801,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} -{"type":"assistant/chunk","seq":73,"time":1781834405801,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" re"}}} -{"type":"assistant/chunk","seq":74,"time":1781834405819,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"-read"}}} -{"type":"assistant/chunk","seq":75,"time":1781834405820,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".\n\n"}}} -{"type":"assistant/chunk","seq":76,"time":1781834405820,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":77,"time":1781834405820,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Use"}}} -{"type":"assistant/chunk","seq":78,"time":1781834405820,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} -{"type":"assistant/chunk","seq":79,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}} -{"type":"assistant/chunk","seq":80,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":81,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":82,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" per"}}} -{"type":"assistant/chunk","seq":83,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} -{"type":"assistant/chunk","seq":84,"time":1781834405848,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":85,"time":1781834405876,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" -"}}} -{"type":"assistant/chunk","seq":86,"time":1781834405877,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} -{"type":"assistant/chunk","seq":87,"time":1781834405877,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" think"}}} -{"type":"assistant/chunk","seq":88,"time":1781834405877,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" this"}}} -{"type":"assistant/chunk","seq":89,"time":1781834405905,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" means"}}} -{"type":"assistant/chunk","seq":90,"time":1781834405906,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" each"}}} -{"type":"assistant/chunk","seq":91,"time":1781834405906,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} -{"type":"assistant/chunk","seq":92,"time":1781834405906,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" should"}}} -{"type":"assistant/chunk","seq":93,"time":1781834405933,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" be"}}} -{"type":"assistant/chunk","seq":94,"time":1781834405934,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} -{"type":"assistant/chunk","seq":95,"time":1781834405962,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" separate"}}} -{"type":"assistant/chunk","seq":96,"time":1781834405962,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":97,"time":1781834405962,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":98,"time":1781834405962,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} -{"type":"assistant/chunk","seq":99,"time":1781834405963,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" not"}}} -{"type":"assistant/chunk","seq":100,"time":1781834405990,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" one"}}} -{"type":"assistant/chunk","seq":101,"time":1781834406018,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" big"}}} -{"type":"assistant/chunk","seq":102,"time":1781834406047,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":103,"time":1781834406048,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":104,"time":1781834406075,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".\n\n"}}} -{"type":"assistant/chunk","seq":105,"time":1781834406076,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Let"}}} -{"type":"assistant/chunk","seq":106,"time":1781834406076,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} -{"type":"assistant/chunk","seq":107,"time":1781834406076,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} -{"type":"assistant/chunk","seq":108,"time":1781834406103,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":\n"}}} -{"type":"assistant/chunk","seq":109,"time":1781834406104,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"1"}}} -{"type":"assistant/chunk","seq":110,"time":1781834406104,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":111,"time":1781834406104,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" First"}}} -{"type":"assistant/chunk","seq":112,"time":1781834406132,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":113,"time":1781834406133,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":114,"time":1781834406160,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} -{"type":"assistant/chunk","seq":115,"time":1781834406161,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} -{"type":"assistant/chunk","seq":116,"time":1781834406161,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":117,"time":1781834406190,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":118,"time":1781834406191,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":119,"time":1781834406218,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" see"}}} -{"type":"assistant/chunk","seq":120,"time":1781834406219,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":121,"time":1781834406219,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" current"}}} -{"type":"assistant/chunk","seq":122,"time":1781834406219,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" content"}}} -{"type":"assistant/chunk","seq":123,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} -{"type":"assistant/chunk","seq":124,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"2"}}} -{"type":"assistant/chunk","seq":125,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":126,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Second"}}} -{"type":"assistant/chunk","seq":127,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":128,"time":1781834406247,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":129,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} -{"type":"assistant/chunk","seq":130,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} -{"type":"assistant/chunk","seq":131,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":132,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} -{"type":"assistant/chunk","seq":133,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} -{"type":"assistant/chunk","seq":134,"time":1781834406276,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":135,"time":1781834406305,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":136,"time":1781834406306,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":137,"time":1781834406306,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":138,"time":1781834406332,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} -{"type":"assistant/chunk","seq":139,"time":1781834406333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"3"}}} -{"type":"assistant/chunk","seq":140,"time":1781834406333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":141,"time":1781834406333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Third"}}} -{"type":"assistant/chunk","seq":142,"time":1781834406333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} -{"type":"assistant/chunk","seq":143,"time":1781834406333,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} -{"type":"assistant/chunk","seq":144,"time":1781834406361,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} -{"type":"assistant/chunk","seq":145,"time":1781834406362,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} -{"type":"assistant/chunk","seq":146,"time":1781834406390,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} -{"type":"assistant/chunk","seq":147,"time":1781834406390,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":148,"time":1781834406390,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":149,"time":1781834406418,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" confirm"}}} -{"type":"assistant/chunk","seq":150,"time":1781834406419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n\n"}}} -{"type":"assistant/chunk","seq":151,"time":1781834406419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"Actually"}}} -{"type":"assistant/chunk","seq":152,"time":1781834406419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} -{"type":"assistant/chunk","seq":153,"time":1781834406419,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" let"}}} -{"type":"assistant/chunk","seq":154,"time":1781834406446,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} -{"type":"assistant/chunk","seq":155,"time":1781834406447,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" just"}}} -{"type":"assistant/chunk","seq":156,"time":1781834406447,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} -{"type":"assistant/chunk","seq":157,"time":1781834406447,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" it"}}} -{"type":"assistant/chunk","seq":158,"time":1781834406476,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" step"}}} -{"type":"assistant/chunk","seq":159,"time":1781834406476,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" by"}}} -{"type":"assistant/chunk","seq":160,"time":1781834406477,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" step"}}} -{"type":"assistant/chunk","seq":161,"time":1781834406477,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":162,"time":1781834406562,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":163,"time":1781834406562,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":""}}} -{"type":"assistant/chunk","seq":164,"time":1781834406589,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"{"}}} -{"type":"assistant/chunk","seq":165,"time":1781834406590,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":166,"time":1781834406590,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"command"}}} -{"type":"assistant/chunk","seq":167,"time":1781834406590,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":168,"time":1781834406590,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":169,"time":1781834406618,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":170,"time":1781834406619,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"cat"}}} -{"type":"assistant/chunk","seq":171,"time":1781834406619,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" greeting"}}} -{"type":"assistant/chunk","seq":172,"time":1781834406619,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":".txt"}}} -{"type":"assistant/chunk","seq":173,"time":1781834406647,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":174,"time":1781834406675,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":", "}}} -{"type":"assistant/chunk","seq":175,"time":1781834406676,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":176,"time":1781834406676,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"description"}}} -{"type":"assistant/chunk","seq":177,"time":1781834406676,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":178,"time":1781834406676,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":179,"time":1781834406705,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":180,"time":1781834406705,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"Read"}}} -{"type":"assistant/chunk","seq":181,"time":1781834406705,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" current"}}} -{"type":"assistant/chunk","seq":182,"time":1781834406705,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" content"}}} -{"type":"assistant/chunk","seq":183,"time":1781834406733,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" of"}}} -{"type":"assistant/chunk","seq":184,"time":1781834406733,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":" greeting"}}} -{"type":"assistant/chunk","seq":185,"time":1781834406733,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":".txt"}}} -{"type":"assistant/chunk","seq":186,"time":1781834406733,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":187,"time":1781834406761,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","argumentsDelta":"}"}}} -{"type":"assistant/chunk","seq":188,"time":1781834406823,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Let me break this down into steps:\n1. First, read the file to see what's in it\n2. Then append \"WORLD\" as a second line\n3. Then read it back with cat\n\nWait, the instruction says \"Use a single bash call per action\" - but I need to do multiple actions. Let me re-read.\n\n\"Use a single bash call per action\" - I think this means each action should be a separate bash call, not one big bash call.\n\nLet me do:\n1. First bash call: read the file to see the current content\n2. Second bash call: append \"WORLD\" to the file\n3. Third bash call: cat the file to confirm\n\nActually, let me just do it step by step."}}}} -{"type":"assistant/chunk","seq":189,"time":1781834406824,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}}}} -{"type":"assistant/chunk","seq":190,"time":1781834406824,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":168,"outputTokens":224,"cacheReadTokens":768,"reasoningTokens":158}}}} -{"type":"assistant/chunk","seq":191,"time":1781834406824,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":192,"time":1781834406825,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"Let me break this down into steps:\n1. First, read the file to see what's in it\n2. Then append \"WORLD\" as a second line\n3. Then read it back with cat\n\nWait, the instruction says \"Use a single bash call per action\" - but I need to do multiple actions. Let me re-read.\n\n\"Use a single bash call per action\" - I think this means each action should be a separate bash call, not one big bash call.\n\nLet me do:\n1. First bash call: read the file to see the current content\n2. Second bash call: append \"WORLD\" to the file\n3. Third bash call: cat the file to confirm\n\nActually, let me just do it step by step."},{"type":"tool-call","id":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}]}} -{"type":"usage","seq":193,"time":1781834406826,"data":{"turn":1,"step":1,"usage":{"inputTokens":168,"outputTokens":224,"cacheReadTokens":768,"reasoningTokens":158}}} -{"type":"tool/call","seq":194,"time":1781834406826,"data":{"turn":1,"step":1,"callId":"call_00_J7zkTYNbCxhU7s0fIfIq4165","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read current content of greeting.txt\"}"}} -{"type":"tool/result","seq":195,"time":1781834406858,"data":{"turn":1,"step":1,"callId":"call_00_J7zkTYNbCxhU7s0fIfIq4165","content":[{"type":"text","text":"hello\n"}],"isError":false}} -{"type":"step/end","seq":196,"time":1781834406859,"data":{"turn":1,"step":1}} -{"type":"step/start","seq":197,"time":1781834406859,"data":{"turn":1,"step":2}} -{"type":"assistant/chunk","seq":198,"time":1781834407670,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} -{"type":"assistant/chunk","seq":199,"time":1781834407670,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} -{"type":"assistant/chunk","seq":200,"time":1781834407822,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":201,"time":1781834407851,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" contains"}}} -{"type":"assistant/chunk","seq":202,"time":1781834407851,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":203,"time":1781834407851,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"hello"}}} -{"type":"assistant/chunk","seq":204,"time":1781834407851,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} -{"type":"assistant/chunk","seq":205,"time":1781834407851,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" Now"}}} -{"type":"assistant/chunk","seq":206,"time":1781834407852,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} -{"type":"assistant/chunk","seq":207,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" need"}}} -{"type":"assistant/chunk","seq":208,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} -{"type":"assistant/chunk","seq":209,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" append"}}} -{"type":"assistant/chunk","seq":210,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":211,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} -{"type":"assistant/chunk","seq":212,"time":1781834407880,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} -{"type":"assistant/chunk","seq":213,"time":1781834407908,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":214,"time":1781834407908,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" as"}}} -{"type":"assistant/chunk","seq":215,"time":1781834407908,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} -{"type":"assistant/chunk","seq":216,"time":1781834407908,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" second"}}} -{"type":"assistant/chunk","seq":217,"time":1781834407908,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" line"}}} -{"type":"assistant/chunk","seq":218,"time":1781834407909,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":219,"time":1781834407994,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":220,"time":1781834407994,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":""}}} -{"type":"assistant/chunk","seq":221,"time":1781834408022,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"{"}}} -{"type":"assistant/chunk","seq":222,"time":1781834408023,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":223,"time":1781834408023,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"description"}}} -{"type":"assistant/chunk","seq":224,"time":1781834408051,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":225,"time":1781834408051,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":226,"time":1781834408051,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":227,"time":1781834408051,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"App"}}} -{"type":"assistant/chunk","seq":228,"time":1781834408079,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"end"}}} -{"type":"assistant/chunk","seq":229,"time":1781834408080,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" WORLD"}}} -{"type":"assistant/chunk","seq":230,"time":1781834408080,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" as"}}} -{"type":"assistant/chunk","seq":231,"time":1781834408080,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" second"}}} -{"type":"assistant/chunk","seq":232,"time":1781834408080,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" line"}}} -{"type":"assistant/chunk","seq":233,"time":1781834408137,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":234,"time":1781834408165,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":", "}}} -{"type":"assistant/chunk","seq":235,"time":1781834408165,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":236,"time":1781834408165,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"command"}}} -{"type":"assistant/chunk","seq":237,"time":1781834408165,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":238,"time":1781834408165,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":239,"time":1781834408193,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":240,"time":1781834408193,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"echo"}}} -{"type":"assistant/chunk","seq":241,"time":1781834408194,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" WORLD"}}} -{"type":"assistant/chunk","seq":242,"time":1781834408222,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" >>"}}} -{"type":"assistant/chunk","seq":243,"time":1781834408222,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":" greeting"}}} -{"type":"assistant/chunk","seq":244,"time":1781834408222,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":".txt"}}} -{"type":"assistant/chunk","seq":245,"time":1781834408222,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":246,"time":1781834408255,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","argumentsDelta":"}"}}} -{"type":"assistant/chunk","seq":247,"time":1781834408309,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The file contains \"hello\". Now I need to append \"WORLD\" as a second line."}}}} -{"type":"assistant/chunk","seq":248,"time":1781834408309,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}}}} -{"type":"assistant/chunk","seq":249,"time":1781834408309,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":278,"outputTokens":88,"cacheReadTokens":896,"reasoningTokens":20}}}} -{"type":"assistant/chunk","seq":250,"time":1781834408309,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":251,"time":1781834408310,"data":{"turn":1,"step":2,"content":[{"type":"reasoning","text":"The file contains \"hello\". Now I need to append \"WORLD\" as a second line."},{"type":"tool-call","id":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}]}} -{"type":"usage","seq":252,"time":1781834408310,"data":{"turn":1,"step":2,"usage":{"inputTokens":278,"outputTokens":88,"cacheReadTokens":896,"reasoningTokens":20}}} -{"type":"tool/call","seq":253,"time":1781834408310,"data":{"turn":1,"step":2,"callId":"call_00_r6yugViLOxPuocpIvXrQ5342","name":"bash","arguments":"{\"description\": \"Append WORLD as second line\", \"command\": \"echo WORLD >> greeting.txt\"}"}} -{"type":"tool/result","seq":254,"time":1781834408321,"data":{"turn":1,"step":2,"callId":"call_00_r6yugViLOxPuocpIvXrQ5342","content":[{"type":"text","text":"(no output)"}],"isError":false}} -{"type":"step/end","seq":255,"time":1781834408321,"data":{"turn":1,"step":2}} -{"type":"step/start","seq":256,"time":1781834408321,"data":{"turn":1,"step":3}} -{"type":"assistant/chunk","seq":257,"time":1781834408885,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} -{"type":"assistant/chunk","seq":258,"time":1781834408885,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"Now"}}} -{"type":"assistant/chunk","seq":259,"time":1781834409001,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" confirm"}}} -{"type":"assistant/chunk","seq":260,"time":1781834409032,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} -{"type":"assistant/chunk","seq":261,"time":1781834409033,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" cat"}}} -{"type":"assistant/chunk","seq":262,"time":1781834409033,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":263,"time":1781834409113,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} -{"type":"assistant/chunk","seq":264,"time":1781834409113,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":""}}} -{"type":"assistant/chunk","seq":265,"time":1781834409142,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"{"}}} -{"type":"assistant/chunk","seq":266,"time":1781834409142,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":267,"time":1781834409142,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"description"}}} -{"type":"assistant/chunk","seq":268,"time":1781834409142,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":269,"time":1781834409142,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":270,"time":1781834409170,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":271,"time":1781834409171,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"Confirm"}}} -{"type":"assistant/chunk","seq":272,"time":1781834409171,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" file"}}} -{"type":"assistant/chunk","seq":273,"time":1781834409199,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" content"}}} -{"type":"assistant/chunk","seq":274,"time":1781834409199,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" with"}}} -{"type":"assistant/chunk","seq":275,"time":1781834409199,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" cat"}}} -{"type":"assistant/chunk","seq":276,"time":1781834409229,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":277,"time":1781834409261,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":", "}}} -{"type":"assistant/chunk","seq":278,"time":1781834409261,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":279,"time":1781834409261,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"command"}}} -{"type":"assistant/chunk","seq":280,"time":1781834409261,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":281,"time":1781834409261,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":": "}}} -{"type":"assistant/chunk","seq":282,"time":1781834409289,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":283,"time":1781834409289,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"cat"}}} -{"type":"assistant/chunk","seq":284,"time":1781834409289,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":" greeting"}}} -{"type":"assistant/chunk","seq":285,"time":1781834409289,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":".txt"}}} -{"type":"assistant/chunk","seq":286,"time":1781834409317,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"\""}}} -{"type":"assistant/chunk","seq":287,"time":1781834409317,"data":{"turn":1,"step":3,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","argumentsDelta":"}"}}} -{"type":"assistant/chunk","seq":288,"time":1781834409374,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Now confirm with cat."}}}} -{"type":"assistant/chunk","seq":289,"time":1781834409374,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}}}} -{"type":"assistant/chunk","seq":290,"time":1781834409374,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":124,"outputTokens":70,"cacheReadTokens":1152,"reasoningTokens":5}}}} -{"type":"assistant/chunk","seq":291,"time":1781834409374,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} -{"type":"assistant/message","seq":292,"time":1781834409375,"data":{"turn":1,"step":3,"content":[{"type":"reasoning","text":"Now confirm with cat."},{"type":"tool-call","id":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}]}} -{"type":"usage","seq":293,"time":1781834409375,"data":{"turn":1,"step":3,"usage":{"inputTokens":124,"outputTokens":70,"cacheReadTokens":1152,"reasoningTokens":5}}} -{"type":"tool/call","seq":294,"time":1781834409375,"data":{"turn":1,"step":3,"callId":"call_00_SC1arlNU29Vn38HnR4Kp9691","name":"bash","arguments":"{\"description\": \"Confirm file content with cat\", \"command\": \"cat greeting.txt\"}"}} -{"type":"tool/result","seq":295,"time":1781834409389,"data":{"turn":1,"step":3,"callId":"call_00_SC1arlNU29Vn38HnR4Kp9691","content":[{"type":"text","text":"hello\nWORLD\n"}],"isError":false}} -{"type":"step/end","seq":296,"time":1781834409389,"data":{"turn":1,"step":3}} -{"type":"step/start","seq":297,"time":1781834409389,"data":{"turn":1,"step":4}} -{"type":"assistant/chunk","seq":298,"time":1781834410109,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} -{"type":"assistant/chunk","seq":299,"time":1781834410109,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} -{"type":"assistant/chunk","seq":300,"time":1781834410216,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} -{"type":"assistant/chunk","seq":301,"time":1781834410245,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" now"}}} -{"type":"assistant/chunk","seq":302,"time":1781834410245,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" has"}}} -{"type":"assistant/chunk","seq":303,"time":1781834410245,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" two"}}} -{"type":"assistant/chunk","seq":304,"time":1781834410245,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" lines"}}} -{"type":"assistant/chunk","seq":305,"time":1781834410274,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} -{"type":"assistant/chunk","seq":306,"time":1781834410274,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":307,"time":1781834410274,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"hello"}}} -{"type":"assistant/chunk","seq":308,"time":1781834410274,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} -{"type":"assistant/chunk","seq":309,"time":1781834410274,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" and"}}} -{"type":"assistant/chunk","seq":310,"time":1781834410275,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} -{"type":"assistant/chunk","seq":311,"time":1781834410302,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} -{"type":"assistant/chunk","seq":312,"time":1781834410302,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} -{"type":"assistant/chunk","seq":313,"time":1781834410302,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"\"."}}} -{"type":"assistant/chunk","seq":314,"time":1781834410302,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" The"}}} -{"type":"assistant/chunk","seq":315,"time":1781834410302,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" task"}}} -{"type":"assistant/chunk","seq":316,"time":1781834410330,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" is"}}} -{"type":"assistant/chunk","seq":317,"time":1781834410331,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":" complete"}}} -{"type":"assistant/chunk","seq":318,"time":1781834410331,"data":{"turn":1,"step":4,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} -{"type":"assistant/chunk","seq":319,"time":1781834410331,"data":{"turn":1,"step":4,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} -{"type":"assistant/chunk","seq":320,"time":1781834410331,"data":{"turn":1,"step":4,"chunk":{"type":"text-delta","index":1,"text":"D"}}} -{"type":"assistant/chunk","seq":321,"time":1781834410331,"data":{"turn":1,"step":4,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} -{"type":"assistant/chunk","seq":322,"time":1781834410359,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The file now has two lines: \"hello\" and \"WORLD\". The task is complete."}}}} -{"type":"assistant/chunk","seq":323,"time":1781834410360,"data":{"turn":1,"step":4,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}}} -{"type":"assistant/chunk","seq":324,"time":1781834410360,"data":{"turn":1,"step":4,"chunk":{"type":"usage","usage":{"inputTokens":211,"outputTokens":23,"cacheReadTokens":1152,"reasoningTokens":20}}}} -{"type":"assistant/chunk","seq":325,"time":1781834410360,"data":{"turn":1,"step":4,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} -{"type":"assistant/message","seq":326,"time":1781834410360,"data":{"turn":1,"step":4,"content":[{"type":"reasoning","text":"The file now has two lines: \"hello\" and \"WORLD\". The task is complete."},{"type":"text","text":"DONE"}]}} -{"type":"usage","seq":327,"time":1781834410360,"data":{"turn":1,"step":4,"usage":{"inputTokens":211,"outputTokens":23,"cacheReadTokens":1152,"reasoningTokens":20}}} -{"type":"step/end","seq":328,"time":1781834410360,"data":{"turn":1,"step":4}} -{"type":"turn/end","seq":329,"time":1781834410360,"data":{"turn":1,"reason":{"kind":"completed"}}} +{"type":"session","version":1,"id":"06bd4899-ec95-43e3-82ca-42c719d8b19b","createdAt":1781834683850,"cwd":"/tmp/acp-snap-cwd-Jsq2M2"} +{"type":"turn/start","seq":0,"time":1781834683853,"data":{"turn":1,"trigger":{"kind":"message","source":{"kind":"user"}}}} +{"type":"user/message","seq":1,"time":1781834683854,"data":{"content":[{"type":"text","text":"A file named greeting.txt in the current directory contains one word. Use the bash tool to append a second line containing the word WORLD to it (so it has two lines), then read the file back with `cat greeting.txt` to confirm, and reply with the single word DONE. Use a single bash call per action."}],"source":{"kind":"user"}}} +{"type":"step/start","seq":2,"time":1781834683854,"data":{"turn":1,"step":1}} +{"type":"assistant/chunk","seq":3,"time":1781834684260,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":4,"time":1781834684260,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":5,"time":1781834684370,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" user"}}} +{"type":"assistant/chunk","seq":6,"time":1781834684399,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" wants"}}} +{"type":"assistant/chunk","seq":7,"time":1781834684399,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" me"}}} +{"type":"assistant/chunk","seq":8,"time":1781834684400,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":9,"time":1781834684400,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":\n"}}} +{"type":"assistant/chunk","seq":10,"time":1781834684400,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"1"}}} +{"type":"assistant/chunk","seq":11,"time":1781834684400,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":12,"time":1781834684428,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Append"}}} +{"type":"assistant/chunk","seq":13,"time":1781834684429,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" a"}}} +{"type":"assistant/chunk","seq":14,"time":1781834684430,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" second"}}} +{"type":"assistant/chunk","seq":15,"time":1781834684430,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" line"}}} +{"type":"assistant/chunk","seq":16,"time":1781834684430,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" containing"}}} +{"type":"assistant/chunk","seq":17,"time":1781834684458,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":18,"time":1781834684458,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"WOR"}}} +{"type":"assistant/chunk","seq":19,"time":1781834684458,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"LD"}}} +{"type":"assistant/chunk","seq":20,"time":1781834684459,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":21,"time":1781834684459,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":22,"time":1781834684459,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" greeting"}}} +{"type":"assistant/chunk","seq":23,"time":1781834684486,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".txt"}}} +{"type":"assistant/chunk","seq":24,"time":1781834684487,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":25,"time":1781834684487,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"2"}}} +{"type":"assistant/chunk","seq":26,"time":1781834684487,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":27,"time":1781834684487,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Read"}}} +{"type":"assistant/chunk","seq":28,"time":1781834684516,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":29,"time":1781834684516,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":30,"time":1781834684516,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" back"}}} +{"type":"assistant/chunk","seq":31,"time":1781834684545,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":32,"time":1781834684545,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" `"}}} +{"type":"assistant/chunk","seq":33,"time":1781834684545,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"cat"}}} +{"type":"assistant/chunk","seq":34,"time":1781834684545,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" greeting"}}} +{"type":"assistant/chunk","seq":35,"time":1781834684574,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":".txt"}}} +{"type":"assistant/chunk","seq":36,"time":1781834684574,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"`"}}} +{"type":"assistant/chunk","seq":37,"time":1781834684574,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" to"}}} +{"type":"assistant/chunk","seq":38,"time":1781834684574,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" confirm"}}} +{"type":"assistant/chunk","seq":39,"time":1781834684603,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\n"}}} +{"type":"assistant/chunk","seq":40,"time":1781834684604,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"3"}}} +{"type":"assistant/chunk","seq":41,"time":1781834684604,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":42,"time":1781834684604,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" Reply"}}} +{"type":"assistant/chunk","seq":43,"time":1781834684604,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":44,"time":1781834684632,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":45,"time":1781834684633,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"D"}}} +{"type":"assistant/chunk","seq":46,"time":1781834684633,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":47,"time":1781834684662,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\"\n\n"}}} +{"type":"assistant/chunk","seq":48,"time":1781834684663,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"But"}}} +{"type":"assistant/chunk","seq":49,"time":1781834684663,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" they"}}} +{"type":"assistant/chunk","seq":50,"time":1781834684663,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" want"}}} +{"type":"assistant/chunk","seq":51,"time":1781834684695,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" \""}}} +{"type":"assistant/chunk","seq":52,"time":1781834684695,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"a"}}} +{"type":"assistant/chunk","seq":53,"time":1781834684724,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" single"}}} +{"type":"assistant/chunk","seq":54,"time":1781834684724,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":55,"time":1781834684724,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" call"}}} +{"type":"assistant/chunk","seq":56,"time":1781834684724,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" per"}}} +{"type":"assistant/chunk","seq":57,"time":1781834684725,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" action"}}} +{"type":"assistant/chunk","seq":58,"time":1781834684725,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"\""}}} +{"type":"assistant/chunk","seq":59,"time":1781834684753,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" -"}}} +{"type":"assistant/chunk","seq":60,"time":1781834684782,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" so"}}} +{"type":"assistant/chunk","seq":61,"time":1781834684783,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":62,"time":1781834684783,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"'ll"}}} +{"type":"assistant/chunk","seq":63,"time":1781834684811,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" do"}}} +{"type":"assistant/chunk","seq":64,"time":1781834684840,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" two"}}} +{"type":"assistant/chunk","seq":65,"time":1781834684873,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" separate"}}} +{"type":"assistant/chunk","seq":66,"time":1781834684873,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" bash"}}} +{"type":"assistant/chunk","seq":67,"time":1781834684873,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" calls"}}} +{"type":"assistant/chunk","seq":68,"time":1781834684902,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":":"}}} +{"type":"assistant/chunk","seq":69,"time":1781834684903,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" one"}}} +{"type":"assistant/chunk","seq":70,"time":1781834684934,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" for"}}} +{"type":"assistant/chunk","seq":71,"time":1781834684935,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" app"}}} +{"type":"assistant/chunk","seq":72,"time":1781834684966,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"ending"}}} +{"type":"assistant/chunk","seq":73,"time":1781834684966,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":","}}} +{"type":"assistant/chunk","seq":74,"time":1781834684967,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" one"}}} +{"type":"assistant/chunk","seq":75,"time":1781834684967,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" for"}}} +{"type":"assistant/chunk","seq":76,"time":1781834684967,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":" reading"}}} +{"type":"assistant/chunk","seq":77,"time":1781834684967,"data":{"turn":1,"step":1,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":78,"time":1781834685092,"data":{"turn":1,"step":1,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":79,"time":1781834685092,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":80,"time":1781834685120,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":81,"time":1781834685120,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":82,"time":1781834685120,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":83,"time":1781834685120,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":84,"time":1781834685120,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":85,"time":1781834685149,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":86,"time":1781834685149,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"echo"}}} +{"type":"assistant/chunk","seq":87,"time":1781834685149,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" '"}}} +{"type":"assistant/chunk","seq":88,"time":1781834685149,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"WOR"}}} +{"type":"assistant/chunk","seq":89,"time":1781834685149,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"LD"}}} +{"type":"assistant/chunk","seq":90,"time":1781834685149,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"'"}}} +{"type":"assistant/chunk","seq":91,"time":1781834685178,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" >>"}}} +{"type":"assistant/chunk","seq":92,"time":1781834685179,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":93,"time":1781834685179,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":94,"time":1781834685179,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":95,"time":1781834685207,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":96,"time":1781834685207,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":97,"time":1781834685236,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":98,"time":1781834685237,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":99,"time":1781834685237,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":100,"time":1781834685237,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":101,"time":1781834685265,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"App"}}} +{"type":"assistant/chunk","seq":102,"time":1781834685266,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"end"}}} +{"type":"assistant/chunk","seq":103,"time":1781834685266,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" WORLD"}}} +{"type":"assistant/chunk","seq":104,"time":1781834685266,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" line"}}} +{"type":"assistant/chunk","seq":105,"time":1781834685309,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" to"}}} +{"type":"assistant/chunk","seq":106,"time":1781834685310,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":107,"time":1781834685310,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":108,"time":1781834685310,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":109,"time":1781834685326,"data":{"turn":1,"step":1,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":110,"time":1781834685385,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The user wants me to:\n1. Append a second line containing \"WORLD\" to greeting.txt\n2. Read the file back with `cat greeting.txt` to confirm\n3. Reply with \"DONE\"\n\nBut they want \"a single bash call per action\" - so I'll do two separate bash calls: one for appending, one for reading."}}}} +{"type":"assistant/chunk","seq":111,"time":1781834685385,"data":{"turn":1,"step":1,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","arguments":"{\"command\": \"echo 'WORLD' >> greeting.txt\", \"description\": \"Append WORLD line to greeting.txt\"}"}}}} +{"type":"assistant/chunk","seq":112,"time":1781834685386,"data":{"turn":1,"step":1,"chunk":{"type":"usage","usage":{"inputTokens":161,"outputTokens":146,"cacheReadTokens":768,"reasoningTokens":74}}}} +{"type":"assistant/chunk","seq":113,"time":1781834685386,"data":{"turn":1,"step":1,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":114,"time":1781834685387,"data":{"turn":1,"step":1,"content":[{"type":"reasoning","text":"The user wants me to:\n1. Append a second line containing \"WORLD\" to greeting.txt\n2. Read the file back with `cat greeting.txt` to confirm\n3. Reply with \"DONE\"\n\nBut they want \"a single bash call per action\" - so I'll do two separate bash calls: one for appending, one for reading."},{"type":"tool-call","id":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","arguments":"{\"command\": \"echo 'WORLD' >> greeting.txt\", \"description\": \"Append WORLD line to greeting.txt\"}"}]}} +{"type":"usage","seq":115,"time":1781834685387,"data":{"turn":1,"step":1,"usage":{"inputTokens":161,"outputTokens":146,"cacheReadTokens":768,"reasoningTokens":74}}} +{"type":"tool/call","seq":116,"time":1781834685387,"data":{"turn":1,"step":1,"callId":"call_00_r3tvHl3fD0tmV0GKQt032338","name":"bash","arguments":"{\"command\": \"echo 'WORLD' >> greeting.txt\", \"description\": \"Append WORLD line to greeting.txt\"}"}} +{"type":"tool/result","seq":117,"time":1781834685400,"data":{"turn":1,"step":1,"callId":"call_00_r3tvHl3fD0tmV0GKQt032338","content":[{"type":"text","text":"(no output)"}],"isError":false}} +{"type":"step/end","seq":118,"time":1781834685400,"data":{"turn":1,"step":1}} +{"type":"step/start","seq":119,"time":1781834685400,"data":{"turn":1,"step":2}} +{"type":"assistant/chunk","seq":120,"time":1781834686163,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":121,"time":1781834686163,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"App"}}} +{"type":"assistant/chunk","seq":122,"time":1781834686261,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"ended"}}} +{"type":"assistant/chunk","seq":123,"time":1781834686290,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" successfully"}}} +{"type":"assistant/chunk","seq":124,"time":1781834686318,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":125,"time":1781834686319,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" Now"}}} +{"type":"assistant/chunk","seq":126,"time":1781834686319,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" read"}}} +{"type":"assistant/chunk","seq":127,"time":1781834686352,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" the"}}} +{"type":"assistant/chunk","seq":128,"time":1781834686352,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":129,"time":1781834686381,"data":{"turn":1,"step":2,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":130,"time":1781834686469,"data":{"turn":1,"step":2,"chunk":{"type":"block-start","index":1,"blockType":"tool-call"}}} +{"type":"assistant/chunk","seq":131,"time":1781834686469,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":""}}} +{"type":"assistant/chunk","seq":132,"time":1781834686497,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"{"}}} +{"type":"assistant/chunk","seq":133,"time":1781834686498,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":134,"time":1781834686498,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"command"}}} +{"type":"assistant/chunk","seq":135,"time":1781834686498,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":136,"time":1781834686498,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":137,"time":1781834686530,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":138,"time":1781834686530,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"cat"}}} +{"type":"assistant/chunk","seq":139,"time":1781834686530,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":140,"time":1781834686530,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":141,"time":1781834686559,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":142,"time":1781834686591,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":", "}}} +{"type":"assistant/chunk","seq":143,"time":1781834686591,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":144,"time":1781834686591,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"description"}}} +{"type":"assistant/chunk","seq":145,"time":1781834686591,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":146,"time":1781834686591,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":": "}}} +{"type":"assistant/chunk","seq":147,"time":1781834686623,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":148,"time":1781834686623,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"Read"}}} +{"type":"assistant/chunk","seq":149,"time":1781834686623,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":" greeting"}}} +{"type":"assistant/chunk","seq":150,"time":1781834686655,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":".txt"}}} +{"type":"assistant/chunk","seq":151,"time":1781834686655,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":" to"}}} +{"type":"assistant/chunk","seq":152,"time":1781834686684,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":" confirm"}}} +{"type":"assistant/chunk","seq":153,"time":1781834686684,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"\""}}} +{"type":"assistant/chunk","seq":154,"time":1781834686713,"data":{"turn":1,"step":2,"chunk":{"type":"tool-call-delta","index":1,"id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","argumentsDelta":"}"}}} +{"type":"assistant/chunk","seq":155,"time":1781834686745,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"Appended successfully. Now read the file."}}}} +{"type":"assistant/chunk","seq":156,"time":1781834686745,"data":{"turn":1,"step":2,"chunk":{"type":"block-end","index":1,"block":{"type":"tool-call","id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read greeting.txt to confirm\"}"}}}} +{"type":"assistant/chunk","seq":157,"time":1781834686745,"data":{"turn":1,"step":2,"chunk":{"type":"usage","usage":{"inputTokens":193,"outputTokens":74,"cacheReadTokens":896,"reasoningTokens":9}}}} +{"type":"assistant/chunk","seq":158,"time":1781834686745,"data":{"turn":1,"step":2,"chunk":{"type":"finish","reason":{"kind":"tool-calls"}}}} +{"type":"assistant/message","seq":159,"time":1781834686745,"data":{"turn":1,"step":2,"content":[{"type":"reasoning","text":"Appended successfully. Now read the file."},{"type":"tool-call","id":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read greeting.txt to confirm\"}"}]}} +{"type":"usage","seq":160,"time":1781834686745,"data":{"turn":1,"step":2,"usage":{"inputTokens":193,"outputTokens":74,"cacheReadTokens":896,"reasoningTokens":9}}} +{"type":"tool/call","seq":161,"time":1781834686745,"data":{"turn":1,"step":2,"callId":"call_00_SkCP8dgN8aCbLiZDcYa68316","name":"bash","arguments":"{\"command\": \"cat greeting.txt\", \"description\": \"Read greeting.txt to confirm\"}"}} +{"type":"tool/result","seq":162,"time":1781834686758,"data":{"turn":1,"step":2,"callId":"call_00_SkCP8dgN8aCbLiZDcYa68316","content":[{"type":"text","text":"hello\nWORLD\n"}],"isError":false}} +{"type":"step/end","seq":163,"time":1781834686758,"data":{"turn":1,"step":2}} +{"type":"step/start","seq":164,"time":1781834686758,"data":{"turn":1,"step":3}} +{"type":"assistant/chunk","seq":165,"time":1781834687255,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":0,"blockType":"reasoning"}}} +{"type":"assistant/chunk","seq":166,"time":1781834687255,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"The"}}} +{"type":"assistant/chunk","seq":167,"time":1781834687336,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" file"}}} +{"type":"assistant/chunk","seq":168,"time":1781834687365,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" now"}}} +{"type":"assistant/chunk","seq":169,"time":1781834687365,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" has"}}} +{"type":"assistant/chunk","seq":170,"time":1781834687365,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" two"}}} +{"type":"assistant/chunk","seq":171,"time":1781834687366,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" lines"}}} +{"type":"assistant/chunk","seq":172,"time":1781834687396,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":173,"time":1781834687425,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" I"}}} +{"type":"assistant/chunk","seq":174,"time":1781834687426,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"'ll"}}} +{"type":"assistant/chunk","seq":175,"time":1781834687455,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" reply"}}} +{"type":"assistant/chunk","seq":176,"time":1781834687455,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" with"}}} +{"type":"assistant/chunk","seq":177,"time":1781834687455,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":" D"}}} +{"type":"assistant/chunk","seq":178,"time":1781834687455,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"ONE"}}} +{"type":"assistant/chunk","seq":179,"time":1781834687455,"data":{"turn":1,"step":3,"chunk":{"type":"reasoning-delta","index":0,"text":"."}}} +{"type":"assistant/chunk","seq":180,"time":1781834687484,"data":{"turn":1,"step":3,"chunk":{"type":"block-start","index":1,"blockType":"text"}}} +{"type":"assistant/chunk","seq":181,"time":1781834687484,"data":{"turn":1,"step":3,"chunk":{"type":"text-delta","index":1,"text":"D"}}} +{"type":"assistant/chunk","seq":182,"time":1781834687484,"data":{"turn":1,"step":3,"chunk":{"type":"text-delta","index":1,"text":"ONE"}}} +{"type":"assistant/chunk","seq":183,"time":1781834687488,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":0,"block":{"type":"reasoning","text":"The file now has two lines. I'll reply with DONE."}}}} +{"type":"assistant/chunk","seq":184,"time":1781834687488,"data":{"turn":1,"step":3,"chunk":{"type":"block-end","index":1,"block":{"type":"text","text":"DONE"}}}} +{"type":"assistant/chunk","seq":185,"time":1781834687488,"data":{"turn":1,"step":3,"chunk":{"type":"usage","usage":{"inputTokens":156,"outputTokens":17,"cacheReadTokens":1024,"reasoningTokens":14}}}} +{"type":"assistant/chunk","seq":186,"time":1781834687488,"data":{"turn":1,"step":3,"chunk":{"type":"finish","reason":{"kind":"stop"}}}} +{"type":"assistant/message","seq":187,"time":1781834687489,"data":{"turn":1,"step":3,"content":[{"type":"reasoning","text":"The file now has two lines. I'll reply with DONE."},{"type":"text","text":"DONE"}]}} +{"type":"usage","seq":188,"time":1781834687489,"data":{"turn":1,"step":3,"usage":{"inputTokens":156,"outputTokens":17,"cacheReadTokens":1024,"reasoningTokens":14}}} +{"type":"step/end","seq":189,"time":1781834687489,"data":{"turn":1,"step":3}} +{"type":"turn/end","seq":190,"time":1781834687489,"data":{"turn":1,"reason":{"kind":"completed"}}} diff --git a/examples/acp-agent/tests/snapshots/workspace-edit/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/workspace-edit/stdout.golden.jsonl index 1f7c191c9d..fa0d19623e 100644 --- a/examples/acp-agent/tests/snapshots/workspace-edit/stdout.golden.jsonl +++ b/examples/acp-agent/tests/snapshots/workspace-edit/stdout.golden.jsonl @@ -1,214 +1,105 @@ {"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":"A file named greeting.txt in the current directory contains one word. Use the bash tool to append a second line containing the word WORLD to it (so it has two lines), then read the file back with `cat greeting.txt` to confirm, and reply with the single word DONE. Use a single bash call per action."}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"Let"}}}} +{"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":" break"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" this"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" down"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" into"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" steps"}}}} +{"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":":\n"}}}} {"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"1"}}}} {"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":" First"}}}} -{"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":" read"}}}} -{"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":" file"}}}} -{"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":" see"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" what"}}}} -{"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":" in"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" it"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"2"}}}} -{"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":" Then"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" append"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" Append"}}}} +{"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":" second"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" line"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" containing"}}}} {"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":"WOR"}}}} {"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"LD"}}}} {"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":" as"}}}} -{"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":" second"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" line"}}}} +{"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":" greeting"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":".txt"}}}} {"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"3"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"2"}}}} {"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":" Then"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" read"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" it"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" Read"}}}} +{"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":" file"}}}} {"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" back"}}}} {"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":" cat"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n\n"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"Wait"}}}} -{"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":" the"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" instruction"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" says"}}}} -{"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":"Use"}}}} -{"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":" single"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" per"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" action"}}}} -{"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":" -"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" but"}}}} -{"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":" `"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"cat"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" greeting"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":".txt"}}}} +{"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":" to"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" do"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" multiple"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" actions"}}}} -{"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":" Let"}}}} -{"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":" re"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"-read"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":".\n\n"}}}} -{"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":"Use"}}}} -{"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":" single"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" per"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" action"}}}} -{"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":" -"}}}} -{"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":" think"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" this"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" means"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" each"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" action"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" should"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" be"}}}} -{"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":" separate"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} -{"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":" not"}}}} -{"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":" big"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":".\n\n"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"Let"}}}} -{"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":" do"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":":\n"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"1"}}}} -{"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":" First"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} -{"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":" read"}}}} -{"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":" file"}}}} -{"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":" see"}}}} -{"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":" current"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" content"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"2"}}}} -{"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":" Second"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} -{"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":" append"}}}} -{"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":"WOR"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"LD"}}}} -{"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":" to"}}}} -{"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":" file"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" confirm"}}}} {"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n"}}}} {"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"3"}}}} {"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":" Third"}}}} +{"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":" \""}}}} +{"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":"\"\n\n"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"But"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" they"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" want"}}}} +{"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":"a"}}}} +{"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":" bash"}}}} {"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" call"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" per"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" action"}}}} +{"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":" -"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" so"}}}} +{"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":"'ll"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" do"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" two"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" separate"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" bash"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" calls"}}}} {"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":" cat"}}}} +{"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":" for"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" app"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"ending"}}}} +{"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":" for"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" reading"}}}} +{"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_r3tvHl3fD0tmV0GKQt032338","title":"echo 'WORLD' >> greeting.txt","kind":"execute","status":"in_progress","rawInput":"echo 'WORLD' >> greeting.txt","content":[{"type":"content","content":{"type":"text","text":"Append WORLD line to greeting.txt"}}]}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_00_r3tvHl3fD0tmV0GKQt032338","status":"completed","content":[{"type":"content","content":{"type":"text","text":"```console\n(no output)\n```"}}]}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"App"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"ended"}}}} +{"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":"."}}}} +{"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":" read"}}}} {"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":" file"}}}} -{"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":" confirm"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"\n\n"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"Actually"}}}} -{"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":" let"}}}} -{"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":" just"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" do"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" it"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" step"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" by"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" step"}}}} {"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_J7zkTYNbCxhU7s0fIfIq4165","title":"cat greeting.txt","kind":"execute","status":"in_progress","rawInput":"cat greeting.txt","content":[{"type":"content","content":{"type":"text","text":"Read current content of greeting.txt"}}]}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_00_J7zkTYNbCxhU7s0fIfIq4165","status":"completed","content":[{"type":"content","content":{"type":"text","text":"```console\nhello\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":" file"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" contains"}}}} -{"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":"hello"}}}} -{"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":" append"}}}} -{"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":"WOR"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"LD"}}}} -{"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":" as"}}}} -{"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":" second"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" line"}}}} -{"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_r6yugViLOxPuocpIvXrQ5342","title":"echo WORLD >> greeting.txt","kind":"execute","status":"in_progress","rawInput":"echo WORLD >> greeting.txt","content":[{"type":"content","content":{"type":"text","text":"Append WORLD as second line"}}]}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_00_r6yugViLOxPuocpIvXrQ5342","status":"completed","content":[{"type":"content","content":{"type":"text","text":"```console\n(no output)\n```"}}]}}} -{"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":" confirm"}}}} -{"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":" cat"}}}} -{"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_SC1arlNU29Vn38HnR4Kp9691","title":"cat greeting.txt","kind":"execute","status":"in_progress","rawInput":"cat greeting.txt","content":[{"type":"content","content":{"type":"text","text":"Confirm file content with cat"}}]}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_00_SC1arlNU29Vn38HnR4Kp9691","status":"completed","content":[{"type":"content","content":{"type":"text","text":"```console\nhello\nWORLD\n```"}}]}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call","toolCallId":"call_00_SkCP8dgN8aCbLiZDcYa68316","title":"cat greeting.txt","kind":"execute","status":"in_progress","rawInput":"cat greeting.txt","content":[{"type":"content","content":{"type":"text","text":"Read greeting.txt to confirm"}}]}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"tool_call_update","toolCallId":"call_00_SkCP8dgN8aCbLiZDcYa68316","status":"completed","content":[{"type":"content","content":{"type":"text","text":"```console\nhello\nWORLD\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":" file"}}}} {"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":" has"}}}} {"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" two"}}}} {"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" lines"}}}} -{"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":" \""}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"hello"}}}} -{"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":" \""}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"WOR"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"LD"}}}} -{"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":" The"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" task"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" is"}}}} -{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":" complete"}}}} +{"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":" I"}}}} +{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"{{sessionId}}","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"'ll"}}}} +{"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":"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"}}}} From 6d02059f9f3afc81bca388203c58782cdf6abd3b Mon Sep 17 00:00:00 2001 From: Tianyi Cui <53024+tianyicui@users.noreply.github.com> Date: Fri, 19 Jun 2026 10:10:32 +0800 Subject: [PATCH 13/13] test(acp-example): snapshot the session/new workspace-scope rejection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Master's "fix(acp): align prompt and workspace contracts" made session/new reject a non-empty additionalDirectories / mcpServers (widening the workspace scope is unimplemented). Add a `reject-extra-dirs` scenario + a `newSessionExpectError` input op that pins this editor-facing contract: the bridge answers with `-32602 Invalid params: additionalDirectories is not supported`. Keyless, deterministic, no model call. (session/load replay — the other new master behavior — needs a two-phase seed-then-load harness and is left for a focused follow-up.) --- examples/acp-agent/tests/acp.snapshot.ts | 1 + examples/acp-agent/tests/snapshot-harness.ts | 16 ++++++++++++++++ .../tests/snapshots/reject-extra-dirs/input.json | 6 ++++++ .../snapshots/reject-extra-dirs/session.jsonl | 1 + .../reject-extra-dirs/stdout.golden.jsonl | 2 ++ 5 files changed, 26 insertions(+) create mode 100644 examples/acp-agent/tests/snapshots/reject-extra-dirs/input.json create mode 100644 examples/acp-agent/tests/snapshots/reject-extra-dirs/session.jsonl create mode 100644 examples/acp-agent/tests/snapshots/reject-extra-dirs/stdout.golden.jsonl diff --git a/examples/acp-agent/tests/acp.snapshot.ts b/examples/acp-agent/tests/acp.snapshot.ts index 582df37b82..9f99ce9913 100644 --- a/examples/acp-agent/tests/acp.snapshot.ts +++ b/examples/acp-agent/tests/acp.snapshot.ts @@ -37,6 +37,7 @@ interface Scenario { const SCENARIOS: Scenario[] = [ { name: 'handshake', hasModelTurn: false, recorded: false }, + { name: 'reject-extra-dirs', hasModelTurn: false, recorded: false }, { name: 'text-turn', hasModelTurn: true, recorded: true }, { name: 'tool-call-turn', hasModelTurn: true, recorded: true }, { name: 'workspace-edit', hasModelTurn: true, recorded: true }, diff --git a/examples/acp-agent/tests/snapshot-harness.ts b/examples/acp-agent/tests/snapshot-harness.ts index de05c8ca98..d66ee45d7f 100644 --- a/examples/acp-agent/tests/snapshot-harness.ts +++ b/examples/acp-agent/tests/snapshot-harness.ts @@ -55,6 +55,7 @@ const repoTsconfig = fileURLToPath(new URL('../../../tsconfig.json', import.meta type InputStep = | { op: 'initialize'; terminalOutput?: boolean } | { op: 'newSession' } + | { op: 'newSessionExpectError'; additionalDirectories?: string[] } | { op: 'prompt'; text: string } | { op: 'promptExpectError'; text: string } | { op: 'promptAndCancel'; text: string } @@ -228,6 +229,21 @@ async function runStep( setSessionId(sessionId) return } + case 'newSessionExpectError': { + // The bridge rejects a session/new that widens the workspace scope + // (non-empty additionalDirectories / mcpServers — unimplemented). The SDK + // surfaces that as a rejected RPC; swallow it so the run completes and the + // error frame is captured in the transcript. + await client.newSession({ + cwd, + mcpServers: [], + ...step.additionalDirectories !== undefined ? { additionalDirectories: step.additionalDirectories } : {}, + }).then( + () => { throw new Error('snapshot-harness: expected session/new to be rejected but it succeeded') }, + () => { /* expected: the bridge rejected the unsupported workspace scope */ }, + ) + return + } case 'prompt': { const sessionId = getSessionId() if (sessionId === undefined) throw new Error('snapshot-harness: prompt before newSession') diff --git a/examples/acp-agent/tests/snapshots/reject-extra-dirs/input.json b/examples/acp-agent/tests/snapshots/reject-extra-dirs/input.json new file mode 100644 index 0000000000..6a10f9a40c --- /dev/null +++ b/examples/acp-agent/tests/snapshots/reject-extra-dirs/input.json @@ -0,0 +1,6 @@ +{ + "steps": [ + { "op": "initialize" }, + { "op": "newSessionExpectError", "additionalDirectories": ["/extra-dir"] } + ] +} diff --git a/examples/acp-agent/tests/snapshots/reject-extra-dirs/session.jsonl b/examples/acp-agent/tests/snapshots/reject-extra-dirs/session.jsonl new file mode 100644 index 0000000000..ab44090be6 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/reject-extra-dirs/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/reject-extra-dirs/stdout.golden.jsonl b/examples/acp-agent/tests/snapshots/reject-extra-dirs/stdout.golden.jsonl new file mode 100644 index 0000000000..4b864fe7f3 --- /dev/null +++ b/examples/acp-agent/tests/snapshots/reject-extra-dirs/stdout.golden.jsonl @@ -0,0 +1,2 @@ +{"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,"error":{"code":-32602,"message":"Invalid params: additionalDirectories is not supported in this MVP"}}