Files
orca/src/shared/worker-transcript-background-task-text.test.ts
T
Brennan Benson e8e144bf3c fix(native-chat): a subagent's words are presented as that subagent's, never the parent's (#23605)
* fix(native-chat): a subagent's words are presented as that subagent's, never the parent's

The journal already names the agent that produced every row, but the transcript
projection dropped it, so a subagent's prose rendered as the parent's reply, its
tool calls folded into the parent's runs, and a settled turn could fold down to
a subagent's words as its only visible answer.

The transcript message now keeps the row's producer. The fold keeps each agent's
calls in that agent's own run, a turn's answer is the session's own agent's last
prose, and a subagent's row names the subagent on desktop, mobile and a worker's
transcript text.

* test(native-chat): give the window fixture's slot the attribution field it now carries

* fix(mobile): read the subagent label the row is given, and pin the caption

* fix(native-chat): keep interleaved agents in order and each agent's own run live

Review follow-ups:
- the fold is main's adjacency fold plus one condition: a row never folds into
  another agent's run, so an agent's later call stays below its subagent's work
  instead of jumping back into its earlier row
- each agent has its own live frontier, so a parent still inside its spawn call
  reads as running while its subagent works below it
- mobile names no one on a row whose only content is hidden behind its settled turn
- a pending question from a subagent keeps its producer
- worker reads serve only the producing agent's id, bounded like the roster key
  that names it, and drop the provenance fields
- the single-message worker formatter is private, so no caller can drop names
2026-09-28 15:28:01 -07:00

48 lines
1.5 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import type { NativeChatMessage } from './native-chat-types'
import { formatWorkerTranscriptMessages } from './worker-transcript-text'
const formatWorkerTranscriptMessage = (message: NativeChatMessage): string =>
formatWorkerTranscriptMessages([message]).join('')
function message(blocks: NativeChatMessage['blocks']): NativeChatMessage {
return { id: 'm-1', role: 'system', blocks, timestamp: null, source: 'hook' }
}
describe('worker transcript text — background task rows', () => {
it('prints the twin once and never the raw block', () => {
const text = formatWorkerTranscriptMessage(
message([
{ type: 'text', text: 'Background command "X" failed with exit code 1' },
{
type: 'background-task',
taskId: 'task-1',
kind: 'command',
label: 'X',
state: 'blocked',
summary: 'Background command "X" failed with exit code 1'
}
])
)
expect(text).toBe('[system] Background command "X" failed with exit code 1')
expect(text).not.toContain('[unsupported block]')
})
it('prints a row that arrived with no twin rather than dropping its sentence', () => {
expect(
formatWorkerTranscriptMessage(
message([
{
type: 'background-task',
taskId: 'task-1',
kind: 'command',
label: 'X',
state: 'blocked',
summary: 'it failed'
}
])
)
).toBe('[system] it failed')
})
})