Files
orca/src/main/opencode/status-plugin-lifecycle-source.ts
Neil 48e63c015f refactor agent config and auth services (#16195)
* refactor: split agent config and auth services

* chore: repoint wsl and global-fetch guards at split module paths

* fix: restore merge-base Claude CLI error propagation

Drop the secret-redaction rewriting added to Claude CLI error paths in the
refactor: spawn errors again reject with the original Error (preserving
.code/.errno/.syscall/.stack) and command output/auth-status logs are no
longer rewritten.
2026-08-24 23:15:01 -07:00

137 lines
7.0 KiB
TypeScript

export function getStatusPluginLifecycleSource(): string[] {
return [
'async function handleLifecycleEvent(client, event, factoryID) {',
' const sessionID = event.properties?.sessionID;',
' const statusType = getStatusType(event);',
' const isResolutionEvent =',
' event.type === "permission.replied" ||',
' event.type === "question.replied" ||',
' event.type === "question.rejected";',
' if (isResolutionEvent) {',
' // Why: the stored owner already identifies the root, so replies clear',
' // immediately even when OpenCode session lookup is slow or unavailable.',
' const rootSessionID = clearAttentionForResolution(event, sessionID, factoryID);',
' if (rootSessionID) await publishOwnershipChange(factoryID, rootSessionID);',
' return;',
' }',
' const isAttentionEvent =',
' event.type === "permission.asked" ||',
' event.type === "question.asked";',
" // Why: attention without OpenCode's required sessionID cannot be",
' // correlated to a later reply/Idle, so it must not become UI authority.',
' if (isAttentionEvent && !sessionID) return;',
' const canFailOpen =',
' statusType === "busy" || statusType === "retry" || isAttentionEvent;',
' const rootSessionID = sessionID ? await resolveRootSessionID(client, sessionID) : null;',
' const childState = rootSessionID === null ? null : rootSessionID !== sessionID;',
' const isIdleEvent = event.type === "session.idle" || statusType === "idle";',
' const resolvedProvisionalBusy =',
' childState === false || (childState === true && isIdleEvent)',
' ? clearProvisionalBusy(sessionID, factoryID)',
' : false;',
' if (resolvedProvisionalBusy && childState === false) {',
' busyRootOwnerBySessionID.delete(sessionID);',
' busyRootOwnerBySessionID.set(sessionID, factoryID);',
' }',
' // Why: child work rolls up to the pane; ignore its normal lifecycle noise,',
' // but preserve blockers that still require the pane owner to respond.',
' if (childState === true && !isAttentionEvent) {',
' let attentionRootSessionID = null;',
' let childBusyChanged = false;',
' if (isIdleEvent) {',
' attentionRootSessionID = clearAttentionForSession(sessionID, factoryID);',
' childBusyChanged = clearBusyChild(sessionID, factoryID);',
' } else if (statusType === "busy" || statusType === "retry") {',
' childBusyChanged = rememberBusyChild(sessionID, rootSessionID, factoryID);',
' }',
' if (resolvedProvisionalBusy || attentionRootSessionID || childBusyChanged) {',
' await publishOwnershipChange(factoryID, attentionRootSessionID || rootSessionID);',
' }',
' return;',
' }',
' if (childState === null && !canFailOpen) {',
' if (isIdleEvent) {',
' // Why: recorded ownership can safely retire a blocker during an SDK',
' // outage without granting unknown child Idle authority over root state.',
' const attentionRootSessionID = clearAttentionForSession(sessionID, factoryID);',
' const clearedProvisionalBusy = clearProvisionalBusy(sessionID, factoryID);',
' const clearedKnownBusyRoot = clearKnownBusyRoot(sessionID, factoryID);',
' // Why: exact-session cleanup, so a child whose finishing Idle lands',
' // during an SDK outage cannot pin the pane Busy forever.',
' const clearedBusyChild = clearBusyChild(sessionID, factoryID);',
' if (',
' attentionRootSessionID ||',
' clearedProvisionalBusy ||',
' clearedKnownBusyRoot ||',
' clearedBusyChild',
' ) {',
' await publishOwnershipChange(factoryID, attentionRootSessionID || sessionID);',
' }',
' }',
' return;',
' }',
' if (childState === null && (statusType === "busy" || statusType === "retry")) {',
' // Unknown lineage may be child work, so keep exact provisional ownership',
' // only until matching Idle/disposal; other blockers still take priority.',
' clearAttentionForSession(sessionID, factoryID);',
' rememberProvisionalBusy(sessionID, factoryID);',
' await publishAggregateStatus(factoryID, sessionID);',
' return;',
' }',
' if (event.type === "permission.asked" || event.type === "question.asked") {',
' stateArrivalRevision += 1;',
' // Why: attention must share the lifecycle FIFO and retry target so a',
' // delayed Busy post cannot overwrite a newer human blocker.',
' const hookEventName =',
' event.type === "permission.asked" ? "PermissionRequest" : "AskUserQuestion";',
' // Why: show the blocker on the root turn while retaining its real child',
' // owner for exact reply, tool-completion, and disposal cleanup.',
' const properties = { ...(event.properties || {}), sessionID: rootSessionID || sessionID };',
' const requestID = properties.id || sessionID || "";',
' const key = attentionKey(factoryID, hookEventName, requestID, sessionID);',
' // Why: unresolved blockers are live UI authority and cannot be evicted;',
' // reply, exact Idle, tool completion, or factory disposal retires them.',
' pendingAttentionByKey.set(key, {',
' hookEventName,',
' properties,',
' factoryID,',
' sourceSessionID: sessionID,',
' });',
' await publishAggregateStatus(factoryID, rootSessionID || sessionID);',
' return;',
' }',
' if (isIdleEvent) {',
' stateArrivalRevision += 1;',
' const idleKey = "idle:" + (sessionID || "");',
' // Why: current OpenCode emits canonical idle followed by deprecated',
' // session.idle; a failed canonical post should keep its backoff.',
' if (',
' event.type === "session.idle" &&',
' desiredStatusKey === idleKey &&',
' statusDeliveryDirty &&',
' statusRetryTimer',
' ) return;',
' // Why: flush the coalesced final reply snapshot before the idle',
' // transition so the done-state preview shows the completed message.',
' await flushPendingAssistantPart(true);',
' clearAttentionForSession(sessionID, factoryID);',
' if (busyRootOwnerBySessionID.get(sessionID) === factoryID) {',
' busyRootOwnerBySessionID.delete(sessionID);',
' }',
' await publishAggregateStatus(factoryID, sessionID);',
' return;',
' }',
' // Why: recoverable compaction failures emit session.error and continue;',
' // canonical session.status is the authority for actual completion.',
' if (event.type === "session.error") return;',
' if (statusType === "busy" || statusType === "retry") {',
' clearAttentionForSession(sessionID, factoryID);',
' busyRootOwnerBySessionID.delete(sessionID);',
' busyRootOwnerBySessionID.set(sessionID, factoryID);',
' await publishAggregateStatus(factoryID, sessionID);',
' }',
'}',
''
]
}