Download src/agents/command/post-run.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 27.4 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/agents/command/post-run.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/agents/command/post-run.ts
-
curl -L -o post-run.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/agents/command/post-run.ts
27.4 kB
| import { coerceErrorMessage } from "@openclaw/normalization-core/error-coercion"; | |
| import { getReplyPayloadMetadata } from "../../auto-reply/reply-payload.js"; | |
| import { recordAgentRunTerminalOutcome } from "../../channels/turn/agent-run-terminal-outcome.js"; | |
| import type { CliDeps } from "../../cli/deps.types.js"; | |
| import { buildRestartRecoveryClaimCleanupPatch } from "../../config/sessions/restart-recovery-state.js"; | |
| import type { RestartRecoveryTerminalDeliveryEvidenceResult } from "../../config/sessions/restart-recovery-types.js"; | |
| import type { SessionEntry } from "../../config/sessions/types.js"; | |
| import { assertAgentRunLifecycleGenerationCurrent } from "../../infra/agent-events.js"; | |
| import { formatErrorMessage } from "../../infra/errors.js"; | |
| import { createSubsystemLogger } from "../../logging/subsystem.js"; | |
| import { isSubagentSessionKey } from "../../routing/session-key.js"; | |
| import type { RuntimeEnv } from "../../runtime.js"; | |
| import type { DeliveryContext } from "../../utils/delivery-context.shared.js"; | |
| import { | |
| buildRestartRecoveryTerminalDeliveryEvidence, | |
| constrainRestartRecoveryDeliveryPayloads, | |
| shouldPersistCurrentRunSessionCleanup, | |
| shouldPersistRestartRecoveryCleanup, | |
| } from "../agent-command-restart-recovery.js"; | |
| import { normalizeAgentRunTerminalDeliverySnapshot } from "../agent-run-terminal-delivery.js"; | |
| import { | |
| buildAgentRunTerminalOutcomeFromLifecycleEvent, | |
| classifyAgentRunTerminalOutcome, | |
| mergeAgentRunTerminalOutcome, | |
| } from "../agent-run-terminal-outcome.js"; | |
| import { OPENCLAW_AGENT_RUNTIME_ID } from "../agent-runtime-id.js"; | |
| import { isHeartbeatLifecycleRunKind } from "../bootstrap-mode.js"; | |
| import type { AcceptedCompactionSuccessor } from "../embedded-agent-runner/compaction-successor.js"; | |
| import { buildMainSessionRecoveryClearPatch } from "../main-session-recovery/main-session-recovery-clear.js"; | |
| import { persistPendingFinalDeliveryMarker } from "../pending-final-delivery-marker.js"; | |
| import type { AgentRunSessionTarget } from "../run-session-target.js"; | |
| import { throwAgentRunRestartAbortReason } from "../run-termination.js"; | |
| import type { SessionMaintenanceRequest } from "../session-maintenance/run.js"; | |
| import { persistAssistantTranscriptRepairRecord } from "./assistant-transcript-repair.js"; | |
| import { persistAgentSession } from "./attempt-execution.shared.js"; | |
| import type { deliverAgentCommandResult } from "./delivery.js"; | |
| import { createCommandBudget } from "./maintenance-budget.js"; | |
| import { createCommandMaintenanceFollowup } from "./maintenance.js"; | |
| import type { PreparedAgentCommandExecution } from "./prepare.js"; | |
| import type { runEmbeddedAgentAttempt } from "./run-embedded-attempt.js"; | |
| import { | |
| loadCliCompactionRuntime, | |
| loadDeliveryRuntime, | |
| loadSessionStoreRuntime, | |
| } from "./runtime-loaders.js"; | |
| import { clearPendingFinalDelivery } from "./session-helpers.js"; | |
| import type { EmbeddedSessionState } from "./session-preparation.js"; | |
| import type { AgentCommandOpts } from "./types.js"; | |
| type EmbeddedAgentAttempt = Awaited<ReturnType<typeof runEmbeddedAgentAttempt>>; | |
| const log = createSubsystemLogger("agents/agent-command"); | |
| export async function clearCommandRecoveryClaim(params: { | |
| prepared: PreparedAgentCommandExecution; | |
| sessionEntry?: SessionEntry; | |
| runOwnedSessionId: string; | |
| sessionReboundDuringRun: boolean; | |
| trackedRestartRecoveryDeliveryClaim: boolean; | |
| terminalDeliveryEvidence?: RestartRecoveryTerminalDeliveryEvidenceResult; | |
| }): Promise<void> { | |
| const { sessionStore, sessionKey, storePath, runId } = params.prepared; | |
| if ( | |
| params.sessionReboundDuringRun || | |
| !params.trackedRestartRecoveryDeliveryClaim || | |
| !sessionStore || | |
| !sessionKey | |
| ) { | |
| return; | |
| } | |
| try { | |
| const entry = sessionStore[sessionKey] ?? params.sessionEntry; | |
| if (entry?.restartRecoveryDeliveryRunId === runId) { | |
| await persistAgentSession({ | |
| sessionStore, | |
| sessionKey, | |
| storePath, | |
| initialEntry: entry, | |
| entry: { | |
| ...entry, | |
| ...buildRestartRecoveryClaimCleanupPatch({ | |
| entry, | |
| recordTerminalSource: true, | |
| terminalRunId: runId, | |
| terminalDeliveryEvidence: params.terminalDeliveryEvidence, | |
| }), | |
| ...buildMainSessionRecoveryClearPatch(entry), | |
| updatedAt: Date.now(), | |
| }, | |
| shouldPersist: (current) => | |
| shouldPersistRestartRecoveryCleanup(current, params.runOwnedSessionId, runId), | |
| }); | |
| } | |
| } catch (error) { | |
| log.warn( | |
| `failed to clear restart recovery delivery context for ${sessionKey}: ${coerceErrorMessage(error)}`, | |
| ); | |
| } | |
| } | |
| export function createCompactionSessionIdReporter( | |
| sessionId: string, | |
| onSessionIdChanged: AgentCommandOpts["onSessionIdChanged"], | |
| ) { | |
| let notifiedSessionId = sessionId; | |
| let pendingCompactionSessionId: string | undefined; | |
| const notifySessionIdChanged = (nextSessionId: string) => { | |
| notifiedSessionId = nextSessionId; | |
| pendingCompactionSessionId = undefined; | |
| onSessionIdChanged?.(nextSessionId); | |
| }; | |
| return { | |
| onSessionIdChanged: notifySessionIdChanged, | |
| onCompactionCommitted: (nextSessionId: string | undefined) => { | |
| if (nextSessionId !== undefined) { | |
| pendingCompactionSessionId = nextSessionId; | |
| } | |
| }, | |
| reportCommitted: () => { | |
| // Compaction can commit before abort or maintenance fails. The command's | |
| // finally reports it outside commit bookkeeping so cleanup targets its row. | |
| if ( | |
| pendingCompactionSessionId !== undefined && | |
| pendingCompactionSessionId !== notifiedSessionId | |
| ) { | |
| try { | |
| notifySessionIdChanged(pendingCompactionSessionId); | |
| } catch (error) { | |
| log.warn(`failed to report settled session identity: ${coerceErrorMessage(error)}`); | |
| } | |
| } | |
| }, | |
| }; | |
| } | |
| export async function finalizeEmbeddedAgentCommand(params: { | |
| prepared: PreparedAgentCommandExecution; | |
| opts: AgentCommandOpts; | |
| deps: CliDeps; | |
| runtime: RuntimeEnv; | |
| sessionEntry?: SessionEntry; | |
| attempt: EmbeddedAgentAttempt; | |
| embeddedSessionState: EmbeddedSessionState; | |
| suppressVisibleSessionEffects: boolean; | |
| preserveUserFacingSessionModelState: boolean; | |
| currentRunDeliveryContext?: DeliveryContext; | |
| sessionOwnership: { | |
| runOwnedSessionId: string; | |
| sessionReboundDuringRun: boolean; | |
| }; | |
| trackInternalModelRunTarget: (target: AgentRunSessionTarget | undefined) => void; | |
| onSessionOwnershipChanged: ( | |
| ownership: { runOwnedSessionId: string; sessionReboundDuringRun: boolean }, | |
| committedCompactionSessionId?: string, | |
| ) => void; | |
| onTerminalDeliveryEvidenceChanged: ( | |
| evidence: RestartRecoveryTerminalDeliveryEvidenceResult, | |
| ) => void; | |
| }) { | |
| const { | |
| cfg, | |
| body, | |
| transcriptBody, | |
| sessionId, | |
| sessionKey, | |
| sessionStore, | |
| storePath, | |
| sessionAgentId, | |
| workspaceDir, | |
| cwd, | |
| agentDir, | |
| timeoutMs, | |
| outboundSession, | |
| runId, | |
| } = params.prepared; | |
| const { | |
| fallbackProvider, | |
| fallbackModel, | |
| fallbackExhausted, | |
| provider, | |
| model, | |
| effectiveTurnThinkLevel, | |
| internalSessionTarget, | |
| attemptExecutionRuntime, | |
| messageChannel, | |
| suppressUserTurnPersistence, | |
| userTurnTranscriptRecorder, | |
| fallbackTrajectoryRecorder, | |
| deferredLifecycle, | |
| lifecycle, | |
| terminal, | |
| lifecycleGeneration, | |
| } = params.attempt; | |
| const { skillsSnapshot, runContext } = params.embeddedSessionState; | |
| const effectiveCwd = cwd ?? workspaceDir; | |
| const isHeartbeatLifecycleRun = isHeartbeatLifecycleRunKind(params.opts.bootstrapContextRunKind); | |
| let sessionEntry = params.sessionEntry; | |
| let result = params.attempt.result; | |
| let deliveryResult: Awaited<ReturnType<typeof deliverAgentCommandResult>>; | |
| let hasResultError: boolean; | |
| let terminalError: string | undefined; | |
| let maintenanceRequest: SessionMaintenanceRequest | undefined; | |
| let { runOwnedSessionId, sessionReboundDuringRun } = params.sessionOwnership; | |
| const publishSessionOwnership = (committedCompactionSessionId?: string) => { | |
| // Outer restart-recovery cleanup runs even after later delivery failures. | |
| params.onSessionOwnershipChanged( | |
| { runOwnedSessionId, sessionReboundDuringRun }, | |
| committedCompactionSessionId, | |
| ); | |
| }; | |
| try { | |
| await fallbackTrajectoryRecorder?.flush(); | |
| const finalVisiblePayload = result.payloads | |
| ?.toReversed() | |
| .find((payload) => !payload.isError && !payload.isReasoning && payload.text?.trim()); | |
| const assistantTranscriptOwned = | |
| finalVisiblePayload !== undefined && | |
| getReplyPayloadMetadata(finalVisiblePayload)?.assistantTranscriptOwned === true; | |
| if (params.opts.internalDeliveryMediaUrls !== undefined) { | |
| result = { | |
| ...result, | |
| payloads: constrainRestartRecoveryDeliveryPayloads( | |
| result.payloads, | |
| params.opts.internalDeliveryMediaUrls, | |
| params.opts.internalDeliverySuppressText === true, | |
| ), | |
| }; | |
| } | |
| const resultErrorPayload = result.payloads?.find((payload) => payload.isError === true); | |
| if (resultErrorPayload) { | |
| const message = | |
| typeof resultErrorPayload.text === "string" && resultErrorPayload.text.trim() | |
| ? resultErrorPayload.text | |
| : undefined; | |
| params.opts.onResultErrorPayload?.(message); | |
| } | |
| params.onTerminalDeliveryEvidenceChanged(buildRestartRecoveryTerminalDeliveryEvidence(result)); | |
| const compactionFact = params.attempt.compactionAccounting; | |
| const effectiveSessionId = | |
| compactionFact?.target.sessionId ?? internalSessionTarget?.sessionId ?? sessionId; | |
| if (sessionStore && sessionKey && !params.suppressVisibleSessionEffects) { | |
| const { updateSessionStoreAfterAgentRun } = await loadSessionStoreRuntime(); | |
| await updateSessionStoreAfterAgentRun({ | |
| cfg, | |
| agentDir, | |
| sessionId: effectiveSessionId, | |
| sessionKey, | |
| storePath, | |
| sessionStore, | |
| defaultProvider: provider, | |
| defaultModel: model, | |
| fallbackProvider, | |
| fallbackModel, | |
| result, | |
| compactionAccounting: compactionFact, | |
| touchInteraction: | |
| params.opts.bootstrapContextRunKind !== "cron" && | |
| !isHeartbeatLifecycleRun && | |
| !params.opts.internalEvents?.length, | |
| // Cron output counts as unread-worthy activity; heartbeat and | |
| // internal-event turns must not re-flag the session unread. | |
| touchActivity: !isHeartbeatLifecycleRun && !params.opts.internalEvents?.length, | |
| preserveRuntimeModel: | |
| fallbackExhausted || | |
| fallbackProvider !== provider || | |
| fallbackModel !== model || | |
| isHeartbeatLifecycleRun || | |
| params.preserveUserFacingSessionModelState, | |
| preserveUserFacingSessionModelState: params.preserveUserFacingSessionModelState, | |
| clearRestartRecoveryForceSafeTools: | |
| params.opts.forceRestartSafeTools === true && params.opts.deliver !== true, | |
| }); | |
| sessionEntry = sessionStore[sessionKey] ?? sessionEntry; | |
| } | |
| runOwnedSessionId = effectiveSessionId; | |
| publishSessionOwnership(); | |
| const transcriptPersistenceRunner = result.meta.executionTrace?.runner; | |
| let persistedCliTurnTranscript = false; | |
| if (!sessionReboundDuringRun && transcriptPersistenceRunner === "cli") { | |
| try { | |
| const transcriptResult = await attemptExecutionRuntime.persistCliTurnTranscript({ | |
| body, | |
| transcriptBody, | |
| result, | |
| sessionId: effectiveSessionId, | |
| sessionKey: internalSessionTarget?.sessionKey ?? sessionKey ?? effectiveSessionId, | |
| sessionEntry: internalSessionTarget?.sessionEntry ?? sessionEntry, | |
| sessionStore: params.suppressVisibleSessionEffects ? undefined : sessionStore, | |
| storePath: internalSessionTarget?.storePath ?? storePath, | |
| sessionAgentId: internalSessionTarget?.agentId ?? sessionAgentId, | |
| threadId: params.opts.threadId, | |
| sessionCwd: effectiveCwd, | |
| config: cfg, | |
| skipAssistantTurn: assistantTranscriptOwned, | |
| skipUserTurn: | |
| suppressUserTurnPersistence || | |
| // A supplied recorder owns input admission; the terminal mirror must | |
| // not synthesize an unkeyed copy when that input never reached execution. | |
| params.opts.userTurnTranscriptRecorder !== undefined || | |
| userTurnTranscriptRecorder.hasPersisted() || | |
| userTurnTranscriptRecorder.isBlocked(), | |
| }); | |
| sessionReboundDuringRun = transcriptResult.kind === "session-rebound"; | |
| publishSessionOwnership(); | |
| if (!internalSessionTarget) { | |
| sessionEntry = transcriptResult.sessionEntry; | |
| } | |
| persistedCliTurnTranscript = transcriptResult.kind === "persisted"; | |
| } catch (error) { | |
| log.warn( | |
| `Turn transcript persistence failed for ${sessionKey ?? sessionId}: ${error instanceof Error ? error.message : String(error)}`, | |
| ); | |
| if ( | |
| sessionStore && | |
| sessionKey && | |
| !params.suppressVisibleSessionEffects && | |
| !sessionReboundDuringRun && | |
| !assistantTranscriptOwned | |
| ) { | |
| await persistAssistantTranscriptRepairRecord({ | |
| context: { | |
| sessionKey: internalSessionTarget?.sessionKey ?? sessionKey ?? effectiveSessionId, | |
| sessionEntry: internalSessionTarget?.sessionEntry ?? sessionEntry, | |
| sessionStore, | |
| storePath: internalSessionTarget?.storePath ?? storePath, | |
| sessionAgentId: internalSessionTarget?.agentId ?? sessionAgentId, | |
| config: cfg, | |
| }, | |
| replyText: attemptExecutionRuntime.resolveCliTranscriptReplyText(result), | |
| provider: result.meta.agentMeta?.provider, | |
| model: result.meta.agentMeta?.model, | |
| runOwnedSessionId, | |
| }); | |
| } | |
| } | |
| } | |
| const payloads = result.payloads ?? []; | |
| const pendingFinalDeliveryMarker = await persistPendingFinalDeliveryMarker({ | |
| deliver: params.opts.deliver === true, | |
| sessionStore, | |
| sessionKey, | |
| sessionEntry, | |
| storePath, | |
| suppressVisibleSessionEffects: params.suppressVisibleSessionEffects, | |
| sessionReboundDuringRun, | |
| payloads, | |
| deliveryContext: params.currentRunDeliveryContext, | |
| runOwnedSessionId, | |
| }); | |
| sessionEntry = pendingFinalDeliveryMarker.sessionEntry; | |
| const resolveFreshSessionEntryForDelivery = | |
| sessionStore && sessionKey && !params.suppressVisibleSessionEffects | |
| ? async (): Promise<SessionEntry | undefined> => { | |
| const { loadSessionEntryReadOnly } = await loadSessionStoreRuntime(); | |
| const freshEntry = loadSessionEntryReadOnly({ | |
| storePath, | |
| sessionKey, | |
| readConsistency: "latest", | |
| clone: false, | |
| }); | |
| if (!freshEntry || freshEntry.sessionId !== runOwnedSessionId) { | |
| return undefined; | |
| } | |
| sessionStore[sessionKey] = freshEntry; | |
| return freshEntry; | |
| } | |
| : undefined; | |
| const agentMeta = result.meta.agentMeta; | |
| const embeddedMaintenance = | |
| transcriptPersistenceRunner === "embedded" && | |
| agentMeta?.agentHarnessId === OPENCLAW_AGENT_RUNTIME_ID && | |
| params.attempt.maintenanceAuthProfile !== undefined && | |
| !fallbackExhausted && | |
| terminal.outcome.status === "ok" && | |
| !resultErrorPayload && | |
| !result.meta.yielded && | |
| !result.meta.aborted && | |
| (compactionFact?.count ?? 0) === 0 && | |
| !params.preserveUserFacingSessionModelState && | |
| params.opts.modelRun !== true && | |
| params.opts.promptMode !== "none"; | |
| maintenanceRequest = | |
| sessionEntry && | |
| sessionKey && | |
| sessionStore && | |
| !params.suppressVisibleSessionEffects && | |
| !sessionReboundDuringRun && | |
| !isHeartbeatLifecycleRun && | |
| cfg.agents?.defaults?.compaction?.enabled !== false && | |
| embeddedMaintenance | |
| ? { | |
| prepared: { cfg, sessionKey, storePath, timeoutMs }, | |
| followupRun: createCommandMaintenanceFollowup({ | |
| prepared: params.prepared, | |
| sessionEntry, | |
| embeddedSessionState: params.embeddedSessionState, | |
| provider: agentMeta?.provider ?? fallbackProvider, | |
| model: agentMeta?.model ?? fallbackModel, | |
| thinkLevel: effectiveTurnThinkLevel, | |
| auth: params.attempt.maintenanceAuthProfile, | |
| }), | |
| sessionId: runOwnedSessionId, | |
| lifecycleRevision: sessionEntry.lifecycleRevision, | |
| lifecycleGeneration, | |
| startedAt: params.attempt.startedAt, | |
| oneShotCliRun: params.opts.oneShotCliRun, | |
| agentHarnessId: agentMeta?.agentHarnessId, | |
| compactionRequestBudget: params.attempt.compactionRequestBudget, | |
| } | |
| : undefined; | |
| // Generic CLI backends may rely on this sole host-compaction path. Keep its | |
| // existing foreground custody until runtime preparation can own preflight. | |
| if ( | |
| persistedCliTurnTranscript && | |
| !params.suppressVisibleSessionEffects && | |
| (params.opts.deliver !== true || | |
| !pendingFinalDeliveryMarker.hasSendableFinalPayload || | |
| pendingFinalDeliveryMarker.pendingFinalDeliveryMarkerPersisted) | |
| ) { | |
| const maintenance = createCommandBudget( | |
| params.attempt.startedAt, | |
| timeoutMs, | |
| params.opts.abortSignal, | |
| ); | |
| let maintenanceLifecycleRevision = sessionEntry?.lifecycleRevision; | |
| const authorize = () => { | |
| throwAgentRunRestartAbortReason(params.opts.abortSignal?.reason); | |
| assertAgentRunLifecycleGenerationCurrent(lifecycleGeneration); | |
| return ( | |
| maintenance.remainingMs() > 0 && !maintenance.signal.aborted && !sessionReboundDuringRun | |
| ); | |
| }; | |
| const onCommitted = (accepted: AcceptedCompactionSuccessor) => { | |
| sessionEntry = accepted.entry; | |
| maintenanceLifecycleRevision = accepted.entry.lifecycleRevision; | |
| runOwnedSessionId = accepted.sessionId; | |
| publishSessionOwnership( | |
| accepted.previousSessionId === undefined ? undefined : accepted.sessionId, | |
| ); | |
| }; | |
| try { | |
| if (maintenance.remainingMs() > 0) { | |
| const { runCliTurnCompactionLifecycle } = await loadCliCompactionRuntime(); | |
| sessionEntry = await runCliTurnCompactionLifecycle( | |
| { | |
| cfg, | |
| sessionId: sessionEntry?.sessionId ?? effectiveSessionId, | |
| sessionKey: sessionKey ?? effectiveSessionId, | |
| sessionEntry, | |
| sessionStore, | |
| storePath, | |
| sessionAgentId, | |
| workspaceDir, | |
| cwd: effectiveCwd, | |
| agentDir, | |
| provider: agentMeta?.provider ?? provider, | |
| model: agentMeta?.model ?? model, | |
| skillsSnapshot, | |
| messageChannel, | |
| agentAccountId: runContext.accountId, | |
| senderIsOwner: params.opts.senderIsOwner, | |
| thinkLevel: effectiveTurnThinkLevel, | |
| extraSystemPrompt: params.opts.extraSystemPrompt, | |
| pluginGeneration: params.prepared.commandRuntimeContext?.pluginGeneration, | |
| abortSignal: maintenance.signal, | |
| }, | |
| { | |
| assertActive: () => { | |
| if (!authorize()) { | |
| throw new Error("Command compaction is no longer active"); | |
| } | |
| }, | |
| onCommitted, | |
| }, | |
| ); | |
| throwAgentRunRestartAbortReason(params.opts.abortSignal?.reason); | |
| assertAgentRunLifecycleGenerationCurrent(lifecycleGeneration); | |
| runOwnedSessionId = sessionEntry?.sessionId ?? runOwnedSessionId; | |
| publishSessionOwnership(); | |
| } | |
| } catch (error) { | |
| throwAgentRunRestartAbortReason(params.opts.abortSignal?.reason); | |
| throwAgentRunRestartAbortReason(error); | |
| assertAgentRunLifecycleGenerationCurrent(lifecycleGeneration); | |
| if (maintenance.signal.aborted) { | |
| params.opts.abortSignal?.throwIfAborted(); | |
| const currentEntry = await resolveFreshSessionEntryForDelivery?.(); | |
| params.opts.abortSignal?.throwIfAborted(); | |
| assertAgentRunLifecycleGenerationCurrent(lifecycleGeneration); | |
| if (!currentEntry || currentEntry.lifecycleRevision !== maintenanceLifecycleRevision) { | |
| throw error; | |
| } | |
| sessionEntry = currentEntry; | |
| } else if ( | |
| params.opts.deliver !== true || | |
| !pendingFinalDeliveryMarker.pendingFinalDeliveryMarkerPersisted || | |
| !pendingFinalDeliveryMarker.hasSendableFinalPayload | |
| ) { | |
| throw error; | |
| } | |
| log.warn( | |
| `Post-turn transcript compaction failed for ${sessionKey ?? sessionId}; continuing final delivery: ${formatErrorMessage(error)}`, | |
| ); | |
| } finally { | |
| maintenance.dispose(); | |
| } | |
| } | |
| const { deliverAgentCommandResult } = await loadDeliveryRuntime(); | |
| const deliveryParams = { | |
| cfg, | |
| deps: params.deps, | |
| runtime: params.runtime, | |
| opts: params.opts, | |
| outboundSession, | |
| sessionEntry, | |
| result, | |
| payloads, | |
| assertDeliveryCurrent: () => { | |
| params.opts.abortSignal?.throwIfAborted(); | |
| assertAgentRunLifecycleGenerationCurrent(lifecycleGeneration); | |
| }, | |
| onDeliveryResult: ( | |
| delivered: Parameters< | |
| NonNullable<Parameters<typeof deliverAgentCommandResult>[0]["onDeliveryResult"]> | |
| >[0], | |
| ) => { | |
| const deliveryStatus = delivered.deliveryStatus; | |
| const terminalDelivery = normalizeAgentRunTerminalDeliverySnapshot( | |
| deliveryStatus && { | |
| status: deliveryStatus.status, | |
| resultCount: deliveryStatus.resultCount ?? 0, | |
| }, | |
| ); | |
| if (terminalDelivery) { | |
| terminal.metadata.terminalDelivery = terminalDelivery; | |
| } | |
| params.onTerminalDeliveryEvidenceChanged( | |
| buildRestartRecoveryTerminalDeliveryEvidence(delivered), | |
| ); | |
| }, | |
| }; | |
| deliveryResult = await deliverAgentCommandResult( | |
| resolveFreshSessionEntryForDelivery | |
| ? { | |
| ...deliveryParams, | |
| expectedSessionIdForFreshDelivery: runOwnedSessionId, | |
| resolveFreshSessionEntryForDelivery, | |
| } | |
| : deliveryParams, | |
| ); | |
| if ( | |
| sessionStore && | |
| sessionKey && | |
| !isSubagentSessionKey(sessionKey) && | |
| !params.suppressVisibleSessionEffects && | |
| !sessionReboundDuringRun | |
| ) { | |
| const entry = | |
| (await resolveFreshSessionEntryForDelivery?.()) ?? sessionStore[sessionKey] ?? sessionEntry; | |
| if (!entry) { | |
| throw new Error("Cannot clear pending delivery without a session entry"); | |
| } | |
| // This command only creates replayable markers, so transport-only is stale from an earlier run. | |
| const clearStaleTransportOnly = | |
| params.opts.deliver === true && | |
| !pendingFinalDeliveryMarker.hasSendableFinalPayload && | |
| entry.pendingFinalDelivery?.kind === "transport-only"; | |
| const clearOwnedPendingFinal = | |
| deliveryResult?.deliverySucceeded === true && | |
| pendingFinalDeliveryMarker.pendingFinalDeliveryIntentId !== undefined; | |
| // Preserve the exact claim snapshot through sibling session writes, then | |
| // revalidate its durable owner immediately before committing cleanup. | |
| const recoveryClaimEntry = | |
| entry.restartRecoveryDeliveryRunId === runId | |
| ? entry | |
| : sessionEntry?.restartRecoveryDeliveryRunId === runId | |
| ? sessionEntry | |
| : params.sessionEntry?.restartRecoveryDeliveryRunId === runId | |
| ? params.sessionEntry | |
| : undefined; | |
| const clearsRecoveryCycle = entry.restartRecoveryDeliveryRunId === runId; | |
| if (clearOwnedPendingFinal || clearStaleTransportOnly || recoveryClaimEntry) { | |
| const now = Date.now(); | |
| sessionEntry = await persistAgentSession({ | |
| sessionStore, | |
| sessionKey, | |
| storePath, | |
| initialEntry: entry, | |
| entry: { | |
| ...(clearOwnedPendingFinal || clearStaleTransportOnly | |
| ? clearPendingFinalDelivery(entry, now) | |
| : { ...entry, updatedAt: now }), | |
| ...(recoveryClaimEntry | |
| ? buildRestartRecoveryClaimCleanupPatch({ | |
| entry: { | |
| ...recoveryClaimEntry, | |
| restartRecoveryTerminalDeliveryEvidence: | |
| entry.restartRecoveryTerminalDeliveryEvidence, | |
| restartRecoveryTerminalRunIds: entry.restartRecoveryTerminalRunIds, | |
| }, | |
| recordTerminalSource: true, | |
| terminalDeliveryEvidence: buildRestartRecoveryTerminalDeliveryEvidence( | |
| deliveryResult ?? result, | |
| ), | |
| terminalRunId: runId, | |
| }) | |
| : {}), | |
| ...(clearsRecoveryCycle ? buildMainSessionRecoveryClearPatch(entry) : {}), | |
| }, | |
| shouldPersist: (current) => | |
| shouldPersistCurrentRunSessionCleanup(current, runOwnedSessionId) && | |
| (!recoveryClaimEntry || | |
| current?.restartRecoveryDeliveryRunId === runId || | |
| (!clearsRecoveryCycle && current?.restartRecoveryDeliveryRunId === undefined)) && | |
| (!clearOwnedPendingFinal || | |
| current?.pendingFinalDelivery?.intentId === | |
| pendingFinalDeliveryMarker.pendingFinalDeliveryIntentId) && | |
| (!clearStaleTransportOnly || current?.pendingFinalDelivery?.kind === "transport-only"), | |
| }); | |
| } | |
| } | |
| hasResultError = Boolean(fallbackExhausted || lifecycle.resolveResultError(result, false)); | |
| terminalError = hasResultError | |
| ? lifecycle.resolveTerminalError(result, fallbackExhausted, terminal) | |
| : terminal.outcome.error; | |
| if (hasResultError) { | |
| lifecycle.emitResultError(result, fallbackExhausted, terminal); | |
| } else { | |
| lifecycle.emitEnd(terminal); | |
| } | |
| } catch (error) { | |
| lifecycle.emitPostTurnError(error, terminal); | |
| throw error; | |
| } finally { | |
| await deferredLifecycle.complete(); | |
| } | |
| // Cancellation can arrive while delivery or deferred cleanup still owns the run. | |
| // Record the final fact on the projected reply without changing its JSON output. | |
| const outcome = deferredLifecycle.signal.aborted | |
| ? mergeAgentRunTerminalOutcome( | |
| terminal.outcome, | |
| buildAgentRunTerminalOutcomeFromLifecycleEvent({ | |
| phase: "end", | |
| abortSignal: deferredLifecycle.signal, | |
| }), | |
| ) | |
| : terminal.outcome; | |
| return { | |
| maintenance: | |
| classifyAgentRunTerminalOutcome(outcome) === "success" && | |
| !hasResultError && | |
| (params.opts.deliver !== true || deliveryResult?.deliverySucceeded === true) | |
| ? maintenanceRequest | |
| : undefined, | |
| deliveryResult: recordAgentRunTerminalOutcome( | |
| deliveryResult, | |
| hasResultError || classifyAgentRunTerminalOutcome(outcome) !== "success" | |
| ? "failed" | |
| : "completed", | |
| terminalError ? formatErrorMessage(terminalError) : undefined, | |
| ), | |
| sessionEntry, | |
| runOwnedSessionId, | |
| sessionReboundDuringRun, | |
| }; | |
| } | |