Download src/auto-reply/reply/agent-runner-cli-candidate.ts from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 25 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/auto-reply/reply/agent-runner-cli-candidate.ts
- Command line
-
hf download hf://SaylorTwift/openclaw/src/auto-reply/reply/agent-runner-cli-candidate.ts
-
curl -L -o agent-runner-cli-candidate.ts https://huggingface.co/SaylorTwift/openclaw/resolve/main/src/auto-reply/reply/agent-runner-cli-candidate.ts
25 kB
| import { resolveBootstrapWarningSignaturesSeen } from "../../agents/bootstrap-budget.js"; | |
| import { | |
| cliBackendAcceptsAuthProfileForwarding, | |
| resolveCliExecutionAuthProfileId, | |
| } from "../../agents/cli-execution-auth.js"; | |
| import { buildCliMcpDelegationCapabilityBinding } from "../../agents/cli-runner/mcp-grant-context.js"; | |
| import { | |
| clearCliSessionInStore, | |
| persistCliSessionBindingResult, | |
| settleCliSessionResult, | |
| } from "../../agents/cli-session-store.js"; | |
| import { | |
| getCliSessionBinding, | |
| shouldClearFailedCliSessionBinding, | |
| } from "../../agents/cli-session.js"; | |
| import { resolveDelegationCapability } from "../../agents/delegation-capability.js"; | |
| import type { EmbeddedAgentRunResult } from "../../agents/embedded-agent-runner/types.js"; | |
| import { findModelInCatalog } from "../../agents/model-catalog-lookup.js"; | |
| import type { ModelFallbackResultClassification } from "../../agents/model-fallback-attempt.js"; | |
| import { createAgentRunSupersededAbortError } from "../../agents/run-termination.js"; | |
| import { withLocalSessionPlacementTurnSettlement } from "../../agents/session-placement-admission.js"; | |
| import { normalizeChatType } from "../../channels/chat-type.js"; | |
| import { loadSessionEntry } from "../../config/sessions/session-accessor.js"; | |
| import { shouldPreserveUserFacingSessionStateForInputProvenance } from "../../sessions/input-provenance.js"; | |
| import { | |
| getGeneratedMediaTaskIdsForSessionKey, | |
| hasNewGeneratedMediaTaskForSessionKey, | |
| } from "../../tasks/task-status-access.js"; | |
| import { createAgentLifecycleTerminalBackstop } from "./agent-lifecycle-terminal.js"; | |
| import { resolveRunAuthProfile } from "./agent-runner-auth-profile.js"; | |
| import { | |
| createCliReasoningStreamBridge, | |
| createCliToolSummaryTracker, | |
| keepCliSessionBindingOnlyWhenReused, | |
| runCliAgentWithLifecycle, | |
| } from "./agent-runner-cli-dispatch.js"; | |
| import { buildCommandOutputFromToolResultEvent } from "./agent-runner-command-output.js"; | |
| import type { AgentFallbackCandidateCommonParams } from "./agent-runner-fallback-cycle.types.js"; | |
| import { resolveRunModelHasVision } from "./agent-runner-run-params.js"; | |
| import { shouldBridgeCliPreambleEvents } from "./get-reply.types.js"; | |
| import { hasInboundAudio } from "./inbound-media.js"; | |
| import { resolveOriginMessageProvider } from "./origin-routing.js"; | |
| import { resolveReplyOperationTerminationFields } from "./reply-operation-abort.js"; | |
| export async function runCliFallbackCandidate( | |
| params: AgentFallbackCandidateCommonParams & { | |
| cliExecutionProvider: string; | |
| classifyResult: (result: EmbeddedAgentRunResult) => ModelFallbackResultClassification; | |
| lifecycleGeneration: string; | |
| }, | |
| ): Promise<{ | |
| result: Awaited<ReturnType<typeof runCliAgentWithLifecycle>>; | |
| bootstrapPromptWarningSignaturesSeen: string[]; | |
| }> { | |
| const turn = params.turn; | |
| const expectedLifecycleRevision = turn.getActiveSessionEntry()?.lifecycleRevision; | |
| const selectedModelEntry = findModelInCatalog( | |
| params.candidateRun.thinkingCatalog ?? [], | |
| params.provider, | |
| params.model, | |
| ); | |
| const modelHasVision = await resolveRunModelHasVision({ | |
| run: params.candidateRun, | |
| provider: params.provider, | |
| model: params.model, | |
| }); | |
| const sessionKey = turn.sessionKey ?? turn.followupRun.run.sessionKey; | |
| const sessionTarget = | |
| sessionKey && turn.storePath | |
| ? { | |
| agentId: turn.followupRun.run.agentId, | |
| sessionId: turn.followupRun.run.sessionId, | |
| sessionKey, | |
| storePath: turn.storePath, | |
| } | |
| : undefined; | |
| const cliLifecycleStartedAt = Date.now(); | |
| const lifecycleBackstop = createAgentLifecycleTerminalBackstop({ | |
| runId: params.runId, | |
| sessionKey: turn.sessionKey, | |
| startedAt: cliLifecycleStartedAt, | |
| getLifecycleGeneration: () => params.lifecycleGeneration, | |
| resolveTerminationFields: (error) => | |
| resolveReplyOperationTerminationFields(error, params.runAbortSignal, turn.replyOperation), | |
| }); | |
| params.onLifecycleBackstop(lifecycleBackstop); | |
| const allowCliAuthProfileForwarding = cliBackendAcceptsAuthProfileForwarding({ | |
| provider: params.cliExecutionProvider, | |
| config: params.runtimeConfig, | |
| agentId: params.candidateRun.agentId, | |
| }); | |
| const hookMessageProvider = resolveOriginMessageProvider({ | |
| originatingChannel: turn.followupRun.originatingChannel, | |
| provider: turn.sessionCtx.Provider, | |
| }); | |
| const cliCurrentThreadId = | |
| turn.followupRun.originatingThreadId ?? turn.sessionCtx.MessageThreadId; | |
| const isRestartSentinelContinuation = | |
| turn.sessionCtx.InputProvenance?.kind === "internal_system" && | |
| turn.sessionCtx.InputProvenance.sourceTool === "restart-sentinel"; | |
| const cliCurrentMessageId = isRestartSentinelContinuation | |
| ? turn.sessionCtx.ReplyToId | |
| : (turn.sessionCtx.MessageSidFull ?? turn.sessionCtx.MessageSid); | |
| const commandDetailsVisible = turn.resolvedVerboseLevel === "full"; | |
| const cliToolSummaryTracker = createCliToolSummaryTracker({ | |
| detailMode: turn.toolProgressDetail, | |
| commandDetailsVisible, | |
| shouldEmitToolResult: turn.shouldEmitToolResult, | |
| shouldEmitToolOutput: turn.shouldEmitToolOutput, | |
| deliver: async (payload) => { | |
| await turn.opts?.onToolResult?.(payload); | |
| }, | |
| }); | |
| // CLI backends report a tool's outcome on the result event and never repeat it, | |
| // so the terminal fact has to be projected here. The embedded path gets this | |
| // from the shared agent-event handler; without it a failed CLI command renders | |
| // exactly like one that succeeded. | |
| const deliverCliCommandOutcome = async ( | |
| payload: { | |
| name: string | undefined; | |
| phase: "start" | "update" | "result"; | |
| args: Record<string, unknown> | undefined; | |
| toolCallId?: string; | |
| isError?: boolean; | |
| result?: unknown; | |
| }, | |
| commandBearing: boolean, | |
| ) => { | |
| const onCommandOutput = turn.opts?.onCommandOutput; | |
| if (!onCommandOutput) { | |
| return; | |
| } | |
| const commandOutput = buildCommandOutputFromToolResultEvent({ | |
| stream: "tool", | |
| data: { ...payload, commandBearing }, | |
| }); | |
| if (commandOutput) { | |
| await onCommandOutput(commandOutput); | |
| } | |
| }; | |
| const bridgeCliPreambleProgress = | |
| Boolean(turn.opts?.onItemEvent) && shouldBridgeCliPreambleEvents(turn.opts); | |
| const bridgeCliDurableCommentary = | |
| Boolean(params.presentation.blockReplyHandler) && | |
| (turn.blockStreamingEnabled || turn.opts?.commentaryPayloadsEnabled === true); | |
| const toolAuthorityRoute = { provider: params.provider, model: params.model }; | |
| const toolAuthorityFingerprint = turn.replyOperation?.bindToolAuthorityRoute(toolAuthorityRoute); | |
| const result = await params.timing.measure("cli_run", () => | |
| withLocalSessionPlacementTurnSettlement( | |
| { | |
| sessionId: turn.followupRun.run.sessionId, | |
| sessionKey, | |
| agentId: turn.followupRun.run.agentId, | |
| runId: params.runId, | |
| }, | |
| async (assertSettlementCurrent) => { | |
| // Placement admission may wait behind an older turn. Snapshot placement, | |
| // permission, and native resume identity only after this turn owns it. | |
| const sessionEntry = sessionTarget | |
| ? loadSessionEntry({ ...sessionTarget, readConsistency: "latest" }) | |
| : turn.getActiveSessionEntry(); | |
| if ( | |
| sessionTarget && | |
| (sessionEntry?.sessionId !== sessionTarget.sessionId || | |
| sessionEntry.lifecycleRevision !== expectedLifecycleRevision) | |
| ) { | |
| throw createAgentRunSupersededAbortError(); | |
| } | |
| const cliSessionBinding = getCliSessionBinding(sessionEntry, params.cliExecutionProvider); | |
| // The CLI owner must see explicit pins before provider scoping can discard them. | |
| const authProfileId = allowCliAuthProfileForwarding | |
| ? resolveCliExecutionAuthProfileId({ | |
| cliExecutionProvider: params.cliExecutionProvider, | |
| authProfileProvider: params.provider, | |
| config: params.runtimeConfig, | |
| agentDir: params.candidateRun.agentDir, | |
| selected: params.candidateRun, | |
| sessionBinding: cliSessionBinding, | |
| }) | |
| : resolveRunAuthProfile(params.candidateRun, params.cliExecutionProvider, { | |
| config: params.runtimeConfig, | |
| }).authProfileId; | |
| const diagnosticOwner = params.deferredLifecycle.handoffToCli(); | |
| const mediaTaskIdsBefore = getGeneratedMediaTaskIdsForSessionKey(turn.sessionKey); | |
| let droppedCliSessionReplacement = false; | |
| const candidateResult = await runCliAgentWithLifecycle({ | |
| runId: params.runId, | |
| lifecycleGeneration: params.lifecycleGeneration, | |
| provider: params.cliExecutionProvider, | |
| startedAt: cliLifecycleStartedAt, | |
| emitLifecycleTerminal: false, | |
| onAgentRunStart: params.notifyAgentRunStart, | |
| suppressAssistantBridge: turn.followupRun.run.silentExpected, | |
| onActivity: () => turn.replyOperation?.recordActivity(), | |
| onErrorBeforeLifecycle: | |
| params.cliExecutionProvider === "claude-cli" && cliSessionBinding?.sessionId | |
| ? async (error) => { | |
| if ( | |
| !shouldClearFailedCliSessionBinding({ | |
| error, | |
| binding: cliSessionBinding, | |
| hasNewGeneratedMediaTask: hasNewGeneratedMediaTaskForSessionKey( | |
| turn.sessionKey, | |
| mediaTaskIdsBefore, | |
| ), | |
| }) | |
| ) { | |
| return; | |
| } | |
| await clearCliSessionInStore({ | |
| provider: params.cliExecutionProvider, | |
| expectedCliSessionId: cliSessionBinding.sessionId, | |
| expectedSessionId: sessionEntry?.sessionId, | |
| assertCommitAllowed: assertSettlementCurrent, | |
| sessionKey: turn.sessionKey, | |
| sessionStore: turn.activeSessionStore, | |
| storePath: turn.storePath, | |
| activeSessionEntry: sessionEntry, | |
| }); | |
| } | |
| : undefined, | |
| preserveProgressCallbackStartOrder: params.preserveProgressCallbackStartOrder, | |
| onAssistantText: async (text) => { | |
| const classified = params.presentation.classifyStreamingPartial({ text }); | |
| if (classified.skip || !classified.text) { | |
| return; | |
| } | |
| const textForTyping = classified.text; | |
| const sanitized = params.presentation.sanitizeStreamingText(textForTyping, false); | |
| const onPartialReply = turn.opts?.onPartialReply; | |
| return await params.presentation.presentWithTyping( | |
| turn.typingSignals.signalTextDelta(textForTyping), | |
| () => | |
| sanitized.skip || !sanitized.text || !onPartialReply | |
| ? false | |
| : onPartialReply({ text: sanitized.text }), | |
| ); | |
| }, | |
| onReasoningText: createCliReasoningStreamBridge(turn.opts?.onReasoningStream), | |
| onPlanUpdate: turn.opts?.onPlanUpdate, | |
| onReasoningProgress: async (payload) => { | |
| await turn.opts?.onReasoningProgress?.(payload); | |
| }, | |
| onCompactionStart: turn.opts?.onCompactionStart, | |
| onCompactionEnd: turn.opts?.onCompactionEnd, | |
| onToolEvent: async (payload) => { | |
| if (!params.preserveProgressCallbackStartOrder) { | |
| const commandBearing = await cliToolSummaryTracker.noteToolEvent(payload); | |
| if (payload.phase === "result") { | |
| await deliverCliCommandOutcome(payload, commandBearing); | |
| return; | |
| } | |
| const { name, phase, args, toolCallId } = payload; | |
| await Promise.all([ | |
| turn.typingSignals.signalToolStart(), | |
| turn.opts?.onToolStart?.({ | |
| ...(toolCallId ? { toolCallId } : {}), | |
| name, | |
| phase, | |
| args, | |
| detailMode: turn.toolProgressDetail, | |
| }), | |
| ]); | |
| return; | |
| } | |
| const summaryPromise = cliToolSummaryTracker.noteToolEvent(payload); | |
| if (payload.phase === "result") { | |
| const commandBearing = await summaryPromise; | |
| await deliverCliCommandOutcome(payload, commandBearing); | |
| return; | |
| } | |
| const { name, phase, args, toolCallId } = payload; | |
| // Tool and assistant bridges drain independently. Preserve source order. | |
| await Promise.all([ | |
| summaryPromise, | |
| params.presentation.presentWithTyping( | |
| turn.typingSignals.signalToolStart(), | |
| async () => { | |
| await turn.opts?.onToolStart?.({ | |
| ...(toolCallId ? { toolCallId } : {}), | |
| name, | |
| phase, | |
| args, | |
| detailMode: turn.toolProgressDetail, | |
| }); | |
| }, | |
| ), | |
| ]); | |
| }, | |
| onCommentaryText: | |
| bridgeCliPreambleProgress || bridgeCliDurableCommentary | |
| ? async (payload) => { | |
| const deliveries: unknown[] = []; | |
| if (bridgeCliPreambleProgress) { | |
| deliveries.push( | |
| turn.opts?.onItemEvent?.({ | |
| itemId: payload.itemId, | |
| kind: "preamble", | |
| progressText: payload.text, | |
| // The block bridge owns durability; this event remains a progress preview. | |
| ...(bridgeCliDurableCommentary ? { suppressDurableProgress: true } : {}), | |
| }), | |
| ); | |
| } | |
| if (bridgeCliDurableCommentary) { | |
| // Block mode treats completed CLI text as an ordinary answer block so | |
| // the existing pipeline owns coalescing and final-payload dedupe. | |
| deliveries.push( | |
| params.presentation.blockReplyHandler?.({ | |
| text: payload.text, | |
| ...(turn.blockStreamingEnabled ? {} : { isCommentary: true }), | |
| }), | |
| ); | |
| } | |
| await Promise.all(deliveries); | |
| } | |
| : undefined, | |
| onFastModeAutoProgress: async (payload) => { | |
| await turn.opts?.onToolResult?.(payload); | |
| }, | |
| transformResult: | |
| turn.followupRun.currentInboundEventKind === "room_event" | |
| ? (resultLocal) => | |
| keepCliSessionBindingOnlyWhenReused({ | |
| result: resultLocal, | |
| existingSessionId: cliSessionBinding?.sessionId, | |
| onDroppedReplacement: () => { | |
| droppedCliSessionReplacement = true; | |
| }, | |
| }) | |
| : undefined, | |
| runParams: { | |
| preparedRunAdmission: params.preparedRunAdmission, | |
| messageActionTurnCapability: params.messageActionTurnCapability, | |
| diagnosticOwner, | |
| sessionId: turn.followupRun.run.sessionId, | |
| sessionKey, | |
| sessionTarget, | |
| sessionEntry, | |
| chatType: | |
| normalizeChatType(turn.followupRun.originatingChatType) ?? | |
| normalizeChatType(turn.sessionCtx.ChatType) ?? | |
| params.candidateRun.chatType, | |
| runtimePolicySessionKey: | |
| turn.followupRun.run.runtimePolicySessionKey ?? turn.runtimePolicySessionKey, | |
| agentId: turn.followupRun.run.agentId, | |
| trigger: turn.isHeartbeat ? "heartbeat" : "user", | |
| sessionFile: turn.followupRun.run.sessionFile, | |
| workspaceDir: turn.followupRun.run.workspaceDir, | |
| cwd: turn.followupRun.run.cwd, | |
| config: params.runtimeConfig, | |
| toolOverrides: turn.followupRun.run.toolOverrides, | |
| prompt: turn.commandBody, | |
| transcriptPrompt: turn.transcriptCommandBody, | |
| media: turn.followupRun.media, | |
| suppressNextUserMessagePersistence: params.suppressQueuedUserPersistenceForCandidate, | |
| userTurnTranscriptRecorder: params.userTurnTranscriptRecorder, | |
| contextEngineLogicalTurnLease: params.contextEngineLogicalTurnLease, | |
| onContextEngineTurnCandidate: params.onContextEngineTurnCandidate, | |
| onUserMessagePersisted: params.notifyUserMessagePersisted, | |
| prepareAssistantTranscriptMessage: turn.opts?.prepareAssistantTranscriptMessage, | |
| persistAssistantTranscript: | |
| turn.followupRun.currentInboundEventKind !== "room_event" && | |
| turn.followupRun.run.suppressTranscriptOnlyAssistantPersistence !== true, | |
| storePath: turn.storePath, | |
| currentInboundEventKind: turn.followupRun.currentInboundEventKind, | |
| currentInboundContext: turn.followupRun.currentInboundContext, | |
| inputProvenance: turn.followupRun.run.inputProvenance, | |
| // Candidate zero is the primary attempt; later candidates are | |
| // fallbacks. Carry the runner-owned fact instead of inferring from | |
| // this shared dispatch path, or primary CLI runs lose delegation. | |
| ...buildCliMcpDelegationCapabilityBinding( | |
| resolveDelegationCapability({ | |
| fallbackActive: params.isFallbackRetry, | |
| inputProvenance: turn.followupRun.run.inputProvenance, | |
| disableTools: turn.opts?.disableTools, | |
| toolsAllow: turn.opts?.toolsAllow, | |
| }), | |
| ), | |
| modelProvider: params.provider, | |
| requesterModel: { provider: params.provider, model: params.model }, | |
| modelHasVision, | |
| modelContextWindow: selectedModelEntry?.contextWindow, | |
| modelContextTokens: selectedModelEntry?.contextTokens, | |
| contextWindow: sessionEntry?.contextWindow, | |
| provider: params.cliExecutionProvider, | |
| execOverrides: turn.followupRun.run.execOverrides, | |
| bashElevated: turn.followupRun.run.bashElevated, | |
| model: params.model, | |
| thinkLevel: params.candidateThinkLevel, | |
| fastMode: params.candidateFastMode.fastMode, | |
| fastModeStartedAtMs: params.fastModeStartedAtMs, | |
| fastModeAutoOnSeconds: params.candidateFastMode.fastModeAutoOnSeconds, | |
| fastModeAutoProgressState: params.fastModeAutoProgressState, | |
| isFinalFallbackAttempt: params.isFinalFallbackAttempt, | |
| timeoutMs: turn.followupRun.run.timeoutMs, | |
| runTimeoutOverrideMs: turn.followupRun.run.runTimeoutOverrideMs, | |
| runId: params.runId, | |
| lane: params.runLane, | |
| extraSystemPrompt: turn.followupRun.run.extraSystemPrompt, | |
| sourceReplyDeliveryMode: turn.followupRun.run.sourceReplyDeliveryMode, | |
| taskSuggestionDeliveryMode: turn.followupRun.run.taskSuggestionDeliveryMode, | |
| // Heartbeat ambient routes are never implicit message recipients. | |
| ...(turn.isHeartbeat ? { requireExplicitMessageTarget: true } : {}), | |
| cleanupBundleMcpOnRunEnd: turn.opts?.cleanupBundleMcpOnRunEnd, | |
| silentReplyPromptMode: turn.followupRun.run.silentReplyPromptMode, | |
| allowEmptyAssistantReplyAsSilent: turn.followupRun.run.allowEmptyAssistantReplyAsSilent, | |
| extraSystemPromptStatic: turn.followupRun.run.extraSystemPromptStatic, | |
| cliSessionBindingFacts: turn.followupRun.run.cliSessionBindingFacts, | |
| ownerNumbers: turn.followupRun.run.ownerNumbers, | |
| cliSessionId: cliSessionBinding?.sessionId, | |
| cliSessionBinding, | |
| authProfileId, | |
| bootstrapContextMode: turn.opts?.bootstrapContextMode, | |
| bootstrapContextRunKind: params.bootstrapContextRunKind, | |
| bootstrapPromptWarningSignaturesSeen: params.bootstrapPromptWarningSignaturesSeen, | |
| bootstrapPromptWarningSignature: | |
| params.bootstrapPromptWarningSignaturesSeen[ | |
| params.bootstrapPromptWarningSignaturesSeen.length - 1 | |
| ], | |
| images: params.currentTurnImages.images, | |
| imageOrder: params.currentTurnImages.imageOrder, | |
| mediaImageLayout: params.currentTurnImages.mediaImageLayout, | |
| skillsSnapshot: turn.followupRun.run.skillsSnapshot, | |
| messageChannel: turn.followupRun.originatingChannel ?? undefined, | |
| messageProvider: hookMessageProvider, | |
| clientCaps: turn.followupRun.run.clientCaps, | |
| gatewayUiCommandTarget: turn.followupRun.run.gatewayUiCommandTarget, | |
| currentChannelId: | |
| turn.followupRun.originatingTo ?? turn.sessionCtx.OriginatingTo ?? turn.sessionCtx.To, | |
| senderId: turn.followupRun.run.senderId, | |
| senderName: turn.followupRun.run.senderName, | |
| senderUsername: turn.followupRun.run.senderUsername, | |
| senderE164: turn.followupRun.run.senderE164, | |
| groupId: turn.followupRun.run.groupId, | |
| groupChannel: turn.followupRun.run.groupChannel, | |
| groupSpace: turn.followupRun.run.groupSpace, | |
| spawnedBy: turn.followupRun.run.spawnedBy, | |
| chatId: turn.followupRun.originatingChatId, | |
| channelContext: turn.followupRun.run.channelContext, | |
| currentThreadTs: cliCurrentThreadId != null ? String(cliCurrentThreadId) : undefined, | |
| currentMessageId: cliCurrentMessageId, | |
| replyToMode: turn.followupRun.originatingReplyToMode ?? turn.sessionCtx.ReplyToMode, | |
| currentInboundAudio: hasInboundAudio(turn.sessionCtx), | |
| agentAccountId: turn.followupRun.run.agentAccountId, | |
| senderIsOwner: turn.followupRun.run.senderIsOwner, | |
| approvalReviewerDeviceId: turn.followupRun.run.approvalReviewerDeviceId, | |
| toolsAllow: turn.opts?.toolsAllow, | |
| skillWorkshopProposalRevision: params.candidateRun.skillWorkshopProposalRevision, | |
| skillLibraryAuthoring: params.candidateRun.skillLibraryAuthoring, | |
| disableTools: turn.opts?.disableTools, | |
| toolAuthorityFingerprint, | |
| abortSignal: params.runAbortSignal, | |
| // Native input is already host-authored. Keep its stable delivery | |
| // context out of the model-output normalization wrapper. | |
| onBlockReply: turn.opts?.onBlockReply, | |
| onPartialReply: turn.opts?.onPartialReply, | |
| onExecutionPhase: params.signalExecutionPhaseForTyping, | |
| replyOperation: turn.replyOperation, | |
| }, | |
| }); | |
| if (droppedCliSessionReplacement) { | |
| // The room-event transform removed native continuity; only its guarded | |
| // invalidation remains, and failure must retain the returned turn. | |
| return await settleCliSessionResult(candidateResult, async () => { | |
| await clearCliSessionInStore({ | |
| provider: params.cliExecutionProvider, | |
| expectedCliSessionId: cliSessionBinding?.sessionId, | |
| expectedSessionId: sessionEntry?.sessionId, | |
| assertCommitAllowed: assertSettlementCurrent, | |
| sessionKey: turn.sessionKey, | |
| sessionStore: turn.activeSessionStore, | |
| storePath: turn.storePath, | |
| activeSessionEntry: sessionEntry, | |
| }); | |
| params.classifyResult(candidateResult); | |
| }); | |
| } | |
| const classification = params.classifyResult(candidateResult); | |
| if ( | |
| (!classification || candidateResult.meta.agentMeta?.clearCliSessionBinding === true) && | |
| !shouldPreserveUserFacingSessionStateForInputProvenance( | |
| turn.followupRun.run.inputProvenance, | |
| ) | |
| ) { | |
| return await persistCliSessionBindingResult({ | |
| provider: params.cliExecutionProvider, | |
| result: candidateResult, | |
| sessionKey, | |
| storePath: turn.storePath, | |
| sessionStore: turn.activeSessionStore, | |
| expectedSession: sessionEntry, | |
| assertSettlementCurrent, | |
| abortSignal: params.runAbortSignal, | |
| }); | |
| } | |
| return candidateResult; | |
| }, | |
| { | |
| preparedRunAdmission: params.preparedRunAdmission, | |
| lifecycleGeneration: params.lifecycleGeneration, | |
| abortSignal: params.runAbortSignal, | |
| trigger: turn.isHeartbeat ? "heartbeat" : "user", | |
| inputProvenance: turn.followupRun.run.inputProvenance, | |
| }, | |
| ), | |
| ); | |
| return { | |
| result, | |
| bootstrapPromptWarningSignaturesSeen: resolveBootstrapWarningSignaturesSeen( | |
| result.meta?.systemPromptReport, | |
| ), | |
| }; | |
| } | |