@openclaw/codex 2026.9.1 → 2026.9.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +6 -6
- package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-Bp1ZOnk2.js} +76 -32
- package/dist/{attempt-context-DmQUNWwT.js → attempt-context-CSazkWns.js} +6 -6
- package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-DxGJRYbY.js} +46 -45
- package/dist/{capabilities-dIjNVCYH.js → capabilities-B1mgvpP8.js} +2 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-CLHhEB1Q.js → command-formatters-DSbGMXA0.js} +2 -2
- package/dist/{command-handlers-CTGb2csu.js → command-handlers-DOJvGv6-.js} +146 -74
- package/dist/{compact-_t0HQrUS.js → compact-Y_xBqrHN.js} +83 -48
- package/dist/{config-BhmfC1s6.js → config-CyapYSji.js} +47 -105
- package/dist/config-utils-C57JiJrU.js +69 -0
- package/dist/doctor-contract-api.js +4 -5
- package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-BwpvTxaX.js} +678 -638
- package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
- package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-B9kp6iGC.js} +11 -2
- package/dist/{event-projector-usage-C5mcrGjp.js → event-projector-usage-ZqEVbAEY.js} +30 -13
- package/dist/{harness-DXVZ5II5.js → harness-Czh2Sdoc.js} +36 -13
- package/dist/harness.js +1 -1
- package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
- package/dist/index.js +68 -84
- package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-CRh-51AK.js} +9 -21
- package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DcpnJF9x.js} +105 -73
- package/dist/media-understanding-provider.js +1 -1
- package/dist/{model-catalog-CUM68Hkl.js → model-catalog-DT5vo6qo.js} +5 -5
- package/dist/{models-sYnEc0gd.js → models-CcrgSMQR.js} +4 -4
- package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-B3bvQGcg.js} +12 -11
- package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-nfbUOtUB.js} +3 -3
- package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-aQVdyL5g.js} +1 -1
- package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → plugin-marketplace-discovery-B7gHXJ3d.js} +35 -22
- package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-BwCLTY_U.js} +5 -5
- package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-BpG9Ltc5.js} +2 -2
- package/dist/{rate-limits-CawQJfUS.js → rate-limits-Fx_l4eNa.js} +1 -1
- package/dist/{request-DYAI5FQE.js → request-C8H22rPi.js} +2 -2
- package/dist/{run-attempt-D1hJO4fX.js → run-attempt-BzthFQSM.js} +977 -723
- package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-Bh_gf6-t.js} +3 -3
- package/dist/{session-binding-BHuTCRZQ.js → session-binding-4Ki04sW-.js} +94 -282
- package/dist/session-binding-record-CyaXZvTe.js +270 -0
- package/dist/{session-catalog-yyvTWFOw.js → session-catalog-B47uwekb.js} +266 -114
- package/dist/{session-cli-CmFEXMAM.js → session-cli-BjLhpmS1.js} +1 -1
- package/dist/session-history-DWmMqiqW.js +93 -0
- package/dist/session-history-read-LHldwvyh.js +36 -0
- package/dist/session-history-worker-runtime.js +48 -0
- package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-zZVcx0ME.js} +30 -31
- package/dist/session-history.worker.js +2 -0
- package/dist/{session-initialization-BeWzjGiR.js → session-initialization-BCFVnLL4.js} +2 -1
- package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-BaueHmSj.js} +1 -1
- package/dist/{session-retirement-BujDjXVF.js → session-retirement-DNdmYdFc.js} +7 -7
- package/dist/{session-upstream-marker-C351-5Qw.js → session-upstream-marker-DReTpGz6.js} +4 -3
- package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
- package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BI-b1sry.js} +53 -42
- package/dist/{shared-client-DxcfF9KX.js → shared-client-CKhX2kFt.js} +279 -268
- package/dist/{side-question-BTZAII4l.js → side-question-B6DWAw1A.js} +85 -36
- package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-DPK30jad.js} +382 -388
- package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-CbucAmmp.js} +5 -5
- package/dist/thread-policy-CTalhWFy.js +105 -0
- package/dist/{thread-resume-C7pyVKeW.js → thread-resume-BLgqkUc1.js} +7 -7
- package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-_njEB84z.js} +67 -125
- package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
- package/dist/{transport-stdio-CyPldczm.js → transport-stdio-CzTngV0j.js} +10 -8
- package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-1fwbNKzQ.js} +85 -165
- package/dist/{usage-Bj-rrzkR.js → usage-i9fv5-4m.js} +3 -3
- package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
- package/package.json +6 -6
- package/dist/binding-connection-E6uDsPlx.js +0 -45
- package/dist/launch-args-RXQwn8zV.js +0 -90
- package/dist/session-history-C5J1AKzG.js +0 -87
- package/dist/thread-policy-g4KbJPzp.js +0 -54
|
@@ -1,41 +1,43 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { c as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { l as
|
|
9
|
-
import {
|
|
10
|
-
import { n as CodexThreadPolicyHandoffError } from "./thread-policy-
|
|
1
|
+
import { l as sessionBindingIdentity } from "./session-binding-record-CyaXZvTe.js";
|
|
2
|
+
import { A as resolveOpenClawExecPolicyForCodexAppServer, B as isJsonObject, D as isCodexSandboxExecServerEnabled, E as isCodexRemoteExecPlacementSandbox, M as resolveCodexAppServerHomeDir, O as readCodexPluginConfig, T as isCodexPairedNodeRemoteExecPlacementSandbox, d as shouldAutoApproveCodexAppServerApprovals, f as withMcpElicitationsApprovalPolicy, h as resolveCodexModelBackedReviewerPolicyContext, k as resolveCodexPluginsPolicy, l as hasCodexMcpToolApprovalOverrides, m as canUseCodexModelBackedApprovalsReviewerForModel, o as resolveCodexComputerUseConfig, r as resolveCodexAppServerHomeScope, y as readCodexRequirementsToml, z as flattenCodexDynamicToolFunctions } from "./config-CyapYSji.js";
|
|
3
|
+
import { A as TURN_FINALIZE_DRAIN_ABORT_GRACE_MS, B as isCodexAppServerIndeterminateRequestCancellationError, Bt as resolveCodexAppServerAuthAccountCacheKey, F as withCodexStartupTimeout, Gt as resolveCodexAppServerPreparedApiKeyCacheKey, H as isCodexAppServerOverloadError, Ht as resolveCodexAppServerAuthProfileIdForAgent, I as getCodexAppServerClientInstanceId, It as readCodexRateLimitsRevision, K as resolveCodexAppServerClientInstanceId, Kt as resolveCodexAppServerPreparedAuthHandoff, L as isCodexAppServerApprovalRequest, Lt as readRecentCodexRateLimits, M as isCodexAppServerStartupError, P as resolveCodexStartupTimeoutMs, Pt as withAbortableTimeout, R as isCodexAppServerBrokenPipeError, Rt as rememberCodexRateLimitsRead, Tt as ensureCodexAppServerClientRuntime, V as isCodexAppServerIndeterminateTransportError, Vt as resolveCodexAppServerAuthProfileId, W as isCodexAppServerRequestTimeoutError, Wt as resolveCodexAppServerFallbackApiKeyCacheKey, _t as toCodexDynamicToolProgressResponse, a as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, c as getLeasedSharedCodexAppServerClient, ct as createCodexElicitationResponse, dt as isDynamicToolTerminalDiagnosticEvent, f as readCodexAppServerClientDesktopGenerationFingerprint, ft as isMatchingDynamicToolTerminalDiagnostic, gt as shouldReleaseTurnAfterTerminalDynamicTool, h as releaseLeasedSharedCodexAppServerClient, ht as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, i as clearSharedCodexAppServerClientIfCurrent, it as readCodexDynamicToolCallParams, j as TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS, k as CodexAppServerStartupError, kt as protectCodexAppServerLiveThread, l as getSharedCodexAppServerClient, lt as handleDynamicToolCallWithTimeout, mt as resolveTerminalDynamicToolBatchAction, ot as readCodexTurn, pt as resolveDynamicToolCallTimeoutMs, q as CodexAppServerRpcError, rt as assertCodexTurnStartResponse, s as createIsolatedCodexAppServerClient, st as readCodexTurnCompletedNotification, u as isCodexAppServerStartSelectionChangedError, ut as hasPendingDynamicToolTerminalDiagnostic, v as retainSharedCodexAppServerClientIfCurrent, vt as toCodexDynamicToolProtocolResponse, y as retireSharedCodexAppServerClientIfCurrent, yt as resolveCodexToolAbortTerminalReason, z as isCodexAppServerConnectionClosedError } from "./shared-client-CKhX2kFt.js";
|
|
4
|
+
import { c as resolveCodexRunSessionBindingAuthority, l as resolveCodexSessionBinding, n as assertCodexBindingMayBeReplaced, r as createCodexSessionGenerationSupersededError, u as scopeCodexRunBindingStore } from "./session-binding-4Ki04sW-.js";
|
|
5
|
+
import { E as itemStatus, F as readCodexProviderRefusal, H as readNullableString, L as readItem, M as extractRawAssistantText, O as matchesCodexSnapshotTurn, P as readCodexErrorNotificationMessage, R as readItemString, U as splitPlanText, V as readNonNegativeInteger, a as closeCodexStartupClientBestEffort, d as unsubscribeCodexThreadBestEffort, f as CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS, g as readCodexNotificationThreadId, h as isCodexNotificationForTurn, j as shouldSynthesizeToolProgressForItem, k as shouldClearTerminalPresentationForNativeItem, l as retireUnsafeCodexTurnClientBestEffort, m as CodexProjectionDiagnostics, o as interruptCodexTurnAndWaitBestEffort, p as getCodexAppServerTurnRouter, r as CodexAppServerUnsafeSubscriptionError, u as terminateCodexBackgroundTerminals } from "./attempt-client-cleanup-Bp1ZOnk2.js";
|
|
6
|
+
import { a as isCodexTurnAbortMarkerNotification, d as readNotificationItemId, f as readRawResponseToolCallId, l as isTerminalTurnStatus, o as isPendingOpenClawDynamicToolCompletionNotification, p as updateActiveTurnItemIds, r as codexExecutionToolName, s as isRawFunctionToolOutputCompletionNotification, t as CodexUsageProjection, u as readCodexNotificationItem } from "./event-projector-usage-ZqEVbAEY.js";
|
|
7
|
+
import { c as defaultCodexAppInventoryCache, i as buildCodexPluginAppCacheKey, r as buildCodexAppServerRuntimeFingerprint } from "./thread-resume-BLgqkUc1.js";
|
|
8
|
+
import { A as readCodexMcpToolConnectorId, B as emitCodexNativePreToolUseFailureDiagnostic, C as buildDeveloperInstructions, Ct as buildCodexPluginThreadConfigInputFingerprint, D as resolveCodexAppServerThreadModelSelection, Et as mergeCodexThreadConfigs, H as resolveCodexNativeHookRelayTtlMs, I as buildCodexNativeHookRelayConfig, L as buildCodexNativeHookRelayDisabledConfig, M as isCodexAppServerProfilerEnabled, Ot as shouldBuildCodexPluginThreadConfig, P as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, Pt as resolveRecoverableCodexPluginConfigKeys, S as resolveCodexWebSearchPlan, St as buildCodexPluginThreadConfig, U as scheduleCodexNativeHookRelayUnregister, V as resolveCodexNativeHookRelayEvents, X as loadCodexNativeToolCatalog, Y as hasCodexNativeToolCatalog, _t as neutralizeCodexExplicitMentionSigils, at as filterCodexDynamicTools, bt as resolveCodexContextEngineProjectionReserveTokens, c as assertScheduledCodexAppAuthorityRuntime, d as buildScheduledCodexAppServerConnectionIdentity, f as captureScheduledCodexAppAuthority, ft as resolveCodexDynamicToolsLoadingForRuntime, gt as fitCodexProjectedContextForTurnStart, h as resolveScheduledCodexAppCreatorCaptureDecision, ht as buildCodexContinuityCalibration, i as buildCodexUserInput, j as readCodexMcpToolUiVisibility, l as buildLegacyScheduledCodexAppRecoveryPrompt, lt as isSystemAgentOnlyCodexDynamicToolAllowlist, m as readCurrentCodexScheduledAppPolicy$1, n as buildTurnCollaborationMode, nt as codexLegacyDynamicToolsFingerprint, p as intersectCodexPluginThreadConfigWithScheduledAuthority, pt as buildContextEngineBinding, r as buildTurnStartParams, s as startOrResumeThread, tt as codexDynamicToolsFingerprint, u as buildScheduledCodexAppAuthorityInputFingerprint, vt as projectContextEngineAssemblyForCodex, wt as buildCodexPluginThreadConfigTimeoutFallback, xt as resolveCodexContinuityProjectionMaxChars, yt as resolveCodexContextEngineProjectionMaxChars, z as createCodexNativeHookRelay } from "./thread-lifecycle-DPK30jad.js";
|
|
9
|
+
import { l as isIncognitoSessionKey, r as retainCodexAppServerBindingSubscription } from "./thread-ownership-CbucAmmp.js";
|
|
10
|
+
import { a as assertCodexSessionRuntimeOwnership, n as CodexThreadPolicyHandoffError, s as resolveCodexBindingAppServerConnection } from "./thread-policy-CTalhWFy.js";
|
|
11
|
+
import { a as buildCodexUserPromptMessage, i as mirrorPromptAtTurnStartBestEffort, n as createCodexAppServerUserMessagePersistenceNotifier, o as promptSnapshot, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-_njEB84z.js";
|
|
11
12
|
import { r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-LphB8slG.js";
|
|
12
|
-
import { t as
|
|
13
|
-
import {
|
|
14
|
-
import { a as
|
|
15
|
-
import { a as
|
|
16
|
-
import { n as
|
|
13
|
+
import { a as hasCodexMirrorOrigin, t as applyCodexTranscriptTaint } from "./transcript-mirror-attestation-Byl34PC-.js";
|
|
14
|
+
import { t as CODEX_CONTROL_METHODS } from "./capabilities-B1mgvpP8.js";
|
|
15
|
+
import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-Fx_l4eNa.js";
|
|
16
|
+
import { a as formatCodexDisplayText } from "./command-formatters-DSbGMXA0.js";
|
|
17
|
+
import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy } from "./session-permission-policy-BaueHmSj.js";
|
|
17
18
|
import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-Ds_QVm-X.js";
|
|
18
19
|
import { t as persistCodexContextCompactionActivity } from "./context-compaction-activity-CMla5FPJ.js";
|
|
19
|
-
import { i as createAssistantReasoningMessage, n as createAssistantCommentaryMessage, r as createAssistantMessage, t as createAssistantAsyncMessage } from "./event-projector-assistant-message-
|
|
20
|
-
import { a as
|
|
21
|
-
import {
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import { a as getCodexWorkspaceMemoryToolNames, c as readContextEngineThreadBootstrapProjection, d as resolveCodexDeliveryHintPreservedInputRange, f as resolveContextEngineBootstrapProjectionDecision, i as buildCodexWorkspaceBootstrapContext, l as readMirroredSessionHistoryMessages, n as buildCodexSystemPromptReport, r as buildCodexWatchedSessionsContext, s as prependCodexOpenClawPromptContext, t as buildCodexOpenClawPromptContext, u as renderCodexSkillsCollaborationInstructions } from "./attempt-context-
|
|
25
|
-
import { n as captureCodexSettledTurnFinalizationContext } from "./settled-turn-context-
|
|
26
|
-
import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-
|
|
20
|
+
import { i as createAssistantReasoningMessage, n as createAssistantCommentaryMessage, r as createAssistantMessage, t as createAssistantAsyncMessage } from "./event-projector-assistant-message-B9kp6iGC.js";
|
|
21
|
+
import { C as shouldRequireCodexSandboxExecServerEnvironment, S as shouldEnableCodexAppServerNativeToolSurface, _ as resolveCodexAppServerHookChannelId, a as emitDynamicToolStartedDiagnostic, c as ensureCodexSandboxExecServerEnvironment, d as CodexNativeToolLifecycleProjector, f as buildDynamicTools, g as resolveCodexAppServerExecutionCwd, h as formatCodexDynamicToolBuildStageSummary, i as emitDynamicToolErrorDiagnostic, l as releaseCodexSandboxExecServerEnvironment, m as disableCodexPluginThreadConfig, n as projectCodexExecutableDynamicTools, o as emitDynamicToolTerminalDiagnostic, p as createCodexDynamicToolBuildStageTracker, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, u as readBoundedCodexRemoteWorkspaceFile, v as resolveCodexExternalSandboxPolicyForOpenClawSandbox, w as shouldWarnCodexDynamicToolBuildStageSummary, x as resolveCodexSandboxEnvironmentSelection, y as resolveCodexMessageToolProvider } from "./dynamic-tools-BwpvTxaX.js";
|
|
22
|
+
import { t as resolveCodexProviderWebSearchSupport } from "./provider-capabilities-BpG9Ltc5.js";
|
|
23
|
+
import { a as CodexToolProgressProjection, c as isCodexCommandBearingToolCall, d as sanitizeCodexToolResponse, i as CodexToolTranscriptProjection, l as resolveCodexToolProgressDetailMode, n as CodexEventProjection, o as shouldEmitTranscriptToolProgress, r as emitCodexAgentEvent, s as inferCodexDynamicToolMeta, t as codexNativeSubagentMonitorRuntime, u as sanitizeCodexToolArguments } from "./native-subagent-monitor-B3bvQGcg.js";
|
|
24
|
+
import { a as requestPluginApprovalOutcome } from "./plugin-approval-roundtrip-aQVdyL5g.js";
|
|
25
|
+
import { a as getCodexWorkspaceMemoryToolNames, c as readContextEngineThreadBootstrapProjection, d as resolveCodexDeliveryHintPreservedInputRange, f as resolveContextEngineBootstrapProjectionDecision, i as buildCodexWorkspaceBootstrapContext, l as readMirroredSessionHistoryMessages, n as buildCodexSystemPromptReport, r as buildCodexWatchedSessionsContext, s as prependCodexOpenClawPromptContext, t as buildCodexOpenClawPromptContext, u as renderCodexSkillsCollaborationInstructions } from "./attempt-context-CSazkWns.js";
|
|
26
|
+
import { n as captureCodexSettledTurnFinalizationContext } from "./settled-turn-context-BOM3Y1pl.js";
|
|
27
|
+
import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-BwCLTY_U.js";
|
|
27
28
|
import { asOptionalRecord, normalizeOptionalString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
29
|
+
import { createHash } from "node:crypto";
|
|
30
|
+
import { resolveAgentConfig, resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
31
|
+
import { parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
|
|
32
|
+
import { MAX_TIMER_TIMEOUT_MS, asDateTimestampMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
28
33
|
import fs from "node:fs/promises";
|
|
29
34
|
import path from "node:path";
|
|
30
35
|
import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
|
|
31
|
-
import {
|
|
32
|
-
import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, agentHarnessAttemptTerminal, agentHarnessStructuredInput, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildEmbeddedForegroundPromptContext, buildHarnessContextEngineRuntimeContext, callGatewayTool, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, detectAndLoadAgentHarnessPromptImages, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, hasBeforeToolCallPolicy, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, prepareHarnessNativeMcpAppPreview, projectAgentHarnessTranscriptMessageForDisplay, resolveAgentDir, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveAttemptFsWorkspaceOnly, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
36
|
+
import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, agentHarnessAttemptTerminal, agentHarnessStructuredInput, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildAgentHookContextChannelFields, buildEmbeddedForegroundPromptContext, buildHarnessContextEngineRuntimeContext, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, detectAndLoadAgentHarnessPromptImages, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, hasBeforeToolCallPolicy, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, prepareHarnessNativeMcpAppPreview, projectAgentHarnessTranscriptMessageForDisplay, resolveAgentDir as resolveAgentDir$1, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveAttemptFsWorkspaceOnly, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
33
37
|
import { isPathStrictlyInside, root } from "openclaw/plugin-sdk/file-access-runtime";
|
|
34
|
-
import {
|
|
35
|
-
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$
|
|
36
|
-
import { resolveAgentConfig as resolveAgentConfig$1, resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
38
|
+
import { isDeepStrictEqual } from "node:util";
|
|
39
|
+
import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$2 } from "openclaw/plugin-sdk/agent-runtime";
|
|
37
40
|
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
38
|
-
import { parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
|
|
39
41
|
import { addAbortListener } from "node:events";
|
|
40
42
|
import { truncateUtf16Safe, truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
41
43
|
import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
|
|
@@ -49,6 +51,48 @@ import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generat
|
|
|
49
51
|
import { resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generation-runtime";
|
|
50
52
|
import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
|
|
51
53
|
import { stripInvisibleUnicode } from "openclaw/plugin-sdk/web-content-extractor";
|
|
54
|
+
import { acknowledgeInternalToolResult } from "openclaw/plugin-sdk/agent-harness-tool-runtime";
|
|
55
|
+
//#region extensions/codex/src/app-server/attempt-preparation-timing.ts
|
|
56
|
+
/** Records startup before the native turn owns inference and tool execution. */
|
|
57
|
+
function createCodexAttemptPreparationTiming(params) {
|
|
58
|
+
const tracker = createCodexDynamicToolBuildStageTracker();
|
|
59
|
+
const profilerEnabled = isCodexAppServerProfilerEnabled(params.config);
|
|
60
|
+
const totalWarnMs = profilerEnabled ? 1e3 : 1e4;
|
|
61
|
+
const stageWarnMs = profilerEnabled ? 500 : 5e3;
|
|
62
|
+
const log = (stage, outcome) => {
|
|
63
|
+
const summary = tracker.snapshot();
|
|
64
|
+
const lastStage = summary.stages.at(-1);
|
|
65
|
+
const slowTotal = outcome !== "completed" && summary.totalMs >= totalWarnMs;
|
|
66
|
+
const slowStage = outcome !== "ready" && (lastStage?.durationMs ?? 0) >= stageWarnMs;
|
|
67
|
+
if (!slowTotal && !slowStage) return;
|
|
68
|
+
embeddedAgentLog.warn(`codex app-server preparation timings runId=${params.runId} sessionId=${params.sessionId} stage=${stage} outcome=${outcome} totalMs=${summary.totalMs} stages=${formatCodexDynamicToolBuildStageSummary(summary)}`, {
|
|
69
|
+
runId: params.runId,
|
|
70
|
+
sessionId: params.sessionId,
|
|
71
|
+
sessionKey: params.sessionKey,
|
|
72
|
+
stage,
|
|
73
|
+
outcome,
|
|
74
|
+
totalMs: summary.totalMs,
|
|
75
|
+
stages: summary.stages
|
|
76
|
+
});
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
async measure(stage, run) {
|
|
80
|
+
let outcome = "error";
|
|
81
|
+
try {
|
|
82
|
+
const result = await run();
|
|
83
|
+
outcome = "completed";
|
|
84
|
+
return result;
|
|
85
|
+
} finally {
|
|
86
|
+
tracker.mark(stage);
|
|
87
|
+
log(stage, outcome);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
ready() {
|
|
91
|
+
log("native-turn-handoff", "ready");
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
52
96
|
//#region extensions/codex/src/app-server/attempt-steering.ts
|
|
53
97
|
/**
|
|
54
98
|
* Debounced steering queue for forwarding user messages to an active Codex
|
|
@@ -130,30 +174,61 @@ function createCodexSteeringQueue(params) {
|
|
|
130
174
|
closeQueue(/* @__PURE__ */ new Error("codex app-server steering queue cancelled"));
|
|
131
175
|
};
|
|
132
176
|
const sendBatch = async (items) => {
|
|
133
|
-
|
|
177
|
+
let liveItems = items.filter((item) => !item.settled);
|
|
134
178
|
if (liveItems.length === 0) return;
|
|
135
179
|
let clientUserMessageId;
|
|
180
|
+
let skippedRevokedBatch = false;
|
|
136
181
|
try {
|
|
137
182
|
assertActive();
|
|
138
|
-
const
|
|
183
|
+
const prepared = /* @__PURE__ */ new Map();
|
|
184
|
+
const isCurrent = (item) => {
|
|
185
|
+
if (item.settled) return false;
|
|
186
|
+
try {
|
|
187
|
+
item.assertCurrent();
|
|
188
|
+
return true;
|
|
189
|
+
} catch (error) {
|
|
190
|
+
rejectItem(item, error);
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
};
|
|
139
194
|
for (const item of liveItems) {
|
|
140
|
-
|
|
195
|
+
if (!isCurrent(item)) continue;
|
|
196
|
+
try {
|
|
197
|
+
prepared.set(item, await params.prepareMessage(item.text, item));
|
|
198
|
+
} catch (error) {
|
|
199
|
+
if (isCurrent(item)) throw error;
|
|
200
|
+
}
|
|
141
201
|
assertActive();
|
|
202
|
+
isCurrent(item);
|
|
142
203
|
}
|
|
204
|
+
liveItems = liveItems.filter(isCurrent);
|
|
205
|
+
if (liveItems.length === 0) return;
|
|
143
206
|
clientUserMessageId = `openclaw:${params.turnId}:steer:${++batchSequence}`;
|
|
144
207
|
dispatchedBatches.set(clientUserMessageId, { items: liveItems });
|
|
145
|
-
|
|
208
|
+
const request = {
|
|
146
209
|
threadId: params.threadId,
|
|
147
210
|
expectedTurnId: params.turnId,
|
|
148
|
-
input,
|
|
211
|
+
input: liveItems.flatMap((item) => prepared.get(item) ?? []),
|
|
149
212
|
clientUserMessageId
|
|
150
|
-
}
|
|
213
|
+
};
|
|
214
|
+
await params.client.request("turn/steer", request, {
|
|
151
215
|
timeoutMs: params.requestTimeoutMs,
|
|
152
|
-
signal: params.signal
|
|
216
|
+
signal: params.signal,
|
|
217
|
+
assertCurrent: () => {
|
|
218
|
+
assertActive();
|
|
219
|
+
liveItems = liveItems.filter(isCurrent);
|
|
220
|
+
request.input = liveItems.flatMap((item) => prepared.get(item) ?? []);
|
|
221
|
+
dispatchedBatches.set(request.clientUserMessageId, { items: liveItems });
|
|
222
|
+
if (liveItems.length === 0) {
|
|
223
|
+
skippedRevokedBatch = true;
|
|
224
|
+
throw new Error("Codex steering batch has no authorized inputs");
|
|
225
|
+
}
|
|
226
|
+
}
|
|
153
227
|
});
|
|
154
228
|
for (const item of liveItems) reportItemAcceptance(item, true);
|
|
155
229
|
} catch (error) {
|
|
156
230
|
if (clientUserMessageId) dispatchedBatches.delete(clientUserMessageId);
|
|
231
|
+
if (skippedRevokedBatch) return;
|
|
157
232
|
const acceptedUnconfirmed = clientUserMessageId !== void 0 && (isCodexAppServerIndeterminateRequestCancellationError(error) || isCodexAppServerIndeterminateTransportError(error));
|
|
158
233
|
for (const item of liveItems) {
|
|
159
234
|
if (acceptedUnconfirmed) reportItemAcceptance(item, true);
|
|
@@ -180,7 +255,7 @@ function createCodexSteeringQueue(params) {
|
|
|
180
255
|
send.catch(() => void 0);
|
|
181
256
|
return send;
|
|
182
257
|
};
|
|
183
|
-
const createPendingMessage = (text, options) => {
|
|
258
|
+
const createPendingMessage = (text, options, assertCurrent = () => {}) => {
|
|
184
259
|
let resolveDelivery;
|
|
185
260
|
let rejectDelivery;
|
|
186
261
|
const delivery = new Promise((resolve, reject) => {
|
|
@@ -189,6 +264,7 @@ function createCodexSteeringQueue(params) {
|
|
|
189
264
|
});
|
|
190
265
|
const item = {
|
|
191
266
|
...options,
|
|
267
|
+
assertCurrent,
|
|
192
268
|
acceptance: "open",
|
|
193
269
|
text,
|
|
194
270
|
resolve: resolveDelivery,
|
|
@@ -204,14 +280,15 @@ function createCodexSteeringQueue(params) {
|
|
|
204
280
|
params.signal.addEventListener("abort", abortQueue, { once: true });
|
|
205
281
|
if (params.signal.aborted) abortQueue();
|
|
206
282
|
return {
|
|
207
|
-
async queue(text, options) {
|
|
283
|
+
async queue(text, options, assertCurrent = () => {}) {
|
|
208
284
|
try {
|
|
209
285
|
assertActive();
|
|
286
|
+
assertCurrent();
|
|
210
287
|
} catch (error) {
|
|
211
288
|
options?.onQueueAccepted?.(false);
|
|
212
289
|
throw error;
|
|
213
290
|
}
|
|
214
|
-
const { item, delivery } = createPendingMessage(text, options);
|
|
291
|
+
const { item, delivery } = createPendingMessage(text, options, assertCurrent);
|
|
215
292
|
batchedMessages.push(item);
|
|
216
293
|
clearBatchTimer();
|
|
217
294
|
const debounceMs = normalizeCodexSteerDebounceMs(options?.debounceMs);
|
|
@@ -320,6 +397,7 @@ var CodexAssistantProjection = class {
|
|
|
320
397
|
this.emitAgentEvent({
|
|
321
398
|
stream: "assistant",
|
|
322
399
|
data: {
|
|
400
|
+
itemId,
|
|
323
401
|
...streamPayload,
|
|
324
402
|
...replaceable ? { replaceable: true } : {}
|
|
325
403
|
}
|
|
@@ -1055,12 +1133,11 @@ function buildCodexAttemptResult(input) {
|
|
|
1055
1133
|
const commentaryMessages = input.assistantProjection.collectCommentaryMessages();
|
|
1056
1134
|
const reasoningText = input.reasoningProjection.reasoningText();
|
|
1057
1135
|
const planText = input.reasoningProjection.planText();
|
|
1058
|
-
const
|
|
1059
|
-
|
|
1136
|
+
const usage = input.usageProjection.usage;
|
|
1137
|
+
const projectedUsage = input.aborted && usage ? {
|
|
1138
|
+
...usage,
|
|
1060
1139
|
contextUsage: { state: "unavailable" }
|
|
1061
|
-
} :
|
|
1062
|
-
const completedUsage = input.responseCompletions.usage ?? (input.responseCompletions.modelIterations > 0 ? unavailableThreadUsage : input.tokenUsage);
|
|
1063
|
-
const projectedUsage = input.aborted ? unavailableThreadUsage : completedUsage;
|
|
1140
|
+
} : usage;
|
|
1064
1141
|
const hasAssistantItemText = input.assistantProjection.hasAssistantItemTextForSynthesis();
|
|
1065
1142
|
const legacyFailClosed = !input.completedTurn || input.completedTurn.status !== "completed" || hasAssistantItemText;
|
|
1066
1143
|
const hasDeliverableAssistantOnCompletedTurn = input.completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
|
|
@@ -1077,10 +1154,11 @@ function buildCodexAttemptResult(input) {
|
|
|
1077
1154
|
const assistantMessageOptions = {
|
|
1078
1155
|
tokenUsage: projectedUsage,
|
|
1079
1156
|
aborted: input.aborted,
|
|
1080
|
-
promptError: input.promptError
|
|
1157
|
+
promptError: input.promptError,
|
|
1158
|
+
providerRefusal: input.providerRefusal
|
|
1081
1159
|
};
|
|
1082
|
-
const lastAssistant = assistantTexts.length ? input.assistantProjection.createAssistantMessage(assistantTexts.join("\n\n"), assistantMessageOptions) : void 0;
|
|
1083
|
-
const currentAttemptAssistant = input.assistantProjection.createCurrentAttemptAssistantMessage(assistantMessageOptions);
|
|
1160
|
+
const lastAssistant = input.providerRefusal ? input.assistantProjection.createAssistantMessage("", assistantMessageOptions) : assistantTexts.length ? input.assistantProjection.createAssistantMessage(assistantTexts.join("\n\n"), assistantMessageOptions) : void 0;
|
|
1161
|
+
const currentAttemptAssistant = input.providerRefusal ? lastAssistant : input.assistantProjection.createCurrentAttemptAssistantMessage(assistantMessageOptions);
|
|
1084
1162
|
const messagesSnapshot = buildCodexMessagesSnapshot({
|
|
1085
1163
|
runParams: input.runParams,
|
|
1086
1164
|
turnId: input.turnId,
|
|
@@ -1092,8 +1170,8 @@ function buildCodexAttemptResult(input) {
|
|
|
1092
1170
|
lastAssistant
|
|
1093
1171
|
});
|
|
1094
1172
|
const turnFailed = input.completedTurn?.status === "failed";
|
|
1095
|
-
const promptError = input.promptError ?? storedMissingToolResultError ?? (turnFailed ? input.completedTurn?.error?.message ?? "codex app-server turn failed" : null);
|
|
1096
|
-
const agentHarnessResultClassification = classifyAgentHarnessTerminalOutcome({
|
|
1173
|
+
const promptError = input.providerRefusal ? null : input.promptError ?? storedMissingToolResultError ?? (turnFailed ? input.completedTurn?.error?.message ?? "codex app-server turn failed" : null);
|
|
1174
|
+
const agentHarnessResultClassification = input.providerRefusal ? void 0 : classifyAgentHarnessTerminalOutcome({
|
|
1097
1175
|
assistantTexts,
|
|
1098
1176
|
reasoningText,
|
|
1099
1177
|
planText,
|
|
@@ -1115,7 +1193,7 @@ function buildCodexAttemptResult(input) {
|
|
|
1115
1193
|
...agentHarnessResultClassification ? { agentHarnessResultClassification } : {},
|
|
1116
1194
|
bootstrapPromptWarningSignaturesSeen: input.runParams.bootstrapPromptWarningSignaturesSeen,
|
|
1117
1195
|
bootstrapPromptWarningSignature: input.runParams.bootstrapPromptWarningSignature,
|
|
1118
|
-
...input.
|
|
1196
|
+
...input.usageProjection.modelIterations > 0 ? { modelIterations: input.usageProjection.modelIterations } : {},
|
|
1119
1197
|
messagesSnapshot,
|
|
1120
1198
|
assistantTexts,
|
|
1121
1199
|
toolMetas,
|
|
@@ -1124,6 +1202,7 @@ function buildCodexAttemptResult(input) {
|
|
|
1124
1202
|
...input.toolProgressProjection.lastToolError ? { lastToolError: input.toolProgressProjection.lastToolError } : {},
|
|
1125
1203
|
didSendViaMessagingTool: input.toolTelemetry.didSendViaMessagingTool,
|
|
1126
1204
|
didDeliverSourceReplyViaMessageTool: input.toolTelemetry.didDeliverSourceReplyViaMessageTool === true,
|
|
1205
|
+
sourceReplyDelivered: input.toolTelemetry.sourceReplyDelivered,
|
|
1127
1206
|
messagingToolSentTexts: input.toolTelemetry.messagingToolSentTexts,
|
|
1128
1207
|
messagingToolSentMediaUrls: input.toolTelemetry.messagingToolSentMediaUrls,
|
|
1129
1208
|
messagingToolSentTargets: input.toolTelemetry.messagingToolSentTargets,
|
|
@@ -1156,93 +1235,39 @@ function buildCodexAttemptResult(input) {
|
|
|
1156
1235
|
return result;
|
|
1157
1236
|
}
|
|
1158
1237
|
//#endregion
|
|
1159
|
-
//#region extensions/codex/src/app-server/transcript-checkpoint.ts
|
|
1160
|
-
/** Commits completed work in receipt order without waiting for the enclosing turn. */
|
|
1161
|
-
var CodexTranscriptCheckpoint = class {
|
|
1162
|
-
constructor(params, threadId, turnId) {
|
|
1163
|
-
this.params = params;
|
|
1164
|
-
this.threadId = threadId;
|
|
1165
|
-
this.turnId = turnId;
|
|
1166
|
-
this.pending = [];
|
|
1167
|
-
this.commentaryItemIds = /* @__PURE__ */ new Set();
|
|
1168
|
-
this.lastTimestamp = 0;
|
|
1169
|
-
this.writing = Promise.resolve();
|
|
1170
|
-
this.tainted = false;
|
|
1171
|
-
this.closed = false;
|
|
1172
|
-
this.nextTimestamp = () => {
|
|
1173
|
-
this.lastTimestamp = Math.max(Date.now(), this.lastTimestamp + 1);
|
|
1174
|
-
return this.lastTimestamp;
|
|
1175
|
-
};
|
|
1176
|
-
this.enqueueCommentary = (itemId, entry) => {
|
|
1177
|
-
if (this.params.config?.ui?.prefs?.chatPersistCommentary === false || this.commentaryItemIds.has(itemId)) return;
|
|
1178
|
-
this.commentaryItemIds.add(itemId);
|
|
1179
|
-
this.enqueue({
|
|
1180
|
-
...entry,
|
|
1181
|
-
read: () => {
|
|
1182
|
-
const message = entry.read();
|
|
1183
|
-
return message ? attachCodexMirrorIdentity(message, `${this.turnId}:commentary:${itemId}`) : void 0;
|
|
1184
|
-
}
|
|
1185
|
-
});
|
|
1186
|
-
};
|
|
1187
|
-
this.enqueue = (entry) => {
|
|
1188
|
-
if (this.params.sessionTarget && !this.closed) this.pending.push(entry);
|
|
1189
|
-
};
|
|
1190
|
-
}
|
|
1191
|
-
flush(close = false) {
|
|
1192
|
-
if (this.closed) return this.writing;
|
|
1193
|
-
this.closed = close;
|
|
1194
|
-
this.writing = this.writing.then(async () => {
|
|
1195
|
-
const blocked = close ? -1 : this.pending.findIndex((entry) => entry.ready?.() === false);
|
|
1196
|
-
const count = blocked < 0 ? this.pending.length : blocked;
|
|
1197
|
-
if (count === 0) return;
|
|
1198
|
-
const taint = { tainted: this.tainted };
|
|
1199
|
-
const messages = this.pending.slice(0, count).flatMap((entry) => {
|
|
1200
|
-
const message = entry.read();
|
|
1201
|
-
return message ? [projectAgentHarnessTranscriptMessageForDisplay({
|
|
1202
|
-
hidden: this.params.trigger === "memory",
|
|
1203
|
-
message: applyCodexTranscriptTaint(message, taint)
|
|
1204
|
-
})] : [];
|
|
1205
|
-
});
|
|
1206
|
-
try {
|
|
1207
|
-
await codexTranscriptMirrorRuntime.mirror({
|
|
1208
|
-
...this.params.sessionTarget,
|
|
1209
|
-
sessionId: this.params.sessionId,
|
|
1210
|
-
cwd: this.params.workspaceDir,
|
|
1211
|
-
messages,
|
|
1212
|
-
idempotencyScope: `codex-app-server:${this.threadId}`,
|
|
1213
|
-
runId: this.params.runId,
|
|
1214
|
-
runMirrorIdentityPrefix: `${this.turnId}:`,
|
|
1215
|
-
config: this.params.config
|
|
1216
|
-
});
|
|
1217
|
-
this.pending.splice(0, count);
|
|
1218
|
-
this.tainted = taint.tainted;
|
|
1219
|
-
} catch (error) {
|
|
1220
|
-
embeddedAgentLog.warn("failed to checkpoint codex app-server transcript", {
|
|
1221
|
-
runId: this.params.runId,
|
|
1222
|
-
sessionId: this.params.sessionId,
|
|
1223
|
-
error: formatErrorMessage(error)
|
|
1224
|
-
});
|
|
1225
|
-
}
|
|
1226
|
-
});
|
|
1227
|
-
return this.writing;
|
|
1228
|
-
}
|
|
1229
|
-
};
|
|
1230
|
-
//#endregion
|
|
1231
1238
|
//#region extensions/codex/src/app-server/usage-limit-error.ts
|
|
1232
1239
|
/**
|
|
1233
1240
|
* Enriches Codex usage-limit failures with current rate-limit information and
|
|
1234
1241
|
* marks blocked auth profiles when Codex exposes a reset time.
|
|
1235
1242
|
*/
|
|
1236
1243
|
const CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS = 5e3;
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1244
|
+
var CodexUsageLimitPromptError = class extends Error {
|
|
1245
|
+
constructor(..._args) {
|
|
1246
|
+
super(..._args);
|
|
1247
|
+
this.status = 429;
|
|
1248
|
+
}
|
|
1249
|
+
};
|
|
1240
1250
|
function resolveCodexPromptError(source) {
|
|
1241
1251
|
const usageLimitMessage = formatCodexUsageLimitErrorMessage(source);
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1252
|
+
if (usageLimitMessage) return new CodexUsageLimitPromptError(usageLimitMessage);
|
|
1253
|
+
const info = source.codexErrorInfo;
|
|
1254
|
+
let status = info === "serverOverloaded" ? 503 : info === "internalServerError" ? 500 : void 0;
|
|
1255
|
+
if (isJsonObject(info)) for (const variant of [
|
|
1256
|
+
"httpConnectionFailed",
|
|
1257
|
+
"responseStreamConnectionFailed",
|
|
1258
|
+
"responseStreamDisconnected",
|
|
1259
|
+
"responseTooManyFailedAttempts"
|
|
1260
|
+
]) {
|
|
1261
|
+
const detail = info[variant];
|
|
1262
|
+
if (isJsonObject(detail) && typeof detail.httpStatusCode === "number") {
|
|
1263
|
+
status = detail.httpStatusCode;
|
|
1264
|
+
break;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
return status === void 0 ? source.message ?? void 0 : Object.assign(new Error(source.message ?? "codex app-server error"), {
|
|
1268
|
+
status,
|
|
1269
|
+
...info === "serverOverloaded" ? { code: "OVERLOADED" } : {}
|
|
1270
|
+
});
|
|
1246
1271
|
}
|
|
1247
1272
|
/** Marks a Codex auth profile blocked until the reset time advertised by rate limits. */
|
|
1248
1273
|
async function markCodexAuthProfileBlockedFromRateLimits(params) {
|
|
@@ -1368,6 +1393,95 @@ function readCodexErrorPayload(error) {
|
|
|
1368
1393
|
};
|
|
1369
1394
|
}
|
|
1370
1395
|
//#endregion
|
|
1396
|
+
//#region extensions/codex/src/app-server/event-projector-terminal-failure.ts
|
|
1397
|
+
var CodexTerminalFailureProjection = class {
|
|
1398
|
+
constructor() {
|
|
1399
|
+
this.promptErrorSource = null;
|
|
1400
|
+
}
|
|
1401
|
+
record(params) {
|
|
1402
|
+
this.providerRefusal ??= readCodexProviderRefusal(params.message, params.codexErrorInfo);
|
|
1403
|
+
if (this.providerRefusal) return;
|
|
1404
|
+
this.promptError = resolveCodexPromptError({
|
|
1405
|
+
message: params.message,
|
|
1406
|
+
codexErrorInfo: params.codexErrorInfo,
|
|
1407
|
+
rateLimits: params.rateLimits
|
|
1408
|
+
}) ?? params.fallbackMessage;
|
|
1409
|
+
this.promptErrorSource = params.promptErrorSource;
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
//#endregion
|
|
1413
|
+
//#region extensions/codex/src/app-server/transcript-checkpoint.ts
|
|
1414
|
+
/** Commits completed work in receipt order without waiting for the enclosing turn. */
|
|
1415
|
+
var CodexTranscriptCheckpoint = class {
|
|
1416
|
+
constructor(params, threadId, turnId) {
|
|
1417
|
+
this.params = params;
|
|
1418
|
+
this.threadId = threadId;
|
|
1419
|
+
this.turnId = turnId;
|
|
1420
|
+
this.pending = [];
|
|
1421
|
+
this.commentaryItemIds = /* @__PURE__ */ new Set();
|
|
1422
|
+
this.lastTimestamp = 0;
|
|
1423
|
+
this.writing = Promise.resolve();
|
|
1424
|
+
this.tainted = false;
|
|
1425
|
+
this.closed = false;
|
|
1426
|
+
this.nextTimestamp = () => {
|
|
1427
|
+
this.lastTimestamp = Math.max(Date.now(), this.lastTimestamp + 1);
|
|
1428
|
+
return this.lastTimestamp;
|
|
1429
|
+
};
|
|
1430
|
+
this.enqueueCommentary = (itemId, entry) => {
|
|
1431
|
+
if (this.params.config?.ui?.prefs?.chatPersistCommentary === false || this.commentaryItemIds.has(itemId)) return;
|
|
1432
|
+
this.commentaryItemIds.add(itemId);
|
|
1433
|
+
this.enqueue({
|
|
1434
|
+
...entry,
|
|
1435
|
+
read: () => {
|
|
1436
|
+
const message = entry.read();
|
|
1437
|
+
return message ? attachCodexMirrorIdentity(message, `${this.turnId}:commentary:${itemId}`) : void 0;
|
|
1438
|
+
}
|
|
1439
|
+
});
|
|
1440
|
+
};
|
|
1441
|
+
this.enqueue = (entry) => {
|
|
1442
|
+
if (this.params.sessionTarget && !this.closed) this.pending.push(entry);
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1445
|
+
flush(close = false) {
|
|
1446
|
+
if (this.closed) return this.writing;
|
|
1447
|
+
this.closed = close;
|
|
1448
|
+
this.writing = this.writing.then(async () => {
|
|
1449
|
+
const blocked = close ? -1 : this.pending.findIndex((entry) => entry.ready?.() === false);
|
|
1450
|
+
const count = blocked < 0 ? this.pending.length : blocked;
|
|
1451
|
+
if (count === 0) return;
|
|
1452
|
+
const taint = { tainted: this.tainted };
|
|
1453
|
+
const messages = this.pending.slice(0, count).flatMap((entry) => {
|
|
1454
|
+
const message = entry.read();
|
|
1455
|
+
return message ? [projectAgentHarnessTranscriptMessageForDisplay({
|
|
1456
|
+
hidden: this.params.trigger === "memory",
|
|
1457
|
+
message: applyCodexTranscriptTaint(message, taint)
|
|
1458
|
+
})] : [];
|
|
1459
|
+
});
|
|
1460
|
+
try {
|
|
1461
|
+
await codexTranscriptMirrorRuntime.mirror({
|
|
1462
|
+
...this.params.sessionTarget,
|
|
1463
|
+
sessionId: this.params.sessionId,
|
|
1464
|
+
cwd: this.params.workspaceDir,
|
|
1465
|
+
messages,
|
|
1466
|
+
idempotencyScope: `codex-app-server:${this.threadId}`,
|
|
1467
|
+
runId: this.params.runId,
|
|
1468
|
+
runMirrorIdentityPrefix: `${this.turnId}:`,
|
|
1469
|
+
config: this.params.config
|
|
1470
|
+
});
|
|
1471
|
+
this.pending.splice(0, count);
|
|
1472
|
+
this.tainted = taint.tainted;
|
|
1473
|
+
} catch (error) {
|
|
1474
|
+
embeddedAgentLog.warn("failed to checkpoint codex app-server transcript", {
|
|
1475
|
+
runId: this.params.runId,
|
|
1476
|
+
sessionId: this.params.sessionId,
|
|
1477
|
+
error: formatErrorMessage(error)
|
|
1478
|
+
});
|
|
1479
|
+
}
|
|
1480
|
+
});
|
|
1481
|
+
return this.writing;
|
|
1482
|
+
}
|
|
1483
|
+
};
|
|
1484
|
+
//#endregion
|
|
1371
1485
|
//#region extensions/codex/src/app-server/event-projector.ts
|
|
1372
1486
|
var CodexAppServerEventProjector = class {
|
|
1373
1487
|
constructor(params, threadId, turnId, options = {}) {
|
|
@@ -1378,14 +1492,12 @@ var CodexAppServerEventProjector = class {
|
|
|
1378
1492
|
this.activeItemIds = /* @__PURE__ */ new Set();
|
|
1379
1493
|
this.completedItemIds = /* @__PURE__ */ new Set();
|
|
1380
1494
|
this.activeCompactionItemIds = /* @__PURE__ */ new Set();
|
|
1381
|
-
this.terminalPresentationClearedItemIds = /* @__PURE__ */ new Set();
|
|
1382
|
-
this.nativeToolOutcomeOrdinals = /* @__PURE__ */ new Map();
|
|
1383
1495
|
this.projectionClosed = false;
|
|
1384
1496
|
this.settledTurnFailureFinalizationAllowed = false;
|
|
1385
|
-
this.
|
|
1497
|
+
this.terminalFailure = new CodexTerminalFailureProjection();
|
|
1386
1498
|
this.synthesizedMissingToolResultError = null;
|
|
1387
1499
|
this.aborted = false;
|
|
1388
|
-
this.
|
|
1500
|
+
this.usageProjection = new CodexUsageProjection();
|
|
1389
1501
|
this.completedCompactionCount = 0;
|
|
1390
1502
|
this.transcriptCheckpoint = new CodexTranscriptCheckpoint(params, threadId, turnId);
|
|
1391
1503
|
this.asyncDeliveryProjection = new CodexAsyncDeliveryProjection(params, threadId, turnId, options);
|
|
@@ -1446,9 +1558,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1446
1558
|
}
|
|
1447
1559
|
/** Resolves the shared model-order position for a native tool item. */
|
|
1448
1560
|
recordNativeToolOutcome(item) {
|
|
1449
|
-
|
|
1450
|
-
const ordinal = this.params.allocateToolOutcomeOrdinal?.(item.id);
|
|
1451
|
-
if (ordinal !== void 0) this.nativeToolOutcomeOrdinals.set(item.id, ordinal);
|
|
1561
|
+
this.nativeToolLifecycleProjector.recordNativeToolOutcome(item);
|
|
1452
1562
|
}
|
|
1453
1563
|
recordNativeToolApprovalFailure(toolCallId, disposition, approvalKind) {
|
|
1454
1564
|
this.nativeToolLifecycleProjector.recordApprovalFailureDisposition(toolCallId, disposition);
|
|
@@ -1513,23 +1623,23 @@ var CodexAppServerEventProjector = class {
|
|
|
1513
1623
|
case "hook/completed":
|
|
1514
1624
|
this.eventProjection.handleHook(notification.method, params);
|
|
1515
1625
|
break;
|
|
1516
|
-
case "thread/tokenUsage/updated":
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
});
|
|
1626
|
+
case "thread/tokenUsage/updated": {
|
|
1627
|
+
const data = this.usageProjection.recordThread(params);
|
|
1628
|
+
if (data.modelContextWindow !== void 0) {
|
|
1629
|
+
this.contextTokens = data.modelContextWindow;
|
|
1630
|
+
this.contextTokensSource = this.params.authoredContextTokenCap === void 0 ? "runtime" : "runtime-configured";
|
|
1631
|
+
}
|
|
1632
|
+
if (Object.keys(data).length > 0) this.emitAgentEvent({
|
|
1633
|
+
stream: "usage",
|
|
1634
|
+
data
|
|
1526
1635
|
});
|
|
1527
1636
|
break;
|
|
1637
|
+
}
|
|
1528
1638
|
case "turn/completed":
|
|
1529
1639
|
await this.handleTurnCompleted(params);
|
|
1530
1640
|
break;
|
|
1531
1641
|
case "rawResponse/completed":
|
|
1532
|
-
this.
|
|
1642
|
+
this.usageProjection.record(params, this.params.hostCapabilities.reportOutputTokens);
|
|
1533
1643
|
break;
|
|
1534
1644
|
case "rawResponseItem/completed":
|
|
1535
1645
|
await this.handleRawResponseItemCompleted(params);
|
|
@@ -1539,17 +1649,19 @@ var CodexAppServerEventProjector = class {
|
|
|
1539
1649
|
this.eventProjection.handleModelRerouted(params);
|
|
1540
1650
|
break;
|
|
1541
1651
|
case "error": {
|
|
1542
|
-
this.
|
|
1652
|
+
this.usageProjection.invalidateContext();
|
|
1543
1653
|
if (params.willRetry === true) break;
|
|
1544
1654
|
const codexErrorInfo = isJsonObject(params.error) ? params.error.codexErrorInfo : void 0;
|
|
1655
|
+
const message = readCodexErrorNotificationMessage(params);
|
|
1545
1656
|
const compactionFailure = codexErrorInfo === "other" && this.isCompacting();
|
|
1546
1657
|
this.settledTurnFailureFinalizationAllowed = codexErrorInfo === "serverOverloaded" || compactionFailure;
|
|
1547
|
-
this.
|
|
1548
|
-
message
|
|
1658
|
+
this.terminalFailure.record({
|
|
1659
|
+
message,
|
|
1549
1660
|
codexErrorInfo,
|
|
1550
|
-
rateLimits: this.options.readRecentRateLimits?.()
|
|
1551
|
-
|
|
1552
|
-
|
|
1661
|
+
rateLimits: this.options.readRecentRateLimits?.(),
|
|
1662
|
+
fallbackMessage: "codex app-server error",
|
|
1663
|
+
promptErrorSource: compactionFailure ? "compaction" : "prompt"
|
|
1664
|
+
});
|
|
1553
1665
|
break;
|
|
1554
1666
|
}
|
|
1555
1667
|
case "thread/compacted":
|
|
@@ -1573,15 +1685,15 @@ var CodexAppServerEventProjector = class {
|
|
|
1573
1685
|
turnId: this.turnId,
|
|
1574
1686
|
upstreamUserText: this.options.upstreamUserText,
|
|
1575
1687
|
completedTurn: this.completedTurn,
|
|
1576
|
-
promptError: this.promptError,
|
|
1577
|
-
promptErrorSource: this.promptErrorSource,
|
|
1688
|
+
promptError: this.terminalFailure.promptError,
|
|
1689
|
+
promptErrorSource: this.terminalFailure.promptErrorSource,
|
|
1690
|
+
providerRefusal: this.terminalFailure.providerRefusal,
|
|
1578
1691
|
synthesizedMissingToolResultError: this.synthesizedMissingToolResultError,
|
|
1579
1692
|
recordSynthesizedMissingToolResultError: (error) => {
|
|
1580
1693
|
this.synthesizedMissingToolResultError = error;
|
|
1581
|
-
this.
|
|
1694
|
+
this.terminalFailure.promptErrorSource ??= "prompt";
|
|
1582
1695
|
},
|
|
1583
1696
|
aborted: this.aborted,
|
|
1584
|
-
tokenUsage: this.tokenUsage,
|
|
1585
1697
|
contextTokens: this.contextTokens,
|
|
1586
1698
|
contextTokensSource: this.contextTokensSource,
|
|
1587
1699
|
completedCompactionCount: this.completedCompactionCount,
|
|
@@ -1593,7 +1705,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1593
1705
|
nativeToolLifecycleProjection: this.nativeToolLifecycleProjector,
|
|
1594
1706
|
assistantProjection: this.assistantProjection,
|
|
1595
1707
|
reasoningProjection: this.reasoningProjection,
|
|
1596
|
-
|
|
1708
|
+
usageProjection: this.usageProjection,
|
|
1597
1709
|
toolTranscriptProjection: this.toolTranscriptProjection,
|
|
1598
1710
|
toolProgressProjection: this.toolProgressProjection,
|
|
1599
1711
|
generatedMediaProjection: this.generatedMediaProjection
|
|
@@ -1616,16 +1728,19 @@ var CodexAppServerEventProjector = class {
|
|
|
1616
1728
|
}
|
|
1617
1729
|
markTimedOut() {
|
|
1618
1730
|
this.aborted = true;
|
|
1619
|
-
this.promptError = "codex app-server attempt timed out";
|
|
1620
|
-
this.promptErrorSource = "prompt";
|
|
1731
|
+
this.terminalFailure.promptError = "codex app-server attempt timed out";
|
|
1732
|
+
this.terminalFailure.promptErrorSource = "prompt";
|
|
1621
1733
|
}
|
|
1622
1734
|
markAborted() {
|
|
1623
1735
|
this.aborted = true;
|
|
1624
|
-
this.
|
|
1736
|
+
this.usageProjection.invalidateContext();
|
|
1625
1737
|
}
|
|
1626
1738
|
isCompacting() {
|
|
1627
1739
|
return this.activeCompactionItemIds.size > 0;
|
|
1628
1740
|
}
|
|
1741
|
+
isCompactionProjectionActive() {
|
|
1742
|
+
return !this.projectionClosed && !this.aborted && !this.options.runAbortSignal?.aborted;
|
|
1743
|
+
}
|
|
1629
1744
|
async handleItemStarted(params) {
|
|
1630
1745
|
const item = readItem(params.item);
|
|
1631
1746
|
const itemId = item?.id ?? readStringField(params, "itemId");
|
|
@@ -1633,12 +1748,16 @@ var CodexAppServerEventProjector = class {
|
|
|
1633
1748
|
if (itemId) this.activeItemIds.add(itemId);
|
|
1634
1749
|
this.recordNativeToolOutcome(item);
|
|
1635
1750
|
if (item?.type === "contextCompaction" && itemId) {
|
|
1751
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1636
1752
|
this.activeCompactionItemIds.add(itemId);
|
|
1753
|
+
const messages = await this.toolTranscriptProjection.readMirroredSessionMessages(this.options.runAbortSignal);
|
|
1754
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1637
1755
|
await runAgentHarnessBeforeCompactionHook({
|
|
1638
1756
|
sessionFile: this.params.sessionFile,
|
|
1639
|
-
messages
|
|
1757
|
+
messages,
|
|
1640
1758
|
ctx: this.options.agentHookContext ?? {}
|
|
1641
1759
|
});
|
|
1760
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1642
1761
|
this.emitAgentEvent({
|
|
1643
1762
|
stream: "compaction",
|
|
1644
1763
|
data: {
|
|
@@ -1675,7 +1794,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1675
1794
|
const item = readItem(params.item);
|
|
1676
1795
|
this.diagnostics.warnUnknownItemStatus(item);
|
|
1677
1796
|
this.recordNativeToolOutcome(item);
|
|
1678
|
-
this.clearTerminalPresentationForNativeItem(item);
|
|
1797
|
+
this.nativeToolLifecycleProjector.clearTerminalPresentationForNativeItem(item);
|
|
1679
1798
|
const itemId = item?.id ?? readStringField(params, "itemId");
|
|
1680
1799
|
if (itemId) {
|
|
1681
1800
|
this.activeItemIds.delete(itemId);
|
|
@@ -1689,17 +1808,20 @@ var CodexAppServerEventProjector = class {
|
|
|
1689
1808
|
await this.generatedMediaProjection.recordNative(item);
|
|
1690
1809
|
if (this.projectionClosed) return;
|
|
1691
1810
|
if (item?.type === "contextCompaction" && itemId) {
|
|
1811
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1692
1812
|
this.activeCompactionItemIds.delete(itemId);
|
|
1693
1813
|
this.completedCompactionCount += 1;
|
|
1694
1814
|
await this.options.onContextCompacted?.();
|
|
1695
|
-
if (this.
|
|
1815
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1816
|
+
const messages = await this.toolTranscriptProjection.readMirroredSessionMessages(this.options.runAbortSignal);
|
|
1817
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1696
1818
|
await runAgentHarnessAfterCompactionHook({
|
|
1697
1819
|
sessionFile: this.params.sessionFile,
|
|
1698
|
-
messages
|
|
1820
|
+
messages,
|
|
1699
1821
|
compactedCount: -1,
|
|
1700
1822
|
ctx: this.options.agentHookContext ?? {}
|
|
1701
1823
|
});
|
|
1702
|
-
if (this.
|
|
1824
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1703
1825
|
await persistCodexContextCompactionActivity({
|
|
1704
1826
|
sessionTarget: this.params.sessionTarget,
|
|
1705
1827
|
config: this.params.config,
|
|
@@ -1710,6 +1832,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1710
1832
|
itemId,
|
|
1711
1833
|
timestamp: this.transcriptCheckpoint.nextTimestamp()
|
|
1712
1834
|
});
|
|
1835
|
+
if (!this.isCompactionProjectionActive()) return;
|
|
1713
1836
|
this.eventProjection.emitCompactionEnd(itemId, true);
|
|
1714
1837
|
}
|
|
1715
1838
|
this.toolProgressProjection.recordToolMeta(item);
|
|
@@ -1724,8 +1847,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1724
1847
|
});
|
|
1725
1848
|
if (this.projectionClosed) return;
|
|
1726
1849
|
this.toolTranscriptProjection.recordNativeToolCall(item);
|
|
1727
|
-
await this.toolTranscriptProjection.
|
|
1850
|
+
const details = await this.toolTranscriptProjection.prepareNativeToolResultDetails(item);
|
|
1728
1851
|
if (this.projectionClosed) return;
|
|
1852
|
+
this.toolTranscriptProjection.recordNativeToolResult(item, details);
|
|
1729
1853
|
this.toolProgressProjection.emitToolResultSummary(item);
|
|
1730
1854
|
this.toolProgressProjection.emitToolResultOutput(item);
|
|
1731
1855
|
this.emitAgentEvent({
|
|
@@ -1741,16 +1865,18 @@ var CodexAppServerEventProjector = class {
|
|
|
1741
1865
|
const turn = readCodexTurn(params.turn);
|
|
1742
1866
|
if (!turn || turn.id !== this.turnId) return;
|
|
1743
1867
|
this.completedTurn = turn;
|
|
1744
|
-
const compactionFailure = turn.status === "failed" && (this.promptErrorSource === "compaction" || turn.error?.codexErrorInfo === "other" && this.isCompacting());
|
|
1868
|
+
const compactionFailure = turn.status === "failed" && (this.terminalFailure.promptErrorSource === "compaction" || turn.error?.codexErrorInfo === "other" && this.isCompacting());
|
|
1745
1869
|
this.settledTurnFailureFinalizationAllowed = turn.status === "failed" && (turn.error?.codexErrorInfo === "serverOverloaded" || compactionFailure);
|
|
1746
|
-
if (turn.status !== "completed") this.
|
|
1870
|
+
if (turn.status !== "completed") this.usageProjection.invalidateContext();
|
|
1747
1871
|
if (turn.status === "failed") {
|
|
1748
|
-
|
|
1872
|
+
const codexErrorInfo = turn.error?.codexErrorInfo;
|
|
1873
|
+
this.terminalFailure.record({
|
|
1749
1874
|
message: turn.error?.message,
|
|
1750
|
-
codexErrorInfo
|
|
1751
|
-
rateLimits: this.options.readRecentRateLimits?.()
|
|
1752
|
-
|
|
1753
|
-
|
|
1875
|
+
codexErrorInfo,
|
|
1876
|
+
rateLimits: this.options.readRecentRateLimits?.(),
|
|
1877
|
+
fallbackMessage: "codex app-server turn failed",
|
|
1878
|
+
promptErrorSource: compactionFailure ? "compaction" : "prompt"
|
|
1879
|
+
});
|
|
1754
1880
|
}
|
|
1755
1881
|
if (compactionFailure) {
|
|
1756
1882
|
const failedCompactionItemIds = [...this.activeCompactionItemIds];
|
|
@@ -1763,7 +1889,7 @@ var CodexAppServerEventProjector = class {
|
|
|
1763
1889
|
const turnItems = turn.items ?? [];
|
|
1764
1890
|
const unsettledAsyncDeliveries = this.asyncDeliveryProjection.pending();
|
|
1765
1891
|
const lastToolItem = turnItems.findLast((item) => matchesCodexSnapshotTurn(item, this.turnId) && (item.type === "dynamicToolCall" || shouldClearTerminalPresentationForNativeItem(item)));
|
|
1766
|
-
if (lastToolItem?.type !== "dynamicToolCall") this.clearTerminalPresentationForNativeItem(lastToolItem);
|
|
1892
|
+
if (lastToolItem?.type !== "dynamicToolCall") this.nativeToolLifecycleProjector.clearTerminalPresentationForNativeItem(lastToolItem);
|
|
1767
1893
|
for (const item of turnItems) {
|
|
1768
1894
|
if (!this.asyncDeliveryProjection.allows(item)) continue;
|
|
1769
1895
|
this.diagnostics.warnUnknownItemStatus(item);
|
|
@@ -1778,8 +1904,9 @@ var CodexAppServerEventProjector = class {
|
|
|
1778
1904
|
await this.emitSnapshotOnlyNativeToolProgress(item);
|
|
1779
1905
|
if (this.projectionClosed) return;
|
|
1780
1906
|
this.toolTranscriptProjection.recordNativeToolCall(item);
|
|
1781
|
-
await this.toolTranscriptProjection.
|
|
1907
|
+
const details = await this.toolTranscriptProjection.prepareNativeToolResultDetails(item);
|
|
1782
1908
|
if (this.projectionClosed) return;
|
|
1909
|
+
this.toolTranscriptProjection.recordNativeToolResult(item, details);
|
|
1783
1910
|
this.toolTranscriptProjection.emitAfterToolCallObservation(item);
|
|
1784
1911
|
this.toolProgressProjection.emitToolResultSummary(item);
|
|
1785
1912
|
this.toolProgressProjection.emitToolResultOutput(item);
|
|
@@ -1825,19 +1952,6 @@ var CodexAppServerEventProjector = class {
|
|
|
1825
1952
|
this.assistantProjection.handleRawResponseItemCompleted(item, this.activeItemIds);
|
|
1826
1953
|
await this.generatedMediaProjection.recordRaw(item);
|
|
1827
1954
|
}
|
|
1828
|
-
clearTerminalPresentationForNativeItem(item) {
|
|
1829
|
-
if (!item || this.terminalPresentationClearedItemIds.has(item.id) || !shouldClearTerminalPresentationForNativeItem(item)) return;
|
|
1830
|
-
const toolCallOrdinal = this.nativeToolOutcomeOrdinals.get(item.id);
|
|
1831
|
-
this.terminalPresentationClearedItemIds.add(item.id);
|
|
1832
|
-
this.params.onToolOutcome?.({
|
|
1833
|
-
toolName: itemName(item) ?? item.type,
|
|
1834
|
-
argsHash: "",
|
|
1835
|
-
resultHash: "",
|
|
1836
|
-
...toolCallOrdinal !== void 0 ? { toolCallOrdinal } : {},
|
|
1837
|
-
terminalPresentation: void 0,
|
|
1838
|
-
presentationOnly: true
|
|
1839
|
-
});
|
|
1840
|
-
}
|
|
1841
1955
|
emitAgentEvent(event) {
|
|
1842
1956
|
if (!this.projectionClosed) emitCodexAgentEvent(this.params, event);
|
|
1843
1957
|
}
|
|
@@ -2107,7 +2221,6 @@ const MAX_USER_INPUT_HEADER = 64;
|
|
|
2107
2221
|
const MAX_USER_INPUT_TEXT = 4096;
|
|
2108
2222
|
/** Creates the single per-turn owner for Codex operator input. */
|
|
2109
2223
|
function createCodexUserInputBridge(params) {
|
|
2110
|
-
const gatewayCall = params.gatewayCall ?? callGatewayTool;
|
|
2111
2224
|
const jobs = [];
|
|
2112
2225
|
let activeCompletion;
|
|
2113
2226
|
const inputSessionKey = params.paramsForRun.sessionKey ?? params.paramsForRun.sessionId;
|
|
@@ -2158,7 +2271,7 @@ function createCodexUserInputBridge(params) {
|
|
|
2158
2271
|
agentId: params.paramsForRun.agentId,
|
|
2159
2272
|
runId: params.paramsForRun.runId,
|
|
2160
2273
|
timeoutMs,
|
|
2161
|
-
gatewayCall,
|
|
2274
|
+
gatewayCall: params.gatewayCall,
|
|
2162
2275
|
delivery: params.paramsForRun,
|
|
2163
2276
|
signal,
|
|
2164
2277
|
promptOptions: {
|
|
@@ -2350,6 +2463,22 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2350
2463
|
const { emitExecutionPhaseOnce, emitLifecycleStart, maybeAnnounceFastModeAutoOff } = lifecycle;
|
|
2351
2464
|
const { enqueueNotification } = notifications;
|
|
2352
2465
|
const activeTurnId = turn.turn.id;
|
|
2466
|
+
const { thread } = resourceState;
|
|
2467
|
+
const runtimeModelSelection = thread.preserveNativeModel && thread.model && thread.modelProvider ? {
|
|
2468
|
+
provider: thread.modelProvider,
|
|
2469
|
+
model: thread.model
|
|
2470
|
+
} : void 0;
|
|
2471
|
+
const projectionParams = runtimeModelSelection ? {
|
|
2472
|
+
...dynamicToolParams,
|
|
2473
|
+
provider: runtimeModelSelection.provider,
|
|
2474
|
+
modelId: runtimeModelSelection.model,
|
|
2475
|
+
model: {
|
|
2476
|
+
...dynamicToolParams.model,
|
|
2477
|
+
id: runtimeModelSelection.model,
|
|
2478
|
+
name: runtimeModelSelection.model,
|
|
2479
|
+
provider: runtimeModelSelection.provider
|
|
2480
|
+
}
|
|
2481
|
+
} : dynamicToolParams;
|
|
2353
2482
|
const progressCardTool = toolBridge.availableTools.find((tool) => tool.name === "progress_card");
|
|
2354
2483
|
let nativePlanUpdateOrdinal = 0;
|
|
2355
2484
|
const prepareNativeMcpAppResultDetails = createCodexNativeMcpAppResultDetailsPreparer({
|
|
@@ -2375,7 +2504,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2375
2504
|
imagesCount: params.images?.length ?? 0
|
|
2376
2505
|
});
|
|
2377
2506
|
projectorRef.current = new CodexAppServerEventProjector({
|
|
2378
|
-
...
|
|
2507
|
+
...projectionParams,
|
|
2379
2508
|
onAgentEvent: (event) => {
|
|
2380
2509
|
if (event.stream === "assistant" && typeof event.data.delta === "string") {
|
|
2381
2510
|
streamState.eventEmitted = true;
|
|
@@ -2390,7 +2519,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2390
2519
|
asyncUserMessageAllowed: params.disableTools !== true && (params.toolsAllow === void 0 || toolBridge.availableTools.some((tool) => tool.name === "message")),
|
|
2391
2520
|
onAsyncDelivery: async (delivery) => {
|
|
2392
2521
|
return await codexTranscriptMirrorRuntime.deliverAsyncMessageBestEffort({
|
|
2393
|
-
params:
|
|
2522
|
+
params: projectionParams,
|
|
2394
2523
|
cwd: effectiveCwd,
|
|
2395
2524
|
threadId: resourceState.thread.threadId,
|
|
2396
2525
|
turnId: activeTurnId,
|
|
@@ -2510,7 +2639,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2510
2639
|
}
|
|
2511
2640
|
};
|
|
2512
2641
|
const assertSteeringActive = () => {
|
|
2513
|
-
|
|
2642
|
+
connection.assertCurrent();
|
|
2514
2643
|
runAbortController.signal.throwIfAborted();
|
|
2515
2644
|
if (state.completed || state.terminalTurnNotificationQueued) throw new Error("codex app-server turn is no longer accepting steering");
|
|
2516
2645
|
};
|
|
@@ -2577,36 +2706,52 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2577
2706
|
}
|
|
2578
2707
|
});
|
|
2579
2708
|
steeringQueueRef.current = activeSteeringQueue;
|
|
2580
|
-
const
|
|
2709
|
+
const injectionGuard = (assertCurrent) => () => {
|
|
2710
|
+
assertCurrent?.();
|
|
2711
|
+
assertSteeringActive();
|
|
2712
|
+
return true;
|
|
2713
|
+
};
|
|
2714
|
+
const claimPendingUserInputAnswer = async (text, optionsLocal, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => {
|
|
2581
2715
|
if (optionsLocal?.isInboundUserMessage !== true || hasPromptImageInput(optionsLocal)) return false;
|
|
2582
2716
|
assertSteeringActive();
|
|
2583
2717
|
return await claimPendingAgentQuestionAnswer({
|
|
2584
2718
|
sessionKey: params.sessionKey ?? params.sessionId,
|
|
2585
2719
|
text,
|
|
2720
|
+
authority: {
|
|
2721
|
+
kind: authorityKind,
|
|
2722
|
+
assertCurrent: injectionGuard(assertCurrent)
|
|
2723
|
+
},
|
|
2586
2724
|
persist: optionsLocal.userTurnTranscriptRecorder ? async () => {
|
|
2587
2725
|
await optionsLocal.userTurnTranscriptRecorder?.persistApproved();
|
|
2588
2726
|
} : void 0
|
|
2589
2727
|
});
|
|
2590
2728
|
};
|
|
2591
|
-
const cancelPendingUserInput = (resolvedBy) => cancelPendingAgentQuestionForSession({
|
|
2729
|
+
const cancelPendingUserInput = (resolvedBy, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => cancelPendingAgentQuestionForSession({
|
|
2592
2730
|
sessionKey: params.sessionKey ?? params.sessionId,
|
|
2593
|
-
resolvedBy
|
|
2731
|
+
resolvedBy,
|
|
2732
|
+
authority: {
|
|
2733
|
+
kind: authorityKind,
|
|
2734
|
+
assertCurrent: injectionGuard(assertCurrent)
|
|
2735
|
+
}
|
|
2594
2736
|
});
|
|
2595
|
-
const queueMessage = async (text, optionsLocal) => {
|
|
2596
|
-
|
|
2737
|
+
const queueMessage = async (text, optionsLocal, assertCurrent, authorityKind = assertCurrent ? "source-bound" : "run") => {
|
|
2738
|
+
const canClaim = injectionGuard(assertCurrent);
|
|
2739
|
+
if (await claimPendingUserInputAnswer(text, optionsLocal, assertCurrent, authorityKind)) {
|
|
2597
2740
|
optionsLocal?.onQueueAccepted?.(true);
|
|
2598
2741
|
return;
|
|
2599
2742
|
}
|
|
2600
2743
|
if (optionsLocal?.isInboundUserMessage === true && hasPromptImageInput(optionsLocal)) {
|
|
2601
2744
|
assertSteeringActive();
|
|
2602
2745
|
try {
|
|
2603
|
-
await cancelPendingUserInput("image-reply");
|
|
2746
|
+
await cancelPendingUserInput("image-reply", assertCurrent, authorityKind);
|
|
2604
2747
|
} catch (error) {
|
|
2748
|
+
canClaim();
|
|
2749
|
+
if (error instanceof Error && error.name === "QuestionDispatchRefusedError") throw error;
|
|
2605
2750
|
embeddedAgentLog.warn("failed to cancel codex gateway question before image steering", { error });
|
|
2606
2751
|
}
|
|
2607
2752
|
}
|
|
2608
2753
|
try {
|
|
2609
|
-
await activeSteeringQueue.queue(text, optionsLocal);
|
|
2754
|
+
await activeSteeringQueue.queue(text, optionsLocal, injectionGuard(assertCurrent));
|
|
2610
2755
|
} catch (error) {
|
|
2611
2756
|
if (error instanceof CodexSteeringAcceptedUnconfirmedError) return {
|
|
2612
2757
|
transcriptCommit: "unconfirmed",
|
|
@@ -2615,6 +2760,13 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2615
2760
|
throw error;
|
|
2616
2761
|
}
|
|
2617
2762
|
};
|
|
2763
|
+
const messageInjection = {
|
|
2764
|
+
version: 2,
|
|
2765
|
+
isAvailable: () => !state.completed && !state.terminalTurnNotificationQueued && !runAbortController.signal.aborted,
|
|
2766
|
+
queueMessage,
|
|
2767
|
+
claimPendingUserInputAnswer,
|
|
2768
|
+
cancelPendingUserInput
|
|
2769
|
+
};
|
|
2618
2770
|
const handle = {
|
|
2619
2771
|
kind: "embedded",
|
|
2620
2772
|
runId: params.runId,
|
|
@@ -2632,10 +2784,8 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2632
2784
|
claimPendingUserInputAnswer,
|
|
2633
2785
|
cancelPendingUserInput,
|
|
2634
2786
|
queueMessage,
|
|
2635
|
-
messageInjection
|
|
2636
|
-
|
|
2637
|
-
queueMessage
|
|
2638
|
-
},
|
|
2787
|
+
messageInjection,
|
|
2788
|
+
messageInjectionV2: messageInjection,
|
|
2639
2789
|
isStreaming: () => !state.completed && !runAbortController.signal.aborted,
|
|
2640
2790
|
isAborted: () => runAbortController.signal.aborted,
|
|
2641
2791
|
isStopped: () => state.completed || runAbortController.signal.aborted,
|
|
@@ -2663,6 +2813,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
|
|
|
2663
2813
|
return {
|
|
2664
2814
|
activeTurnId,
|
|
2665
2815
|
activeProjector,
|
|
2816
|
+
runtimeModelSelection,
|
|
2666
2817
|
streamState,
|
|
2667
2818
|
handle,
|
|
2668
2819
|
freezeRunTerminalOutcome,
|
|
@@ -2708,8 +2859,8 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2708
2859
|
});
|
|
2709
2860
|
await runCleanupStep("codex-trajectory-flush", () => trajectoryRecorder?.flush());
|
|
2710
2861
|
const retainLiveIncognitoThread = (terminalState.turnSucceeded || state.permissionChangeRestart === "confirmed" && !params.abortSignal?.aborted) && isIncognitoSessionKey(params.sessionKey);
|
|
2711
|
-
const retainLiveThread = ((retainLiveIncognitoThread && resourceState.thread.liveThreadEphemeralPolicy !== void 0 || terminalState.turnSucceeded && !isIncognitoSessionKey(params.sessionKey) && params.cleanupBundleMcpOnRunEnd !== true && resourceState.thread.liveThreadConfigFingerprint !== void 0 && resourceState.thread.preserveNativeModel !== true && resourceState.thread.connectionScope !== "supervision" && !resourceState.thread.ringZeroConfigFingerprint) && resourceState.thread.clientId === resolveCodexAppServerClientInstanceId(resourceState.client) ?
|
|
2712
|
-
if (
|
|
2862
|
+
const retainLiveThread = ((retainLiveIncognitoThread && resourceState.thread.liveThreadEphemeralPolicy !== void 0 || terminalState.turnSucceeded && !isIncognitoSessionKey(params.sessionKey) && params.cleanupBundleMcpOnRunEnd !== true && resourceState.thread.liveThreadConfigFingerprint !== void 0 && resourceState.thread.preserveNativeModel !== true && resourceState.thread.connectionScope !== "supervision" && !resourceState.thread.ringZeroConfigFingerprint) && resourceState.thread.clientId === resolveCodexAppServerClientInstanceId(resourceState.client) ? bindingStore.read(bindingIdentity)?.threadId === resourceState.thread.threadId && await bindingStore.withLease(bindingIdentity, async () => {
|
|
2863
|
+
if (bindingStore.read(bindingIdentity)?.threadId !== resourceState.thread.threadId) return false;
|
|
2713
2864
|
return await retainCodexAppServerBindingSubscription(resourceState.client, resourceState.thread.threadId, {
|
|
2714
2865
|
release: resourceState.thread.liveThreadOwnership?.release,
|
|
2715
2866
|
configFingerprint: resourceState.thread.liveThreadConfigFingerprint,
|
|
@@ -2751,8 +2902,6 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
|
|
|
2751
2902
|
else nativeHookRelay.unregister();
|
|
2752
2903
|
});
|
|
2753
2904
|
await runCleanupStep("codex-sandbox-release", releaseSandboxExecEnvironment);
|
|
2754
|
-
await runCleanupStep("codex-scoped-mcp-dispose", () => prompt.context.attemptTools.scopedMcpTools?.dispose());
|
|
2755
|
-
await runCleanupStep("codex-configured-mcp-dispose", () => prompt.context.attemptTools.configuredMcp?.dispose());
|
|
2756
2905
|
await runCleanupStep("codex-abort-listener-remove", () => {
|
|
2757
2906
|
runAbortController.signal.removeEventListener("abort", abortListener);
|
|
2758
2907
|
});
|
|
@@ -2995,8 +3144,9 @@ async function readCodexAppServerRolloutTokenSnapshot(file, openedHandle) {
|
|
|
2995
3144
|
bytesRead += result.bytesRead;
|
|
2996
3145
|
}
|
|
2997
3146
|
let lineEnd = bytesRead;
|
|
2998
|
-
|
|
2999
|
-
|
|
3147
|
+
while (lineEnd > 0) {
|
|
3148
|
+
const index = chunk.lastIndexOf(10, lineEnd - 1);
|
|
3149
|
+
if (index < 0) break;
|
|
3000
3150
|
const lineFragment = chunk.subarray(index + 1, lineEnd);
|
|
3001
3151
|
const line = partialLineFragments.length === 0 ? lineFragment.toString("utf8") : Buffer.concat([lineFragment, ...partialLineFragments.toReversed()]).toString("utf8");
|
|
3002
3152
|
partialLineFragments.length = 0;
|
|
@@ -3078,6 +3228,7 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3078
3228
|
await Promise.all(rolloutFiles.map(async (file) => {
|
|
3079
3229
|
await file.handle?.close();
|
|
3080
3230
|
}));
|
|
3231
|
+
assertCodexBindingMayBeReplaced(binding, "rotating an oversized native transcript", params.expectedSessionRuntimeOwnership);
|
|
3081
3232
|
embeddedAgentLog.warn("codex app-server native transcript exceeded active byte limit; starting a fresh thread", {
|
|
3082
3233
|
threadId: binding.threadId,
|
|
3083
3234
|
maxBytes,
|
|
@@ -3089,7 +3240,7 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3089
3240
|
await params.bindingStore.mutate(params.identity, {
|
|
3090
3241
|
kind: "clear",
|
|
3091
3242
|
threadId: binding.threadId
|
|
3092
|
-
});
|
|
3243
|
+
}, params.assertCurrent);
|
|
3093
3244
|
return { binding: void 0 };
|
|
3094
3245
|
}
|
|
3095
3246
|
}
|
|
@@ -3106,6 +3257,7 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3106
3257
|
const sessionTokens = sessionRecord?.totalTokensFresh === true && sessionRecord.totalTokensVersion === 1 && typeof sessionRecord?.totalTokens === "number" && Number.isFinite(sessionRecord.totalTokens) ? sessionRecord.totalTokens : void 0;
|
|
3107
3258
|
const tokenCount = maxFiniteNumber([sessionTokens, nativeTokens]);
|
|
3108
3259
|
if (tokenCount !== void 0 && tokenCount >= maxTokens) {
|
|
3260
|
+
assertCodexBindingMayBeReplaced(binding, "rotating a full native context", params.expectedSessionRuntimeOwnership);
|
|
3109
3261
|
embeddedAgentLog.warn("codex app-server native transcript exceeded active token limit; starting a fresh thread", {
|
|
3110
3262
|
threadId: binding.threadId,
|
|
3111
3263
|
maxTokens,
|
|
@@ -3120,7 +3272,7 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
|
|
|
3120
3272
|
await params.bindingStore.mutate(params.identity, {
|
|
3121
3273
|
kind: "clear",
|
|
3122
3274
|
threadId: binding.threadId
|
|
3123
|
-
});
|
|
3275
|
+
}, params.assertCurrent);
|
|
3124
3276
|
return { binding: void 0 };
|
|
3125
3277
|
}
|
|
3126
3278
|
const startupContextTokens = nativeModelContextWindow ?? sessionModelContextWindow;
|
|
@@ -3142,7 +3294,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3142
3294
|
offAnnounced: false,
|
|
3143
3295
|
resetAnnounced: false
|
|
3144
3296
|
};
|
|
3145
|
-
const preDynamicStartupStages = createCodexDynamicToolBuildStageTracker(
|
|
3297
|
+
const preDynamicStartupStages = createCodexDynamicToolBuildStageTracker();
|
|
3146
3298
|
const runtimeArtifactRequest = params.captureRuntimeArtifact || params.expectedRuntimeArtifact ? params.expectedRuntimeArtifact ? { expected: params.expectedRuntimeArtifact } : {} : void 0;
|
|
3147
3299
|
const pluginConfig = readCodexPluginConfig(options.pluginConfig);
|
|
3148
3300
|
const requirementsToml = readCodexRequirementsToml({});
|
|
@@ -3174,7 +3326,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3174
3326
|
config: params.config,
|
|
3175
3327
|
agentId: policyAgentId
|
|
3176
3328
|
});
|
|
3177
|
-
const agentDir = params.agentDir ?? resolveAgentDir$
|
|
3329
|
+
const agentDir = params.agentDir ?? resolveAgentDir$2(params.config ?? {}, sessionAgentId);
|
|
3178
3330
|
const preparedEnvironment = params.hostCapabilities.preparedEnvironment?.();
|
|
3179
3331
|
const remoteExec = isCodexRemoteExecPlacementSandbox(sandbox);
|
|
3180
3332
|
const assertLocalTargetSupported = (unsupported) => {
|
|
@@ -3233,16 +3385,17 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3233
3385
|
bindingIdentity = physicalIdentity;
|
|
3234
3386
|
}
|
|
3235
3387
|
}
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
}
|
|
3388
|
+
const { binding: admittedBinding, assertCurrent } = await resolveCodexSessionBinding({
|
|
3389
|
+
reclaimStale: true,
|
|
3390
|
+
bindingStore,
|
|
3391
|
+
identity: bindingIdentity,
|
|
3392
|
+
config: params.config,
|
|
3393
|
+
storePath: params.sessionTarget?.storePath,
|
|
3394
|
+
assertCurrent: params.hostCapabilities.assertActive,
|
|
3395
|
+
signal: params.abortSignal,
|
|
3396
|
+
assertBinding: params.expectedSessionRuntimeOwnership ? (binding) => assertCodexSessionRuntimeOwnership(binding, params.expectedSessionRuntimeOwnership) : void 0
|
|
3397
|
+
});
|
|
3398
|
+
let startupBinding = admittedBinding;
|
|
3246
3399
|
preDynamicStartupStages.mark("read-binding");
|
|
3247
3400
|
const usesSupervisionConnection = startupBinding?.connectionScope === "supervision";
|
|
3248
3401
|
if (usesSupervisionConnection) activeContextEngine = void 0;
|
|
@@ -3393,104 +3546,113 @@ async function prepareCodexAttemptConnection({ params, options }) {
|
|
|
3393
3546
|
};
|
|
3394
3547
|
if (params.abortSignal?.aborted) abortFromUpstream();
|
|
3395
3548
|
else params.abortSignal?.addEventListener("abort", abortFromUpstream, { once: true });
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
(
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3468
|
-
|
|
3469
|
-
|
|
3470
|
-
|
|
3471
|
-
|
|
3472
|
-
|
|
3473
|
-
|
|
3474
|
-
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
|
|
3481
|
-
|
|
3482
|
-
|
|
3483
|
-
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3549
|
+
try {
|
|
3550
|
+
const startupBindingBeforeRotation = startupBinding;
|
|
3551
|
+
const startupBindingResolution = await rotateOversizedCodexAppServerStartupBinding({
|
|
3552
|
+
assertCurrent,
|
|
3553
|
+
binding: startupBinding,
|
|
3554
|
+
bindingStore,
|
|
3555
|
+
identity: bindingIdentity,
|
|
3556
|
+
sessionFile: params.sessionFile,
|
|
3557
|
+
agentDir,
|
|
3558
|
+
codexHome: appServer.start.env?.CODEX_HOME,
|
|
3559
|
+
config: params.config,
|
|
3560
|
+
contextEngineActive: Boolean(activeContextEngine),
|
|
3561
|
+
expectedSessionRuntimeOwnership: params.expectedSessionRuntimeOwnership
|
|
3562
|
+
});
|
|
3563
|
+
startupBinding = startupBindingResolution.binding;
|
|
3564
|
+
const initialInactiveThreadBootstrapBindingForcedFreshStart = initialStartupBindingHadInactiveThreadBootstrap && !startupBinding?.threadId;
|
|
3565
|
+
preDynamicStartupStages.mark("rotate-binding");
|
|
3566
|
+
if (startupBinding !== startupBindingBeforeRotation) {
|
|
3567
|
+
reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
|
|
3568
|
+
configuredAppServer = resolveRuntimeOptionsForBinding(startupBinding, {
|
|
3569
|
+
modelProvider: reviewerPolicyContext.modelProvider,
|
|
3570
|
+
model: reviewerPolicyContext.model
|
|
3571
|
+
});
|
|
3572
|
+
resolvedAppServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
|
|
3573
|
+
appServer = resolvedAppServer.appServer;
|
|
3574
|
+
}
|
|
3575
|
+
const sessionPermissionPolicy = resolveCodexEffectiveSessionPermissionPolicy({
|
|
3576
|
+
appServer,
|
|
3577
|
+
permissionMode: params.permissionMode,
|
|
3578
|
+
sessionRoot: params.sessionRoot,
|
|
3579
|
+
defaultRoot: effectiveWorkspace
|
|
3580
|
+
});
|
|
3581
|
+
if (sessionPermissionPolicy) {
|
|
3582
|
+
params.permissionMode = sessionPermissionPolicy.mode;
|
|
3583
|
+
params.sessionRoot = sessionPermissionPolicy.root;
|
|
3584
|
+
(params.execOverrides ??= {}).mode = sessionPermissionPolicy.execMode;
|
|
3585
|
+
}
|
|
3586
|
+
const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
|
|
3587
|
+
configuredEvents: options.nativeHookRelay?.events,
|
|
3588
|
+
appServer
|
|
3589
|
+
});
|
|
3590
|
+
const mutable = {
|
|
3591
|
+
startupBinding,
|
|
3592
|
+
startupContextTokens: startupBindingResolution.startupContextTokens,
|
|
3593
|
+
pluginAppServer: appServer,
|
|
3594
|
+
continuityCalibration: startupBindingBeforeRotation?.continuityCalibration
|
|
3595
|
+
};
|
|
3596
|
+
const resolveRuntimeOptionsForCurrentBinding = (selection) => resolveFinalAppServer(resolveRuntimeOptionsForBinding(mutable.startupBinding, selection), selection).appServer;
|
|
3597
|
+
assertCurrent();
|
|
3598
|
+
return {
|
|
3599
|
+
params,
|
|
3600
|
+
assertCurrent,
|
|
3601
|
+
options,
|
|
3602
|
+
attemptStartedAt,
|
|
3603
|
+
profilerEnabled,
|
|
3604
|
+
codexModelCallTrace,
|
|
3605
|
+
codexModelContentCapture,
|
|
3606
|
+
codexModelCallId,
|
|
3607
|
+
fastModeAutoStartedAtMs,
|
|
3608
|
+
fastModeAutoProgressState,
|
|
3609
|
+
preDynamicStartupStages,
|
|
3610
|
+
attemptClientFactory,
|
|
3611
|
+
runtimeArtifactRequest,
|
|
3612
|
+
pluginConfig,
|
|
3613
|
+
computerUseConfig,
|
|
3614
|
+
sessionAgentId,
|
|
3615
|
+
policyAgentId,
|
|
3616
|
+
resolvedWorkspace,
|
|
3617
|
+
sandboxSessionKey,
|
|
3618
|
+
contextSessionKey,
|
|
3619
|
+
sandbox,
|
|
3620
|
+
agentDir,
|
|
3621
|
+
shellEnvironment,
|
|
3622
|
+
disableLoginShell,
|
|
3623
|
+
bindingIdentity,
|
|
3624
|
+
bindingStore,
|
|
3625
|
+
activeContextEngine,
|
|
3626
|
+
isInactiveThreadBootstrapBinding,
|
|
3627
|
+
usesSupervisionConnection,
|
|
3628
|
+
startupAuthProfileId,
|
|
3629
|
+
startupAuthRequirement: preparedAuthRoute?.authRequirement,
|
|
3630
|
+
startupPreparedAuth,
|
|
3631
|
+
startupClientAuthProfileId,
|
|
3632
|
+
effectiveWorkspace,
|
|
3633
|
+
effectiveCwd,
|
|
3634
|
+
appServer,
|
|
3635
|
+
sessionPermissionPolicy,
|
|
3636
|
+
nativeHookRelayEvents,
|
|
3637
|
+
runAbortController,
|
|
3638
|
+
terminalState,
|
|
3639
|
+
abortExplicitly,
|
|
3640
|
+
abortFromUpstream,
|
|
3641
|
+
resolveReviewerPolicyContext,
|
|
3642
|
+
resolveRuntimeOptionsForCurrentBinding,
|
|
3643
|
+
mutable,
|
|
3644
|
+
initialStartupBindingHadInactiveThreadBootstrap,
|
|
3645
|
+
initialInactiveThreadBootstrapBindingForcedFreshStart
|
|
3646
|
+
};
|
|
3647
|
+
} catch (error) {
|
|
3648
|
+
params.abortSignal?.removeEventListener("abort", abortFromUpstream);
|
|
3649
|
+
throw error;
|
|
3650
|
+
}
|
|
3489
3651
|
}
|
|
3490
3652
|
//#endregion
|
|
3491
3653
|
//#region extensions/codex/src/app-server/run-attempt-state.ts
|
|
3492
|
-
async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields) {
|
|
3493
|
-
const currentBinding =
|
|
3654
|
+
async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields, expected) {
|
|
3655
|
+
const currentBinding = bindingStore.read(identity);
|
|
3494
3656
|
const expectedThreadId = fields.threadId ?? currentBinding?.threadId;
|
|
3495
3657
|
if (!expectedThreadId) return;
|
|
3496
3658
|
if (currentBinding && currentBinding.threadId !== expectedThreadId) {
|
|
@@ -3500,8 +3662,8 @@ async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity,
|
|
|
3500
3662
|
});
|
|
3501
3663
|
return;
|
|
3502
3664
|
}
|
|
3503
|
-
if (currentBinding?.connectionScope === "supervision") {
|
|
3504
|
-
embeddedAgentLog.warn("codex app-server image payload error detected for
|
|
3665
|
+
if (expected || currentBinding?.connectionScope === "supervision") {
|
|
3666
|
+
embeddedAgentLog.warn("codex app-server image payload error detected for native-owned thread; preserving binding", fields);
|
|
3505
3667
|
return;
|
|
3506
3668
|
}
|
|
3507
3669
|
embeddedAgentLog.warn("codex app-server image payload error detected; clearing thread binding", fields);
|
|
@@ -3510,16 +3672,6 @@ async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity,
|
|
|
3510
3672
|
threadId: expectedThreadId
|
|
3511
3673
|
});
|
|
3512
3674
|
}
|
|
3513
|
-
async function markCodexAppServerBindingCoveredThroughTurn(params) {
|
|
3514
|
-
await params.bindingStore.mutate(params.identity, {
|
|
3515
|
-
kind: "patch",
|
|
3516
|
-
threadId: params.threadId,
|
|
3517
|
-
patch: {
|
|
3518
|
-
historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString(),
|
|
3519
|
-
...params.continuityCalibration ? { continuityCalibration: params.continuityCalibration } : {}
|
|
3520
|
-
}
|
|
3521
|
-
});
|
|
3522
|
-
}
|
|
3523
3675
|
function isNonEmptyString(value) {
|
|
3524
3676
|
return typeof value === "string" && value.length > 0;
|
|
3525
3677
|
}
|
|
@@ -3556,10 +3708,14 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
|
|
|
3556
3708
|
};
|
|
3557
3709
|
const readFencedHistory = async () => {
|
|
3558
3710
|
const transcriptReadFence = params.userTurnTranscriptRecorder?.getAdmissionReceipt();
|
|
3559
|
-
|
|
3711
|
+
const messages = await readMirroredSessionHistoryMessages({
|
|
3560
3712
|
...activeTranscriptTarget,
|
|
3713
|
+
signal: connection.runAbortController.signal,
|
|
3561
3714
|
...transcriptReadFence ? { admission: transcriptReadFence } : {}
|
|
3562
3715
|
});
|
|
3716
|
+
connection.runAbortController.signal.throwIfAborted();
|
|
3717
|
+
connection.assertCurrent();
|
|
3718
|
+
return messages;
|
|
3563
3719
|
};
|
|
3564
3720
|
const historyState = { messages: !activeContextEngine && initialStartupBindingHadInactiveThreadBootstrap ? [] : await readFencedHistory() ?? [] };
|
|
3565
3721
|
const hadSessionTranscriptState = historyState.messages.length > 0;
|
|
@@ -3940,18 +4096,32 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
3940
4096
|
const { effectiveRuntimeProviderId, effectiveRuntimeModelId } = runtime;
|
|
3941
4097
|
const { params, terminalState, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, usesSupervisionConnection, sessionAgentId, contextSessionKey, effectiveCwd, agentDir, attemptStartedAt, startupAuthProfileId } = connection;
|
|
3942
4098
|
const { toolBridge, toolState } = attemptTools;
|
|
4099
|
+
const canClearBindingForRecovery = (operation) => {
|
|
4100
|
+
if (params.expectedSessionRuntimeOwnership) {
|
|
4101
|
+
embeddedAgentLog.warn("codex app-server preserved native binding instead of recovery rotation", {
|
|
4102
|
+
threadId: resourceState.thread.threadId,
|
|
4103
|
+
operation
|
|
4104
|
+
});
|
|
4105
|
+
return false;
|
|
4106
|
+
}
|
|
4107
|
+
assertCodexBindingMayBeReplaced(resourceState.thread, operation);
|
|
4108
|
+
return true;
|
|
4109
|
+
};
|
|
3943
4110
|
const { state, completion, deadlines } = turnRuntime;
|
|
3944
4111
|
const { emitLifecycleTerminal, buildLifecycleTerminalMeta } = lifecycle;
|
|
3945
4112
|
const { drainNotificationQueue } = notifications;
|
|
3946
4113
|
const { codexModelCallDiagnostics } = requestRuntime;
|
|
3947
|
-
const { activeTurnId, activeProjector, streamState, freezeRunTerminalOutcome, notifyUserMessagePersisted } = activeTurn;
|
|
4114
|
+
const { activeTurnId, activeProjector, runtimeModelSelection, streamState, freezeRunTerminalOutcome, notifyUserMessagePersisted } = activeTurn;
|
|
3948
4115
|
await completion;
|
|
3949
4116
|
const abortGraceElapsed = createDeferred();
|
|
3950
|
-
let
|
|
4117
|
+
let settlementPhase = "active";
|
|
3951
4118
|
let abortGraceTimer;
|
|
3952
4119
|
const beginAbortGrace = () => {
|
|
3953
|
-
if (
|
|
3954
|
-
abortGraceTimer = setTimeout(() =>
|
|
4120
|
+
if (settlementPhase !== "active") return;
|
|
4121
|
+
abortGraceTimer = setTimeout(() => {
|
|
4122
|
+
settlementPhase = "expired";
|
|
4123
|
+
abortGraceElapsed.resolve();
|
|
4124
|
+
}, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS);
|
|
3955
4125
|
abortGraceTimer.unref?.();
|
|
3956
4126
|
};
|
|
3957
4127
|
const abortListener = addAbortListener(runAbortController.signal, () => {
|
|
@@ -3961,244 +4131,308 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
|
|
|
3961
4131
|
state.projectionClosed = true;
|
|
3962
4132
|
return activeProjector.closeProjection();
|
|
3963
4133
|
};
|
|
3964
|
-
const
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
if (runAbortController.signal.aborted) await state.abortCleanup;
|
|
3968
|
-
} finally {
|
|
3969
|
-
settlementClosed = true;
|
|
4134
|
+
const closeSettlement = () => {
|
|
4135
|
+
if (settlementPhase === "closed") return;
|
|
4136
|
+
settlementPhase = "closed";
|
|
3970
4137
|
abortListener[Symbol.dispose]();
|
|
3971
4138
|
clearTimeout(abortGraceTimer);
|
|
3972
4139
|
deadlines.dispose();
|
|
3973
|
-
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
contextEngineActive: Boolean(activeContextEngine),
|
|
3991
|
-
thread: resourceState.thread
|
|
3992
|
-
})) {
|
|
3993
|
-
embeddedAgentLog.warn("codex app-server context-engine turn overflowed after resume; clearing thread binding for recovery", {
|
|
4140
|
+
};
|
|
4141
|
+
const settlement = drainNotificationQueue().then(closeProjection);
|
|
4142
|
+
let projectionDrained = false;
|
|
4143
|
+
try {
|
|
4144
|
+
try {
|
|
4145
|
+
projectionDrained = await Promise.race([settlement.then(() => true), abortGraceElapsed.promise.then(() => false)]);
|
|
4146
|
+
if (runAbortController.signal.aborted) await state.abortCleanup;
|
|
4147
|
+
} finally {
|
|
4148
|
+
if (!state.projectionClosed) await resources.runCleanupStep("codex-transcript-checkpoint", closeProjection);
|
|
4149
|
+
}
|
|
4150
|
+
const result = activeProjector.buildResult(toolBridge.telemetry, { yieldDetected: toolState.yieldDetected });
|
|
4151
|
+
const projectedTerminal = attemptTerminal.project(result.terminal);
|
|
4152
|
+
const isFinalAborted = () => terminalState.explicitCancellationObserved || !resourceState.executionDisconnectError && (projectedTerminal.aborted || runAbortController.signal.aborted && !state.clientClosedAbort);
|
|
4153
|
+
let enrichedPromptError = resourceState.executionDisconnectError ?? state.clientClosedPromptError ?? (state.timeout?.kind === "settlement" ? "codex app-server terminal settlement timed out" : state.timeout?.kind === "execution" ? "codex app-server execution budget timed out" : projectedTerminal.promptError);
|
|
4154
|
+
const enrichedPromptErrorMessage = typeof enrichedPromptError === "string" ? enrichedPromptError : enrichedPromptError instanceof Error ? enrichedPromptError.message : enrichedPromptError ? formatErrorMessage(enrichedPromptError) : void 0;
|
|
4155
|
+
if (isInvalidCodexImagePayloadError(enrichedPromptErrorMessage)) await clearCodexBindingAfterInvalidImagePayload(bindingStore, bindingIdentity, {
|
|
4156
|
+
phase: "turn_completed",
|
|
3994
4157
|
threadId: resourceState.thread.threadId,
|
|
3995
4158
|
turnId: activeTurnId,
|
|
3996
|
-
error:
|
|
3997
|
-
});
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4159
|
+
error: enrichedPromptErrorMessage
|
|
4160
|
+
}, params.expectedSessionRuntimeOwnership);
|
|
4161
|
+
if (resourceState.thread.connectionScope !== "supervision" && shouldUseFreshCodexThreadAfterContextEngineOverflow({
|
|
4162
|
+
error: enrichedPromptError,
|
|
4163
|
+
contextEngineActive: Boolean(activeContextEngine),
|
|
4164
|
+
thread: resourceState.thread
|
|
4165
|
+
}) && canClearBindingForRecovery("clearing a native context after overflow")) {
|
|
4166
|
+
embeddedAgentLog.warn("codex app-server context-engine turn overflowed after resume; clearing thread binding for recovery", {
|
|
4167
|
+
threadId: resourceState.thread.threadId,
|
|
4168
|
+
turnId: activeTurnId,
|
|
4169
|
+
error: enrichedPromptErrorMessage
|
|
4170
|
+
});
|
|
4171
|
+
await bindingStore.mutate(bindingIdentity, {
|
|
4172
|
+
kind: "clear",
|
|
4173
|
+
threadId: resourceState.thread.threadId
|
|
4174
|
+
});
|
|
4175
|
+
}
|
|
4176
|
+
const refreshedUsageLimitPromptError = await refreshCodexUsageLimitPromptError({
|
|
4177
|
+
client: resourceState.client,
|
|
4178
|
+
message: enrichedPromptErrorMessage,
|
|
4179
|
+
timeoutMs: appServer.requestTimeoutMs,
|
|
4180
|
+
signal: runAbortController.signal
|
|
4001
4181
|
});
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
|
|
4009
|
-
|
|
4010
|
-
await markCodexAuthProfileBlockedFromRateLimits({
|
|
4182
|
+
if (refreshedUsageLimitPromptError) {
|
|
4183
|
+
await markCodexAuthProfileBlockedFromRateLimits({
|
|
4184
|
+
params,
|
|
4185
|
+
authProfileId: startupAuthProfileId,
|
|
4186
|
+
rateLimits: refreshedUsageLimitPromptError.rateLimitsForProfile
|
|
4187
|
+
});
|
|
4188
|
+
enrichedPromptError = new CodexUsageLimitPromptError(refreshedUsageLimitPromptError.message);
|
|
4189
|
+
} else if (enrichedPromptError instanceof CodexUsageLimitPromptError && state.rateLimitsRevisionBeforeLastTurnStart !== void 0 && readCodexRateLimitsRevision(resourceState.client) > state.rateLimitsRevisionBeforeLastTurnStart) await markCodexAuthProfileBlockedFromRateLimits({
|
|
4011
4190
|
params,
|
|
4012
4191
|
authProfileId: startupAuthProfileId,
|
|
4013
|
-
rateLimits:
|
|
4192
|
+
rateLimits: readRecentCodexRateLimits(resourceState.client)
|
|
4014
4193
|
});
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
|
|
4034
|
-
|
|
4035
|
-
|
|
4036
|
-
|
|
4037
|
-
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4042
|
-
|
|
4043
|
-
|
|
4044
|
-
|
|
4045
|
-
|
|
4046
|
-
|
|
4047
|
-
|
|
4048
|
-
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
|
|
4052
|
-
|
|
4053
|
-
|
|
4054
|
-
|
|
4055
|
-
|
|
4056
|
-
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4063
|
-
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
|
|
4075
|
-
|
|
4076
|
-
|
|
4077
|
-
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
4081
|
-
|
|
4082
|
-
|
|
4083
|
-
|
|
4194
|
+
const projectTerminalOutcome = () => {
|
|
4195
|
+
const effectiveTimedOut = state.timeout !== void 0;
|
|
4196
|
+
const clientClosedPromptErrorForFinal = state.clientClosedPromptError;
|
|
4197
|
+
const finalPromptError = resourceState.executionDisconnectError ?? clientClosedPromptErrorForFinal ?? (state.timeout?.kind === "settlement" ? "codex app-server terminal settlement timed out" : state.timeout?.kind === "execution" ? "codex app-server execution budget timed out" : enrichedPromptError);
|
|
4198
|
+
const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : projectedTerminal.promptErrorSource;
|
|
4199
|
+
const codexAppServerFailureKind = clientClosedPromptErrorForFinal ? "client_closed_before_turn_completed" : state.timeout?.kind === "settlement" ? "turn_settlement_timeout" : void 0;
|
|
4200
|
+
const replayBlockedReason = codexAppServerFailureKind ? resolveCodexAppServerReplayBlockedReason(result) : void 0;
|
|
4201
|
+
const promptTimeoutOutcome = buildCodexAppServerPromptTimeoutOutcome(state.timeout);
|
|
4202
|
+
const failureDiagnostics = codexAppServerFailureKind === "client_closed_before_turn_completed" && state.clientClosedDiagnostic ? { transportError: state.clientClosedDiagnostic } : state.timeout?.kind === "settlement" ? { timeoutMs: state.timeout.timeoutMs } : void 0;
|
|
4203
|
+
const codexAppServerFailure = codexAppServerFailureKind ? {
|
|
4204
|
+
kind: codexAppServerFailureKind,
|
|
4205
|
+
transport: appServer.start.transport,
|
|
4206
|
+
threadId: resourceState.thread.threadId,
|
|
4207
|
+
turnId: activeTurnId,
|
|
4208
|
+
replaySafe: codexAppServerFailureKind === "client_closed_before_turn_completed" && replayBlockedReason === void 0,
|
|
4209
|
+
...replayBlockedReason ? { replayBlockedReason } : {},
|
|
4210
|
+
...failureDiagnostics ? { diagnostics: failureDiagnostics } : {}
|
|
4211
|
+
} : void 0;
|
|
4212
|
+
const finalAborted = isFinalAborted();
|
|
4213
|
+
if (finalAborted && result.attemptUsage) result.attemptUsage = {
|
|
4214
|
+
...result.attemptUsage,
|
|
4215
|
+
contextUsage: { state: "unavailable" }
|
|
4216
|
+
};
|
|
4217
|
+
const completedTurnStatus = activeProjector.getCompletedTurnStatus();
|
|
4218
|
+
const locallyCompletedTurn = state.completed && state.localCompletionRequested && !state.timeout && clientClosedPromptErrorForFinal === void 0;
|
|
4219
|
+
const turnSucceeded = !finalAborted && !effectiveTimedOut && (finalPromptError === null || finalPromptError === void 0) && (completedTurnStatus === "completed" || locallyCompletedTurn);
|
|
4220
|
+
if (toolBridge.telemetry.messagingToolSentTargets.some((target) => target.sourceReplyFinal === true)) result.agentHarnessResultClassification = void 0;
|
|
4221
|
+
const attemptSucceeded = turnSucceeded && result.agentHarnessResultClassification === void 0;
|
|
4222
|
+
result.terminal = attemptTerminal.normalize({
|
|
4223
|
+
timedOut: effectiveTimedOut,
|
|
4224
|
+
aborted: finalAborted,
|
|
4225
|
+
promptError: finalPromptError,
|
|
4226
|
+
promptErrorSource: finalPromptErrorSource
|
|
4227
|
+
});
|
|
4228
|
+
for (const message of [
|
|
4229
|
+
result.lastAssistant,
|
|
4230
|
+
result.currentAttemptAssistant,
|
|
4231
|
+
result.messagesSnapshot.find((candidate) => readMirrorIdentity(candidate) === `${activeTurnId}:assistant`)
|
|
4232
|
+
]) if (message?.role === "assistant") {
|
|
4233
|
+
if (!message.diagnostics?.some((diagnostic) => diagnostic.type === "provider_refusal") || finalAborted || finalPromptError) {
|
|
4234
|
+
message.stopReason = finalAborted ? "aborted" : finalPromptError ? "error" : "stop";
|
|
4235
|
+
message.errorMessage = finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
|
|
4236
|
+
}
|
|
4237
|
+
}
|
|
4238
|
+
return {
|
|
4239
|
+
effectiveTimedOut,
|
|
4240
|
+
finalPromptError,
|
|
4241
|
+
codexAppServerFailure,
|
|
4242
|
+
promptTimeoutOutcome,
|
|
4243
|
+
finalAborted,
|
|
4244
|
+
turnSucceeded,
|
|
4245
|
+
attemptSucceeded,
|
|
4246
|
+
completedTurnStatus
|
|
4247
|
+
};
|
|
4248
|
+
};
|
|
4249
|
+
const mirrorTerminal = projectTerminalOutcome();
|
|
4250
|
+
const unavailableMirror = {
|
|
4251
|
+
assistantTranscriptOwned: false,
|
|
4252
|
+
mirroredMessages: []
|
|
4253
|
+
};
|
|
4254
|
+
let mirrorOutcome = unavailableMirror;
|
|
4255
|
+
try {
|
|
4256
|
+
if (projectionDrained && settlementPhase === "active") mirrorOutcome = await Promise.race([codexTranscriptMirrorRuntime.mirrorBestEffort({
|
|
4257
|
+
assertWriteCurrent: () => {
|
|
4258
|
+
if (settlementPhase !== "active") throw new Error("Codex transcript settlement is no longer active");
|
|
4259
|
+
const current = projectTerminalOutcome();
|
|
4260
|
+
if (current.finalAborted !== mirrorTerminal.finalAborted || current.effectiveTimedOut !== mirrorTerminal.effectiveTimedOut || current.finalPromptError !== mirrorTerminal.finalPromptError) throw new Error("Codex transcript terminal outcome changed before write");
|
|
4261
|
+
},
|
|
4262
|
+
params,
|
|
4263
|
+
agentId: sessionAgentId,
|
|
4264
|
+
notifyUserMessagePersisted,
|
|
4265
|
+
result,
|
|
4266
|
+
sessionKey: contextSessionKey,
|
|
4267
|
+
cwd: effectiveCwd,
|
|
4268
|
+
threadId: resourceState.thread.threadId,
|
|
4269
|
+
turnId: activeTurnId
|
|
4270
|
+
}), abortGraceElapsed.promise.then(() => unavailableMirror)]);
|
|
4271
|
+
if (runAbortController.signal.aborted) await state.abortCleanup;
|
|
4272
|
+
} finally {
|
|
4273
|
+
closeSettlement();
|
|
4274
|
+
}
|
|
4275
|
+
const { effectiveTimedOut, finalPromptError, codexAppServerFailure, promptTimeoutOutcome, finalAborted, turnSucceeded, attemptSucceeded, completedTurnStatus } = projectTerminalOutcome();
|
|
4276
|
+
terminalState.turnSucceeded = turnSucceeded;
|
|
4277
|
+
terminalState.sharedAbortAllowedAfterTerminalOutcome = shouldKeepCodexSharedAbortOpen({
|
|
4278
|
+
trigger: params.trigger,
|
|
4279
|
+
result,
|
|
4280
|
+
attemptSucceeded,
|
|
4281
|
+
explicitCancellationObserved: terminalState.explicitCancellationObserved
|
|
4282
|
+
});
|
|
4283
|
+
freezeRunTerminalOutcome();
|
|
4284
|
+
const modelCallFailureKind = classifyCodexModelCallFailureKind({
|
|
4285
|
+
error: finalPromptError,
|
|
4286
|
+
timedOut: effectiveTimedOut,
|
|
4287
|
+
runAborted: finalAborted,
|
|
4288
|
+
abortReason: terminalState.explicitCancellationReason ?? runAbortController.signal.reason,
|
|
4289
|
+
clientClosedAbort: state.clientClosedAbort,
|
|
4290
|
+
formatError: formatErrorMessage
|
|
4291
|
+
}) ?? (finalAborted ? "aborted" : void 0);
|
|
4292
|
+
if (modelCallFailureKind) codexModelCallDiagnostics.emitError(finalPromptError ?? "codex app-server attempt interrupted", { failureKind: modelCallFailureKind });
|
|
4293
|
+
else if (finalPromptError) codexModelCallDiagnostics.emitError(finalPromptError);
|
|
4294
|
+
else codexModelCallDiagnostics.emitCompleted(result);
|
|
4295
|
+
const { assistantTranscriptOwned, assistantTranscriptIdempotencyKey, terminalAnchor } = mirrorOutcome;
|
|
4296
|
+
const settledTurnFinalizationContext = result.assistantTexts.every((text) => !text.trim()) && result.messagesSnapshot.some((message) => message.role === "toolResult") && (!finalPromptError || activeProjector.settledTurnFailureFinalizationAllowed) ? (!usesSupervisionConnection ? await captureCodexSettledTurnFinalizationContext({
|
|
4297
|
+
...activeTranscriptTarget,
|
|
4298
|
+
model: resourceState.thread.model,
|
|
4299
|
+
modelProvider: resourceState.thread.modelProvider,
|
|
4300
|
+
authProfileId: startupAuthProfileId,
|
|
4301
|
+
mirroredMessages: mirrorOutcome.mirroredMessages,
|
|
4302
|
+
settledMessages: result.messagesSnapshot,
|
|
4303
|
+
turnId: activeTurnId,
|
|
4304
|
+
signal: params.abortSignal,
|
|
4305
|
+
assertActive: connection.assertCurrent
|
|
4306
|
+
}) : void 0) ?? Object.freeze({ source: "unavailable" }) : void 0;
|
|
4307
|
+
if (settledTurnFinalizationContext?.source === "unavailable") embeddedAgentLog.warn("codex settled-turn finalization context is unavailable", {
|
|
4084
4308
|
runId: params.runId,
|
|
4085
|
-
sessionId: params.sessionId,
|
|
4086
|
-
provider: usesSupervisionConnection ? resourceState.thread.modelProvider ?? effectiveRuntimeProviderId : params.provider,
|
|
4087
|
-
model: usesSupervisionConnection ? resourceState.thread.model ?? effectiveRuntimeModelId : params.modelId,
|
|
4088
|
-
...hookContextWindowFields,
|
|
4089
|
-
resolvedRef: usesSupervisionConnection ? `${resourceState.thread.modelProvider ?? effectiveRuntimeProviderId}/${resourceState.thread.model ?? effectiveRuntimeModelId}` : params.runtimePlan?.observability.resolvedRef ?? `${params.provider}/${params.modelId}`,
|
|
4090
|
-
...!usesSupervisionConnection && params.runtimePlan?.observability.harnessId ? { harnessId: params.runtimePlan.observability.harnessId } : {},
|
|
4091
|
-
assistantTexts: result.assistantTexts,
|
|
4092
|
-
...result.lastAssistant ? { lastAssistant: result.lastAssistant } : {},
|
|
4093
|
-
...result.attemptUsage ? { usage: result.attemptUsage } : {}
|
|
4094
|
-
},
|
|
4095
|
-
ctx: hookContext,
|
|
4096
|
-
hookRunner
|
|
4097
|
-
});
|
|
4098
|
-
await runCodexAgentEndHook(params, {
|
|
4099
|
-
event: {
|
|
4100
|
-
messages: result.messagesSnapshot,
|
|
4101
|
-
success: !finalAborted && !finalPromptError,
|
|
4102
|
-
...finalPromptError ? { error: formatErrorMessage(finalPromptError) } : {},
|
|
4103
|
-
durationMs: Date.now() - attemptStartedAt
|
|
4104
|
-
},
|
|
4105
|
-
ctx: {
|
|
4106
|
-
...hookContext,
|
|
4107
|
-
modelProviderId: resourceState.thread.modelProvider ?? effectiveRuntimeProviderId,
|
|
4108
|
-
modelId: resourceState.thread.model ?? effectiveRuntimeModelId,
|
|
4109
|
-
authProfileId: resourceState.thread.authProfileId ?? startupAuthProfileId,
|
|
4110
|
-
modelIterations: result.modelIterations ?? 0,
|
|
4111
|
-
skillWorkshopAvailable: flattenCodexDynamicToolFunctions(attemptTools.toolBridge.availableSpecs).some((tool) => tool.name === "skill_workshop"),
|
|
4112
|
-
compacted: (result.compactionCount ?? 0) > 0,
|
|
4113
|
-
senderId: params.senderId ?? void 0,
|
|
4114
|
-
foregroundPromptContext: buildEmbeddedForegroundPromptContext({
|
|
4115
|
-
...params,
|
|
4116
|
-
agentId: sessionAgentId
|
|
4117
|
-
}, agentDir)
|
|
4118
|
-
},
|
|
4119
|
-
hookRunner
|
|
4120
|
-
});
|
|
4121
|
-
state.shouldDelayNativeHookRelayUnregister = completedTurnStatus === "completed" && !effectiveTimedOut && !runAbortController.signal.aborted && !finalAborted && !finalPromptError;
|
|
4122
|
-
if (state.shouldDelayNativeHookRelayUnregister) try {
|
|
4123
|
-
await markCodexAppServerBindingCoveredThroughTurn({
|
|
4124
|
-
bindingStore,
|
|
4125
|
-
identity: bindingIdentity,
|
|
4126
4309
|
threadId: resourceState.thread.threadId,
|
|
4127
|
-
|
|
4310
|
+
turnId: activeTurnId,
|
|
4311
|
+
reason: usesSupervisionConnection ? "native_auth_finalization_unsupported" : "context_unavailable"
|
|
4312
|
+
});
|
|
4313
|
+
runAgentHarnessLlmOutputHook({
|
|
4314
|
+
event: {
|
|
4315
|
+
runId: params.runId,
|
|
4316
|
+
sessionId: params.sessionId,
|
|
4317
|
+
provider: usesSupervisionConnection ? resourceState.thread.modelProvider ?? effectiveRuntimeProviderId : params.provider,
|
|
4318
|
+
model: usesSupervisionConnection ? resourceState.thread.model ?? effectiveRuntimeModelId : params.modelId,
|
|
4319
|
+
...hookContextWindowFields,
|
|
4320
|
+
resolvedRef: usesSupervisionConnection ? `${resourceState.thread.modelProvider ?? effectiveRuntimeProviderId}/${resourceState.thread.model ?? effectiveRuntimeModelId}` : params.runtimePlan?.observability.resolvedRef ?? `${params.provider}/${params.modelId}`,
|
|
4321
|
+
...!usesSupervisionConnection && params.runtimePlan?.observability.harnessId ? { harnessId: params.runtimePlan.observability.harnessId } : {},
|
|
4322
|
+
assistantTexts: result.assistantTexts,
|
|
4323
|
+
...result.lastAssistant ? { lastAssistant: result.lastAssistant } : {},
|
|
4324
|
+
...result.attemptUsage ? { usage: result.attemptUsage } : {}
|
|
4325
|
+
},
|
|
4326
|
+
ctx: hookContext,
|
|
4327
|
+
hookRunner
|
|
4328
|
+
});
|
|
4329
|
+
await runCodexAgentEndHook(params, {
|
|
4330
|
+
event: {
|
|
4331
|
+
messages: result.messagesSnapshot,
|
|
4332
|
+
success: !finalAborted && !finalPromptError,
|
|
4333
|
+
...finalPromptError ? { error: formatErrorMessage(finalPromptError) } : {},
|
|
4334
|
+
durationMs: Date.now() - attemptStartedAt
|
|
4335
|
+
},
|
|
4336
|
+
ctx: {
|
|
4337
|
+
...hookContext,
|
|
4338
|
+
modelProviderId: resourceState.thread.modelProvider ?? effectiveRuntimeProviderId,
|
|
4339
|
+
modelId: resourceState.thread.model ?? effectiveRuntimeModelId,
|
|
4340
|
+
authProfileId: resourceState.thread.authProfileId ?? startupAuthProfileId,
|
|
4341
|
+
modelIterations: result.modelIterations ?? 0,
|
|
4342
|
+
skillWorkshopAvailable: flattenCodexDynamicToolFunctions(attemptTools.toolBridge.availableSpecs).some((tool) => tool.name === "skill_workshop"),
|
|
4343
|
+
compacted: (result.compactionCount ?? 0) > 0,
|
|
4344
|
+
senderId: params.senderId ?? void 0,
|
|
4345
|
+
foregroundPromptContext: buildEmbeddedForegroundPromptContext({
|
|
4346
|
+
...params,
|
|
4347
|
+
agentId: sessionAgentId
|
|
4348
|
+
}, agentDir)
|
|
4349
|
+
},
|
|
4350
|
+
hookRunner
|
|
4351
|
+
});
|
|
4352
|
+
state.shouldDelayNativeHookRelayUnregister = completedTurnStatus === "completed" && !effectiveTimedOut && !runAbortController.signal.aborted && !finalAborted && !finalPromptError;
|
|
4353
|
+
if (state.shouldDelayNativeHookRelayUnregister) try {
|
|
4354
|
+
const continuityCalibration = context.promptState.noEngineContinuityProjectionApplied ? buildCodexContinuityCalibration({
|
|
4128
4355
|
promptChars: prompt.turnState.codexTurnPromptText.length,
|
|
4129
|
-
inputTokens:
|
|
4130
|
-
}) : void 0
|
|
4356
|
+
inputTokens: result.attemptUsage?.contextUsage?.state === "available" ? result.attemptUsage.contextUsage.promptTokens ?? 0 : 0
|
|
4357
|
+
}) : void 0;
|
|
4358
|
+
await bindingStore.mutate(bindingIdentity, {
|
|
4359
|
+
kind: "patch",
|
|
4360
|
+
threadId: resourceState.thread.threadId,
|
|
4361
|
+
patch: {
|
|
4362
|
+
historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString(),
|
|
4363
|
+
...continuityCalibration ? { continuityCalibration } : {}
|
|
4364
|
+
}
|
|
4365
|
+
}, connection.assertCurrent);
|
|
4366
|
+
} catch (error) {
|
|
4367
|
+
if (resourceState.thread.connectionScope === "supervision") throw error;
|
|
4368
|
+
if (canClearBindingForRecovery("clearing native coverage after a completed turn")) {
|
|
4369
|
+
if (!await bindingStore.mutate(bindingIdentity, {
|
|
4370
|
+
kind: "clear",
|
|
4371
|
+
threadId: resourceState.thread.threadId
|
|
4372
|
+
}, connection.assertCurrent)) throw error;
|
|
4373
|
+
embeddedAgentLog.warn("codex app-server binding coverage update failed after completed turn; cleared stale binding", {
|
|
4374
|
+
threadId: resourceState.thread.threadId,
|
|
4375
|
+
turnId: activeTurnId,
|
|
4376
|
+
error
|
|
4377
|
+
});
|
|
4378
|
+
}
|
|
4379
|
+
}
|
|
4380
|
+
recordCodexTrajectoryCompletion(trajectoryRecorder, {
|
|
4381
|
+
attempt: params,
|
|
4382
|
+
result,
|
|
4383
|
+
threadId: resourceState.thread.threadId,
|
|
4384
|
+
turnId: activeTurnId,
|
|
4385
|
+
timedOut: effectiveTimedOut,
|
|
4386
|
+
yieldDetected: toolState.yieldDetected
|
|
4131
4387
|
});
|
|
4132
|
-
|
|
4133
|
-
|
|
4134
|
-
if (!await bindingStore.mutate(bindingIdentity, {
|
|
4135
|
-
kind: "clear",
|
|
4136
|
-
threadId: resourceState.thread.threadId
|
|
4137
|
-
})) throw error;
|
|
4138
|
-
embeddedAgentLog.warn("codex app-server binding coverage update failed after completed turn; cleared stale binding", {
|
|
4388
|
+
trajectoryRecorder?.recordEvent("session.ended", {
|
|
4389
|
+
status: finalPromptError ? "error" : finalAborted || effectiveTimedOut ? "interrupted" : "success",
|
|
4139
4390
|
threadId: resourceState.thread.threadId,
|
|
4140
4391
|
turnId: activeTurnId,
|
|
4141
|
-
|
|
4392
|
+
timedOut: effectiveTimedOut,
|
|
4393
|
+
yieldDetected: toolState.yieldDetected,
|
|
4394
|
+
promptError: normalizeCodexTrajectoryError(finalPromptError)
|
|
4395
|
+
});
|
|
4396
|
+
markTrajectoryEndRecorded();
|
|
4397
|
+
const terminalAssistantText = collectTerminalAssistantText(result);
|
|
4398
|
+
if (terminalAssistantText && (!streamState.eventEmitted || streamState.needsTerminalSnapshot) && !finalAborted && !finalPromptError) emitCodexAppServerEvent(params, {
|
|
4399
|
+
stream: "assistant",
|
|
4400
|
+
data: { text: terminalAssistantText }
|
|
4401
|
+
});
|
|
4402
|
+
emitLifecycleTerminal(finalPromptError ? {
|
|
4403
|
+
phase: "error",
|
|
4404
|
+
error: formatErrorMessage(finalPromptError),
|
|
4405
|
+
...buildLifecycleTerminalMeta({
|
|
4406
|
+
aborted: finalAborted,
|
|
4407
|
+
timedOut: effectiveTimedOut
|
|
4408
|
+
})
|
|
4409
|
+
} : {
|
|
4410
|
+
phase: "end",
|
|
4411
|
+
...buildLifecycleTerminalMeta({
|
|
4412
|
+
aborted: finalAborted,
|
|
4413
|
+
timedOut: effectiveTimedOut,
|
|
4414
|
+
yielded: toolState.yieldDetected
|
|
4415
|
+
})
|
|
4142
4416
|
});
|
|
4417
|
+
const finalizedResult = Object.assign(result, {
|
|
4418
|
+
...runtimeModelSelection ? { runtimeModelSelection } : {},
|
|
4419
|
+
...toolState.yieldAcknowledgment ? { yieldAcknowledgment: toolState.yieldAcknowledgment } : {},
|
|
4420
|
+
...codexAppServerFailure ? { codexAppServerFailure } : {},
|
|
4421
|
+
...promptTimeoutOutcome ? { promptTimeoutOutcome } : {},
|
|
4422
|
+
...assistantTranscriptOwned ? { assistantTranscriptOwned: true } : {},
|
|
4423
|
+
...assistantTranscriptIdempotencyKey ? { assistantTranscriptIdempotencyKey } : {},
|
|
4424
|
+
...terminalAnchor ? { contextEngineTerminalAnchor: terminalAnchor } : {},
|
|
4425
|
+
...settledTurnFinalizationContext ? { settledTurnFinalizationContext } : {},
|
|
4426
|
+
...resourceState.runtimeArtifact ? { runtimeArtifact: resourceState.runtimeArtifact } : {},
|
|
4427
|
+
...resourceState.runtimeContinuationStarted ? { runtimeContinuationStarted: true } : {},
|
|
4428
|
+
...!finalAborted && !effectiveTimedOut && !finalPromptError && preparedAuthBinding ? { authBindingFingerprint: preparedAuthBinding.fingerprint } : {},
|
|
4429
|
+
systemPromptReport
|
|
4430
|
+
});
|
|
4431
|
+
if (turnSucceeded && toolState.yieldDetected && !runAbortController.signal.aborted) resourceState.nativeHookRelay?.authorizeRetentionAfterSuccessfulYield();
|
|
4432
|
+
return finalizedResult;
|
|
4433
|
+
} finally {
|
|
4434
|
+
closeSettlement();
|
|
4143
4435
|
}
|
|
4144
|
-
recordCodexTrajectoryCompletion(trajectoryRecorder, {
|
|
4145
|
-
attempt: params,
|
|
4146
|
-
result,
|
|
4147
|
-
threadId: resourceState.thread.threadId,
|
|
4148
|
-
turnId: activeTurnId,
|
|
4149
|
-
timedOut: effectiveTimedOut,
|
|
4150
|
-
yieldDetected: toolState.yieldDetected
|
|
4151
|
-
});
|
|
4152
|
-
trajectoryRecorder?.recordEvent("session.ended", {
|
|
4153
|
-
status: finalPromptError ? "error" : finalAborted || effectiveTimedOut ? "interrupted" : "success",
|
|
4154
|
-
threadId: resourceState.thread.threadId,
|
|
4155
|
-
turnId: activeTurnId,
|
|
4156
|
-
timedOut: effectiveTimedOut,
|
|
4157
|
-
yieldDetected: toolState.yieldDetected,
|
|
4158
|
-
promptError: normalizeCodexTrajectoryError(finalPromptError)
|
|
4159
|
-
});
|
|
4160
|
-
markTrajectoryEndRecorded();
|
|
4161
|
-
const terminalAssistantText = collectTerminalAssistantText(result);
|
|
4162
|
-
if (terminalAssistantText && (!streamState.eventEmitted || streamState.needsTerminalSnapshot) && !finalAborted && !finalPromptError) emitCodexAppServerEvent(params, {
|
|
4163
|
-
stream: "assistant",
|
|
4164
|
-
data: { text: terminalAssistantText }
|
|
4165
|
-
});
|
|
4166
|
-
emitLifecycleTerminal(finalPromptError ? {
|
|
4167
|
-
phase: "error",
|
|
4168
|
-
error: formatErrorMessage(finalPromptError),
|
|
4169
|
-
...buildLifecycleTerminalMeta({
|
|
4170
|
-
aborted: finalAborted,
|
|
4171
|
-
timedOut: effectiveTimedOut
|
|
4172
|
-
})
|
|
4173
|
-
} : {
|
|
4174
|
-
phase: "end",
|
|
4175
|
-
...buildLifecycleTerminalMeta({
|
|
4176
|
-
aborted: finalAborted,
|
|
4177
|
-
timedOut: effectiveTimedOut,
|
|
4178
|
-
yielded: toolState.yieldDetected
|
|
4179
|
-
})
|
|
4180
|
-
});
|
|
4181
|
-
const finalizedResult = Object.assign(result, {
|
|
4182
|
-
...toolState.yieldAcknowledgment ? { yieldAcknowledgment: toolState.yieldAcknowledgment } : {},
|
|
4183
|
-
terminal: attemptTerminal.normalize({
|
|
4184
|
-
timedOut: effectiveTimedOut,
|
|
4185
|
-
aborted: finalAborted,
|
|
4186
|
-
promptError: finalPromptError,
|
|
4187
|
-
promptErrorSource: finalPromptErrorSource
|
|
4188
|
-
}),
|
|
4189
|
-
...codexAppServerFailure ? { codexAppServerFailure } : {},
|
|
4190
|
-
...promptTimeoutOutcome ? { promptTimeoutOutcome } : {},
|
|
4191
|
-
...assistantTranscriptOwned ? { assistantTranscriptOwned: true } : {},
|
|
4192
|
-
...assistantTranscriptIdempotencyKey ? { assistantTranscriptIdempotencyKey } : {},
|
|
4193
|
-
...terminalAnchor ? { contextEngineTerminalAnchor: terminalAnchor } : {},
|
|
4194
|
-
...settledTurnFinalizationContext ? { settledTurnFinalizationContext } : {},
|
|
4195
|
-
...resourceState.runtimeArtifact ? { runtimeArtifact: resourceState.runtimeArtifact } : {},
|
|
4196
|
-
...resourceState.runtimeContinuationStarted ? { runtimeContinuationStarted: true } : {},
|
|
4197
|
-
...!finalAborted && !effectiveTimedOut && !finalPromptError && preparedAuthBinding ? { authBindingFingerprint: preparedAuthBinding.fingerprint } : {},
|
|
4198
|
-
systemPromptReport
|
|
4199
|
-
});
|
|
4200
|
-
if (turnSucceeded && toolState.yieldDetected && !runAbortController.signal.aborted) resourceState.nativeHookRelay?.authorizeRetentionAfterSuccessfulYield();
|
|
4201
|
-
return finalizedResult;
|
|
4202
4436
|
}
|
|
4203
4437
|
//#endregion
|
|
4204
4438
|
//#region extensions/codex/src/app-server/attempt-notification-state.ts
|
|
@@ -4422,7 +4656,7 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4422
4656
|
const { attemptTools, runtime } = context;
|
|
4423
4657
|
const { appServer, runAbortController } = runtime.connection;
|
|
4424
4658
|
const { allocateCodexToolOutcomeOrdinal } = attemptTools;
|
|
4425
|
-
const { state, turnIdRef, userInputBridgeRef, steeringQueueRef, activeTurnItemIds, pendingOpenClawDynamicToolCompletionIds, completeTurn, noteProgress, deadlines } = turnRuntime;
|
|
4659
|
+
const { state, turnIdRef, userInputBridgeRef, steeringQueueRef, activeTurnItemIds, pendingOpenClawDynamicToolCompletionIds, openClawDynamicToolExecutions, completeTurn, noteProgress, deadlines } = turnRuntime;
|
|
4426
4660
|
const { scheduleTerminalDynamicToolReleaseCheck, reportExecutionNotification, maybeAnnounceFastModeAutoOff } = lifecycle;
|
|
4427
4661
|
const isTerminalTurnNotificationForTurn = (notification, notificationTurnId) => isTerminalCodexTurnNotificationForTurn({
|
|
4428
4662
|
notification,
|
|
@@ -4457,6 +4691,14 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
|
|
|
4457
4691
|
if (notification.method === "item/completed") {
|
|
4458
4692
|
if (activeTurnItemIds.size === 0) scheduleTerminalDynamicToolReleaseCheck();
|
|
4459
4693
|
const item = readCodexNotificationItem(notification.params);
|
|
4694
|
+
if (item?.type === "dynamicToolCall" && typeof item.id === "string") {
|
|
4695
|
+
const response = await openClawDynamicToolExecutions.get({
|
|
4696
|
+
threadId: resourceState.thread.threadId,
|
|
4697
|
+
turnId,
|
|
4698
|
+
callId: item.id
|
|
4699
|
+
});
|
|
4700
|
+
if (response && !state.projectionClosed && !runAbortController.signal.aborted && turnIdRef.current === turnId && item.success === response.success && isDeepStrictEqual(item.contentItems, response.contentItems)) acknowledgeInternalToolResult(response);
|
|
4701
|
+
}
|
|
4460
4702
|
if (item?.type === "userMessage" && typeof item.clientId === "string") await steeringQueueRef.current?.confirmConsumed(item.clientId);
|
|
4461
4703
|
}
|
|
4462
4704
|
if (isCodexTurnAbortMarkerNotification(notification, { currentPromptTexts: [turnState.codexTurnPromptText] })) state.sawCodexInterruptMarker = true;
|
|
@@ -4633,7 +4875,7 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4633
4875
|
toolAuthority: {
|
|
4634
4876
|
fingerprint: params.toolAuthorityFingerprint,
|
|
4635
4877
|
activeToolNames: () => flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString),
|
|
4636
|
-
assertActive:
|
|
4878
|
+
assertActive: connection.assertCurrent
|
|
4637
4879
|
}
|
|
4638
4880
|
});
|
|
4639
4881
|
};
|
|
@@ -4758,6 +5000,7 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4758
5000
|
const previousThreadId = binding.threadId;
|
|
4759
5001
|
const hadInactiveThreadBootstrapBinding = isInactiveThreadBootstrapBinding(binding);
|
|
4760
5002
|
const startupBindingResolution = await rotateOversizedCodexAppServerStartupBinding({
|
|
5003
|
+
assertCurrent: connection.assertCurrent,
|
|
4761
5004
|
binding,
|
|
4762
5005
|
bindingStore,
|
|
4763
5006
|
identity: bindingIdentity,
|
|
@@ -4766,6 +5009,7 @@ async function prepareCodexAttemptPrompt(context) {
|
|
|
4766
5009
|
codexHome: appServer.start.env?.CODEX_HOME,
|
|
4767
5010
|
config: params.config,
|
|
4768
5011
|
contextEngineActive: Boolean(activeContextEngine),
|
|
5012
|
+
expectedSessionRuntimeOwnership: params.expectedSessionRuntimeOwnership,
|
|
4769
5013
|
projectedTurnTokens: estimateCodexAppServerProjectedTurnTokens({
|
|
4770
5014
|
prompt: turnState.codexTurnPromptText,
|
|
4771
5015
|
developerInstructions: buildRenderedCodexDeveloperInstructions()
|
|
@@ -5016,6 +5260,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5016
5260
|
loopDetectionPreToolUseRelay: appServer.loopDetectionPreToolUseRelay,
|
|
5017
5261
|
signal: runAbortController.signal,
|
|
5018
5262
|
hostCapabilities: params.hostCapabilities,
|
|
5263
|
+
assertCurrent: connection.assertCurrent,
|
|
5019
5264
|
onPreToolUseFailure: (failure) => {
|
|
5020
5265
|
const projector = projectorRef.current;
|
|
5021
5266
|
if (projector) projector.recordNativeToolPreToolUseFailure(failure);
|
|
@@ -5057,7 +5302,7 @@ function prepareCodexAttemptResources(prompt) {
|
|
|
5057
5302
|
async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, handleServerRequest) {
|
|
5058
5303
|
const { prompt, state: resourceState, trajectoryRecorder, releaseCurrentRoute, registerNativeSubagentMonitor, activateNativePreToolUseFailureFallback, releaseSandboxExecEnvironment, releaseSharedClientLeaseOnce } = resources;
|
|
5059
5304
|
const { connection } = prompt.context.runtime;
|
|
5060
|
-
const {
|
|
5305
|
+
const { runAbortController } = connection;
|
|
5061
5306
|
const { state, turnIdRef, completeTurn } = turnRuntime;
|
|
5062
5307
|
const { noteNotificationReceived, enqueueNotification } = notifications;
|
|
5063
5308
|
const attachRouteAbort = (route) => {
|
|
@@ -5112,7 +5357,6 @@ async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, h
|
|
|
5112
5357
|
resourceState.nativeHookRelay?.unregister();
|
|
5113
5358
|
await releaseSandboxExecEnvironment();
|
|
5114
5359
|
releaseSharedClientLeaseOnce();
|
|
5115
|
-
params.abortSignal?.removeEventListener("abort", abortFromUpstream);
|
|
5116
5360
|
throw error;
|
|
5117
5361
|
}
|
|
5118
5362
|
return { ensureCurrentThreadRoute };
|
|
@@ -5125,6 +5369,7 @@ function prewarmCodexAttemptClient(params) {
|
|
|
5125
5369
|
const { appServer, attemptClientFactory, options, pluginConfig, runtimeArtifactRequest, startupAuthRequirement, startupClientAuthProfileId, startupPreparedAuth, agentDir, params: runParams, runAbortController } = connection;
|
|
5126
5370
|
if (options.clientFactory || attemptClientFactory !== getLeasedSharedCodexAppServerClient || runtimeArtifactRequest) return;
|
|
5127
5371
|
getSharedCodexAppServerClient({
|
|
5372
|
+
assertCurrent: connection.assertCurrent,
|
|
5128
5373
|
startOptions: appServer.start,
|
|
5129
5374
|
pluginConfig,
|
|
5130
5375
|
...startupPreparedAuth ? { preparedAuth: startupPreparedAuth } : { authProfileId: startupClientAuthProfileId },
|
|
@@ -5236,7 +5481,7 @@ async function prepareCodexAttemptRuntime(connection) {
|
|
|
5236
5481
|
const authenticatedScheduledMode = params.trigger === "cron" && params.scheduledToolPolicy !== void 0 && Array.isArray(params.toolsAllow);
|
|
5237
5482
|
const scheduledConfiguredMcpSurface = authenticatedScheduledMode && (bundleMcpThreadConfig.staticServerNames.length > 0 || mutable.startupBinding?.configuredMcpOwnershipVersion === 1);
|
|
5238
5483
|
const cronCreatorAuthorityCapability = params.cronCreatorAuthorityCapability;
|
|
5239
|
-
const hasFreshCreatorAuthority = cronCreatorAuthorityCapability?.active === true && cronCreatorAuthorityCapability.runId === params.runId && !cronCreatorAuthorityCapability.signal.aborted;
|
|
5484
|
+
const hasFreshCreatorAuthority = cronCreatorAuthorityCapability?.active === true && !(cronCreatorAuthorityCapability.controlUiAdmin && cronCreatorAuthorityCapability.callerOrigin.kind === "unknown") && cronCreatorAuthorityCapability.runId === params.runId && !cronCreatorAuthorityCapability.signal.aborted;
|
|
5240
5485
|
const mayResolveScheduledConfiguredMcpCreatorAuthority = !authenticatedScheduledMode && canResolveScheduledConfiguredMcpCreatorAuthority({
|
|
5241
5486
|
trigger: params.trigger,
|
|
5242
5487
|
connectionClass: appServer.connectionClass,
|
|
@@ -5677,7 +5922,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
|
|
|
5677
5922
|
//#region extensions/codex/src/app-server/attempt-runtime-artifact.ts
|
|
5678
5923
|
async function verifyStartupArtifact(params) {
|
|
5679
5924
|
if (!params.request) return;
|
|
5680
|
-
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-
|
|
5925
|
+
const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-Bh_gf6-t.js");
|
|
5681
5926
|
const runtimeArtifact = readCodexAppServerClientRuntimeArtifact(params.client);
|
|
5682
5927
|
const expected = params.request.expected;
|
|
5683
5928
|
const matchesExpected = !expected || runtimeArtifact?.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint;
|
|
@@ -5802,15 +6047,22 @@ function resolveCodexPluginThreadConfigStartupPolicy(params) {
|
|
|
5802
6047
|
/** Builds plugin config without allowing sequential RPC timeouts to consume the turn. */
|
|
5803
6048
|
async function buildCodexPluginThreadConfigWithinDeadline(params) {
|
|
5804
6049
|
const { requestTimeoutMs, signal, request, failClosedOnTimeout, transform, ...buildParams } = params;
|
|
6050
|
+
signal.throwIfAborted();
|
|
5805
6051
|
const timeoutMs = resolveCodexPluginThreadConfigTimeoutMs(requestTimeoutMs);
|
|
5806
6052
|
const deadlineMs = Date.now() + timeoutMs;
|
|
5807
|
-
|
|
6053
|
+
let requestTimedOut = false;
|
|
6054
|
+
const boundedRequest = async (method, requestParams) => {
|
|
5808
6055
|
const remainingTimeoutMs = deadlineMs - Date.now();
|
|
5809
|
-
if (remainingTimeoutMs <= 0) throw new CodexPluginThreadConfigDeadlineError();
|
|
5810
|
-
|
|
5811
|
-
|
|
5812
|
-
|
|
5813
|
-
|
|
6056
|
+
if (requestTimedOut || remainingTimeoutMs <= 0) throw new CodexPluginThreadConfigDeadlineError();
|
|
6057
|
+
try {
|
|
6058
|
+
return await request(method, requestParams, {
|
|
6059
|
+
timeoutMs: remainingTimeoutMs,
|
|
6060
|
+
signal
|
|
6061
|
+
});
|
|
6062
|
+
} catch (error) {
|
|
6063
|
+
requestTimedOut ||= isCodexPluginThreadConfigTimeoutError(error);
|
|
6064
|
+
throw error;
|
|
6065
|
+
}
|
|
5814
6066
|
};
|
|
5815
6067
|
try {
|
|
5816
6068
|
return await withAbortableTimeout({
|
|
@@ -5821,14 +6073,16 @@ async function buildCodexPluginThreadConfigWithinDeadline(params) {
|
|
|
5821
6073
|
...buildParams,
|
|
5822
6074
|
request: boundedRequest
|
|
5823
6075
|
});
|
|
5824
|
-
|
|
6076
|
+
const result = transform ? await transform(config, boundedRequest) : config;
|
|
6077
|
+
if (requestTimedOut || Date.now() >= deadlineMs) throw new CodexPluginThreadConfigDeadlineError();
|
|
6078
|
+
return result;
|
|
5825
6079
|
})(),
|
|
5826
6080
|
timeoutMessage: "Codex plugin thread config deadline elapsed",
|
|
5827
6081
|
createTimeoutError: () => new CodexPluginThreadConfigDeadlineError()
|
|
5828
6082
|
});
|
|
5829
6083
|
} catch (error) {
|
|
5830
|
-
if (signal.aborted || !isCodexPluginThreadConfigTimeoutError(error)) throw error;
|
|
5831
|
-
if (failClosedOnTimeout) throw new AgentHarnessPreflightError(`
|
|
6084
|
+
if (signal.aborted || !requestTimedOut && !isCodexPluginThreadConfigTimeoutError(error) && Date.now() < deadlineMs) throw error;
|
|
6085
|
+
if (failClosedOnTimeout) throw new AgentHarnessPreflightError(`Codex app policy verification exceeded its ${timeoutMs} ms startup budget. No app tools were executed. Retry after Codex app inventory is responsive.`);
|
|
5832
6086
|
return buildCodexPluginThreadConfigTimeoutFallback({
|
|
5833
6087
|
pluginConfig: buildParams.pluginConfig,
|
|
5834
6088
|
appCacheKey: buildParams.appCacheKey,
|
|
@@ -5842,7 +6096,7 @@ function createCodexPluginThreadConfigStartupProvider(params) {
|
|
|
5842
6096
|
const metadataCache = configuredMetadataCache ?? defaultCodexPluginMetadataCache;
|
|
5843
6097
|
return {
|
|
5844
6098
|
enabled: true,
|
|
5845
|
-
requiresCurrentPolicyCheck: Boolean(params.scheduledRuntimeAuthority),
|
|
6099
|
+
requiresCurrentPolicyCheck: Boolean(policy?.enabled || params.scheduledRuntimeAuthority),
|
|
5846
6100
|
inputFingerprint,
|
|
5847
6101
|
enabledPluginConfigKeys,
|
|
5848
6102
|
accountAppRecoveryEnabled: policy?.allowAllPlugins,
|
|
@@ -5905,7 +6159,6 @@ async function startCodexAttemptThread(params) {
|
|
|
5905
6159
|
let releaseSharedClientLease;
|
|
5906
6160
|
let startupClientForAbandonedRequestCleanup;
|
|
5907
6161
|
let releaseStartupResourcesOnTimeout;
|
|
5908
|
-
let startupAbandoned = false;
|
|
5909
6162
|
const startupAbandonController = new AbortController();
|
|
5910
6163
|
const abandonStartupAcquire = () => startupAbandonController.abort();
|
|
5911
6164
|
params.signal.addEventListener("abort", abandonStartupAcquire, { once: true });
|
|
@@ -5914,7 +6167,6 @@ async function startCodexAttemptThread(params) {
|
|
|
5914
6167
|
timeoutMs: params.startupTimeoutMs,
|
|
5915
6168
|
signal: params.signal,
|
|
5916
6169
|
onTimeout: async () => {
|
|
5917
|
-
startupAbandoned = true;
|
|
5918
6170
|
startupAbandonController.abort();
|
|
5919
6171
|
await params.onStartupTimeout();
|
|
5920
6172
|
await releaseStartupResourcesOnTimeout?.();
|
|
@@ -5942,7 +6194,9 @@ async function startCodexAttemptThread(params) {
|
|
|
5942
6194
|
let startupAttemptSucceeded = false;
|
|
5943
6195
|
try {
|
|
5944
6196
|
const attemptParams = params.buildAttemptParams();
|
|
6197
|
+
params.assertCurrent?.();
|
|
5945
6198
|
startupClient = await params.attemptClientFactory({
|
|
6199
|
+
assertCurrent: params.assertCurrent,
|
|
5946
6200
|
startOptions: params.appServer.start,
|
|
5947
6201
|
pluginConfig: params.pluginConfig,
|
|
5948
6202
|
...params.startupPreparedAuth ? { preparedAuth: params.startupPreparedAuth } : { authProfileId: params.startupAuthProfileId },
|
|
@@ -5958,7 +6212,7 @@ async function startCodexAttemptThread(params) {
|
|
|
5958
6212
|
config: params.config,
|
|
5959
6213
|
onStartedClient: (client) => {
|
|
5960
6214
|
startupClientForAbandonedRequestCleanup = client;
|
|
5961
|
-
if (
|
|
6215
|
+
if (startupAbandonController.signal.aborted) closeCodexStartupClientBestEffort(client);
|
|
5962
6216
|
},
|
|
5963
6217
|
abandonSignal: startupAbandonController.signal,
|
|
5964
6218
|
timeoutMs: params.appServer.requestTimeoutMs
|
|
@@ -5974,13 +6228,13 @@ async function startCodexAttemptThread(params) {
|
|
|
5974
6228
|
releaseSharedClientLease = startupClientLease;
|
|
5975
6229
|
attemptedClient = activeStartupClient;
|
|
5976
6230
|
startupClientForAbandonedRequestCleanup = activeStartupClient;
|
|
5977
|
-
if (startupAbandoned) throw new CodexAppServerStartupError("timed_out");
|
|
5978
6231
|
if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
|
|
5979
6232
|
const runtimeArtifact = await verifyStartupArtifact({
|
|
5980
6233
|
client: activeStartupClient,
|
|
5981
6234
|
request: params.runtimeArtifactRequest,
|
|
5982
6235
|
signal: startupAbandonController.signal
|
|
5983
6236
|
});
|
|
6237
|
+
params.assertCurrent?.();
|
|
5984
6238
|
ensureCodexAppServerClientRuntime(activeStartupClient, {
|
|
5985
6239
|
agentDir: params.agentDir,
|
|
5986
6240
|
authProfileId: startupRuntimeAuthProfileId,
|
|
@@ -6046,6 +6300,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6046
6300
|
};
|
|
6047
6301
|
releaseStartupResourcesOnTimeout = releaseStartupSandboxEnvironment;
|
|
6048
6302
|
try {
|
|
6303
|
+
params.assertCurrent?.();
|
|
6049
6304
|
const sandboxEnvironmentRequired = shouldRequireCodexSandboxExecServerEnvironment({
|
|
6050
6305
|
sandbox: params.sandbox,
|
|
6051
6306
|
nativeToolSurfaceEnabled: params.nativeToolSurfaceEnabled,
|
|
@@ -6061,10 +6316,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6061
6316
|
onExecutionDisconnect: params.onExecutionDisconnect
|
|
6062
6317
|
}) : void 0;
|
|
6063
6318
|
startupSandboxEnvironmentAcquired = Boolean(startupSandboxEnvironment);
|
|
6064
|
-
if (startupAbandonController.signal.aborted)
|
|
6065
|
-
await releaseStartupSandboxEnvironment();
|
|
6066
|
-
throw new CodexAppServerStartupError("aborted");
|
|
6067
|
-
}
|
|
6319
|
+
if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
|
|
6068
6320
|
if (sandboxEnvironmentRequired && !startupSandboxEnvironment) throw new Error("Codex app-server did not register an OpenClaw sandbox exec-server environment.");
|
|
6069
6321
|
} catch (error) {
|
|
6070
6322
|
await releaseStartupSandboxEnvironment();
|
|
@@ -6101,6 +6353,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6101
6353
|
client: activeStartupClient,
|
|
6102
6354
|
reserveResumeThread,
|
|
6103
6355
|
bindingStore: params.bindingStore,
|
|
6356
|
+
assertCurrent: params.assertCurrent,
|
|
6104
6357
|
params: params.buildAttemptParams(),
|
|
6105
6358
|
runtimeModelId: params.runtimeModelId,
|
|
6106
6359
|
agentId: params.sessionAgentId,
|
|
@@ -6191,7 +6444,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6191
6444
|
}
|
|
6192
6445
|
} catch (error) {
|
|
6193
6446
|
startupAttemptError = error;
|
|
6194
|
-
if (!
|
|
6447
|
+
if (!startupAbandonController.signal.aborted && !startupClient) {
|
|
6195
6448
|
const sharedClient = clearSharedCodexAppServerClientIfCurrentAndUnclaimed(startupClientForAbandonedRequestCleanup);
|
|
6196
6449
|
if (sharedClient.found && !sharedClient.closed) startupClientForAbandonedRequestCleanup = void 0;
|
|
6197
6450
|
}
|
|
@@ -6200,10 +6453,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6200
6453
|
if (!startupAttemptSucceeded) {
|
|
6201
6454
|
if (releaseSharedClientLease === startupClientLease) releaseSharedClientLease = void 0;
|
|
6202
6455
|
startupClientLease?.();
|
|
6203
|
-
if (
|
|
6204
|
-
if (startupClientForAbandonedRequestCleanup === startupClient) startupClientForAbandonedRequestCleanup = void 0;
|
|
6205
|
-
await closeCodexStartupClientBestEffort(startupClient);
|
|
6206
|
-
} else if (!isCodexAppServerStartSelectionChangedError(startupAttemptError) && (shouldClearSharedClientAfterStartupRace(startupAttemptError) || shouldClearSharedClientAfterStartupFailure(startupAttemptError, params.spawnedBy))) {
|
|
6456
|
+
if (shouldRetireCodexStartupClient(startupAttemptError, params.spawnedBy, startupAbandonController.signal)) {
|
|
6207
6457
|
if (startupClientForAbandonedRequestCleanup === startupClient) startupClientForAbandonedRequestCleanup = void 0;
|
|
6208
6458
|
await closeCodexStartupClientBestEffort(startupClient);
|
|
6209
6459
|
}
|
|
@@ -6214,7 +6464,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6214
6464
|
return await startupAttempt();
|
|
6215
6465
|
} catch (error) {
|
|
6216
6466
|
const selectionChanged = isCodexAppServerStartSelectionChangedError(error);
|
|
6217
|
-
if (
|
|
6467
|
+
if (startupAbandonController.signal.aborted || !selectionChanged && !isCodexAppServerConnectionClosedError(error)) throw error;
|
|
6218
6468
|
const refreshedSharedClient = selectionChanged ? retireSharedCodexAppServerClientIfCurrent(attemptedClient) : clearSharedCodexAppServerClientIfCurrent(attemptedClient);
|
|
6219
6469
|
if (startupClientForAbandonedRequestCleanup === attemptedClient) startupClientForAbandonedRequestCleanup = void 0;
|
|
6220
6470
|
if (attempt >= CODEX_APP_SERVER_STARTUP_MAX_ATTEMPTS) {
|
|
@@ -6247,12 +6497,7 @@ async function startCodexAttemptThread(params) {
|
|
|
6247
6497
|
releaseSharedClientLease
|
|
6248
6498
|
};
|
|
6249
6499
|
} catch (error) {
|
|
6250
|
-
if (params.signal
|
|
6251
|
-
releaseSharedClientLease?.();
|
|
6252
|
-
releaseSharedClientLease = void 0;
|
|
6253
|
-
await closeCodexStartupClientBestEffort(startupClientForAbandonedRequestCleanup);
|
|
6254
|
-
startupClientForAbandonedRequestCleanup = void 0;
|
|
6255
|
-
} else if (!isCodexAppServerStartSelectionChangedError(error) && (shouldClearSharedClientAfterStartupRace(error) || shouldClearSharedClientAfterStartupFailure(error, params.spawnedBy))) {
|
|
6500
|
+
if (shouldRetireCodexStartupClient(error, params.spawnedBy, startupAbandonController.signal)) {
|
|
6256
6501
|
releaseSharedClientLease?.();
|
|
6257
6502
|
releaseSharedClientLease = void 0;
|
|
6258
6503
|
await closeCodexStartupClientBestEffort(startupClientForAbandonedRequestCleanup);
|
|
@@ -6263,11 +6508,9 @@ async function startCodexAttemptThread(params) {
|
|
|
6263
6508
|
params.signal.removeEventListener("abort", abandonStartupAcquire);
|
|
6264
6509
|
}
|
|
6265
6510
|
}
|
|
6266
|
-
function
|
|
6267
|
-
|
|
6268
|
-
|
|
6269
|
-
function shouldClearSharedClientAfterStartupFailure(error, spawnedBy) {
|
|
6270
|
-
return !isCodexAppServerOverloadError(error) && !(error instanceof AgentHarnessPreflightError && error.scope === void 0) && (isCodexAppServerBrokenPipeError(error) || !spawnedBy);
|
|
6511
|
+
function shouldRetireCodexStartupClient(error, spawnedBy, signal) {
|
|
6512
|
+
if (signal.aborted || isCodexAppServerStartupError(error) || isCodexAppServerRequestTimeoutError(error)) return true;
|
|
6513
|
+
return !isCodexAppServerStartSelectionChangedError(error) && !isCodexAppServerOverloadError(error) && !(error instanceof AgentHarnessPreflightError && error.scope === void 0) && (isCodexAppServerBrokenPipeError(error) || !spawnedBy);
|
|
6271
6514
|
}
|
|
6272
6515
|
//#endregion
|
|
6273
6516
|
//#region extensions/codex/src/app-server/run-attempt-start.ts
|
|
@@ -6278,15 +6521,16 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6278
6521
|
const { connection, runtimeParams, preparedAuthBinding, buildActiveRunAttemptParams, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, effectiveRuntimeModelId, sandboxExecServerEnabled } = runtime;
|
|
6279
6522
|
const { toolBridge, toolState } = attemptTools;
|
|
6280
6523
|
const developerInstructions = joinPresentSections(turnState.promptBuild.developerInstructions, attemptTools.configuredMcp?.diagnosticNotice);
|
|
6281
|
-
const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, startupAuthRequirement
|
|
6524
|
+
const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, startupAuthRequirement } = connection;
|
|
6282
6525
|
let pluginAppServer = withCodexAppServerFastModeServiceTier(appServer, runtimeParams);
|
|
6283
|
-
const loopDetectionEnabled = (sessionAgentId && params.config ? resolveAgentConfig
|
|
6526
|
+
const loopDetectionEnabled = (sessionAgentId && params.config ? resolveAgentConfig(params.config, sessionAgentId)?.tools?.loopDetection?.enabled : void 0) ?? params.config?.tools?.loopDetection?.enabled ?? false;
|
|
6284
6527
|
try {
|
|
6285
6528
|
emitCodexAppServerEvent(params, {
|
|
6286
6529
|
stream: "codex_app_server.lifecycle",
|
|
6287
6530
|
data: { phase: "startup" }
|
|
6288
6531
|
});
|
|
6289
6532
|
const startupResult = await startCodexAttemptThread({
|
|
6533
|
+
assertCurrent: connection.assertCurrent,
|
|
6290
6534
|
attemptClientFactory,
|
|
6291
6535
|
bindingStore,
|
|
6292
6536
|
runtime: connection.options.runtime,
|
|
@@ -6342,6 +6586,7 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6342
6586
|
state.sandboxExecEnvironment = startupResult.sandboxEnvironment;
|
|
6343
6587
|
state.releaseSharedClientLease = startupResult.releaseSharedClientLease;
|
|
6344
6588
|
state.restartContextEngineCodexThread = startupResult.restartContextEngineCodexThread;
|
|
6589
|
+
await attemptTools.captureCronCreatorToolAllowlist();
|
|
6345
6590
|
pluginAppServer = startupResult.pluginAppServer;
|
|
6346
6591
|
toolBridge.setRemoteWorkspaceFileReader?.(({ path, maxBytes, workspaceRoot, signal, timeoutMs }) => readBoundedCodexRemoteWorkspaceFile({
|
|
6347
6592
|
client: startupResult.client,
|
|
@@ -6413,7 +6658,6 @@ async function startCodexAttemptRuntime(resources) {
|
|
|
6413
6658
|
await runCleanupStep("codex-start-failure-native-hook-relay", () => nativeHookRelay?.unregister());
|
|
6414
6659
|
await runCleanupStep("codex-start-failure-sandbox-release", releaseSandboxExecEnvironment);
|
|
6415
6660
|
await runCleanupStep("codex-start-failure-shared-client-release", releaseSharedClientLeaseAndRetireOneShotClient);
|
|
6416
|
-
await runCleanupStep("codex-start-failure-abort-listener", () => params.abortSignal?.removeEventListener("abort", abortFromUpstream));
|
|
6417
6661
|
throw error instanceof CodexThreadPolicyHandoffError ? error : state.executionDisconnectError ?? error;
|
|
6418
6662
|
}
|
|
6419
6663
|
}
|
|
@@ -6424,15 +6668,14 @@ function isAuthorityResolutionOperationAbort(error, signal) {
|
|
|
6424
6668
|
}
|
|
6425
6669
|
async function prepareCodexAttemptTools(runtime) {
|
|
6426
6670
|
const { connection, bundleMcpThreadConfig, bundleManifestRegistry, runtimeParams, effectiveRuntimeModelId, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, hookChannelId, codexMcpToolOverrides, authenticatedScheduledMode, configuredMcpSurface, canResolveScheduledConfiguredMcpCreatorAuthority } = runtime;
|
|
6427
|
-
const { params, preDynamicStartupStages, mutable,
|
|
6671
|
+
const { params, preDynamicStartupStages, mutable, resolvedWorkspace, effectiveWorkspace, effectiveCwd, sandboxSessionKey, contextSessionKey, sandbox, sessionPermissionPolicy, runAbortController, sessionAgentId, policyAgentId, pluginConfig, profilerEnabled, agentDir } = connection;
|
|
6428
6672
|
const preDynamicSummary = preDynamicStartupStages.snapshot();
|
|
6429
|
-
if (shouldWarnCodexDynamicToolBuildStageSummary(preDynamicSummary)) embeddedAgentLog.warn(`codex app-server pre-dynamic startup timings runId=${params.runId} sessionId=${params.sessionId} totalMs=${preDynamicSummary.totalMs} stages=${formatCodexDynamicToolBuildStageSummary(preDynamicSummary)}`, {
|
|
6673
|
+
if (shouldWarnCodexDynamicToolBuildStageSummary(preDynamicSummary, profilerEnabled)) embeddedAgentLog.warn(`codex app-server pre-dynamic startup timings runId=${params.runId} sessionId=${params.sessionId} totalMs=${preDynamicSummary.totalMs} stages=${formatCodexDynamicToolBuildStageSummary(preDynamicSummary)}`, {
|
|
6430
6674
|
runId: params.runId,
|
|
6431
6675
|
sessionId: params.sessionId,
|
|
6432
6676
|
totalMs: preDynamicSummary.totalMs,
|
|
6433
6677
|
stages: preDynamicSummary.stages,
|
|
6434
6678
|
hasStartupBinding: Boolean(mutable.startupBinding?.threadId),
|
|
6435
|
-
startupAuthProfileId: startupAuthProfileId ?? null,
|
|
6436
6679
|
bundleMcpDiagnosticCount: bundleMcpThreadConfig.diagnostics.length,
|
|
6437
6680
|
nativeToolSurfaceEnabled
|
|
6438
6681
|
});
|
|
@@ -6495,7 +6738,6 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6495
6738
|
const canResolveScheduledCodexAppAuthority = appCreatorCapture.supported;
|
|
6496
6739
|
const requiresScheduledCodexAppAuthority = appCreatorCapture.required;
|
|
6497
6740
|
const canResolveAnyScheduledCreatorAuthority = canResolveScheduledConfiguredMcpCreatorAuthority || requiresScheduledCodexAppAuthority;
|
|
6498
|
-
let toolBridge;
|
|
6499
6741
|
let creatorAuthorityPromise;
|
|
6500
6742
|
let resolveCreatorAuthorityImpl;
|
|
6501
6743
|
const runtimeYieldCompletionClaim = {};
|
|
@@ -6540,8 +6782,9 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6540
6782
|
let nativeSpecs;
|
|
6541
6783
|
if (hasCodexNativeToolCatalog(mutable.startupBinding)) {
|
|
6542
6784
|
runAbortController.signal.throwIfAborted();
|
|
6543
|
-
|
|
6785
|
+
connection.assertCurrent();
|
|
6544
6786
|
const client = await connection.attemptClientFactory({
|
|
6787
|
+
assertCurrent: connection.assertCurrent,
|
|
6545
6788
|
startOptions: connection.appServer.start,
|
|
6546
6789
|
authProfileId: connection.startupClientAuthProfileId,
|
|
6547
6790
|
agentDir,
|
|
@@ -6556,7 +6799,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6556
6799
|
agentDir,
|
|
6557
6800
|
assertCurrent: () => {
|
|
6558
6801
|
runAbortController.signal.throwIfAborted();
|
|
6559
|
-
|
|
6802
|
+
connection.assertCurrent();
|
|
6560
6803
|
}
|
|
6561
6804
|
});
|
|
6562
6805
|
} finally {
|
|
@@ -6588,7 +6831,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6588
6831
|
sessionId: params.sessionId,
|
|
6589
6832
|
runId: params.runId,
|
|
6590
6833
|
agentId: policyAgentId,
|
|
6591
|
-
agentDir: agentDir ?? resolveAgentDir(params.config ?? {}, sessionAgentId),
|
|
6834
|
+
agentDir: agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId),
|
|
6592
6835
|
agentAccountId: params.agentAccountId,
|
|
6593
6836
|
messageProvider: params.messageProvider ?? params.messageChannel,
|
|
6594
6837
|
messageChannel: params.messageChannel,
|
|
@@ -6672,6 +6915,15 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6672
6915
|
warn: (message) => embeddedAgentLog.warn(message)
|
|
6673
6916
|
}) : void 0;
|
|
6674
6917
|
let scopedMcpTools = void 0;
|
|
6918
|
+
const disposeMcpTools = async () => {
|
|
6919
|
+
for (const [step, materialized] of [["codex-scoped-mcp-dispose", scopedMcpTools], ["codex-configured-mcp-dispose", configuredMcp]]) await runAgentCleanupStep({
|
|
6920
|
+
runId: params.runId,
|
|
6921
|
+
sessionId: params.sessionId,
|
|
6922
|
+
step,
|
|
6923
|
+
log: embeddedAgentLog,
|
|
6924
|
+
cleanup: async () => materialized?.dispose()
|
|
6925
|
+
});
|
|
6926
|
+
};
|
|
6675
6927
|
try {
|
|
6676
6928
|
scopedMcpTools = authenticatedScheduledMode ? void 0 : await materializeRequesterScopedMcpToolsForHarnessRun({
|
|
6677
6929
|
sessionId: params.sessionId,
|
|
@@ -6722,7 +6974,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6722
6974
|
...params.agentAccountId ? { turnSourceAccountId: params.agentAccountId } : {},
|
|
6723
6975
|
...params.currentThreadTs !== void 0 ? { turnSourceThreadId: params.currentThreadTs } : {}
|
|
6724
6976
|
};
|
|
6725
|
-
toolBridge = createCodexDynamicToolBridge({
|
|
6977
|
+
const toolBridge = createCodexDynamicToolBridge({
|
|
6726
6978
|
tools: toolsWithScopedMcp,
|
|
6727
6979
|
registeredTools: registeredWithScopedMcp,
|
|
6728
6980
|
registeredSpecs: nativeSpecs,
|
|
@@ -6732,17 +6984,14 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6732
6984
|
directToolNames: resolveCodexDynamicToolDirectNames(params, isHostScopedAgentToolActive("openclaw")),
|
|
6733
6985
|
hookContext
|
|
6734
6986
|
});
|
|
6735
|
-
|
|
6736
|
-
|
|
6737
|
-
|
|
6987
|
+
const captureCronCreatorToolAllowlist = async () => {
|
|
6988
|
+
await captureFinalCodexCronCreatorToolAllowlist(cronCreatorToolAllowlist, cronCreatorToolAllowlistCaptureRef, toolBridge.availableTools, { nativeToolSurfaceEnabled });
|
|
6989
|
+
if (!authenticatedScheduledMode && bundleMcpThreadConfig.staticServerNames.length > 0 && !canResolveScheduledConfiguredMcpCreatorAuthority) delete cronCreatorToolAllowlistCaptureRef.value;
|
|
6990
|
+
if (requiresScheduledCodexAppAuthority) delete cronCreatorToolAllowlistCaptureRef.value;
|
|
6991
|
+
};
|
|
6738
6992
|
if (canResolveAnyScheduledCreatorAuthority) resolveCreatorAuthorityImpl = async (options) => {
|
|
6739
6993
|
options?.signal?.throwIfAborted();
|
|
6740
6994
|
if (codexAppAuthorityUnavailableReason) throw new Error(codexAppAuthorityUnavailableReason);
|
|
6741
|
-
if (!toolBridge) throw new Error("cron creator authority resolver lost the active tool bridge");
|
|
6742
|
-
const authorityTools = [];
|
|
6743
|
-
const captureRef = {};
|
|
6744
|
-
await captureFinalCodexCronCreatorToolAllowlist(authorityTools, captureRef, toolBridge.availableTools);
|
|
6745
|
-
if (!captureRef.value) throw new Error("cron creator authority snapshot did not produce provenance");
|
|
6746
6995
|
const appSource = scheduledAppAuthoritySourceRef.current;
|
|
6747
6996
|
const runtimeAuthority = canResolveScheduledCodexAppAuthority && scheduledCodexAppAuth ? appSource ? await captureScheduledCodexAppAuthority({
|
|
6748
6997
|
...appSource,
|
|
@@ -6751,46 +7000,39 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6751
7000
|
}) : (() => {
|
|
6752
7001
|
throw new Error("Codex app authority is unavailable before the exact creator thread is active. Retry this automation mutation from the current owner turn.");
|
|
6753
7002
|
})() : void 0;
|
|
6754
|
-
if (!canResolveScheduledConfiguredMcpCreatorAuthority) {
|
|
6755
|
-
options?.signal?.throwIfAborted();
|
|
6756
|
-
return Object.freeze({
|
|
6757
|
-
tools: Object.freeze(authorityTools.map((entry) => Object.freeze(entry))),
|
|
6758
|
-
provenance: Object.freeze(captureRef.value),
|
|
6759
|
-
...runtimeAuthority ? { runtimeAuthority } : {}
|
|
6760
|
-
});
|
|
6761
|
-
}
|
|
6762
|
-
const authorityRuntimeId = `cron-authority:${params.runId}`;
|
|
6763
7003
|
let materialized;
|
|
6764
7004
|
try {
|
|
6765
|
-
|
|
6766
|
-
|
|
6767
|
-
|
|
6768
|
-
|
|
6769
|
-
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
6774
|
-
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
6782
|
-
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
7005
|
+
if (canResolveScheduledConfiguredMcpCreatorAuthority) try {
|
|
7006
|
+
materialized = await materializeStaticMcpToolsForHarnessRun({
|
|
7007
|
+
sessionId: `cron-authority:${params.runId}`,
|
|
7008
|
+
agentId: sessionAgentId,
|
|
7009
|
+
workspaceDir: effectiveWorkspace,
|
|
7010
|
+
agentDir: policyContext.agentDir,
|
|
7011
|
+
cfg: params.config,
|
|
7012
|
+
manifestRegistry: bundleManifestRegistry,
|
|
7013
|
+
reservedToolNames: toolBridge.availableTools.map((tool) => tool.name),
|
|
7014
|
+
toolsAllow: params.toolsAllow,
|
|
7015
|
+
toolOverrides: codexMcpToolOverrides,
|
|
7016
|
+
autoApproveCodexAppServerApprovals: shouldAutoApproveCodexAppServerApprovals(connection.appServer),
|
|
7017
|
+
projectedMcpServers: bundleMcpThreadConfig.configPatch?.mcp_servers,
|
|
7018
|
+
policyContext,
|
|
7019
|
+
warn: (message) => embeddedAgentLog.warn(message),
|
|
7020
|
+
retireSessionRuntimeAfterDispose: true
|
|
7021
|
+
});
|
|
7022
|
+
} catch (error) {
|
|
7023
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
7024
|
+
throw new Error(`Configured MCP discovery failed while resolving inherited automation authority: ${detail}. Retry after the server is available, or provide an explicit finite toolsAllow list containing only currently visible tools; no automation changes were saved.`, { cause: error });
|
|
7025
|
+
}
|
|
6786
7026
|
options?.signal?.throwIfAborted();
|
|
6787
|
-
if (materialized
|
|
6788
|
-
const
|
|
7027
|
+
if (materialized?.diagnosticNotice) throw new Error(`${materialized.diagnosticNotice} Sign in to the affected MCP server and retry, or provide an explicit finite toolsAllow list containing only currently visible tools. No automation changes were saved.`);
|
|
7028
|
+
const configuredTools = materialized ? projectCodexExecutableDynamicTools({
|
|
6789
7029
|
tools: filterCodexDynamicTools(materialized.tools, pluginConfig),
|
|
6790
7030
|
hookContext
|
|
6791
|
-
});
|
|
6792
|
-
|
|
6793
|
-
|
|
7031
|
+
}).availableTools : [];
|
|
7032
|
+
const authorityTools = [];
|
|
7033
|
+
const captureRef = {};
|
|
7034
|
+
await captureFinalCodexCronCreatorToolAllowlist(authorityTools, captureRef, [...toolBridge.availableTools, ...configuredTools], { nativeToolSurfaceEnabled });
|
|
7035
|
+
if (!captureRef.value) throw new Error("cron creator authority snapshot did not produce provenance");
|
|
6794
7036
|
options?.signal?.throwIfAborted();
|
|
6795
7037
|
return Object.freeze({
|
|
6796
7038
|
tools: Object.freeze(authorityTools.map((entry) => Object.freeze(entry))),
|
|
@@ -6798,7 +7040,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6798
7040
|
...runtimeAuthority ? { runtimeAuthority } : {}
|
|
6799
7041
|
});
|
|
6800
7042
|
} finally {
|
|
6801
|
-
await materialized
|
|
7043
|
+
await materialized?.dispose();
|
|
6802
7044
|
}
|
|
6803
7045
|
};
|
|
6804
7046
|
return {
|
|
@@ -6806,9 +7048,9 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6806
7048
|
registeredTools: registeredWithScopedMcp,
|
|
6807
7049
|
scopedMcpTools,
|
|
6808
7050
|
configuredMcp,
|
|
7051
|
+
disposeMcpTools,
|
|
6809
7052
|
configuredMcpOwnershipVersion: configuredMcpSurface === "scheduled" ? 1 : void 0,
|
|
6810
|
-
|
|
6811
|
-
cronCreatorToolAllowlistCaptureRef,
|
|
7053
|
+
captureCronCreatorToolAllowlist,
|
|
6812
7054
|
scheduledAppAuthoritySourceRef,
|
|
6813
7055
|
dynamicToolParams,
|
|
6814
7056
|
compactionPlanState,
|
|
@@ -6823,8 +7065,7 @@ async function prepareCodexAttemptTools(runtime) {
|
|
|
6823
7065
|
runtimeYieldCompletionClaim
|
|
6824
7066
|
};
|
|
6825
7067
|
} catch (error) {
|
|
6826
|
-
await
|
|
6827
|
-
await configuredMcp?.dispose();
|
|
7068
|
+
await disposeMcpTools();
|
|
6828
7069
|
throw error;
|
|
6829
7070
|
}
|
|
6830
7071
|
}
|
|
@@ -6909,6 +7150,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
|
|
|
6909
7150
|
};
|
|
6910
7151
|
const startCodexTurn = async () => {
|
|
6911
7152
|
const activeTurnRoute = await ensureCurrentThreadRoute();
|
|
7153
|
+
assertCodexSessionRuntimeOwnership(resourceState.thread, params.expectedSessionRuntimeOwnership);
|
|
6912
7154
|
const turnAppServer = withCodexAppServerFastModeServiceTier(connection.mutable.pluginAppServer, runtimeParams);
|
|
6913
7155
|
connection.mutable.pluginAppServer = turnAppServer;
|
|
6914
7156
|
const turnStartParams = buildTurnStartParams(runtimeParams, {
|
|
@@ -6949,9 +7191,11 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
|
|
|
6949
7191
|
try {
|
|
6950
7192
|
const startedTurn = assertCodexTurnStartResponse(await resourceState.client.request("turn/start", turnStartParams, {
|
|
6951
7193
|
timeoutMs: params.timeoutMs,
|
|
6952
|
-
signal: runAbortController.signal
|
|
7194
|
+
signal: runAbortController.signal,
|
|
7195
|
+
assertCurrent: connection.assertCurrent
|
|
6953
7196
|
}));
|
|
6954
7197
|
acceptedTurnId = startedTurn.turn.id;
|
|
7198
|
+
connection.assertCurrent();
|
|
6955
7199
|
throwIfTurnStartAcceptedAfterAbort();
|
|
6956
7200
|
return startedTurn;
|
|
6957
7201
|
} catch (error) {
|
|
@@ -7004,7 +7248,7 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
|
|
|
7004
7248
|
const { context, turnState, systemPromptReport } = prompt;
|
|
7005
7249
|
const { runtime, historyState, hookContext, hookContextWindowFields, hookRunner } = context;
|
|
7006
7250
|
const { connection, runtimeParams, effectiveRuntimeProviderId, effectiveRuntimeModelId } = runtime;
|
|
7007
|
-
const { params, usesSupervisionConnection, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, attemptStartedAt, startupAuthProfileId
|
|
7251
|
+
const { params, usesSupervisionConnection, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, attemptStartedAt, startupAuthProfileId } = connection;
|
|
7008
7252
|
const { state, turnIdRef } = turnRuntime;
|
|
7009
7253
|
const { waitForActiveNativeTurnCompletion } = notifications;
|
|
7010
7254
|
const { codexModelCallDiagnostics, startCodexTurn, buildLlmInputEvent } = requestRuntime;
|
|
@@ -7040,52 +7284,51 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
|
|
|
7040
7284
|
error: turnStartError,
|
|
7041
7285
|
contextEngineActive: Boolean(activeContextEngine),
|
|
7042
7286
|
thread: resourceState.thread
|
|
7043
|
-
}) && resourceState.restartContextEngineCodexThread) {
|
|
7287
|
+
}) && resourceState.restartContextEngineCodexThread) try {
|
|
7288
|
+
assertCodexBindingMayBeReplaced(resourceState.thread, "retrying an overflow on a fresh native thread", params.expectedSessionRuntimeOwnership);
|
|
7044
7289
|
embeddedAgentLog.warn("codex app-server context-engine turn overflowed on resume; retrying with fresh thread", {
|
|
7045
7290
|
threadId: resourceState.thread.threadId,
|
|
7046
7291
|
error: formatErrorMessage(turnStartError)
|
|
7047
7292
|
});
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
|
|
7051
|
-
|
|
7052
|
-
|
|
7053
|
-
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
|
|
7057
|
-
|
|
7058
|
-
|
|
7059
|
-
|
|
7060
|
-
|
|
7061
|
-
|
|
7062
|
-
|
|
7063
|
-
|
|
7064
|
-
|
|
7065
|
-
|
|
7066
|
-
} }
|
|
7067
|
-
});
|
|
7068
|
-
embeddedAgentLog.info("codex app-server cleared stale context-engine projection after overflow retry", {
|
|
7069
|
-
threadId: resourceState.thread.threadId,
|
|
7070
|
-
previousEpoch: retryBinding.contextEngine.projection.epoch
|
|
7071
|
-
});
|
|
7072
|
-
}
|
|
7073
|
-
emitCodexAppServerEvent(params, {
|
|
7074
|
-
stream: "codex_app_server.lifecycle",
|
|
7075
|
-
data: {
|
|
7076
|
-
phase: "thread_ready_retry",
|
|
7077
|
-
threadId: resourceState.thread.threadId
|
|
7078
|
-
}
|
|
7293
|
+
if (!await bindingStore.mutate(bindingIdentity, {
|
|
7294
|
+
kind: "clear",
|
|
7295
|
+
threadId: resourceState.thread.threadId
|
|
7296
|
+
})) embeddedAgentLog.warn("codex app-server preserved newer context-engine binding after resume overflow; skipping fresh retry", {
|
|
7297
|
+
threadId: resourceState.thread.threadId,
|
|
7298
|
+
error: formatErrorMessage(turnStartError)
|
|
7299
|
+
});
|
|
7300
|
+
else {
|
|
7301
|
+
resourceState.thread = await resourceState.restartContextEngineCodexThread();
|
|
7302
|
+
const retryBinding = bindingStore.read(bindingIdentity);
|
|
7303
|
+
if (retryBinding && retryBinding.threadId === resourceState.thread.threadId && retryBinding.contextEngine?.projection) {
|
|
7304
|
+
await bindingStore.mutate(bindingIdentity, {
|
|
7305
|
+
kind: "patch",
|
|
7306
|
+
threadId: retryBinding.threadId,
|
|
7307
|
+
patch: { contextEngine: {
|
|
7308
|
+
...retryBinding.contextEngine,
|
|
7309
|
+
projection: void 0
|
|
7310
|
+
} }
|
|
7079
7311
|
});
|
|
7080
|
-
|
|
7081
|
-
|
|
7082
|
-
|
|
7083
|
-
|
|
7312
|
+
embeddedAgentLog.info("codex app-server cleared stale context-engine projection after overflow retry", {
|
|
7313
|
+
threadId: resourceState.thread.threadId,
|
|
7314
|
+
previousEpoch: retryBinding.contextEngine.projection.epoch
|
|
7315
|
+
});
|
|
7316
|
+
}
|
|
7317
|
+
emitCodexAppServerEvent(params, {
|
|
7318
|
+
stream: "codex_app_server.lifecycle",
|
|
7319
|
+
data: {
|
|
7320
|
+
phase: "thread_ready_retry",
|
|
7321
|
+
threadId: resourceState.thread.threadId
|
|
7084
7322
|
}
|
|
7323
|
+
});
|
|
7324
|
+
try {
|
|
7325
|
+
turn = await startCodexTurn();
|
|
7326
|
+
} catch (retryError) {
|
|
7327
|
+
turnStartError = retryError;
|
|
7085
7328
|
}
|
|
7086
|
-
} catch (retrySetupError) {
|
|
7087
|
-
turnStartError = retrySetupError;
|
|
7088
7329
|
}
|
|
7330
|
+
} catch (retrySetupError) {
|
|
7331
|
+
turnStartError = retrySetupError;
|
|
7089
7332
|
}
|
|
7090
7333
|
if (turn === void 0) {
|
|
7091
7334
|
const usageLimitError = await formatCodexTurnStartUsageLimitError({
|
|
@@ -7101,7 +7344,7 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
|
|
|
7101
7344
|
phase: "turn_start",
|
|
7102
7345
|
threadId: resourceState.thread.threadId,
|
|
7103
7346
|
error: message
|
|
7104
|
-
});
|
|
7347
|
+
}, params.expectedSessionRuntimeOwnership);
|
|
7105
7348
|
emitCodexAppServerEvent(params, {
|
|
7106
7349
|
stream: "codex_app_server.lifecycle",
|
|
7107
7350
|
data: {
|
|
@@ -7180,7 +7423,6 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
|
|
|
7180
7423
|
log: embeddedAgentLog,
|
|
7181
7424
|
cleanup: async () => trajectoryRecorder?.flush()
|
|
7182
7425
|
});
|
|
7183
|
-
params.abortSignal?.removeEventListener("abort", abortFromUpstream);
|
|
7184
7426
|
await releaseSharedClientLeaseAndRetireOneShotClient();
|
|
7185
7427
|
if (usageLimitError) {
|
|
7186
7428
|
await markCodexAuthProfileBlockedFromRateLimits({
|
|
@@ -7191,7 +7433,7 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
|
|
|
7191
7433
|
return { result: buildCodexTurnStartFailureResult({
|
|
7192
7434
|
params,
|
|
7193
7435
|
message: usageLimitError.message,
|
|
7194
|
-
promptError:
|
|
7436
|
+
promptError: new CodexUsageLimitPromptError(usageLimitError.message),
|
|
7195
7437
|
messagesSnapshot,
|
|
7196
7438
|
systemPromptReport
|
|
7197
7439
|
}) };
|
|
@@ -7407,35 +7649,47 @@ function createCodexAttemptTurnState(resources) {
|
|
|
7407
7649
|
//#endregion
|
|
7408
7650
|
//#region extensions/codex/src/app-server/run-attempt.ts
|
|
7409
7651
|
async function runCodexAppServerAttempt(params, options) {
|
|
7410
|
-
const
|
|
7652
|
+
const preparation = createCodexAttemptPreparationTiming(params);
|
|
7653
|
+
const connection = await preparation.measure("connection", () => prepareCodexAttemptConnection({
|
|
7411
7654
|
params,
|
|
7412
7655
|
options
|
|
7413
|
-
});
|
|
7414
|
-
const runtime = await prepareCodexAttemptRuntime(connection);
|
|
7415
|
-
const attemptTools = await prepareCodexAttemptTools(runtime);
|
|
7416
|
-
const resources = prepareCodexAttemptResources(await prepareCodexAttemptPrompt(await prepareCodexAttemptContext(runtime, attemptTools)));
|
|
7417
|
-
attemptTools.runtimeYieldCompletionClaim.current = () => resources.state.nativeHookRelay?.hasClaimedDirectChild() ?? false;
|
|
7418
|
-
await startCodexAttemptRuntime(resources);
|
|
7419
|
-
const turnRuntime = createCodexAttemptTurnState(resources);
|
|
7656
|
+
}));
|
|
7420
7657
|
try {
|
|
7421
|
-
const
|
|
7422
|
-
const
|
|
7423
|
-
const { ensureCurrentThreadRoute } = await prepareCodexAttemptRoute(resources, turnRuntime, notifications, createCodexAttemptServerRequestController(resources, turnRuntime, lifecycle).handleServerRequest);
|
|
7424
|
-
const turnRequest = await prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurrentThreadRoute, notifications.waitForActiveNativeTurnCompletion);
|
|
7425
|
-
const turnStart = await startCodexAttemptTurn(resources, turnRuntime, notifications, turnRequest);
|
|
7426
|
-
if ("result" in turnStart) return turnStart.result;
|
|
7427
|
-
const activeTurn = activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notifications, turnStart.turn);
|
|
7428
|
-
let finalizedResult;
|
|
7658
|
+
const runtime = await preparation.measure("runtime", () => prepareCodexAttemptRuntime(connection));
|
|
7659
|
+
const attemptTools = await preparation.measure("tools", () => prepareCodexAttemptTools(runtime));
|
|
7429
7660
|
try {
|
|
7430
|
-
await
|
|
7431
|
-
|
|
7661
|
+
const attemptContext = await preparation.measure("context", () => prepareCodexAttemptContext(runtime, attemptTools));
|
|
7662
|
+
const resources = prepareCodexAttemptResources(await preparation.measure("prompt", () => prepareCodexAttemptPrompt(attemptContext)));
|
|
7663
|
+
attemptTools.runtimeYieldCompletionClaim.current = () => resources.state.nativeHookRelay?.hasClaimedDirectChild() ?? false;
|
|
7664
|
+
await preparation.measure("runtime-start", () => startCodexAttemptRuntime(resources));
|
|
7665
|
+
const turnRuntime = createCodexAttemptTurnState(resources);
|
|
7666
|
+
try {
|
|
7667
|
+
const lifecycle = createCodexAttemptLifecycleController(resources, turnRuntime);
|
|
7668
|
+
const notifications = createCodexAttemptNotificationController(resources, turnRuntime, lifecycle);
|
|
7669
|
+
const serverRequests = createCodexAttemptServerRequestController(resources, turnRuntime, lifecycle);
|
|
7670
|
+
const { ensureCurrentThreadRoute } = await preparation.measure("thread-route", () => prepareCodexAttemptRoute(resources, turnRuntime, notifications, serverRequests.handleServerRequest));
|
|
7671
|
+
const turnRequest = await preparation.measure("turn-request", () => prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurrentThreadRoute, notifications.waitForActiveNativeTurnCompletion));
|
|
7672
|
+
preparation.ready();
|
|
7673
|
+
const turnStart = await startCodexAttemptTurn(resources, turnRuntime, notifications, turnRequest);
|
|
7674
|
+
if ("result" in turnStart) return turnStart.result;
|
|
7675
|
+
const activeTurn = activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notifications, turnStart.turn);
|
|
7676
|
+
let finalizedResult;
|
|
7677
|
+
try {
|
|
7678
|
+
await activeTurn.ready;
|
|
7679
|
+
finalizedResult = await finalizeCodexAttempt(resources, turnRuntime, lifecycle, notifications, turnRequest, activeTurn);
|
|
7680
|
+
} finally {
|
|
7681
|
+
await cleanupCodexAttempt(resources, turnRuntime, lifecycle, turnRequest, activeTurn);
|
|
7682
|
+
}
|
|
7683
|
+
if (resources.state.executionDisconnectError && !connection.terminalState.explicitCancellationObserved) throw resources.state.executionDisconnectError;
|
|
7684
|
+
return finalizedResult;
|
|
7685
|
+
} finally {
|
|
7686
|
+
turnRuntime.deadlines.dispose();
|
|
7687
|
+
}
|
|
7432
7688
|
} finally {
|
|
7433
|
-
await
|
|
7689
|
+
await attemptTools.disposeMcpTools();
|
|
7434
7690
|
}
|
|
7435
|
-
if (resources.state.executionDisconnectError && !connection.terminalState.explicitCancellationObserved) throw resources.state.executionDisconnectError;
|
|
7436
|
-
return finalizedResult;
|
|
7437
7691
|
} finally {
|
|
7438
|
-
|
|
7692
|
+
params.abortSignal?.removeEventListener("abort", connection.abortFromUpstream);
|
|
7439
7693
|
}
|
|
7440
7694
|
}
|
|
7441
7695
|
//#endregion
|