mirror of
https://github.com/stablyai/orca.git
synced 2026-11-01 01:27:35 +00:00
* fix(native-chat): fold thoughts and tool calls between replies into one row A model that thinks before every tool call drew a 'Thought for Ns' row between each call, and each thought also stopped the calls from merging, so a turn read as dozens of alternating rows. The transcript now draws an unbroken stretch of tool calls and thoughts within a turn as one tool run; thoughts read in order inside it when opened and are not counted in its label. * fix(native-chat): keep work runs whole while a turn edits files A live turn that had edited a file kept splitting its newest call or thought off the run (the row carrying the turn's diff rollup could not join), so a lone "Thought for Ns" row came back at the bottom. - Run boundaries are now one pure pass in src/shared (nativeChatWorkRunSpans), applied over the built transcript slots. Section heads end runs by sitting between rows, and rows inside an expanded subagent section are grouped the same way. - The row carrying the turn's diff rollup joins as the run's last member; the run takes the rollup from it and the bar from its head. - A collapsed run reserves one tool row plus a lead's words, not every thought's text. - Lone rows and runs draw through the same MessageRow, with one flat keyed line list, so a row becoming a run no longer remounts (a revealed diff card no longer re-fires its scroll). - A run opens by default while the reader holds one of its thoughts open; the run's own choice still wins. - A drawn thought with no visible text joins a run instead of splitting it. * fix(native-chat): pair each row's result with its own call; keep open thoughts out of runs - A structured journal row's call and result now share one id (the provider's call id, else the row's own id), so a diff or output can no longer pair with an earlier unanswered call in the same work run or folded message. A quiet command followed by edits now shows each diff card under its own call, and the rollup's reveal lands on it. - A thought still being thought, while its turn or subagent works, keeps its own row after the run and joins once it ends. - Removed the rule that opened a run because a thought inside it was open; a thought keeps its own open state inside its run. * fix(native-chat): an open thought the live line lets go of joins its run Only a subagent section keeps a still-running thought out of its run. At the top level the live line owns the open thought; when it lets go (a Stop in flight, a prompt waiting on the reader) the thought now joins the run at once instead of flashing as its own row until the turn ends. * test(native-chat): guard the run row memo; name the slot post-pass test after it Settled work runs must not rebuild their lines and thoughts on every stream frame of the live run. Renames the slot-level run test so it no longer shares a name with the shared span test.
52 lines
2.2 KiB
TypeScript
52 lines
2.2 KiB
TypeScript
// The one definition of a structured journal's tool actions: which rows the chat draws as a
|
|
// tool call, and the block it draws. The status line reads the same definition, so the sidebar
|
|
// names a tool exactly as the chat draws it.
|
|
|
|
import type {
|
|
AgentJournalDiffItem,
|
|
AgentJournalItemBody,
|
|
AgentJournalToolCallItem
|
|
} from './agent-session-journal-types'
|
|
import type { NativeChatToolCallBlock } from './native-chat-types'
|
|
|
|
export type StructuredAgentSessionToolAction = AgentJournalToolCallItem | AgentJournalDiffItem
|
|
|
|
// Codex rewrites an edit's `apply_patch` call into a diff once its changes exist.
|
|
export function isStructuredAgentSessionToolAction(
|
|
body: AgentJournalItemBody | undefined
|
|
): body is StructuredAgentSessionToolAction {
|
|
return body?.kind === 'tool-call' || body?.kind === 'diff'
|
|
}
|
|
|
|
/** A diff carries no lifecycle, so it reads as settled; otherwise a finished edit would stay the
|
|
* running call for the rest of its turn. */
|
|
export function isRunningStructuredAgentSessionToolAction(
|
|
action: StructuredAgentSessionToolAction
|
|
): boolean {
|
|
return action.kind === 'tool-call' && action.state === 'running'
|
|
}
|
|
|
|
/** `itemId`: the journal row's, the call's id when the provider gave none. A call and its result
|
|
* are one row, so the result names its call by it; without an id a result pairs with the oldest
|
|
* unanswered call, which in a run of several rows can be another row's. */
|
|
export function structuredAgentSessionToolCallBlock(
|
|
action: StructuredAgentSessionToolAction,
|
|
itemId: string
|
|
): NativeChatToolCallBlock {
|
|
if (action.kind === 'diff') {
|
|
return { type: 'tool-call', name: 'Diff', input: { path: action.path }, callId: itemId }
|
|
}
|
|
return {
|
|
type: 'tool-call',
|
|
name: action.name,
|
|
input: action.input,
|
|
state: action.state,
|
|
...(action.endedAs !== undefined ? { endedAs: action.endedAs } : {}),
|
|
callId: action.callId ?? itemId,
|
|
...(action.mcpIdentity !== undefined ? { mcpIdentity: action.mcpIdentity } : {}),
|
|
...(action.exitCode !== undefined ? { exitCode: action.exitCode } : {}),
|
|
...(action.durationMs !== undefined ? { durationMs: action.durationMs } : {}),
|
|
...(action.webSearchResults !== undefined ? { webSearchResults: action.webSearchResults } : {})
|
|
}
|
|
}
|