From ba432791fdb7b3720ee9becc2ddd56c7c989f717 Mon Sep 17 00:00:00 2001 From: Brennan Benson <79079362+brennanb2025@users.noreply.github.com> Date: Thu, 8 Oct 2026 12:24:29 -0700 Subject: [PATCH] fix(acp): keep OMP replies that follow its reasoning --- .../scripts/vitest-sqlite-runtime-files.mjs | 3 + src/main/acp/acp-session-update.ts | 9 +- src/main/acp/acp-structured-acquire.ts | 2 + src/main/acp/acp-structured-lane.ts | 34 ++- .../acp/acp-structured-omp-recordings.test.ts | 62 +++++ .../acp/acp-text-message-ownership.test.ts | 114 +++++++++ src/main/acp/acp-text-stream-identity.test.ts | 130 ++++++++++ src/main/acp/acp-timeline-translator.ts | 23 +- src/main/acp/acp-turn-messages.ts | 48 +++- .../omp-v17-reply-after-thought.jsonl | 228 ++++++++++++++++++ .../omp-v17-reply-without-thought.jsonl | 42 ++++ ...rovider-timeline-assembler-test-support.ts | 19 +- 12 files changed, 703 insertions(+), 11 deletions(-) create mode 100644 src/main/acp/acp-text-message-ownership.test.ts create mode 100644 src/main/acp/acp-text-stream-identity.test.ts create mode 100644 src/main/acp/fixtures/omp-v17-reply-after-thought.jsonl create mode 100644 src/main/acp/fixtures/omp-v17-reply-without-thought.jsonl diff --git a/config/scripts/vitest-sqlite-runtime-files.mjs b/config/scripts/vitest-sqlite-runtime-files.mjs index 64fd1a0181aa..31c3b2e48073 100644 --- a/config/scripts/vitest-sqlite-runtime-files.mjs +++ b/config/scripts/vitest-sqlite-runtime-files.mjs @@ -3,6 +3,9 @@ import { SQLITE_DATABASE_RUNTIME_INCLUDE } from './vitest-sqlite-database-runtim // Real SQLite fixtures keep Node publication and close semantics. export const SQLITE_RUNTIME_INCLUDE = [ ...SQLITE_DATABASE_RUNTIME_INCLUDE, + 'src/main/acp/acp-structured-omp-recordings.test.ts', + 'src/main/acp/acp-text-stream-identity.test.ts', + 'src/main/acp/acp-text-message-ownership.test.ts', 'src/main/active-view-persistence-boundary.test.ts', 'src/main/automations/automation-dispatch-host-fence.test.ts', 'src/main/automations/automation-owner-fencing.test.ts', diff --git a/src/main/acp/acp-session-update.ts b/src/main/acp/acp-session-update.ts index 1f39a4d0ed6c..437382ed358f 100644 --- a/src/main/acp/acp-session-update.ts +++ b/src/main/acp/acp-session-update.ts @@ -8,6 +8,7 @@ import type { AcpDialect } from './acp-dialects/acp-dialect' import type { AcpBackgroundTaskTimeline } from './acp-background-task-timeline' import type { AcpToolTimeline } from './acp-tool-timeline' import type { SessionNotification } from './generated/acp-protocol.generated' +import { acpNamedTextKey } from './acp-turn-messages' export function acpSessionUpdate( notification: SessionNotification, @@ -24,7 +25,8 @@ export function acpSessionUpdate( const join = { join: { thread: notification.sessionId, ...(turn === undefined ? {} : { turn }) } } switch (update.sessionUpdate) { case 'agent_message_chunk': - case 'agent_thought_chunk': + case 'agent_thought_chunk': { + const channel = update.sessionUpdate === 'agent_thought_chunk' ? 'reasoning' : 'assistant' return update.content.type === 'text' ? [ { @@ -32,14 +34,15 @@ export function acpSessionUpdate( item: context.messageKey ? { id: context.messageKey } : update.messageId - ? { id: `message:${update.messageId}` } + ? { id: acpNamedTextKey(update.messageId, channel) } : { stream: update.sessionUpdate }, - channel: update.sessionUpdate === 'agent_thought_chunk' ? 'reasoning' : 'assistant', + channel, text: update.content.text, ...join } ] : [{ type: 'provider.frame', frameKind: update.sessionUpdate, payload: update, ...join }] + } case 'user_message_chunk': // A live echo of the send is the send's own row. return [] diff --git a/src/main/acp/acp-structured-acquire.ts b/src/main/acp/acp-structured-acquire.ts index b9c8b41d209f..4567e2432e58 100644 --- a/src/main/acp/acp-structured-acquire.ts +++ b/src/main/acp/acp-structured-acquire.ts @@ -44,6 +44,7 @@ import { import type { AcpStructuredSessionAdapterDeps } from './acp-structured-session-adapter-deps' import { AcpStructuredTurns, type AcpStructuredTurnsDeps } from './acp-structured-turns' import { RequestPermissionResponseSchema } from './generated/acp-protocol.generated' +import { createStructuredAgentSessionLogger } from '../native-chat/agent-session-wire/structured-agent-session-logger' /** Frames an agent may send before its session exists; past this they are dropped. */ const MAX_EARLY_FRAMES = 2_048 @@ -195,6 +196,7 @@ export async function acquireAcpStructuredSession(input: { generation, providerSessionId, dialect: spec.dialect, + logger: deps.logger ?? createStructuredAgentSessionLogger(), onInputAccepted: (clientMessageId) => session?.turns.accept(clientMessageId), onFailed: () => input.forceClose(sessionId) }) diff --git a/src/main/acp/acp-structured-lane.ts b/src/main/acp/acp-structured-lane.ts index 958d20dc47ef..167014375fcf 100644 --- a/src/main/acp/acp-structured-lane.ts +++ b/src/main/acp/acp-structured-lane.ts @@ -12,6 +12,11 @@ import { createLegacyProviderTimelineIdentityScheme } from '../native-chat/agent import type { ProviderTimelineSink } from '../native-chat/agent-session-timeline/provider-timeline-plan' import type { AcpDialect } from './acp-dialects/acp-dialect' import { AcpTimelineTranslator } from './acp-timeline-translator' +import { + neverThrowingStructuredAgentSessionLogger, + type StructuredAgentSessionLogger +} from '../native-chat/agent-session-wire/structured-agent-session-logger' +import type { AcpTextDrop } from './acp-turn-messages' /** How long a held event waits for the sink to say it drained before trying again on its own. */ const BACKPRESSURE_RETRY_MS = 250 @@ -25,6 +30,7 @@ export type AcpStructuredLaneDeps = { generation: string providerSessionId: string dialect: AcpDialect + logger: StructuredAgentSessionLogger /** A send of Orca's reached the agent: the turn it opened has its first provider event. */ onInputAccepted: (clientMessageId: string) => void /** The sink refused for good; nothing more this child says can be journaled. */ @@ -40,12 +46,15 @@ export class AcpStructuredLane { private retryTimer: ReturnType | null = null private failed = false private disposed = false + private readonly logger: StructuredAgentSessionLogger constructor(private readonly deps: AcpStructuredLaneDeps) { + this.logger = neverThrowingStructuredAgentSessionLogger(deps.logger) this.translator = new AcpTimelineTranslator({ sessionId: deps.providerSessionId, dialect: deps.dialect, - agentName: deps.agentName + agentName: deps.agentName, + onTextDropped: (drop) => this.reportTextDrop(drop) }) this.requestIdentity = createLegacyProviderTimelineIdentityScheme({ agent: deps.agent, @@ -123,7 +132,17 @@ export class AcpStructuredLane { this.clearRetry() while (this.backlog.length > 0 && !this.failed && !this.disposed) { const event = this.backlog[0] - const { admission } = this.assembler.apply(event) + const { admission, dropped } = this.assembler.apply(event) + if (dropped === 'stream-mismatch' && event.type === 'text.delta') { + this.reportTextDrop({ + reason: dropped, + itemId: 'id' in event.item ? event.item.id : undefined, + channel: event.channel, + threadId: event.join?.thread, + turnId: event.join?.turn, + producerAgentId: event.producer?.agentId + }) + } if (!admission.accepted) { if (admission.reason === 'backpressure') { this.retryTimer = setTimeout(() => this.drain(), BACKPRESSURE_RETRY_MS) @@ -149,6 +168,17 @@ export class AcpStructuredLane { } } + private reportTextDrop(drop: AcpTextDrop): void { + this.logger.warn('ACP text chunk rejected by its message stream', { + scope: `acp-text-${drop.reason}`, + sessionId: this.deps.sessionId, + providerSessionId: this.deps.providerSessionId, + agent: this.deps.agent, + generation: this.deps.generation, + ...drop + }) + } + private clearRetry(): void { if (this.retryTimer) { clearTimeout(this.retryTimer) diff --git a/src/main/acp/acp-structured-omp-recordings.test.ts b/src/main/acp/acp-structured-omp-recordings.test.ts index f7a63f632f44..62666cc9ba9e 100644 --- a/src/main/acp/acp-structured-omp-recordings.test.ts +++ b/src/main/acp/acp-structured-omp-recordings.test.ts @@ -16,6 +16,7 @@ import { } from './acp-structured-adapter.test-support' import { GrokFixtureReplay } from './acp-structured-fixture-replay.test-support' import { readAcpFixture } from './acp-timeline-fixture.test-support' +import { SessionNotificationSchema } from './generated/acp-protocol.generated' afterEach(async () => { await closeProviderTimelineRigs() @@ -67,6 +68,67 @@ async function allowOnce(rig: AcpAdapterRig, replay: GrokFixtureReplay) { } describe('OMP recordings through the adapter', () => { + it.each(['omp-v17-reply-without-thought', 'omp-v17-reply-after-thought'])( + 'keeps both ordinary answers from %s', + async (name) => { + const frames = await readAcpFixture(name) + const replay = new GrokFixtureReplay(frames) + const rig = await openAcpAdapterRig({ + spec: acpLaunchSpecFor('omp')!, + script: (scripted) => replay.attach(scripted) + }) + await rig.acquire() + await rig.adapter.dispatch({ + sessionId: SESSION, + clientMessageId: 'send-1', + body: ask, + fence: 1 + }) + await waitFor(async () => expect(await turns(rig)).toHaveLength(1)) + await rig.adapter.dispatch({ + sessionId: SESSION, + clientMessageId: 'send-2', + body: ask, + fence: 1 + }) + await waitFor(() => expect(replay.awaiting).toBeNull()) + await waitFor(async () => expect(await turns(rig)).toHaveLength(2)) + const recordedAnswers = frames + .flatMap((frame) => { + const parsed = SessionNotificationSchema.safeParse(frame.message.params) + const update = parsed.data?.update + return update?.sessionUpdate === 'agent_message_chunk' && update.content.type === 'text' + ? [update.content.text] + : [] + }) + .join('') + const rows = await rig.rig.rows() + const answers = rows + .flatMap((row) => + row.body.kind === 'message' && row.body.role === 'assistant' + ? row.body.blocks.flatMap((block) => (block.type === 'text' ? [block.text] : [])) + : [] + ) + .join('') + expect(await turns(rig)).toMatchObject([ + { state: 'completed', outcome: 'success' }, + { state: 'completed', outcome: 'success' } + ]) + expect(answers).toBe(recordedAnswers) + if (name === 'omp-v17-reply-after-thought') { + expect( + rows.filter((row) => row.body.kind === 'message' && row.body.role === 'reasoning') + ).toHaveLength(1) + } + await rig.adapter.closeSession(SESSION) + const savedMessages = (await rig.rig.rows()).filter((row) => row.body.kind === 'message') + const reopened = await rig.rig.reopenJournal() + expect(reopened.snapshot().items.filter((row) => row.body.kind === 'message')).toEqual( + savedMessages + ) + } + ) + it("a failed command's row shows its output and exit code, not the command again", async () => { const { rig, replay } = await replaying('omp-v17-shell-exit-3') await allowOnce(rig, replay) diff --git a/src/main/acp/acp-text-message-ownership.test.ts b/src/main/acp/acp-text-message-ownership.test.ts new file mode 100644 index 000000000000..746e83e43fb6 --- /dev/null +++ b/src/main/acp/acp-text-message-ownership.test.ts @@ -0,0 +1,114 @@ +import { afterEach, describe, expect, it } from 'vitest' +import { + closeProviderTimelineRigs, + SESSION +} from '../native-chat/agent-session-timeline/provider-timeline-assembler-test-support' +import { recordingStructuredAgentSessionLogger } from '../native-chat/agent-session-wire/structured-agent-session-logger-test-support' +import { acpLaunchSpecFor } from './acp-launch-specs' +import { + openAcpAdapterRig, + PROVIDER_SESSION, + sendHello, + waitFor +} from './acp-structured-adapter.test-support' + +afterEach(closeProviderTimelineRigs) + +describe.each(['omp', 'opencode', 'grok'] as const)('%s provider message ownership', (agent) => { + it.each([ + { stopReason: 'end_turn', nextPrompt: false }, + { stopReason: 'cancelled', nextPrompt: false }, + { stopReason: 'end_turn', nextPrompt: true }, + { stopReason: 'cancelled', nextPrompt: true } + ] as const)( + 'refuses a late answer after $stopReason (next prompt: $nextPrompt)', + async ({ stopReason, nextPrompt }) => { + const recording = recordingStructuredAgentSessionLogger() + let prompts = 0 + const rig = await openAcpAdapterRig({ + spec: acpLaunchSpecFor(agent)!, + deps: { logger: recording.logger }, + script: (scripted) => { + scripted.on('session/prompt', (frame) => { + prompts += 1 + scripted.notify('session/update', { + sessionId: PROVIDER_SESSION, + _meta: { promptId: `prompt:send-${prompts}` }, + update: { + sessionUpdate: 'agent_thought_chunk', + messageId: prompts === 1 ? 'first-message' : 'next-message', + content: { type: 'text', text: `Thought ${prompts}` } + } + }) + if (prompts === 1) { + scripted.reply(frame, { stopReason }) + } + }) + } + }) + await rig.acquire() + await sendHello(rig, 'send-1') + await waitFor(async () => + expect(await rig.rig.turns()).toMatchObject([ + { state: stopReason === 'cancelled' ? 'interrupted' : 'completed' } + ]) + ) + if (nextPrompt) { + await sendHello(rig, 'send-2') + await waitFor(async () => expect(await rig.rig.turns()).toHaveLength(2)) + } + rig.child().agent.notify('session/update', { + sessionId: PROVIDER_SESSION, + update: { + sessionUpdate: 'agent_message_chunk', + messageId: 'first-message', + content: { type: 'text', text: 'Private late answer' } + } + }) + await waitFor(() => + expect(recording.entries).toContainEqual({ + level: 'warn', + message: 'ACP text chunk rejected by its message stream', + fields: { + scope: 'acp-text-turn-settled', + reason: 'turn-settled', + sessionId: SESSION, + providerSessionId: PROVIDER_SESSION, + agent, + generation: 'gen-acp', + itemId: 'message:["first-message","assistant"]', + channel: 'assistant', + threadId: PROVIDER_SESSION, + turnId: 'prompt:send-1' + } + }) + ) + if (nextPrompt) { + rig.child().agent.notify('session/update', { + sessionId: PROVIDER_SESSION, + _meta: { promptId: 'prompt:send-2' }, + update: { + sessionUpdate: 'agent_message_chunk', + messageId: 'next-message', + content: { type: 'text', text: 'Next answer' } + } + }) + rig.child().agent.reply(await rig.frame('session/prompt', 1), { stopReason: 'end_turn' }) + await waitFor(async () => + expect(await rig.rig.turns()).toMatchObject([ + { state: stopReason === 'cancelled' ? 'interrupted' : 'completed' }, + { state: 'completed', outcome: 'success' } + ]) + ) + } + const rows = await rig.rig.rows() + expect( + rows + .filter((row) => row.body.kind === 'message' && row.body.role === 'assistant') + .map((row) => row.body) + ).toMatchObject(nextPrompt ? [{ blocks: [{ text: 'Next answer' }] }] : []) + expect(rows.filter((row) => row.body.kind === 'status')).toEqual([]) + await rig.adapter.closeSession(SESSION) + } + ) +}) diff --git a/src/main/acp/acp-text-stream-identity.test.ts b/src/main/acp/acp-text-stream-identity.test.ts new file mode 100644 index 000000000000..dd5f142d5746 --- /dev/null +++ b/src/main/acp/acp-text-stream-identity.test.ts @@ -0,0 +1,130 @@ +import { afterEach, describe, expect, it, vi } from 'vitest' +import { + closeProviderTimelineRigs, + openProviderTimelineRig +} from '../native-chat/agent-session-timeline/provider-timeline-assembler-test-support' +import { recordingStructuredAgentSessionLogger } from '../native-chat/agent-session-wire/structured-agent-session-logger-test-support' +import { acpLaunchSpecFor } from './acp-launch-specs' +import { AcpStructuredLane } from './acp-structured-lane' +import { AcpTimelineTranslator } from './acp-timeline-translator' + +afterEach(async () => { + vi.restoreAllMocks() + await closeProviderTimelineRigs() +}) + +describe('shared ACP text identity', () => { + it.each(['omp', 'opencode', 'grok'] as const)( + 'keeps interleaved reasoning and answers separate for %s', + async (agent) => { + const rig = await openProviderTimelineRig() + const dialect = acpLaunchSpecFor(agent)!.dialect + const lane = new AcpTimelineTranslator({ sessionId: 'provider-1', dialect }) + const prompt = lane.openPrompt('send-1', 1000) + const events = [...prompt.events] + for (const [sessionUpdate, text] of [ + ['agent_thought_chunk', 'Think '], + ['agent_message_chunk', 'Answer '], + ['agent_thought_chunk', 'more'], + ['agent_message_chunk', 'complete'] + ]) { + events.push( + ...lane.notification( + 'session/update', + { + sessionId: 'provider-1', + _meta: { promptId: prompt.promptId }, + update: { sessionUpdate, messageId: 'one-message', content: { type: 'text', text } } + }, + 1100 + ) + ) + } + events.push(...lane.promptResult('send-1', { stopReason: 'end_turn' }, 1200)) + for (const event of events) { + expect(rig.assembler.apply(event)).toEqual({ admission: { accepted: true } }) + } + expect( + (await rig.rows()).filter((row) => row.body.kind === 'message').map((row) => row.body) + ).toMatchObject([ + { role: 'reasoning', blocks: [{ text: 'Think more' }] }, + { role: 'assistant', blocks: [{ text: 'Answer complete' }] } + ]) + } + ) + + it.each([false, true])( + 'diagnoses stream rejection without blocking settlement (logger throws: %s)', + async (throws) => { + const rig = await openProviderTimelineRig() + const recording = recordingStructuredAgentSessionLogger() + const fallback = vi.spyOn(console, 'warn').mockImplementation(() => {}) + const lane = new AcpStructuredLane({ + sink: rig.sink, + sessionId: 'chat-1', + agent: 'omp', + agentName: 'OMP', + generation: 'generation-1', + providerSessionId: 'provider-1', + dialect: acpLaunchSpecFor('omp')!.dialect, + logger: throws + ? { + warn: () => { + throw new Error('logging failed') + }, + error: recording.logger.error + } + : recording.logger, + onInputAccepted: () => {}, + onFailed: () => { + throw new Error('unexpected lane failure') + } + }) + lane.apply([ + { type: 'turn.open', turn: 'turn-1', at: 1000 }, + { + type: 'text.delta', + item: { id: 'invalid-message' }, + channel: 'reasoning', + text: 'private thought', + join: { thread: 'provider-1', turn: 'turn-1' } + }, + { + type: 'text.delta', + item: { id: 'invalid-message' }, + channel: 'assistant', + text: 'private answer', + join: { thread: 'provider-1', turn: 'turn-1' } + }, + { type: 'turn.end', turn: 'turn-1', at: 1200, state: 'completed', outcome: 'success' } + ]) + if (throws) { + expect(fallback).toHaveBeenCalledOnce() + expect(await rig.turns()).toMatchObject([{ state: 'completed', outcome: 'success' }]) + lane.dispose() + return + } + expect(recording.entries).toEqual([ + { + level: 'warn', + message: 'ACP text chunk rejected by its message stream', + fields: { + scope: 'acp-text-stream-mismatch', + reason: 'stream-mismatch', + sessionId: 'chat-1', + providerSessionId: 'provider-1', + agent: 'omp', + generation: 'generation-1', + itemId: 'invalid-message', + channel: 'assistant', + threadId: 'provider-1', + turnId: 'turn-1', + producerAgentId: undefined + } + } + ]) + expect((await rig.rows()).filter((row) => row.body.kind === 'status')).toEqual([]) + lane.dispose() + } + ) +}) diff --git a/src/main/acp/acp-timeline-translator.ts b/src/main/acp/acp-timeline-translator.ts index 30af2bf56444..d177468f3d54 100644 --- a/src/main/acp/acp-timeline-translator.ts +++ b/src/main/acp/acp-timeline-translator.ts @@ -11,7 +11,7 @@ import { translateAcpRequest } from './acp-timeline-requests' import { acpSessionUpdate } from './acp-session-update' import { AcpToolTimeline } from './acp-tool-timeline' import { AcpTurnFailures, acpPromptErrorDetail } from './acp-turn-failures' -import { AcpTurnMessages } from './acp-turn-messages' +import { acpNamedTextKey, AcpTurnMessages, type AcpTextDrop } from './acp-turn-messages' import type { PromptResponse } from './generated/acp-protocol.generated' export { acpTurnEnd } from './acp-prompt-turns' @@ -31,6 +31,7 @@ export type AcpTimelineTranslatorOptions = { dialect?: AcpDialect /** The agent's display name, for a failed turn the provider gave no words for. */ agentName?: string + onTextDropped?: (drop: AcpTextDrop) => void } /** Consumes each frame once; the host retries the returned grammar events. Lives exactly as long @@ -168,8 +169,26 @@ export class AcpTimelineTranslator { (update !== undefined && SUBSTANTIVE_UPDATES.includes(update.sessionUpdate)) || extension?.end !== undefined || extension?.started === true - const turn = + const offeredTurn = providerTurn ?? (this.prompts.current?.opened ? this.prompts.current.turn : this.activeTurn) + const owner = update ? this.messages.owner(offeredTurn, update) : { turn: offeredTurn } + const turn = owner.turn + if ( + owner.settled && + (update?.sessionUpdate === 'agent_message_chunk' || + update?.sessionUpdate === 'agent_thought_chunk') && + update.messageId + ) { + const channel = update.sessionUpdate === 'agent_thought_chunk' ? 'reasoning' : 'assistant' + this.options.onTextDropped?.({ + reason: 'turn-settled', + itemId: acpNamedTextKey(update.messageId, channel), + channel, + threadId: this.options.sessionId, + turnId: turn + }) + return [] + } const events: ProviderTimelineEvent[] = [] if (turn && opens) { events.push(...this.start(turn, extension?.at ?? at)) diff --git a/src/main/acp/acp-turn-messages.ts b/src/main/acp/acp-turn-messages.ts index 0cf39c5834c3..3df459ebc907 100644 --- a/src/main/acp/acp-turn-messages.ts +++ b/src/main/acp/acp-turn-messages.ts @@ -1,11 +1,49 @@ import { BoundedMap } from '../../shared/bounded-map' import type { SessionUpdate } from './generated/acp-protocol.generated' +import type { ProviderTimelineTextChannel } from '../native-chat/agent-session-timeline/provider-timeline-event' +import { providerTimelineKeyPart } from '../native-chat/agent-session-timeline/provider-timeline-identity' + +/** One provider message may contain both reasoning and visible text. */ +export function acpNamedTextKey(messageId: string, channel: ProviderTimelineTextChannel): string { + return `message:${JSON.stringify([messageId, channel])}` +} type MessagePosition = { ordinal: number; channel?: string } +type MessageOwner = { turn: string; settled: boolean } + +export type AcpTextDrop = { + reason: 'turn-settled' | 'stream-mismatch' + itemId: string | undefined + channel: ProviderTimelineTextChannel + threadId: string | undefined + turnId: string | undefined + producerAgentId?: string +} /** Stable turn-relative message positions. */ export class AcpTurnMessages { private readonly turns = new BoundedMap({ maxEntries: 128 }) + private readonly owners = new BoundedMap({ maxEntries: 128 }) + + /** Channel items inherit the provider message's first turn, including trailing chunks. */ + owner(turn: string | undefined, update: SessionUpdate): { turn?: string; settled?: boolean } { + if ( + (update.sessionUpdate !== 'agent_message_chunk' && + update.sessionUpdate !== 'agent_thought_chunk') || + !update.messageId + ) { + return { turn } + } + const key = providerTimelineKeyPart(update.messageId) + const owner = this.owners.get(key) + if (owner) { + return owner + } + if (turn !== undefined) { + this.owners.set(key, { turn, settled: false }) + } + return { turn } + } key(turn: string, update: SessionUpdate): string | undefined { const state = this.turns.get(turn) ?? { ordinal: 0 } @@ -20,7 +58,10 @@ export class AcpTurnMessages { return undefined } if (update.messageId) { - return `message:${update.messageId}` + return acpNamedTextKey( + update.messageId, + update.sessionUpdate === 'agent_thought_chunk' ? 'reasoning' : 'assistant' + ) } if (state.channel !== update.sessionUpdate) { state.ordinal += 1 @@ -31,5 +72,10 @@ export class AcpTurnMessages { end(turn: string): void { this.turns.delete(turn) + for (const owner of this.owners.values()) { + if (owner.turn === turn) { + owner.settled = true + } + } } } diff --git a/src/main/acp/fixtures/omp-v17-reply-after-thought.jsonl b/src/main/acp/fixtures/omp-v17-reply-after-thought.jsonl new file mode 100644 index 000000000000..1ec505ae4028 --- /dev/null +++ b/src/main/acp/fixtures/omp-v17-reply-after-thought.jsonl @@ -0,0 +1,228 @@ +{"direction":"out","process":"A","message":{"jsonrpc":"2.0","id":3,"method":"session/prompt","params":{"sessionId":"session-1","prompt":[{"type":"text","text":"Captured source-context question."}]}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"available_commands_update","availableCommands":[{"name":"model","description":"Show current model selection"},{"name":"fast","description":"Toggle fast mode","input":{"hint":"[on|off|status]"}},{"name":"prewalk","description":"Prewalk at the next action"},{"name":"advisor","description":"Toggle advisor","input":{"hint":"[on|off|status|dump [raw]|configure]"}},{"name":"export","description":"Export session to HTML file","input":{"hint":"[path]"}},{"name":"dump","description":"Return full transcript as plain text, with LLM request JSON path"},{"name":"share","description":"Share session via an encrypted link (share server or secret gist)"},{"name":"browser","description":"Toggle browser headless vs visible mode","input":{"hint":"[headless|visible]"}},{"name":"todo","description":"Manage todos","input":{"hint":""}},{"name":"session","description":"Show session information","input":{"hint":"info|delete"}},{"name":"jobs","description":"Show background jobs"},{"name":"usage","description":"Show token usage","input":{"hint":"[show|reset [account|active]]"}},{"name":"stats","description":"Launch the local stats dashboard","input":{"hint":"[--port ]"}},{"name":"changelog","description":"Show changelog","input":{"hint":"[full]"}},{"name":"tools","description":"Show available tools"},{"name":"context","description":"Show context usage"},{"name":"mcp","description":"Manage MCP servers","input":{"hint":""}},{"name":"ssh","description":"Manage SSH connections","input":{"hint":""}},{"name":"fresh","description":"Reset provider stream state without changing the local transcript"},{"name":"compact","description":"Compact the conversation","input":{"hint":"[soft|remote|snapcompact] [focus]"}},{"name":"shake","description":"Shake heavy content out of the conversation context","input":{"hint":"[elide|images]"}},{"name":"memory","description":"Manage memory","input":{"hint":""}},{"name":"rename","description":"Rename the current session","input":{"hint":""}},{"name":"move","description":"Move the current session to a different directory","input":{"hint":"[<path>]"}},{"name":"marketplace","description":"Manage plugins from marketplaces","input":{"hint":"<subcommand>"}},{"name":"plugins","description":"Manage plugins","input":{"hint":"[list|enable|disable]"}},{"name":"reload-plugins","description":"Reload all plugins"},{"name":"force","description":"Force next turn to use a specific tool","input":{"hint":"<tool-name> [prompt]"}},{"name":"autoresearch","description":"Toggle builtin autoresearch mode, or pass off / clear, or a goal message.","input":{"hint":"arguments"}},{"name":"green","description":"Generate a prompt to iterate on CI failures until the branch is green","input":{"hint":"arguments"}},{"name":"review","description":"Launch interactive code review","input":{"hint":"arguments"}},{"name":"init","description":"Generate AGENTS.md for current codebase"}]}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"session_info_update","updatedAt":"2026-10-08T18:56:27.031Z","title":"Captured conversation"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"marker"},"messageId":"message-1"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" recorded"},"messageId":"message-1"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"usage_update","size":272000,"used":18142,"cost":{"amount":0.01079,"currency":"USD"}}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"session_info_update","updatedAt":"2026-10-08T18:56:30.493Z","title":"Captured conversation"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","id":3,"result":{"stopReason":"end_turn","usage":{"inputTokens":222,"outputTokens":24,"totalTokens":18166,"cachedReadTokens":17920}}}} +{"direction":"out","process":"A","message":{"jsonrpc":"2.0","id":4,"method":"session/prompt","params":{"sessionId":"session-1","prompt":[{"type":"text","text":"Captured source-context question."}]}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_thought_chunk","content":{"type":"text","text":"**Analyzing compaction no-op conditions**"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Default"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" retained"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"-history"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" setting"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":":"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"keep"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Recent"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Tokens"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":":"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" "},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"200"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"00"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`.\n\n"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Preparation"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" no"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"-"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"ops"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" (`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"undefined"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"):\n"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"1"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"."},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"path"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Entries"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" is"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" non"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"empty"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" and"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" the"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" last"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" entry"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" is"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" already"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"type"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" ==="},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" \""},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"comp"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"action"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"\""},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`.\n"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"2"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"."},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" The"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" computed"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" first"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" kept"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" entry"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" is"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" missing"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" or"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" has"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" no"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"id"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" (`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"path"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Entries"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" empty"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" also"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" lands"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" here"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":").\n"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"3"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"."},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" After"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" selection"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":","},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" both"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"messages"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"To"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Summ"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"ar"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"ize"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" and"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"turn"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Prefix"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Messages"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" are"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" empty"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":".\n\n"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Flow"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":":"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" choose"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" latest"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" reusable"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" previous"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" comp"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"action"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":";"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" boundary"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" is"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" after"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" it"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"."},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" Compute"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"tokens"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Before"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" from"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" last"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" valid"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" assistant"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" usage"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"."},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" Option"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"ally"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" scale"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"keep"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Recent"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Tokens"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" down"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" if"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" provider"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" prompt"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" tokens"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" exceed"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" local"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" estimate"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"."},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"find"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Cut"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Point"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" walks"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" backward"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" over"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" messages"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":","},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" then"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" snaps"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" to"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" a"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" valid"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" cut"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" point"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":".\n\n"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Assistant"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" split"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":":"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" valid"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" cuts"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" include"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" assistant"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" messages"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":","},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" not"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" tool"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" results"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"."},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" If"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" the"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" cut"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" is"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" an"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" assistant"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":","},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"is"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Split"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Turn"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" is"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" true"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" when"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" a"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" prior"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" turn"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" start"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" exists"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"."},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" Then"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" old"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" history"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" ends"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" at"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" the"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" turn"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" start"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":";"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" turn"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"-start"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"-through"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"-before"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"-ass"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"istant"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" becomes"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"turn"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Prefix"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Messages"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`;"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" assistant"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" and"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" later"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" entries"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" become"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" `"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"recent"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Messages"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"`."},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"usage_update","size":272000,"used":32602,"cost":{"amount":0.11527,"currency":"USD"}}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"session_info_update","updatedAt":"2026-10-08T18:56:40.423Z","title":"Captured conversation"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","id":4,"result":{"stopReason":"end_turn","usage":{"inputTokens":14682,"outputTokens":737,"totalTokens":33339,"cachedReadTokens":17920}}}} diff --git a/src/main/acp/fixtures/omp-v17-reply-without-thought.jsonl b/src/main/acp/fixtures/omp-v17-reply-without-thought.jsonl new file mode 100644 index 000000000000..3663d9e1be17 --- /dev/null +++ b/src/main/acp/fixtures/omp-v17-reply-without-thought.jsonl @@ -0,0 +1,42 @@ +{"direction":"out","process":"A","message":{"jsonrpc":"2.0","id":3,"method":"session/prompt","params":{"sessionId":"session-1","prompt":[{"type":"text","text":"Captured source-context question."}]}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"available_commands_update","availableCommands":[{"name":"model","description":"Show current model selection"},{"name":"fast","description":"Toggle fast mode","input":{"hint":"[on|off|status]"}},{"name":"prewalk","description":"Prewalk at the next action"},{"name":"advisor","description":"Toggle advisor","input":{"hint":"[on|off|status|dump [raw]|configure]"}},{"name":"export","description":"Export session to HTML file","input":{"hint":"[path]"}},{"name":"dump","description":"Return full transcript as plain text, with LLM request JSON path"},{"name":"share","description":"Share session via an encrypted link (share server or secret gist)"},{"name":"browser","description":"Toggle browser headless vs visible mode","input":{"hint":"[headless|visible]"}},{"name":"todo","description":"Manage todos","input":{"hint":"<subcommand>"}},{"name":"session","description":"Show session information","input":{"hint":"info|delete"}},{"name":"jobs","description":"Show background jobs"},{"name":"usage","description":"Show token usage","input":{"hint":"[show|reset [account|active]]"}},{"name":"stats","description":"Launch the local stats dashboard","input":{"hint":"[--port <port>]"}},{"name":"changelog","description":"Show changelog","input":{"hint":"[full]"}},{"name":"tools","description":"Show available tools"},{"name":"context","description":"Show context usage"},{"name":"mcp","description":"Manage MCP servers","input":{"hint":"<subcommand>"}},{"name":"ssh","description":"Manage SSH connections","input":{"hint":"<subcommand>"}},{"name":"fresh","description":"Reset provider stream state without changing the local transcript"},{"name":"compact","description":"Compact the conversation","input":{"hint":"[soft|remote|snapcompact] [focus]"}},{"name":"shake","description":"Shake heavy content out of the conversation context","input":{"hint":"[elide|images]"}},{"name":"memory","description":"Manage memory","input":{"hint":"<subcommand>"}},{"name":"rename","description":"Rename the current session","input":{"hint":"<title>"}},{"name":"move","description":"Move the current session to a different directory","input":{"hint":"[<path>]"}},{"name":"marketplace","description":"Manage plugins from marketplaces","input":{"hint":"<subcommand>"}},{"name":"plugins","description":"Manage plugins","input":{"hint":"[list|enable|disable]"}},{"name":"reload-plugins","description":"Reload all plugins"},{"name":"force","description":"Force next turn to use a specific tool","input":{"hint":"<tool-name> [prompt]"}},{"name":"autoresearch","description":"Toggle builtin autoresearch mode, or pass off / clear, or a goal message.","input":{"hint":"arguments"}},{"name":"green","description":"Generate a prompt to iterate on CI failures until the branch is green","input":{"hint":"arguments"}},{"name":"review","description":"Launch interactive code review","input":{"hint":"arguments"}},{"name":"init","description":"Generate AGENTS.md for current codebase"}]}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"session_info_update","updatedAt":"2026-10-08T18:55:19.899Z","title":"Captured conversation"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"marker"},"messageId":"message-1"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" recorded"},"messageId":"message-1"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"usage_update","size":272000,"used":18141,"cost":{"amount":0.091395,"currency":"USD"}}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"session_info_update","updatedAt":"2026-10-08T18:55:22.497Z","title":"Captured conversation"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","id":3,"result":{"stopReason":"end_turn","usage":{"inputTokens":18141,"outputTokens":23,"totalTokens":18164}}}} +{"direction":"out","process":"A","message":{"jsonrpc":"2.0","id":4,"method":"session/prompt","params":{"sessionId":"session-1","prompt":[{"type":"text","text":"Captured source-context question."}]}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Default"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" retained"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" history"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":":"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" keep"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Recent"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Tokens"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" ="},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" "},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"200"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"00"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"."},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" Preparation"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" is"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" no"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"-op"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" when"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" both"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" messages"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"To"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Summ"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"ar"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"ize"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" and"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" turn"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Prefix"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"Messages"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" are"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":" empty"},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"agent_message_chunk","content":{"type":"text","text":"."},"messageId":"message-2"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"usage_update","size":272000,"used":32563,"cost":{"amount":0.17837,"currency":"USD"}}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","method":"session/update","params":{"sessionId":"session-1","update":{"sessionUpdate":"session_info_update","updatedAt":"2026-10-08T18:55:24.646Z","title":"Captured conversation"}}}} +{"direction":"in","process":"A","message":{"jsonrpc":"2.0","id":4,"result":{"stopReason":"end_turn","usage":{"inputTokens":14643,"outputTokens":160,"totalTokens":32723,"cachedReadTokens":17920}}}} diff --git a/src/main/native-chat/agent-session-timeline/provider-timeline-assembler-test-support.ts b/src/main/native-chat/agent-session-timeline/provider-timeline-assembler-test-support.ts index 6946d455314b..79c1aea2fabf 100644 --- a/src/main/native-chat/agent-session-timeline/provider-timeline-assembler-test-support.ts +++ b/src/main/native-chat/agent-session-timeline/provider-timeline-assembler-test-support.ts @@ -19,7 +19,11 @@ import { isBackgroundTaskBlock, type NativeChatBackgroundTaskBlock } from '../../../shared/native-chat-types' -import { createTrackedJournalOpener } from '../agent-session-journal/journal-host-database-test-support' +import { + closeTestJournalHostDatabase, + createTrackedJournalOpener, + type TestJournalOptions +} from '../agent-session-journal/journal-host-database-test-support' import type { AgentSessionJournal } from '../agent-session-journal/journal-store' import { createDeferredStructuredAgentSessionEventSink, @@ -199,6 +203,8 @@ export type ProviderTimelineRig = { * sink; the rig's own assembler must then stay unused. */ assemble(overrides?: Partial<ProviderTimelineAssemblerDeps>): ProviderTimelineAssembler rows(): Promise<AgentJournalRenderItem[]> + /** Closes the original journal and database, then reads the persisted chat through a new store. */ + reopenJournal(): Promise<AgentSessionJournal> row(itemId: string): Promise<AgentJournalRenderItem | undefined> /** The turn row of provider turn `turnKey`, or the row whose turn id is `turnKey`. */ turn(turnKey: string, namespace?: string): Promise<AgentJournalTurnLifecycle | undefined> @@ -222,7 +228,7 @@ export async function openProviderTimelineRig( overrides: Partial<ProviderTimelineAssemblerDeps> = {} ): Promise<ProviderTimelineRig> { const root = await mkdtemp(join(tmpdir(), 'orca-provider-timeline-')) - const journal = await journals.open({ + const journalOptions: TestJournalOptions = { identity: { sessionId: SESSION, workspaceId: 'workspace-1', @@ -232,7 +238,8 @@ export async function openProviderTimelineRig( }, stateDirectory: root, now: () => 1_000 - }) + } + const journal = await journals.open(journalOptions) const deferred = createDeferredStructuredAgentSessionEventSink(testEventSinkLogging()) deferred.bind({ journal, fence: 1, publish: () => {} }) cleanups.push(async () => { @@ -282,6 +289,12 @@ export async function openProviderTimelineRig( assembler: build(), sink, eventSink: deferred.sink, + reopenJournal: async () => { + await rows() + await journal.close() + closeTestJournalHostDatabase(root) + return journals.open(journalOptions) + }, restart: async (more = {}) => { generations += 1 const generation = more.generation ?? `gen-${generations}`