@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.
Files changed (67) hide show
  1. package/dist/api.js +6 -6
  2. package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-Bp1ZOnk2.js} +76 -32
  3. package/dist/{attempt-context-DmQUNWwT.js → attempt-context-CSazkWns.js} +6 -6
  4. package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-DxGJRYbY.js} +46 -45
  5. package/dist/{capabilities-dIjNVCYH.js → capabilities-B1mgvpP8.js} +2 -1
  6. package/dist/cli-metadata.js +1 -1
  7. package/dist/{command-formatters-CLHhEB1Q.js → command-formatters-DSbGMXA0.js} +2 -2
  8. package/dist/{command-handlers-CTGb2csu.js → command-handlers-DOJvGv6-.js} +146 -74
  9. package/dist/{compact-_t0HQrUS.js → compact-Y_xBqrHN.js} +83 -48
  10. package/dist/{config-BhmfC1s6.js → config-CyapYSji.js} +47 -105
  11. package/dist/config-utils-C57JiJrU.js +69 -0
  12. package/dist/doctor-contract-api.js +4 -5
  13. package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-BwpvTxaX.js} +678 -638
  14. package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
  15. package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-B9kp6iGC.js} +11 -2
  16. package/dist/{event-projector-usage-C5mcrGjp.js → event-projector-usage-ZqEVbAEY.js} +30 -13
  17. package/dist/{harness-DXVZ5II5.js → harness-Czh2Sdoc.js} +36 -13
  18. package/dist/harness.js +1 -1
  19. package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
  20. package/dist/index.js +68 -84
  21. package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-CRh-51AK.js} +9 -21
  22. package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DcpnJF9x.js} +105 -73
  23. package/dist/media-understanding-provider.js +1 -1
  24. package/dist/{model-catalog-CUM68Hkl.js → model-catalog-DT5vo6qo.js} +5 -5
  25. package/dist/{models-sYnEc0gd.js → models-CcrgSMQR.js} +4 -4
  26. package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-B3bvQGcg.js} +12 -11
  27. package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-nfbUOtUB.js} +3 -3
  28. package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-aQVdyL5g.js} +1 -1
  29. package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → plugin-marketplace-discovery-B7gHXJ3d.js} +35 -22
  30. package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-BwCLTY_U.js} +5 -5
  31. package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-BpG9Ltc5.js} +2 -2
  32. package/dist/{rate-limits-CawQJfUS.js → rate-limits-Fx_l4eNa.js} +1 -1
  33. package/dist/{request-DYAI5FQE.js → request-C8H22rPi.js} +2 -2
  34. package/dist/{run-attempt-D1hJO4fX.js → run-attempt-BzthFQSM.js} +977 -723
  35. package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-Bh_gf6-t.js} +3 -3
  36. package/dist/{session-binding-BHuTCRZQ.js → session-binding-4Ki04sW-.js} +94 -282
  37. package/dist/session-binding-record-CyaXZvTe.js +270 -0
  38. package/dist/{session-catalog-yyvTWFOw.js → session-catalog-B47uwekb.js} +266 -114
  39. package/dist/{session-cli-CmFEXMAM.js → session-cli-BjLhpmS1.js} +1 -1
  40. package/dist/session-history-DWmMqiqW.js +93 -0
  41. package/dist/session-history-read-LHldwvyh.js +36 -0
  42. package/dist/session-history-worker-runtime.js +48 -0
  43. package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-zZVcx0ME.js} +30 -31
  44. package/dist/session-history.worker.js +2 -0
  45. package/dist/{session-initialization-BeWzjGiR.js → session-initialization-BCFVnLL4.js} +2 -1
  46. package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-BaueHmSj.js} +1 -1
  47. package/dist/{session-retirement-BujDjXVF.js → session-retirement-DNdmYdFc.js} +7 -7
  48. package/dist/{session-upstream-marker-C351-5Qw.js → session-upstream-marker-DReTpGz6.js} +4 -3
  49. package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
  50. package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BI-b1sry.js} +53 -42
  51. package/dist/{shared-client-DxcfF9KX.js → shared-client-CKhX2kFt.js} +279 -268
  52. package/dist/{side-question-BTZAII4l.js → side-question-B6DWAw1A.js} +85 -36
  53. package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-DPK30jad.js} +382 -388
  54. package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-CbucAmmp.js} +5 -5
  55. package/dist/thread-policy-CTalhWFy.js +105 -0
  56. package/dist/{thread-resume-C7pyVKeW.js → thread-resume-BLgqkUc1.js} +7 -7
  57. package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-_njEB84z.js} +67 -125
  58. package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
  59. package/dist/{transport-stdio-CyPldczm.js → transport-stdio-CzTngV0j.js} +10 -8
  60. package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-1fwbNKzQ.js} +85 -165
  61. package/dist/{usage-Bj-rrzkR.js → usage-i9fv5-4m.js} +3 -3
  62. package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
  63. package/package.json +6 -6
  64. package/dist/binding-connection-E6uDsPlx.js +0 -45
  65. package/dist/launch-args-RXQwn8zV.js +0 -90
  66. package/dist/session-history-C5J1AKzG.js +0 -87
  67. package/dist/thread-policy-g4KbJPzp.js +0 -54
@@ -1,41 +1,43 @@
1
- import { $t as isJsonObject, A as TURN_FINALIZE_DRAIN_ABORT_GRACE_MS, B as isCodexAppServerIndeterminateRequestCancellationError, Bt as resolveCodexAppServerAuthProfileIdForAgent, Ct as ensureCodexAppServerClientRuntime, Dt as protectCodexAppServerLiveThread, F as withCodexStartupTimeout, Ft as readRecentCodexRateLimits, H as isCodexAppServerOverloadError, Ht as resolveCodexAppServerFallbackApiKeyCacheKey, I as getCodexAppServerClientInstanceId, It as rememberCodexRateLimitsRead, K as resolveCodexAppServerClientInstanceId, L as isCodexAppServerApprovalRequest, M as isCodexAppServerStartupError, Mt as withAbortableTimeout, P as resolveCodexStartupTimeoutMs, Pt as readCodexRateLimitsRevision, Qt as flattenCodexDynamicToolFunctions, R as isCodexAppServerBrokenPipeError, Rt as resolveCodexAppServerAuthAccountCacheKey, Ut as resolveCodexAppServerPreparedApiKeyCacheKey, V as isCodexAppServerIndeterminateTransportError, W as isCodexAppServerRequestTimeoutError, Wt as resolveCodexAppServerPreparedAuthHandoff, _t as resolveCodexToolAbortTerminalReason, a as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, at as readCodexTurnCompletedNotification, c as getLeasedSharedCodexAppServerClient, ct as hasPendingDynamicToolTerminalDiagnostic, dt as resolveDynamicToolCallTimeoutMs, f as readCodexAppServerClientDesktopGenerationFingerprint, ft as resolveTerminalDynamicToolBatchAction, gt as toCodexDynamicToolProtocolResponse, h as releaseLeasedSharedCodexAppServerClient, ht as toCodexDynamicToolProgressResponse, i as clearSharedCodexAppServerClientIfCurrent, it as readCodexTurn, j as TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS, k as CodexAppServerStartupError, l as getSharedCodexAppServerClient, lt as isDynamicToolTerminalDiagnosticEvent, mt as shouldReleaseTurnAfterTerminalDynamicTool, nt as readCodexDynamicToolCallParams, ot as createCodexElicitationResponse, pt as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, q as CodexAppServerRpcError, s as createIsolatedCodexAppServerClient, st as handleDynamicToolCallWithTimeout, tt as assertCodexTurnStartResponse, u as isCodexAppServerStartSelectionChangedError, ut as isMatchingDynamicToolTerminalDiagnostic, v as retainSharedCodexAppServerClientIfCurrent, y as retireSharedCodexAppServerClientIfCurrent, z as isCodexAppServerConnectionClosedError, zt as resolveCodexAppServerAuthProfileId } from "./shared-client-DxcfF9KX.js";
2
- import { C as isCodexPairedNodeRemoteExecPlacementSandbox, D as resolveCodexPluginsPolicy, E as readCodexPluginConfig, F as resolveCodexAppServerHomeDir, O as resolveOpenClawExecPolicyForCodexAppServer, T as isCodexSandboxExecServerEnabled, d as shouldAutoApproveCodexAppServerApprovals, f as withMcpElicitationsApprovalPolicy, h as resolveCodexModelBackedReviewerPolicyContext, l as hasCodexMcpToolApprovalOverrides, m as canUseCodexModelBackedApprovalsReviewerForModel, o as resolveCodexComputerUseConfig, r as resolveCodexAppServerHomeScope, w as isCodexRemoteExecPlacementSandbox, y as readCodexRequirementsToml } from "./config-BhmfC1s6.js";
3
- import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, i as createCodexSessionGenerationSupersededError, l as resolveCodexRunSessionBindingAuthority, u as scopeCodexRunBindingStore } from "./session-binding-BHuTCRZQ.js";
4
- import { B as readNonNegativeInteger, E as itemStatus, H as splitPlanText, I as readItem, L as readItemString, M as extractRawAssistantText, O as matchesCodexSnapshotTurn, P as readCodexErrorNotificationMessage, T as itemName, V as readNullableString, 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-DYHcRQAa.js";
5
- import { a as codexExecutionToolName, c as isPendingOpenClawDynamicToolCompletionNotification, d as isTerminalTurnStatus, f as readCodexNotificationItem, h as updateActiveTurnItemIds, l as isRawFunctionToolOutputCompletionNotification, m as readRawResponseToolCallId, p as readNotificationItemId, r as projectCodexThreadUsageUpdate, s as isCodexTurnAbortMarkerNotification, t as CodexResponseCompletionProjection } from "./event-projector-usage-C5mcrGjp.js";
6
- import { i as buildCodexPluginAppCacheKey, r as buildCodexAppServerRuntimeFingerprint, s as defaultCodexAppInventoryCache } from "./thread-resume-C7pyVKeW.js";
7
- import { A as readCodexMcpToolConnectorId, B as emitCodexNativePreToolUseFailureDiagnostic, C as buildDeveloperInstructions, Ct as buildCodexPluginThreadConfig, D as resolveCodexAppServerThreadModelSelection, Dt 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, Tt as buildCodexPluginThreadConfigTimeoutFallback, 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 buildCodexPluginThreadConfigInputFingerprint, xt as resolveCodexContinuityProjectionMaxChars, yt as resolveCodexContextEngineProjectionMaxChars, z as createCodexNativeHookRelay } from "./thread-lifecycle-DAcEJ_Om.js";
8
- import { l as isIncognitoSessionKey, r as retainCodexAppServerBindingSubscription } from "./thread-ownership-zGokd8i1.js";
9
- import { a as buildCodexUserPromptMessage, i as mirrorPromptAtTurnStartBestEffort, l as hasCodexMirrorOrigin, n as createCodexAppServerUserMessagePersistenceNotifier, o as promptSnapshot, s as applyCodexTranscriptTaint, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-DTUxFWa_.js";
10
- import { n as CodexThreadPolicyHandoffError } from "./thread-policy-g4KbJPzp.js";
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 CODEX_CONTROL_METHODS } from "./capabilities-dIjNVCYH.js";
13
- import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-CawQJfUS.js";
14
- import { a as formatCodexDisplayText } from "./command-formatters-CLHhEB1Q.js";
15
- import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy } from "./session-permission-policy-DeWVTCMj.js";
16
- import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-E6uDsPlx.js";
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-DHRFXKbS.js";
20
- 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-CnH147jH.js";
21
- import { a as requestPluginApprovalOutcome } from "./plugin-approval-roundtrip-CNe-Xrjx.js";
22
- import { S as shouldWarnCodexDynamicToolBuildStageSummary, T as CodexNativeToolLifecycleProjector, _ as resolveCodexMessageToolProvider, a as emitDynamicToolStartedDiagnostic, b as shouldEnableCodexAppServerNativeToolSurface, c as ensureCodexSandboxExecServerEnvironment, d as createCodexDynamicToolBuildStageTracker, f as disableCodexPluginThreadConfig, g as resolveCodexExternalSandboxPolicyForOpenClawSandbox, h as resolveCodexAppServerHookChannelId, i as emitDynamicToolErrorDiagnostic, l as releaseCodexSandboxExecServerEnvironment, m as resolveCodexAppServerExecutionCwd, n as projectCodexExecutableDynamicTools, o as emitDynamicToolTerminalDiagnostic, p as formatCodexDynamicToolBuildStageSummary, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, u as buildDynamicTools, w as readBoundedCodexRemoteWorkspaceFile, x as shouldRequireCodexSandboxExecServerEnvironment, y as resolveCodexSandboxEnvironmentSelection } from "./dynamic-tools-BU9tmlYm.js";
23
- import { t as resolveCodexProviderWebSearchSupport } from "./provider-capabilities-DW5p4k9w.js";
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-DmQUNWwT.js";
25
- import { n as captureCodexSettledTurnFinalizationContext } from "./settled-turn-context-D3SNWtUn.js";
26
- import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-BFrPhb2c.js";
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 { MAX_TIMER_TIMEOUT_MS, asDateTimestampMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
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 { createHash } from "node:crypto";
35
- import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-runtime";
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
- const liveItems = items.filter((item) => !item.settled);
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 input = [];
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
- input.push(...await params.prepareMessage(item.text, item));
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
- await params.client.request("turn/steer", {
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 unavailableThreadUsage = input.tokenUsage ? {
1059
- ...input.tokenUsage,
1136
+ const usage = input.usageProjection.usage;
1137
+ const projectedUsage = input.aborted && usage ? {
1138
+ ...usage,
1060
1139
  contextUsage: { state: "unavailable" }
1061
- } : void 0;
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.responseCompletions.modelIterations > 0 ? { modelIterations: input.responseCompletions.modelIterations } : {},
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
- function createCodexUsageLimitPromptError(message) {
1238
- return Object.assign(new Error(message), { status: 429 });
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
- return usageLimitMessage ? createCodexUsageLimitPromptError(usageLimitMessage) : source.message ?? void 0;
1243
- }
1244
- function isCodexUsageLimitPromptError(error) {
1245
- return error instanceof Error && "status" in error && error.status === 429;
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.promptErrorSource = null;
1497
+ this.terminalFailure = new CodexTerminalFailureProjection();
1386
1498
  this.synthesizedMissingToolResultError = null;
1387
1499
  this.aborted = false;
1388
- this.responseCompletions = new CodexResponseCompletionProjection();
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
- if (!item || this.nativeToolOutcomeOrdinals.has(item.id) || !shouldClearTerminalPresentationForNativeItem(item)) return;
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
- projectCodexThreadUsageUpdate(params, this.tokenUsage, (usage) => this.tokenUsage = usage, (data) => {
1518
- if (data.modelContextWindow !== void 0) {
1519
- this.contextTokens = data.modelContextWindow;
1520
- this.contextTokensSource = this.params.authoredContextTokenCap === void 0 ? "runtime" : "runtime-configured";
1521
- }
1522
- this.emitAgentEvent({
1523
- stream: "usage",
1524
- data
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.responseCompletions.record(params, this.params.hostCapabilities.reportOutputTokens);
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.responseCompletions.clear();
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.promptError = resolveCodexPromptError({
1548
- message: readCodexErrorNotificationMessage(params),
1658
+ this.terminalFailure.record({
1659
+ message,
1549
1660
  codexErrorInfo,
1550
- rateLimits: this.options.readRecentRateLimits?.()
1551
- }) ?? "codex app-server error";
1552
- this.promptErrorSource = compactionFailure ? "compaction" : "prompt";
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.promptErrorSource = this.promptErrorSource ?? "prompt";
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
- responseCompletions: this.responseCompletions,
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.responseCompletions.clear();
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: await this.toolTranscriptProjection.readMirroredSessionMessages(),
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.projectionClosed) return;
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: await this.toolTranscriptProjection.readMirroredSessionMessages(),
1820
+ messages,
1699
1821
  compactedCount: -1,
1700
1822
  ctx: this.options.agentHookContext ?? {}
1701
1823
  });
1702
- if (this.projectionClosed) return;
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.recordNativeToolResultWithDetails(item);
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.responseCompletions.clear();
1870
+ if (turn.status !== "completed") this.usageProjection.invalidateContext();
1747
1871
  if (turn.status === "failed") {
1748
- this.promptError = resolveCodexPromptError({
1872
+ const codexErrorInfo = turn.error?.codexErrorInfo;
1873
+ this.terminalFailure.record({
1749
1874
  message: turn.error?.message,
1750
- codexErrorInfo: turn.error?.codexErrorInfo,
1751
- rateLimits: this.options.readRecentRateLimits?.()
1752
- }) ?? "codex app-server turn failed";
1753
- this.promptErrorSource = compactionFailure ? "compaction" : "prompt";
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.recordNativeToolResultWithDetails(item);
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
- ...dynamicToolParams,
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: dynamicToolParams,
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
- params.hostCapabilities.assertActive();
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 claimPendingUserInputAnswer = async (text, optionsLocal) => {
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
- if (await claimPendingUserInputAnswer(text, optionsLocal)) {
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
- isAvailable: () => !state.completed && !state.terminalTurnNotificationQueued && !runAbortController.signal.aborted,
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) ? (await bindingStore.read(bindingIdentity))?.threadId === resourceState.thread.threadId && await bindingStore.withLease(bindingIdentity, async () => {
2712
- if ((await bindingStore.read(bindingIdentity))?.threadId !== resourceState.thread.threadId) return false;
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
- for (let index = bytesRead - 1; index >= 0; index -= 1) {
2999
- if (chunk[index] !== 10) continue;
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({ enabled: profilerEnabled });
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$1(params.config ?? {}, sessionAgentId);
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
- let startupBinding = await bindingStore.read(bindingIdentity);
3237
- if (!startupBinding && bindingIdentity.kind === "session" && bindingIdentity.sessionKey) {
3238
- if (!await reclaimCurrentCodexSessionGeneration({
3239
- bindingStore,
3240
- identity: bindingIdentity,
3241
- config: params.config,
3242
- storePath: params.sessionTarget?.storePath
3243
- })) throw createCodexSessionGenerationSupersededError(bindingIdentity.sessionId);
3244
- startupBinding = await bindingStore.read(bindingIdentity);
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
- const startupBindingBeforeRotation = startupBinding;
3397
- const startupBindingResolution = await rotateOversizedCodexAppServerStartupBinding({
3398
- binding: startupBinding,
3399
- bindingStore,
3400
- identity: bindingIdentity,
3401
- sessionFile: params.sessionFile,
3402
- agentDir,
3403
- codexHome: appServer.start.env?.CODEX_HOME,
3404
- config: params.config,
3405
- contextEngineActive: Boolean(activeContextEngine)
3406
- });
3407
- startupBinding = startupBindingResolution.binding;
3408
- const initialInactiveThreadBootstrapBindingForcedFreshStart = initialStartupBindingHadInactiveThreadBootstrap && !startupBinding?.threadId;
3409
- preDynamicStartupStages.mark("rotate-binding");
3410
- if (startupBinding !== startupBindingBeforeRotation) {
3411
- reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
3412
- configuredAppServer = resolveRuntimeOptionsForBinding(startupBinding, {
3413
- modelProvider: reviewerPolicyContext.modelProvider,
3414
- model: reviewerPolicyContext.model
3415
- });
3416
- resolvedAppServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
3417
- appServer = resolvedAppServer.appServer;
3418
- }
3419
- const sessionPermissionPolicy = resolveCodexEffectiveSessionPermissionPolicy({
3420
- appServer,
3421
- permissionMode: params.permissionMode,
3422
- sessionRoot: params.sessionRoot,
3423
- defaultRoot: effectiveWorkspace
3424
- });
3425
- if (sessionPermissionPolicy) {
3426
- params.permissionMode = sessionPermissionPolicy.mode;
3427
- params.sessionRoot = sessionPermissionPolicy.root;
3428
- (params.execOverrides ??= {}).mode = sessionPermissionPolicy.execMode;
3429
- }
3430
- const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
3431
- configuredEvents: options.nativeHookRelay?.events,
3432
- appServer
3433
- });
3434
- const mutable = {
3435
- startupBinding,
3436
- startupContextTokens: startupBindingResolution.startupContextTokens,
3437
- pluginAppServer: appServer,
3438
- continuityCalibration: startupBindingBeforeRotation?.continuityCalibration
3439
- };
3440
- const resolveRuntimeOptionsForCurrentBinding = (selection) => resolveFinalAppServer(resolveRuntimeOptionsForBinding(mutable.startupBinding, selection), selection).appServer;
3441
- return {
3442
- params,
3443
- options,
3444
- attemptStartedAt,
3445
- profilerEnabled,
3446
- codexModelCallTrace,
3447
- codexModelContentCapture,
3448
- codexModelCallId,
3449
- fastModeAutoStartedAtMs,
3450
- fastModeAutoProgressState,
3451
- preDynamicStartupStages,
3452
- attemptClientFactory,
3453
- runtimeArtifactRequest,
3454
- pluginConfig,
3455
- computerUseConfig,
3456
- sessionAgentId,
3457
- policyAgentId,
3458
- resolvedWorkspace,
3459
- sandboxSessionKey,
3460
- contextSessionKey,
3461
- sandbox,
3462
- agentDir,
3463
- shellEnvironment,
3464
- disableLoginShell,
3465
- bindingIdentity,
3466
- bindingStore,
3467
- activeContextEngine,
3468
- isInactiveThreadBootstrapBinding,
3469
- usesSupervisionConnection,
3470
- startupAuthProfileId,
3471
- startupAuthRequirement: preparedAuthRoute?.authRequirement,
3472
- startupPreparedAuth,
3473
- startupClientAuthProfileId,
3474
- effectiveWorkspace,
3475
- effectiveCwd,
3476
- appServer,
3477
- sessionPermissionPolicy,
3478
- nativeHookRelayEvents,
3479
- runAbortController,
3480
- terminalState,
3481
- abortExplicitly,
3482
- abortFromUpstream,
3483
- resolveReviewerPolicyContext,
3484
- resolveRuntimeOptionsForCurrentBinding,
3485
- mutable,
3486
- initialStartupBindingHadInactiveThreadBootstrap,
3487
- initialInactiveThreadBootstrapBindingForcedFreshStart
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 = await bindingStore.read(identity);
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 supervised thread; preserving native binding", fields);
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
- return await readMirroredSessionHistoryMessages({
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 settlementClosed = false;
4117
+ let settlementPhase = "active";
3951
4118
  let abortGraceTimer;
3952
4119
  const beginAbortGrace = () => {
3953
- if (settlementClosed) return;
3954
- abortGraceTimer = setTimeout(() => abortGraceElapsed.resolve(), TURN_FINALIZE_DRAIN_ABORT_GRACE_MS);
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 settlement = drainNotificationQueue().then(closeProjection);
3965
- try {
3966
- await Promise.race([settlement, abortGraceElapsed.promise]);
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
- if (!state.projectionClosed) await resources.runCleanupStep("codex-transcript-checkpoint", closeProjection);
3974
- }
3975
- const result = activeProjector.buildResult(toolBridge.telemetry, { yieldDetected: toolState.yieldDetected });
3976
- const projectedTerminal = attemptTerminal.project(result.terminal);
3977
- const effectiveTimedOut = state.timeout !== void 0;
3978
- const isFinalAborted = () => terminalState.explicitCancellationObserved || !resourceState.executionDisconnectError && (projectedTerminal.aborted || runAbortController.signal.aborted && !state.clientClosedAbort);
3979
- const clientClosedPromptErrorForFinal = state.clientClosedPromptError;
3980
- let 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" : projectedTerminal.promptError);
3981
- const finalPromptErrorMessage = typeof finalPromptError === "string" ? finalPromptError : finalPromptError instanceof Error ? finalPromptError.message : finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
3982
- if (isInvalidCodexImagePayloadError(finalPromptErrorMessage)) await clearCodexBindingAfterInvalidImagePayload(bindingStore, bindingIdentity, {
3983
- phase: "turn_completed",
3984
- threadId: resourceState.thread.threadId,
3985
- turnId: activeTurnId,
3986
- error: finalPromptErrorMessage
3987
- });
3988
- if (resourceState.thread.connectionScope !== "supervision" && shouldUseFreshCodexThreadAfterContextEngineOverflow({
3989
- error: finalPromptError,
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: finalPromptErrorMessage
3997
- });
3998
- await bindingStore.mutate(bindingIdentity, {
3999
- kind: "clear",
4000
- threadId: resourceState.thread.threadId
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
- const refreshedUsageLimitPromptError = await refreshCodexUsageLimitPromptError({
4004
- client: resourceState.client,
4005
- message: finalPromptErrorMessage,
4006
- timeoutMs: appServer.requestTimeoutMs,
4007
- signal: runAbortController.signal
4008
- });
4009
- if (refreshedUsageLimitPromptError) {
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: refreshedUsageLimitPromptError.rateLimitsForProfile
4192
+ rateLimits: readRecentCodexRateLimits(resourceState.client)
4014
4193
  });
4015
- finalPromptError = createCodexUsageLimitPromptError(refreshedUsageLimitPromptError.message);
4016
- } else if (isCodexUsageLimitPromptError(finalPromptError) && state.rateLimitsRevisionBeforeLastTurnStart !== void 0 && readCodexRateLimitsRevision(resourceState.client) > state.rateLimitsRevisionBeforeLastTurnStart) await markCodexAuthProfileBlockedFromRateLimits({
4017
- params,
4018
- authProfileId: startupAuthProfileId,
4019
- rateLimits: readRecentCodexRateLimits(resourceState.client)
4020
- });
4021
- finalPromptError = resourceState.executionDisconnectError ?? finalPromptError;
4022
- const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : projectedTerminal.promptErrorSource;
4023
- const codexAppServerFailureKind = clientClosedPromptErrorForFinal ? "client_closed_before_turn_completed" : state.timeout?.kind === "settlement" ? "turn_settlement_timeout" : void 0;
4024
- const replayBlockedReason = codexAppServerFailureKind ? resolveCodexAppServerReplayBlockedReason(result) : void 0;
4025
- const promptTimeoutOutcome = buildCodexAppServerPromptTimeoutOutcome(state.timeout);
4026
- const failureDiagnostics = codexAppServerFailureKind === "client_closed_before_turn_completed" && state.clientClosedDiagnostic ? { transportError: state.clientClosedDiagnostic } : state.timeout?.kind === "settlement" ? { timeoutMs: state.timeout.timeoutMs } : void 0;
4027
- const codexAppServerFailure = codexAppServerFailureKind ? {
4028
- kind: codexAppServerFailureKind,
4029
- transport: appServer.start.transport,
4030
- threadId: resourceState.thread.threadId,
4031
- turnId: activeTurnId,
4032
- replaySafe: codexAppServerFailureKind === "client_closed_before_turn_completed" && replayBlockedReason === void 0,
4033
- ...replayBlockedReason ? { replayBlockedReason } : {},
4034
- ...failureDiagnostics ? { diagnostics: failureDiagnostics } : {}
4035
- } : void 0;
4036
- const finalAborted = isFinalAborted();
4037
- const completedTurnStatus = activeProjector.getCompletedTurnStatus();
4038
- const locallyCompletedTurn = state.completed && state.localCompletionRequested && !state.timeout && clientClosedPromptErrorForFinal === void 0;
4039
- const turnSucceeded = !finalAborted && !effectiveTimedOut && (finalPromptError === null || finalPromptError === void 0) && (completedTurnStatus === "completed" || locallyCompletedTurn);
4040
- if (toolBridge.telemetry.messagingToolSentTargets.some((target) => target.sourceReplyFinal === true)) result.agentHarnessResultClassification = void 0;
4041
- const attemptSucceeded = turnSucceeded && result.agentHarnessResultClassification === void 0;
4042
- terminalState.turnSucceeded = turnSucceeded;
4043
- terminalState.sharedAbortAllowedAfterTerminalOutcome = shouldKeepCodexSharedAbortOpen({
4044
- trigger: params.trigger,
4045
- result,
4046
- attemptSucceeded,
4047
- explicitCancellationObserved: terminalState.explicitCancellationObserved
4048
- });
4049
- freezeRunTerminalOutcome();
4050
- const modelCallFailureKind = classifyCodexModelCallFailureKind({
4051
- error: finalPromptError,
4052
- timedOut: effectiveTimedOut,
4053
- runAborted: finalAborted,
4054
- abortReason: terminalState.explicitCancellationReason ?? runAbortController.signal.reason,
4055
- clientClosedAbort: state.clientClosedAbort,
4056
- formatError: formatErrorMessage
4057
- }) ?? (finalAborted ? "aborted" : void 0);
4058
- if (modelCallFailureKind) codexModelCallDiagnostics.emitError(finalPromptError ?? "codex app-server attempt interrupted", { failureKind: modelCallFailureKind });
4059
- else if (finalPromptError) codexModelCallDiagnostics.emitError(finalPromptError);
4060
- else codexModelCallDiagnostics.emitCompleted(result);
4061
- const mirrorOutcome = await codexTranscriptMirrorRuntime.mirrorBestEffort({
4062
- params,
4063
- agentId: sessionAgentId,
4064
- notifyUserMessagePersisted,
4065
- result,
4066
- sessionKey: contextSessionKey,
4067
- cwd: effectiveCwd,
4068
- threadId: resourceState.thread.threadId,
4069
- turnId: activeTurnId
4070
- });
4071
- const { assistantTranscriptOwned, assistantTranscriptIdempotencyKey, terminalAnchor } = mirrorOutcome;
4072
- const settledTurnFinalizationContext = result.assistantTexts.every((text) => !text.trim()) && result.messagesSnapshot.some((message) => message.role === "toolResult") && (!finalPromptError || activeProjector.settledTurnFailureFinalizationAllowed) ? await captureCodexSettledTurnFinalizationContext({
4073
- ...activeTranscriptTarget,
4074
- mirroredMessages: mirrorOutcome.mirroredMessages,
4075
- settledMessages: result.messagesSnapshot,
4076
- turnId: activeTurnId
4077
- }) ?? Object.freeze({ source: "unavailable" }) : void 0;
4078
- if (settledTurnFinalizationContext?.source === "unavailable") embeddedAgentLog.warn("codex settled-turn finalization context is unavailable", {
4079
- threadId: resourceState.thread.threadId,
4080
- turnId: activeTurnId
4081
- });
4082
- runAgentHarnessLlmOutputHook({
4083
- event: {
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
- continuityCalibration: context.promptState.noEngineContinuityProjectionApplied ? buildCodexContinuityCalibration({
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: (result.attemptUsage?.input ?? 0) + (result.attemptUsage?.cacheRead ?? 0) + (result.attemptUsage?.cacheWrite ?? 0)
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
- } catch (error) {
4133
- if (resourceState.thread.connectionScope === "supervision") throw error;
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
- error
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: params.hostCapabilities.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 { params, runAbortController, abortFromUpstream } = connection;
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-C3jVimFn.js");
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
- const boundedRequest = (method, requestParams) => {
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
- return request(method, requestParams, {
5811
- timeoutMs: remainingTimeoutMs,
5812
- signal
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
- return transform ? await transform(config, boundedRequest) : config;
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(`Scheduled Codex app policy verification exceeded its ${timeoutMs} ms startup budget. No app tools were executed. Retry after Codex app inventory is responsive, or reauthorize the automation.`);
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 (startupAbandoned || startupAbandonController.signal.aborted) closeCodexStartupClientBestEffort(client);
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 (!startupAbandoned && !params.signal.aborted && !startupClient) {
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 (startupAbandoned || params.signal.aborted) {
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 (startupAbandoned || params.signal.aborted || !selectionChanged && !isCodexAppServerConnectionClosedError(error)) throw error;
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.aborted || isCodexAppServerStartupError(error)) {
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 shouldClearSharedClientAfterStartupRace(error) {
6267
- return isCodexAppServerStartupError(error) || isCodexAppServerRequestTimeoutError(error);
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, abortFromUpstream } = connection;
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$1(params.config, sessionAgentId)?.tools?.loopDetection?.enabled : void 0) ?? params.config?.tools?.loopDetection?.enabled ?? false;
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, startupAuthProfileId, resolvedWorkspace, effectiveWorkspace, effectiveCwd, sandboxSessionKey, contextSessionKey, sandbox, sessionPermissionPolicy, runAbortController, sessionAgentId, policyAgentId, pluginConfig, profilerEnabled, agentDir } = connection;
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
- params.hostCapabilities.assertActive();
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
- params.hostCapabilities.assertActive();
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
- await captureFinalCodexCronCreatorToolAllowlist(cronCreatorToolAllowlist, cronCreatorToolAllowlistCaptureRef, toolBridge.availableTools);
6736
- if (!authenticatedScheduledMode && bundleMcpThreadConfig.staticServerNames.length > 0 && !canResolveScheduledConfiguredMcpCreatorAuthority) delete cronCreatorToolAllowlistCaptureRef.value;
6737
- if (requiresScheduledCodexAppAuthority) delete cronCreatorToolAllowlistCaptureRef.value;
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
- materialized = await materializeStaticMcpToolsForHarnessRun({
6766
- sessionId: authorityRuntimeId,
6767
- agentId: sessionAgentId,
6768
- workspaceDir: effectiveWorkspace,
6769
- agentDir: policyContext.agentDir,
6770
- cfg: params.config,
6771
- manifestRegistry: bundleManifestRegistry,
6772
- reservedToolNames: toolBridge.availableTools.map((tool) => tool.name),
6773
- toolsAllow: params.toolsAllow,
6774
- toolOverrides: codexMcpToolOverrides,
6775
- autoApproveCodexAppServerApprovals: shouldAutoApproveCodexAppServerApprovals(connection.appServer),
6776
- projectedMcpServers: bundleMcpThreadConfig.configPatch?.mcp_servers,
6777
- policyContext,
6778
- warn: (message) => embeddedAgentLog.warn(message),
6779
- retireSessionRuntimeAfterDispose: true
6780
- });
6781
- } catch (error) {
6782
- const detail = error instanceof Error ? error.message : String(error);
6783
- 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 });
6784
- }
6785
- try {
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.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.`);
6788
- const projectedConfiguredMcp = projectCodexExecutableDynamicTools({
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
- await captureFinalCodexCronCreatorToolAllowlist(authorityTools, captureRef, [...toolBridge.availableTools, ...projectedConfiguredMcp.availableTools]);
6793
- if (!captureRef.value) throw new Error("configured MCP authority snapshot did not produce provenance");
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.dispose();
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
- cronCreatorToolAllowlist,
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 scopedMcpTools?.dispose();
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, abortFromUpstream } = connection;
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
- try {
7049
- if (!await bindingStore.mutate(bindingIdentity, {
7050
- kind: "clear",
7051
- threadId: resourceState.thread.threadId
7052
- })) embeddedAgentLog.warn("codex app-server preserved newer context-engine binding after resume overflow; skipping fresh retry", {
7053
- threadId: resourceState.thread.threadId,
7054
- error: formatErrorMessage(turnStartError)
7055
- });
7056
- else {
7057
- resourceState.thread = await resourceState.restartContextEngineCodexThread();
7058
- const retryBinding = await bindingStore.read(bindingIdentity);
7059
- if (retryBinding && retryBinding.threadId === resourceState.thread.threadId && retryBinding.contextEngine?.projection) {
7060
- await bindingStore.mutate(bindingIdentity, {
7061
- kind: "patch",
7062
- threadId: retryBinding.threadId,
7063
- patch: { contextEngine: {
7064
- ...retryBinding.contextEngine,
7065
- projection: void 0
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
- try {
7081
- turn = await startCodexTurn();
7082
- } catch (retryError) {
7083
- turnStartError = retryError;
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: createCodexUsageLimitPromptError(usageLimitError.message),
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 connection = await prepareCodexAttemptConnection({
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 lifecycle = createCodexAttemptLifecycleController(resources, turnRuntime);
7422
- const notifications = createCodexAttemptNotificationController(resources, turnRuntime, lifecycle);
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 activeTurn.ready;
7431
- finalizedResult = await finalizeCodexAttempt(resources, turnRuntime, lifecycle, notifications, turnRequest, activeTurn);
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 cleanupCodexAttempt(resources, turnRuntime, lifecycle, turnRequest, activeTurn);
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
- turnRuntime.deadlines.dispose();
7692
+ params.abortSignal?.removeEventListener("abort", connection.abortFromUpstream);
7439
7693
  }
7440
7694
  }
7441
7695
  //#endregion