Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import {
type StructuredAgentSessionState
} from '../../../src/shared/structured-agent-session-reducer'
import { selectStructuredAgentTurnBars } from '../../../src/shared/structured-agent-session-turn-timing'
import { TUI_AGENT_DISPLAY_NAMES } from '../../../src/shared/tui-agent-display-names'
import {
buildMobileNativeChatTransientData,
foldMobileNativeChatMessages
Expand Down Expand Up @@ -55,9 +54,7 @@ function apply(
/** The rows the phone's transcript reads, as its session hook builds them: the journal plus the
* notice a cut turn gets, projected with no other rejected send drawn in place. */
function phoneTranscript(state: StructuredAgentSessionState) {
const items = withNativeChatCutTurnNotices(state.items, {
agentName: TUI_AGENT_DISPLAY_NAMES.codex
})
const items = withNativeChatCutTurnNotices(state.items)
return {
items,
messages: projectStructuredAgentSessionMessages(items, [], state.submissions)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,8 +120,8 @@ describe('useMobileStructuredAgentSession transcript', () => {
role: 'system',
blocks: [
{
text: 'Codex stopped while this response was in progress. You can continue in this conversation.',
tone: 'error'
text: 'This response was interrupted. You can continue in this conversation.',
tone: 'notice'
}
]
})
Expand Down
8 changes: 1 addition & 7 deletions mobile/src/session/use-mobile-structured-agent-session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,7 @@ export function useMobileStructuredAgentSession(args: {

// What the transcript reads, as desktop does: the journal plus the one notice a cut turn with no
// row gets.
const transcriptItems = useMemo(
() =>
withNativeChatCutTurnNotices(state.items, {
agentName: agent ? (tuiAgentDisplayName(agent) ?? agent) : undefined
}),
[agent, state.items]
)
const transcriptItems = useMemo(() => withNativeChatCutTurnNotices(state.items), [state.items])
const sends = useMobileStructuredSends({
sessionKey,
submissions: state.submissions,
Expand Down
4 changes: 2 additions & 2 deletions src/main/acp/acp-structured-host-lifecycle.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ describe('reopening a Grok chat through the host', () => {
'completed'
)
// The transcript explains the cut the way a Claude or Codex chat's does.
const transcript = withNativeChatCutTurnNotices(rows, { agentName: 'Grok' })
const transcript = withNativeChatCutTurnNotices(rows)
expect(
transcript.some(
(row) =>
Expand Down Expand Up @@ -150,7 +150,7 @@ describe('a Grok crash whose exit is not proven yet', () => {
child.exit()
await rig.settle()
await host.flushStreamedEvents(SESSION)
const transcript = withNativeChatCutTurnNotices(await rows(), { agentName: 'Grok' })
const transcript = withNativeChatCutTurnNotices(await rows())
// The crash's own notice, as for any crash; not a Stop's.
expect(
transcript.flatMap((row) =>
Expand Down
2 changes: 1 addition & 1 deletion src/main/acp/acp-structured-host-stop.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ describe('a Grok chat Stop', () => {
expect(framesOf(second, 'session/new')).toHaveLength(0)
expect(await messages()).toEqual(['hello', 'partial', 'again'])
// Only the Stop's own note: no exit or cut-reply notice for a Stop the person asked for.
const transcript = withNativeChatCutTurnNotices(await rows(), { agentName: 'Grok' })
const transcript = withNativeChatCutTurnNotices(await rows())
expect(
transcript.flatMap((row) => (row.body.kind === 'status' ? [row.body.text] : []))
).toEqual(['Cancellation requested.'])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
} from './structured-agent-session-launch-env'
import { refuseAgentSessionMutation } from './structured-agent-session-mutation-admission'
import { settleStaleStructuredAgentSessionState } from './structured-agent-session-dead-generation-settlement'
import { structuredAgentSessionFailureWordsContext } from './structured-agent-session-send-preparation'
import type { StructuredAgentSessionAttachContext } from './structured-agent-session-attach-context'
import type { StructuredAgentSessionProviderChild } from './structured-agent-session-host-types'
import {
Expand Down Expand Up @@ -241,8 +240,7 @@ async function runAttachUnderAbort(
fence,
acquisitionGeneration,
deathEvidence: priorDeathEvidence,
replaced: context.deps.store.replacedRuntime(sessionId),
failureTextContext: structuredAgentSessionFailureWordsContext(priorRecord)
replaced: context.deps.store.replacedRuntime(sessionId)
})
}
await bindAndDrain(eventSink, attached.journal, fence, (activity) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
} from '../../../shared/agent-session-journal-types'
import type { AgentSessionStatusEvent } from '../../../shared/agent-session-wire'
import { readAgentJournalTurn } from '../../../shared/agent-session-turn-record'
import { AGENT_SESSION_ORCA_STOP_TEXT } from '../../../shared/agent-session-orca-stop'
import { describeNativeChatTurnStatus } from '../../../shared/native-chat-turn-status'
import { withNativeChatCutTurnNotices } from '../../../shared/native-chat-cut-turn-notice'
import { selectStructuredAgentSettledTurns } from '../../../shared/structured-agent-session-turn-timing'
Expand Down Expand Up @@ -125,17 +126,15 @@ async function settledTurn() {
const turn = items.map((item) => readAgentJournalTurn(item.body)).find(Boolean)
const [settled] = [...selectStructuredAgentSettledTurns(items).values()]
const label = settled && describeNativeChatTurnStatus({ elapsedSeconds: 0, ...settled }).key
// Every error row a reader's transcript shows, the cut turn's derived notice included.
const notices = withNativeChatCutTurnNotices(items, { agentName: 'Codex' }).flatMap((item) =>
item.body.kind === 'status' && item.body.tone === 'error' ? [item.body.text] : []
// Every status row a reader's transcript shows, the cut turn's derived notice included.
const notices = withNativeChatCutTurnNotices(items).flatMap((item) =>
item.body.kind === 'status' ? [item.body.text] : []
)
return { turn, settled, label, notices }
}

/** A turn nobody stopped reads like a finished one, with exactly one row saying it stopped. */
const ONE_NOTICE = [
'Codex stopped while this response was in progress. You can continue in this conversation.'
]
const ONE_NOTICE = [AGENT_SESSION_ORCA_STOP_TEXT]

function lastSummary(statuses: AgentSessionStatusEvent[]) {
const last = statuses.at(-1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
} from './structured-agent-session-attach'
import type { AgentSessionRecordStore } from '../../runtime/agent-session-record-store'
import { settleStaleStructuredAgentSessionState } from './structured-agent-session-dead-generation-settlement'
import { structuredAgentSessionFailureWordsContext } from './structured-agent-session-send-preparation'
import {
markStructuredQueueReopen,
structuredAgentSessionHostInstance
Expand Down Expand Up @@ -173,8 +172,7 @@ async function settleGoneGeneration(
fence: record.lease.runtimeFence,
acquisitionGeneration: null,
deathEvidence: record.lease.deathEvidence ?? null,
replaced: deps.store?.replacedRuntime(record.sessionId),
failureTextContext: structuredAgentSessionFailureWordsContext(record)
replaced: deps.store?.replacedRuntime(record.sessionId)
})
} catch (error) {
// Best effort: the next open or acquire re-derives it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
// that runs for half a minute leaves one journal row at its start. The lease renewal the host
// wrote every ten seconds is what saw the child working after that row.

import { AGENT_SESSION_ORCA_STOP_TEXT } from '../../../shared/agent-session-orca-stop'
import { mkdtemp, rm } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
Expand Down Expand Up @@ -236,15 +237,11 @@ describe('a turn a crash cut short mid-tool', () => {

const { items } = await host.journalSnapshot(SESSION)
// As a reader's transcript shows it: the stored row is the explanation, so none is derived.
const statusRows = withNativeChatCutTurnNotices(items, { agentName: 'Claude' }).flatMap(
(item) => (item.body.kind === 'status' ? [item.body] : [])
const statusRows = withNativeChatCutTurnNotices(items).flatMap((item) =>
item.body.kind === 'status' ? [item.body] : []
)
expect(statusRows).toEqual([
expect.objectContaining({
text: 'Claude stopped while this response was in progress. You can continue in this conversation.',
failure: expect.objectContaining({ kind: 'providerExited' }),
tone: 'error'
})
expect.objectContaining({ text: AGENT_SESSION_ORCA_STOP_TEXT, tone: 'notice' })
])
const [timing] = selectStructuredAgentTurnTimings(items).values()
expect(
Expand Down Expand Up @@ -392,7 +389,7 @@ describe('a turn a read reached before the reconcile proved its owner dead', ()
{ kind: 'turn', turnItemId }
])
expect(latestNativeChatOrcaStopCut(items, [])).toEqual({ turnItemId, cause: 'crash' })
const readerRows = withNativeChatCutTurnNotices(items, { agentName: 'Claude' }).filter(
const readerRows = withNativeChatCutTurnNotices(items).filter(
(item) => item.body.kind === 'status'
)
expect(readerRows).toHaveLength(1)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,6 @@ export async function settleStaleStructuredAgentSessionState(input: {
deathEvidence: AgentSessionDeathEvidence | null
/** The runtimes this one replaced for this chat: every owner they held lost its pipes with them. */
replaced?: AgentSessionReplacedRuntime
/** Who the exit row names. */
failureTextContext?: AgentSessionFailureWordsContext
}): Promise<number> {
const { journal, replaced } = input
const items = journal.snapshot().items
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import {
recordStructuredAgentSessionShutdownCut,
runningRootTurnItemId
} from './structured-agent-session-orca-stop-row'
import { structuredAgentSessionFailureWordsContext } from './structured-agent-session-send-preparation'
export type { StructuredAgentSessionStopEnding } from './structured-agent-session-host-stop-event'
import {
recordStopEvent,
Expand Down Expand Up @@ -190,17 +189,13 @@ export async function stopStructuredAgentSessionAgentUnderSerialize(
}
// The exit handler has settled the turn by now, so the row reads its verdict.
if ('quit' in ending && ending.quit) {
const record = context.deps.store.getRecord(sessionId)
await recordStructuredAgentSessionShutdownCut({
journal: session.journal,
sessionId,
fence: child.fence,
generation: child.generation ?? 'unknown',
turnItemId: quitCuts,
trigger: ending.quit,
...(record
? { failureTextContext: structuredAgentSessionFailureWordsContext(record) }
: {}),
logger: context.deps.logger
})
}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,23 +1,11 @@
// The row that says why a quit or update cut a reply: the cut turn's own explanation, in the words
// every client already prints for a stopped agent, with the cause beside them for clients that
// name it (`AgentSessionOrcaStop`).
// The row that says why a quit or update cut a reply: the cut turn's own explanation, with the cause
// beside it for clients that name it (`AgentSessionOrcaStop`).

import { agentSessionFailureFact } from '../../../shared/agent-session-failure'
import {
AGENT_SESSION_ORCA_STOP_PRESENTATION,
isAgentSessionOrcaStopCause
} from '../../../shared/agent-session-orca-stop'
import { agentSessionOrcaStopRowBody } from '../../../shared/agent-session-orca-stop'
import type { AgentSessionResumeTrigger } from '../../../shared/agent-session-resume-marker'
import {
agentSessionFailureWords,
type AgentSessionFailureWordsContext
} from '../../../shared/agent-session-failure-words'
import { parseAgentJournalItemKey } from '../../../shared/agent-session-journal-item-key'
import { isRootAgentJournalItem } from '../../../shared/agent-session-journal-producer'
import type {
AgentJournalRenderItem,
AgentJournalStatusItem
} from '../../../shared/agent-session-journal-types'
import type { AgentJournalRenderItem } from '../../../shared/agent-session-journal-types'
import {
readAgentJournalTurn,
readAgentJournalTurnOutcome
Expand All @@ -29,26 +17,6 @@ import type { StructuredAgentSessionLogger } from './structured-agent-session-lo

type OrcaStopRowJournal = Pick<AgentSessionJournal, 'snapshot' | 'appendItem'>

/** The row about an owner gone from under a turn: today's words and tone, which every client prints
* as it always has, and why Orca stopped when it was Orca, which a client that knows the cause names
* instead, muted. */
export function orcaStopRowBody(
context: AgentSessionFailureWordsContext | undefined,
orcaEnd: unknown
): AgentJournalStatusItem {
return {
kind: 'status',
...agentSessionFailureWords(agentSessionFailureFact('providerExited'), {
...context,
surface: 'row'
}),
tone: 'error',
...(isAgentSessionOrcaStopCause(orcaEnd)
? { presentation: AGENT_SESSION_ORCA_STOP_PRESENTATION, orcaStop: { cause: orcaEnd } }
: {})
}
}

/** The root turn running as the quit stops the child: the one its stop may cut. */
export function runningRootTurnItemId(
journal: Pick<AgentSessionJournal, 'snapshot'>
Expand Down Expand Up @@ -84,7 +52,6 @@ export async function recordStructuredAgentSessionShutdownCut(input: {
generation: string
turnItemId: string | null
trigger: AgentSessionResumeTrigger
failureTextContext?: AgentSessionFailureWordsContext
logger: StructuredAgentSessionLogger
}): Promise<void> {
try {
Expand All @@ -107,7 +74,7 @@ export async function recordStructuredAgentSessionShutdownCut(input: {
}
await input.journal.appendItem(
{ provider: 'orca', clientMessageId },
orcaStopRowBody(input.failureTextContext, input.trigger),
agentSessionOrcaStopRowBody(input.trigger),
{ fence: input.fence, turnScope: { kind: 'turn', turnItemId } }
)
} catch (error) {
Expand Down
Loading
Loading