mirror of
https://github.com/stablyai/orca.git
synced 2026-10-18 16:03:17 +00:00
* fix(native-chat): the chat reads whether a turn runs from the host, not the loaded history page * fix(native-chat): the Working bar, card cancel and phone Stop follow the host's turn when its rows are not loaded * fix(native-chat): keep the phone's Stop as it was, naming the host's running turn Drops the conversation-wide phone Stop: the phone shows Stop only once a turn is running, so a Stop naming no turn could not be reached and only changed the ordinary Stop's request. Stop and card cancel still name the turn the host says is running. * fix(native-chat): the host's turn answer never outlives its host, and a half-loaded turn shows no edit totals - A batch carrying rows restates the host's newest turn record, so one without it (an older host after a downgrade) drops back to the loaded rows instead of holding the last answer; the event coalescer merges by the same rule. - A turn whose record is above the loaded rows is grouped only while it runs, and its loaded tail gets no "N changed files" total, which would undercount. - "Thinking" reads the host's running turn too, so it shows when the turn's record is not loaded. - The wire doc for observedAt says what the journal stores: creation time. * refactor(native-chat): totals per turn come from their own hook, keeping the transcript list under its line limit Also drops the chat zoom prop main removed from the unloaded live turn test.
50 lines
2.5 KiB
TypeScript
50 lines
2.5 KiB
TypeScript
import type { AgentJournalTurnOutcome } from './agent-session-journal-types'
|
|
import { agentSessionScopeKey, type AgentSessionExecutionLocation } from './agent-session-record'
|
|
|
|
// Turn completion feed: the per-turn EDGE beside the status feed's STATE.
|
|
|
|
/**
|
|
* The session's latest request reaching a terminal outcome — a root turn, or a send the agent or
|
|
* its start refused — derived by the EXECUTION HOST at journal commit.
|
|
*
|
|
* This is the EDGE, with turn identity; `AgentSessionStatusSummary.turnOutcome` is the STATE.
|
|
* The summary carries the verdict only while the session is idle, as a fact about the main agent's
|
|
* last turn that a status reader may act on (attention alerts, the `mainAgent.outcome` row field),
|
|
* and never a turn id: a reader that needs to know WHICH turn finished, or to react exactly once
|
|
* per finish, subscribes here. Re-broadcasting the summary on every status change therefore
|
|
* repeats a state, not a completion.
|
|
*
|
|
* `outcome` is the journal's recorded verdict (the provider's, a stop, or the host's supersede) and
|
|
* is never inferred — a turn the host only observed ending carries no outcome and produces no event
|
|
* at all, because absent means UNKNOWN, not success.
|
|
*/
|
|
export type AgentSessionTurnCompletion = {
|
|
/** Host-and-workspace scope; a bare provider turn id is not globally unique. */
|
|
scope: AgentSessionExecutionLocation
|
|
sessionId: string
|
|
/** The request's identity: the root turn's id, or for a send refused before any turn, that
|
|
* send's journal item key. Neither is minted here. */
|
|
turnId: string
|
|
outcome: AgentJournalTurnOutcome
|
|
/** Execution host's clock at journal commit. */
|
|
completedAt: number
|
|
/** The request settled while a prompt waits on the user. Absent otherwise, and from older hosts. */
|
|
awaitingUser?: true
|
|
}
|
|
|
|
/**
|
|
* LIVE-ONLY: there is no snapshot arm and no replay arm, by decision. A subscriber is told what
|
|
* completes while it is subscribed and nothing else; completions that land while it is away are
|
|
* dropped rather than queued, so nothing durable can strand. On reconnect the client baselines.
|
|
*/
|
|
export type AgentSessionTurnCompletionEvent =
|
|
| { type: 'completion'; completion: AgentSessionTurnCompletion }
|
|
| { type: 'end' }
|
|
|
|
/** Delivery dedupe address. Unread is idempotent and does not need it; mobile fanout does. */
|
|
export function agentSessionTurnCompletionKey(completion: AgentSessionTurnCompletion): string {
|
|
return [agentSessionScopeKey(completion.scope), completion.sessionId, completion.turnId].join(
|
|
'\u0000'
|
|
)
|
|
}
|