mirror of
https://github.com/stablyai/orca.git
synced 2026-11-05 11:37:25 +00:00
#23682 established that only `turn/completed` ends a Codex turn and deleted `codex-structured-journal-provider-verdicts.ts`, but the child-turn reader kept importing `readCodexProviderVerdict` and branching on its `turn-failed` verdict. The module is gone, so the import resolves to nothing: typecheck and static analysis fail on every pull request, which skips the whole unit matrix behind them, and the esbuild pass behind Bun profile scope detection throws, so every run falls back to all six platforms. A closed thread is now the only child-turn end without `turn/completed`, which is what #23682 intended: Codex follows a turn-ending `error` with a failed `turn/completed` for the same turn 0-32 ms later, and that completion carries the duration and receipt time the error does not.
103 lines
3.3 KiB
TypeScript
103 lines
3.3 KiB
TypeScript
import type { NativeChatSubagentState } from '../../shared/native-chat-types'
|
|
import {
|
|
codexSubagentLabel,
|
|
isCodexRootAgentActivity,
|
|
readCodexSubagentActivity
|
|
} from './codex-subagent-activity'
|
|
import { codexChildTurnState } from './codex-subagent-executions'
|
|
import { readRecord } from './codex-item-field-readers'
|
|
import { readCodexThreadItem } from './codex-structured-item-translation'
|
|
import { readCodexTurnId } from './codex-structured-thread-facts'
|
|
|
|
export type CodexBackgroundTaskFrame =
|
|
| {
|
|
kind: 'subagent'
|
|
agentThreadId: string
|
|
label: string | null
|
|
parentTurnId: string | null | undefined
|
|
/** The reporting thread, for a `started` activity: the agent that spawned the child. */
|
|
spawnerThreadId: string | undefined
|
|
}
|
|
| {
|
|
kind: 'turn'
|
|
threadId: string
|
|
turnId: string
|
|
state: NativeChatSubagentState
|
|
}
|
|
| {
|
|
/** A child turn that ended with no `turn/completed`. No `turnId`: the one it is running. */
|
|
kind: 'turn-ended'
|
|
threadId: string
|
|
turnId: null
|
|
state: Extract<NativeChatSubagentState, 'unverifiable'>
|
|
}
|
|
|
|
export type CodexBackgroundTaskEvent = {
|
|
method: string
|
|
threadId: string
|
|
params: unknown
|
|
}
|
|
|
|
/**
|
|
* The one way Codex ends a child's turn without `turn/completed`: a closed thread ran its last
|
|
* turn and Codex never said how it went. A turn-ending `error` is not one — Codex follows it with
|
|
* a failed `turn/completed` for the same turn, which is that turn's end and carries the duration
|
|
* and receipt time the error does not.
|
|
*/
|
|
function readCodexChildTurnEnding(
|
|
event: CodexBackgroundTaskEvent
|
|
): CodexBackgroundTaskFrame | null {
|
|
return event.method === 'thread/closed'
|
|
? { kind: 'turn-ended', threadId: event.threadId, turnId: null, state: 'unverifiable' }
|
|
: null
|
|
}
|
|
|
|
export function readCodexBackgroundTaskFrame(
|
|
event: CodexBackgroundTaskEvent,
|
|
primaryThreadId: string
|
|
): CodexBackgroundTaskFrame | null {
|
|
// The session's own turn ends through the journal's turn boundaries, never here.
|
|
const ending = event.threadId === primaryThreadId ? null : readCodexChildTurnEnding(event)
|
|
if (ending) {
|
|
return ending
|
|
}
|
|
if (event.method === 'turn/started' || event.method === 'turn/completed') {
|
|
const turnId = readCodexTurnId(event.params)
|
|
if (turnId === null) {
|
|
return null
|
|
}
|
|
return {
|
|
kind: 'turn',
|
|
threadId: event.threadId,
|
|
turnId,
|
|
state:
|
|
event.method === 'turn/started'
|
|
? 'working'
|
|
: codexChildTurnState(readRecord(readRecord(event.params).turn).status)
|
|
}
|
|
}
|
|
if (event.method !== 'item/started' && event.method !== 'item/completed') {
|
|
return null
|
|
}
|
|
const item = readCodexThreadItem(readRecord(event.params).item)
|
|
const activity = item && readCodexSubagentActivity(item)
|
|
if (
|
|
!activity ||
|
|
activity.agentThreadId === primaryThreadId ||
|
|
isCodexRootAgentActivity(activity)
|
|
) {
|
|
return null
|
|
}
|
|
return {
|
|
kind: 'subagent',
|
|
agentThreadId: activity.agentThreadId,
|
|
label: codexSubagentLabel(activity),
|
|
parentTurnId:
|
|
activity.kind === 'started' || activity.kind === 'interacted'
|
|
? readCodexTurnId(event.params)
|
|
: undefined,
|
|
// Only `started` names the spawner: other kinds ride whichever agent acted.
|
|
spawnerThreadId: activity.kind === 'started' ? event.threadId : undefined
|
|
}
|
|
}
|