@openclaw/codex 2026.9.2 → 2026.9.3

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 (108) hide show
  1. package/README.md +2 -0
  2. package/dist/api.js +14 -19
  3. package/dist/apply-B6el6hdO.js +357 -0
  4. package/dist/{attempt-client-cleanup-Bp1ZOnk2.js → attempt-client-cleanup-D6cR54TV.js} +39 -19
  5. package/dist/{attempt-context-CSazkWns.js → attempt-context-AO4DSjE0.js} +8 -6
  6. package/dist/{event-projector-usage-ZqEVbAEY.js → attempt-notifications--H8zXR5-.js} +3 -106
  7. package/dist/auth-cache-key-Kq6oerr6.js +498 -0
  8. package/dist/auth-profile-CwzO4_RG.js +43 -0
  9. package/dist/auth-profile-selection-DFu9e167.js +45 -0
  10. package/dist/binding-connection-QqgcPCgk.js +60 -0
  11. package/dist/{bounded-turn-DxGJRYbY.js → bounded-turn-lRpmZHFv.js} +25 -122
  12. package/dist/build-state-6RL6qohz.js +19 -0
  13. package/dist/{capabilities-B1mgvpP8.js → capabilities-BeqLPbtM.js} +1 -1
  14. package/dist/cli-metadata.js +1 -1
  15. package/dist/client-BEKu4yDx.js +3983 -0
  16. package/dist/command-dispatch-CisT9Jqq.js +21 -0
  17. package/dist/{command-formatters-DSbGMXA0.js → command-formatters-DeTfrapr.js} +2 -2
  18. package/dist/{command-handlers-DOJvGv6-.js → command-handlers-BfIsJEuA.js} +31 -21
  19. package/dist/command-rpc-BMqRQOFX.js +226 -0
  20. package/dist/{compact-Y_xBqrHN.js → compact-CGJZ2rlb.js} +19 -14
  21. package/dist/config-JDfTI4VI.js +106 -0
  22. package/dist/{config-CyapYSji.js → config-options-jnIFvwxD.js} +204 -592
  23. package/dist/config-runtime-BWf6JLWG.js +11 -0
  24. package/dist/conversation-binding-CxOlHiix.js +889 -0
  25. package/dist/{plugin-marketplace-discovery-B7gHXJ3d.js → conversation-control-CUCrSIQI.js} +10 -142
  26. package/dist/doctor-contract-api.js +5 -5
  27. package/dist/{dynamic-tools-BwpvTxaX.js → dynamic-tools-D-JBoaLt.js} +66 -70
  28. package/dist/{effective-mcp-catalog-CY9Jn4bA.js → effective-mcp-catalog-J_5Ep5Um.js} +3 -3
  29. package/dist/{elicitation-input-DMkeki8d.js → elicitation-input-DPoK8F7w.js} +8 -22
  30. package/dist/ephemeral-turn-DSwzP8YY.js +101 -0
  31. package/dist/{event-projector-assistant-message-B9kp6iGC.js → event-projector-assistant-message-BmBM4qBV.js} +12 -25
  32. package/dist/event-projector-usage-CIyrYYid.js +102 -0
  33. package/dist/{harness-Czh2Sdoc.js → harness-FR6eQgyO.js} +31 -24
  34. package/dist/harness.js +1 -1
  35. package/dist/history-rejection-B4nOXNXF.js +13 -0
  36. package/dist/incognito-session-uhrBF6wJ.js +15 -0
  37. package/dist/index.js +411 -2875
  38. package/dist/{isolated-completion-CRh-51AK.js → isolated-completion-DHBefrzg.js} +7 -4
  39. package/dist/launch-args-RXQwn8zV.js +90 -0
  40. package/dist/{managed-binary-DcpnJF9x.js → managed-binary-DrjjRRUD.js} +4 -103
  41. package/dist/managed-thread-store-D1t5jh3G.js +66 -0
  42. package/dist/media-understanding-provider.js +4 -1
  43. package/dist/{model-catalog-DT5vo6qo.js → model-catalog-B_6M04Wo.js} +6 -5
  44. package/dist/{models-CcrgSMQR.js → models-P9k2qAof.js} +3 -3
  45. package/dist/native-execution-policy-umd0tgh4.js +128 -0
  46. package/dist/{native-subagent-monitor-B3bvQGcg.js → native-subagent-monitor-BbCUKRwC.js} +69 -42
  47. package/dist/node-cli-sessions-rj0ysJwM.js +527 -0
  48. package/dist/{node-exec-server.runtime-nfbUOtUB.js → node-exec-server.runtime-BY_ctYnT.js} +53 -22
  49. package/dist/plan-BMJdMOEF.js +711 -0
  50. package/dist/plugin-activation-BQK-f5sV.js +133 -0
  51. package/dist/{thread-resume-BLgqkUc1.js → plugin-app-cache-key-CdSQzWyX.js} +4 -52
  52. package/dist/{plugin-approval-roundtrip-aQVdyL5g.js → plugin-approval-roundtrip-DeW95wB5.js} +1 -1
  53. package/dist/plugin-inventory-CoRCzWW4.js +325 -0
  54. package/dist/plugin-marketplace-discovery-3akBizzF.js +134 -0
  55. package/dist/{plugin-metadata-cache-BwCLTY_U.js → plugin-metadata-cache-DgNfRAGA.js} +13 -9
  56. package/dist/protocol-CAAcVIKF.js +275 -0
  57. package/dist/{provider-capabilities-BpG9Ltc5.js → provider-capabilities-W4tfK5Y5.js} +2 -2
  58. package/dist/{rate-limits-Fx_l4eNa.js → rate-limits-Bqnx1N4z.js} +1 -1
  59. package/dist/request-CGvGOpeR.js +198 -0
  60. package/dist/{run-attempt-BzthFQSM.js → run-attempt-DwKds3DN.js} +589 -373
  61. package/dist/{runtime-artifact-Bh_gf6-t.js → runtime-artifact-T-NwqeSH.js} +27 -27
  62. package/dist/sandbox-guard-BcT66fWy.js +165 -0
  63. package/dist/{session-binding-4Ki04sW-.js → session-binding-CKSepwIC.js} +29 -47
  64. package/dist/{session-binding-record-CyaXZvTe.js → session-binding-record-CaZjYwNS.js} +11 -25
  65. package/dist/session-catalog-HaDcp7Sv.js +1533 -0
  66. package/dist/session-catalog-adoption-BKLtSrwi.js +251 -0
  67. package/dist/session-catalog-archive-D0i2pGj2.js +56 -0
  68. package/dist/session-catalog-home-id-D7-aLiNt.js +190 -0
  69. package/dist/session-catalog-node-adoption-BUuDYY8R.js +182 -0
  70. package/dist/session-catalog-node-continue-CBtc4wkI.js +238 -0
  71. package/dist/session-catalog-parsing-CdD3JhdM.js +280 -0
  72. package/dist/session-catalog-provenance-DkJHo735.js +124 -0
  73. package/dist/{session-cli-BjLhpmS1.js → session-cli-CbgaHh0f.js} +3 -2
  74. package/dist/{session-history-DWmMqiqW.js → session-history-Cz-tOOYj.js} +6 -3
  75. package/dist/{session-upstream-marker-DReTpGz6.js → session-history-import-DFN7sWRU.js} +5 -50
  76. package/dist/{session-history-read-LHldwvyh.js → session-history-read-cxPUxyVV.js} +21 -7
  77. package/dist/session-history-worker-runtime.js +18 -6
  78. package/dist/{session-history.worker-zZVcx0ME.js → session-history.worker-CNEvGaU5.js} +58 -51
  79. package/dist/session-history.worker.js +1 -1
  80. package/dist/{session-initialization-BCFVnLL4.js → session-initialization-Jo86C60I.js} +2 -2
  81. package/dist/{session-permission-policy-BaueHmSj.js → session-permission-policy-B22InTp_.js} +4 -7
  82. package/dist/{session-retirement-DNdmYdFc.js → session-retirement-BSNG_mhf.js} +6 -5
  83. package/dist/session-upstream-marker-D15C9NHp.js +46 -0
  84. package/dist/{settled-turn-context-BOM3Y1pl.js → settled-turn-context-Du6gdUDd.js} +9 -9
  85. package/dist/{settled-turn-finalizer-BI-b1sry.js → settled-turn-finalizer-BuLUrZl2.js} +7 -6
  86. package/dist/shared-client-CVhez2Uo.js +2911 -0
  87. package/dist/{side-question-B6DWAw1A.js → side-question-DLbr2vUU.js} +64 -169
  88. package/dist/source-Da-h6f7e.js +518 -0
  89. package/dist/thread-archive-guard-D1bP04Tf.js +53 -0
  90. package/dist/{thread-lifecycle-DPK30jad.js → thread-lifecycle-D1pzRwHB.js} +112 -616
  91. package/dist/{thread-ownership-CbucAmmp.js → thread-ownership-D6oASVRu.js} +13 -15
  92. package/dist/thread-policy-D8kI7yAO.js +54 -0
  93. package/dist/thread-resume-T5cveyxA.js +52 -0
  94. package/dist/timeout-BVw8aaM1.js +33 -0
  95. package/dist/{transcript-mirror-attestation-Byl34PC-.js → transcript-mirror-attestation-DibE0krH.js} +17 -4
  96. package/dist/{transcript-mirror-_njEB84z.js → transcript-mirror-t5TOccct.js} +50 -260
  97. package/dist/{transport-stdio-CzTngV0j.js → transport-stdio-BGjHoYLr.js} +73 -43
  98. package/dist/{upstream-session-fork-1fwbNKzQ.js → upstream-session-fork-De-sLJ2r.js} +26 -18
  99. package/dist/{usage-i9fv5-4m.js → usage-CPPTmBvZ.js} +4 -3
  100. package/dist/version-omm6IPI3.js +12 -0
  101. package/dist/{web-search-provider.runtime-DKQn67A7.js → web-search-provider.runtime-CSVgQL0w.js} +3 -3
  102. package/openclaw.plugin.json +22 -1
  103. package/package.json +4 -4
  104. package/dist/request-C8H22rPi.js +0 -475
  105. package/dist/session-catalog-B47uwekb.js +0 -3272
  106. package/dist/shared-client-CKhX2kFt.js +0 -7505
  107. package/dist/thread-policy-CTalhWFy.js +0 -105
  108. package/dist/{auth-binding-Ds_QVm-X.js → auth-binding-Co2Vfcf_.js} +1 -1
@@ -1,50 +1,61 @@
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";
1
+ import { l as sessionBindingIdentity, n as assertCodexBindingMayBeReplaced } from "./session-binding-record-CaZjYwNS.js";
2
+ import { n as defineCodexBuildState } from "./build-state-6RL6qohz.js";
3
+ import { b as readCodexRequirementsToml, c as hasCodexMcpToolApprovalOverrides, d as withMcpElicitationsApprovalPolicy, i as resolveCodexAppServerHomeScope, m as resolveCodexModelBackedReviewerPolicyContext, o as resolveCodexComputerUseConfig, u as shouldAutoApproveCodexAppServerApprovals } from "./config-options-jnIFvwxD.js";
4
+ import { S as resolveCodexPluginsPolicy, a as flattenCodexDynamicToolFunctions, b as isCodexSandboxExecServerEnabled, o as isJsonObject, s as resolveCodexAppServerHomeDir, v as isCodexPairedNodeRemoteExecPlacementSandbox, x as readCodexPluginConfig, y as isCodexRemoteExecPlacementSandbox } from "./protocol-CAAcVIKF.js";
5
+ import { A as isMatchingDynamicToolTerminalDiagnostic, D as handleDynamicToolCallWithTimeout, E as createCodexElicitationResponse, F as toCodexDynamicToolProgressResponse, I as toCodexDynamicToolProtocolResponse, L as resolveCodexToolAbortTerminalReason, M as resolveTerminalDynamicToolBatchAction, N as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, O as hasPendingDynamicToolTerminalDiagnostic, P as shouldReleaseTurnAfterTerminalDynamicTool, S as readCodexDynamicToolCallParams, T as readCodexTurnCompletedNotification, a as isCodexAppServerBrokenPipeError, c as isCodexAppServerIndeterminateTransportError, d as isCodexAppServerRequestTimeoutError, i as isCodexAppServerApprovalRequest, j as resolveDynamicToolCallTimeoutMs, k as isDynamicToolTerminalDiagnosticEvent, l as isCodexAppServerOverloadError, o as isCodexAppServerConnectionClosedError, p as resolveCodexAppServerClientInstanceId, r as getCodexAppServerClientInstanceId, s as isCodexAppServerIndeterminateRequestCancellationError, w as readCodexTurn, x as assertCodexTurnStartResponse } from "./client-BEKu4yDx.js";
6
+ import { c as resolveCodexAppServerPreparedApiKeyCacheKey, m as retireSharedCodexAppServerClientIfCurrent, s as resolveCodexAppServerFallbackApiKeyCacheKey } from "./auth-cache-key-Kq6oerr6.js";
7
+ import { t as isIncognitoSessionKey } from "./incognito-session-uhrBF6wJ.js";
8
+ import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-Bqnx1N4z.js";
9
+ import { a as formatCodexDisplayText } from "./command-formatters-DeTfrapr.js";
10
+ import { r as CodexAppServerRpcError } from "./session-catalog-provenance-DkJHo735.js";
11
+ import { t as CODEX_CONTROL_METHODS } from "./capabilities-BeqLPbtM.js";
12
12
  import { r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-LphB8slG.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";
18
- import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-Ds_QVm-X.js";
13
+ import { n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey, s as defaultCodexAppInventoryCache } from "./plugin-app-cache-key-CdSQzWyX.js";
14
+ import { t as withAbortableTimeout } from "./timeout-BVw8aaM1.js";
15
+ import { n as resolveOpenClawExecPolicyForCodexAppServer, t as canUseCodexModelBackedApprovalsReviewerForModel } from "./config-JDfTI4VI.js";
16
+ import { o as hasCodexMirrorOrigin, t as applyCodexTranscriptTaint } from "./transcript-mirror-attestation-DibE0krH.js";
17
+ import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-Co2Vfcf_.js";
18
+ import { i as resolveCodexBindingAppServerConnection, t as assertCodexSessionRuntimeOwnership } from "./binding-connection-QqgcPCgk.js";
19
+ import { i as resolveCodexAppServerAuthProfileIdForAgent, r as resolveCodexAppServerAuthProfileId } from "./auth-profile-CwzO4_RG.js";
20
+ import { B as prepareCodexWorkspaceReferences, D as TURN_FINALIZE_DRAIN_ABORT_GRACE_MS, E as CodexAppServerStartupError, F as ensureCodexAppServerClientRuntime, J as rememberCodexRateLimitsRead, K as readCodexRateLimitsRevision, M as withCodexStartupTimeout, O as TURN_TERMINAL_SETTLEMENT_TIMEOUT_MS, V as protectCodexAppServerLiveThread, X as resolveCodexAppServerAuthAccountCacheKey, Z as resolveCodexAppServerPreparedAuthHandoff, a as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, c as getLeasedSharedCodexAppServerClient, f as readCodexAppServerClientDesktopGenerationFingerprint, h as releaseLeasedSharedCodexAppServerClient, i as clearSharedCodexAppServerClientIfCurrent, j as resolveCodexStartupTimeoutMs, k as isCodexAppServerStartupError, l as getSharedCodexAppServerClient, q as readRecentCodexRateLimits, s as createIsolatedCodexAppServerClient, u as isCodexAppServerStartSelectionChangedError, v as retainSharedCodexAppServerClientIfCurrent } from "./shared-client-CVhez2Uo.js";
21
+ import { 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, 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-D6cR54TV.js";
22
+ import { a as isRawFunctionToolOutputCompletionNotification, c as readNotificationItemId, i as isPendingOpenClawDynamicToolCompletionNotification, l as readRawResponseToolCallId, o as isTerminalTurnStatus, r as isCodexTurnAbortMarkerNotification, s as readCodexNotificationItem, t as codexExecutionToolName, u as updateActiveTurnItemIds } from "./attempt-notifications--H8zXR5-.js";
23
+ import { t as CodexUsageProjection } from "./event-projector-usage-CIyrYYid.js";
24
+ import { s as resolveRecoverableCodexPluginConfigKeys } from "./plugin-inventory-CoRCzWW4.js";
25
+ import { $ as codexLegacyDynamicToolsFingerprint, A as readCodexMcpToolConnectorId, B as emitCodexNativePreToolUseFailureDiagnostic, C as buildDeveloperInstructions, Ct as buildCodexPluginThreadConfigTimeoutFallback, D as resolveCodexAppServerThreadModelSelection, Dt as shouldBuildCodexPluginThreadConfig, H as resolveCodexNativeHookRelayTtlMs, I as buildCodexNativeHookRelayConfig, K as hasCodexNativeToolCatalog, L as buildCodexNativeHookRelayDisabledConfig, M as isCodexAppServerProfilerEnabled, P as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, Q as codexDynamicToolsFingerprint, S as resolveCodexWebSearchPlan, St as buildCodexPluginThreadConfigInputFingerprint, Tt as mergeCodexThreadConfigs, U as scheduleCodexNativeHookRelayUnregister, V as resolveCodexNativeHookRelayEvents, _t as projectContextEngineAssemblyForCodex, bt as resolveCodexContinuityProjectionMaxChars, c as assertScheduledCodexAppAuthorityRuntime, d as buildScheduledCodexAppServerConnectionIdentity, f as captureScheduledCodexAppAuthority, ft as CodexContextAttachmentError, gt as neutralizeCodexExplicitMentionSigils, h as resolveScheduledCodexAppCreatorCaptureDecision, ht as isCodexDurableCustomMessage, i as buildCodexUserInput, j as readCodexMcpToolUiVisibility, l as buildLegacyScheduledCodexAppRecoveryPrompt, lt as resolveCodexDynamicToolsLoadingForRuntime, m as readCurrentCodexScheduledAppPolicy$1, mt as fitCodexProjectedContextForTurnStart, n as buildTurnCollaborationMode, nt as filterCodexDynamicTools, ot as isSystemAgentOnlyCodexDynamicToolAllowlist, p as intersectCodexPluginThreadConfigWithScheduledAuthority, pt as buildCodexContinuityCalibration, q as loadCodexNativeToolCatalog, r as buildTurnStartParams, s as startOrResumeThread, u as buildScheduledCodexAppAuthorityInputFingerprint, ut as buildContextEngineBinding, vt as resolveCodexContextEngineProjectionMaxChars, xt as buildCodexPluginThreadConfig, yt as resolveCodexContextEngineProjectionReserveTokens, z as createCodexNativeHookRelay } from "./thread-lifecycle-D1pzRwHB.js";
26
+ import { a as resolveCodexRunSessionBindingAuthority, n as createCodexSessionGenerationSupersededError, o as resolveCodexSessionBinding, s as scopeCodexRunBindingStore } from "./session-binding-CKSepwIC.js";
27
+ import { n as CodexThreadPolicyHandoffError } from "./thread-policy-D8kI7yAO.js";
28
+ import { r as retainCodexAppServerBindingSubscription } from "./thread-ownership-D6oASVRu.js";
29
+ import { i as mirrorPromptAtTurnStartBestEffort, n as createCodexAppServerUserMessagePersistenceNotifier, o as buildCodexUserPromptMessage, s as promptSnapshot, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-t5TOccct.js";
19
30
  import { t as persistCodexContextCompactionActivity } from "./context-compaction-activity-CMla5FPJ.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";
31
+ import { i as createAssistantReasoningMessage, n as createAssistantCommentaryMessage, r as createAssistantMessage, t as createAssistantAsyncMessage } from "./event-projector-assistant-message-BmBM4qBV.js";
32
+ 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-D-JBoaLt.js";
33
+ import { t as resolveCodexProviderWebSearchSupport } from "./provider-capabilities-W4tfK5Y5.js";
34
+ 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-BbCUKRwC.js";
35
+ import { a as requestPluginApprovalOutcome } from "./plugin-approval-roundtrip-DeW95wB5.js";
36
+ import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy } from "./session-permission-policy-B22InTp_.js";
37
+ 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-AO4DSjE0.js";
38
+ import { n as captureCodexSettledTurnFinalizationContext } from "./settled-turn-context-Du6gdUDd.js";
39
+ import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-DgNfRAGA.js";
28
40
  import { asOptionalRecord, normalizeOptionalString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
29
41
  import { createHash } from "node:crypto";
30
42
  import { resolveAgentConfig, resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
31
- import { parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
32
43
  import { MAX_TIMER_TIMEOUT_MS, asDateTimestampMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
33
- import fs from "node:fs/promises";
34
44
  import path from "node:path";
45
+ import fs from "node:fs/promises";
46
+ import { addAbortListener } from "node:events";
47
+ import { truncateUtf16Safe, truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
48
+ import { Buffer as Buffer$1 } from "node:buffer";
35
49
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
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";
37
50
  import { isPathStrictlyInside, root } from "openclaw/plugin-sdk/file-access-runtime";
38
51
  import { isDeepStrictEqual } from "node:util";
39
- import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$2 } from "openclaw/plugin-sdk/agent-runtime";
52
+ import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-runtime";
53
+ 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, projectProgressCardChannelUpdate, resolveAgentDir as resolveAgentDir$2, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveAttemptFsWorkspaceOnly, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
40
54
  import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
41
- import { addAbortListener } from "node:events";
42
- import { truncateUtf16Safe, truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
55
+ import { parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
43
56
  import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
44
57
  import { captureFinalCodexCronCreatorToolAllowlist, formatMcpCodexApprovalRemedy, materializeStaticMcpToolsForHarnessRun, resolveCodexMcpToolOverridesForAgent, resolveCodexTtsProvenanceTransfer } from "openclaw/plugin-sdk/codex-mcp-projection";
45
- import { hasPromptImageInput } from "openclaw/plugin-sdk/session-transcript-runtime";
46
- import { Buffer as Buffer$1 } from "node:buffer";
47
- import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
58
+ import { appendSessionYieldContext, hasPromptImageInput } from "openclaw/plugin-sdk/session-transcript-runtime";
48
59
  import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-local-roots";
49
60
  import { isSilentReplyPayloadText } from "openclaw/plugin-sdk/reply-chunking";
50
61
  import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
@@ -52,6 +63,7 @@ import { resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generat
52
63
  import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
53
64
  import { stripInvisibleUnicode } from "openclaw/plugin-sdk/web-content-extractor";
54
65
  import { acknowledgeInternalToolResult } from "openclaw/plugin-sdk/agent-harness-tool-runtime";
66
+ import { sleepWithAbort } from "openclaw/plugin-sdk/runtime-env";
55
67
  //#region extensions/codex/src/app-server/attempt-preparation-timing.ts
56
68
  /** Records startup before the native turn owns inference and tool execution. */
57
69
  function createCodexAttemptPreparationTiming(params) {
@@ -203,6 +215,12 @@ function createCodexSteeringQueue(params) {
203
215
  }
204
216
  liveItems = liveItems.filter(isCurrent);
205
217
  if (liveItems.length === 0) return;
218
+ if (params.beforeSubmit) {
219
+ await params.beforeSubmit(liveItems);
220
+ assertActive();
221
+ liveItems = liveItems.filter(isCurrent);
222
+ if (liveItems.length === 0) return;
223
+ }
206
224
  clientUserMessageId = `openclaw:${params.turnId}:steer:${++batchSequence}`;
207
225
  dispatchedBatches.set(clientUserMessageId, { items: liveItems });
208
226
  const request = {
@@ -303,21 +321,8 @@ function createCodexSteeringQueue(params) {
303
321
  const batch = dispatchedBatches.get(clientUserMessageId);
304
322
  if (!batch) return false;
305
323
  dispatchedBatches.delete(clientUserMessageId);
306
- for (const item of batch.items) reportItemAcceptance(item, true);
307
- const resolveBatch = () => {
308
- for (const item of batch.items) resolveItem(item);
309
- return true;
310
- };
311
- const rejectBatch = (error) => {
312
- for (const item of batch.items) rejectItem(item, error);
313
- return true;
314
- };
315
- if (!params.beforeConfirmConsumed) return resolveBatch();
316
- try {
317
- return params.beforeConfirmConsumed(batch.items).then(resolveBatch, rejectBatch);
318
- } catch (error) {
319
- return rejectBatch(error);
320
- }
324
+ for (const item of batch.items) resolveItem(item);
325
+ return true;
321
326
  },
322
327
  sealAdmission: sealQueueAdmission,
323
328
  cancel: cancelQueue
@@ -328,6 +333,9 @@ function normalizeCodexSteerDebounceMs(value) {
328
333
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : CODEX_STEER_ALL_DEBOUNCE_MS;
329
334
  }
330
335
  //#endregion
336
+ //#region extensions/codex/src/app-server/attempt-terminal.ts
337
+ const attemptTerminal = agentHarnessAttemptTerminal;
338
+ //#endregion
331
339
  //#region extensions/codex/src/app-server/event-projector-assistant.ts
332
340
  var CodexAssistantProjection = class {
333
341
  constructor(params, emitAgentEvent, matchesToolProgressEcho, nextTranscriptTimestamp, checkpointCommentary) {
@@ -1078,8 +1086,61 @@ function reasoningMethodOrder(method) {
1078
1086
  return method === "item/reasoning/summaryTextDelta" ? 0 : 1;
1079
1087
  }
1080
1088
  //#endregion
1081
- //#region extensions/codex/src/app-server/attempt-terminal.ts
1082
- const attemptTerminal = agentHarnessAttemptTerminal;
1089
+ //#region extensions/codex/src/app-server/event-projector-settlement.ts
1090
+ var CodexProjectionSettlement = class {
1091
+ constructor(params, isActive) {
1092
+ this.turnTainted = false;
1093
+ this.pending = /* @__PURE__ */ new Map();
1094
+ const detach = (stage, callback) => callback ? (...args) => {
1095
+ if (!isActive()) return;
1096
+ const completion = createDeferred();
1097
+ this.pending.set(completion.promise, stage);
1098
+ const settled = () => {
1099
+ this.pending.delete(completion.promise);
1100
+ completion.resolve();
1101
+ };
1102
+ const failed = (error) => {
1103
+ embeddedAgentLog.warn(`codex app-server ${stage} callback failed: ${String(error)}`);
1104
+ settled();
1105
+ };
1106
+ try {
1107
+ Promise.resolve(callback(...args)).then(settled, failed);
1108
+ } catch (error) {
1109
+ failed(error);
1110
+ }
1111
+ } : void 0;
1112
+ this.params = {
1113
+ ...params,
1114
+ onAssistantMessageStart: detach("onAssistantMessageStart", params.onAssistantMessageStart),
1115
+ onPartialReply: detach("onPartialReply", params.onPartialReply),
1116
+ onReasoningStream: detach("onReasoningStream", params.onReasoningStream),
1117
+ onReasoningEnd: detach("onReasoningEnd", params.onReasoningEnd)
1118
+ };
1119
+ }
1120
+ get pendingStage() {
1121
+ return this.stage ?? this.pending.values().next().value;
1122
+ }
1123
+ get completedAnswer() {
1124
+ const turn = this.terminalReceipt;
1125
+ const answer = turn?.items?.findLast((item) => item.type === "agentMessage" && item.phase !== "commentary" && item.delivery !== "async" && typeof item.text === "string" && item.text.trim().length > 0);
1126
+ return turn?.status === "completed" && answer ? {
1127
+ turn,
1128
+ answer
1129
+ } : void 0;
1130
+ }
1131
+ async project(stage, project) {
1132
+ const previous = this.stage;
1133
+ this.stage = stage;
1134
+ try {
1135
+ return await project();
1136
+ } finally {
1137
+ this.stage = previous;
1138
+ }
1139
+ }
1140
+ async drain() {
1141
+ while (this.pending.size > 0) await Promise.all(this.pending.keys());
1142
+ }
1143
+ };
1083
1144
  //#endregion
1084
1145
  //#region extensions/codex/src/app-server/event-projector-snapshot.ts
1085
1146
  function buildCodexMessagesSnapshot(params) {
@@ -1094,7 +1155,10 @@ function buildCodexMessagesSnapshot(params) {
1094
1155
  ...params.toolMessages
1095
1156
  ].toSorted((left, right) => (asDateTimestampMs(left.timestamp) ?? 0) - (asDateTimestampMs(right.timestamp) ?? 0));
1096
1157
  messages.push(...visibleWorkMessages);
1097
- if (params.lastAssistant) messages.push(attachCodexMirrorIdentity(params.lastAssistant, `${params.turnId}:assistant`));
1158
+ if (params.lastAssistant) {
1159
+ const assistant = applyCodexTranscriptTaint(params.lastAssistant, { tainted: params.turnTainted === true });
1160
+ messages.push(attachCodexMirrorIdentity(assistant, `${params.turnId}:assistant`));
1161
+ }
1098
1162
  const taint = { tainted: false };
1099
1163
  return messages.map((message) => projectAgentHarnessTranscriptMessageForDisplay({
1100
1164
  hidden: params.runParams.trigger === "memory",
@@ -1125,116 +1189,6 @@ function buildCodexSteeringMessagesSnapshot(params) {
1125
1189
  };
1126
1190
  }
1127
1191
  //#endregion
1128
- //#region extensions/codex/src/app-server/event-projector-result.ts
1129
- function buildCodexAttemptResult(input) {
1130
- input.nativeToolLifecycleProjection.finalizeActive();
1131
- const assistantTexts = input.assistantProjection.collectAssistantTexts();
1132
- const asyncMessages = input.assistantProjection.collectAsyncMessages();
1133
- const commentaryMessages = input.assistantProjection.collectCommentaryMessages();
1134
- const reasoningText = input.reasoningProjection.reasoningText();
1135
- const planText = input.reasoningProjection.planText();
1136
- const usage = input.usageProjection.usage;
1137
- const projectedUsage = input.aborted && usage ? {
1138
- ...usage,
1139
- contextUsage: { state: "unavailable" }
1140
- } : usage;
1141
- const hasAssistantItemText = input.assistantProjection.hasAssistantItemTextForSynthesis();
1142
- const legacyFailClosed = !input.completedTurn || input.completedTurn.status !== "completed" || hasAssistantItemText;
1143
- const hasDeliverableAssistantOnCompletedTurn = input.completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
1144
- const synthesizedMissingToolResultError = input.toolTranscriptProjection.synthesizeMissingToolResults({
1145
- synthesize: legacyFailClosed,
1146
- terminalDisposition: input.aborted ? "tool_error" : hasDeliverableAssistantOnCompletedTurn ? "diagnostic_only" : "prompt_error"
1147
- });
1148
- const storedMissingToolResultError = synthesizedMissingToolResultError ?? input.synthesizedMissingToolResultError;
1149
- let promptErrorSource = input.promptErrorSource;
1150
- if (synthesizedMissingToolResultError) {
1151
- input.recordSynthesizedMissingToolResultError(synthesizedMissingToolResultError);
1152
- promptErrorSource = promptErrorSource ?? "prompt";
1153
- }
1154
- const assistantMessageOptions = {
1155
- tokenUsage: projectedUsage,
1156
- aborted: input.aborted,
1157
- promptError: input.promptError,
1158
- providerRefusal: input.providerRefusal
1159
- };
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);
1162
- const messagesSnapshot = buildCodexMessagesSnapshot({
1163
- runParams: input.runParams,
1164
- turnId: input.turnId,
1165
- upstreamUserText: input.upstreamUserText,
1166
- reasoningText,
1167
- asyncMessages,
1168
- commentaryMessages,
1169
- toolMessages: input.toolTranscriptProjection.transcriptMessages,
1170
- lastAssistant
1171
- });
1172
- const turnFailed = input.completedTurn?.status === "failed";
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({
1175
- assistantTexts,
1176
- reasoningText,
1177
- planText,
1178
- promptError,
1179
- turnCompleted: Boolean(input.completedTurn)
1180
- });
1181
- const toolMetas = input.toolProgressProjection.toolMetas;
1182
- const hadPotentialSideEffects = input.toolTelemetry.didSendViaMessagingTool || Boolean(input.toolTelemetry.successfulCronAdds || input.toolTelemetry.acceptedSessionSpawns?.length) || input.generatedMediaProjection.hasGeneratedMedia() || input.toolProgressProjection.hasPotentialSideEffects;
1183
- const sentMediaUrls = new Set(input.toolTelemetry.messagingToolSentMediaUrls.map((url) => url.trim()));
1184
- const toolAutoDeliveryMediaUrls = input.toolTelemetry.toolAutoDeliveryMediaUrls?.filter((url) => !sentMediaUrls.has(url.trim()));
1185
- const result = {
1186
- terminal: attemptTerminal.normalize({
1187
- aborted: input.aborted,
1188
- promptError,
1189
- promptErrorSource: promptError ? promptErrorSource || "prompt" : null
1190
- }),
1191
- sessionIdUsed: input.runParams.sessionId,
1192
- terminalTurnId: input.turnId,
1193
- ...agentHarnessResultClassification ? { agentHarnessResultClassification } : {},
1194
- bootstrapPromptWarningSignaturesSeen: input.runParams.bootstrapPromptWarningSignaturesSeen,
1195
- bootstrapPromptWarningSignature: input.runParams.bootstrapPromptWarningSignature,
1196
- ...input.usageProjection.modelIterations > 0 ? { modelIterations: input.usageProjection.modelIterations } : {},
1197
- messagesSnapshot,
1198
- assistantTexts,
1199
- toolMetas,
1200
- lastAssistant,
1201
- currentAttemptAssistant,
1202
- ...input.toolProgressProjection.lastToolError ? { lastToolError: input.toolProgressProjection.lastToolError } : {},
1203
- didSendViaMessagingTool: input.toolTelemetry.didSendViaMessagingTool,
1204
- didDeliverSourceReplyViaMessageTool: input.toolTelemetry.didDeliverSourceReplyViaMessageTool === true,
1205
- sourceReplyDelivered: input.toolTelemetry.sourceReplyDelivered,
1206
- messagingToolSentTexts: input.toolTelemetry.messagingToolSentTexts,
1207
- messagingToolSentMediaUrls: input.toolTelemetry.messagingToolSentMediaUrls,
1208
- messagingToolSentTargets: input.toolTelemetry.messagingToolSentTargets,
1209
- messagingToolSourceReplyPayloads: input.toolTelemetry.messagingToolSourceReplyPayloads ?? [],
1210
- heartbeatToolResponse: input.toolTelemetry.heartbeatToolResponse,
1211
- toolMediaUrls: input.generatedMediaProjection.buildToolMediaUrls(input.toolTelemetry),
1212
- hostOwnedToolMediaUrls: input.generatedMediaProjection.buildHostOwnedMediaUrls(input.toolTelemetry),
1213
- toolAudioAsVoice: input.toolTelemetry.toolAudioAsVoice,
1214
- successfulCronAdds: input.toolTelemetry.successfulCronAdds,
1215
- acceptedSessionSpawns: input.toolTelemetry.acceptedSessionSpawns,
1216
- cloudCodeAssistFormatError: false,
1217
- contextTokens: input.contextTokens,
1218
- contextTokensSource: input.contextTokensSource,
1219
- attemptUsage: projectedUsage,
1220
- ...input.completedCompactionCount > 0 ? { compactionCount: input.completedCompactionCount } : {},
1221
- replayMetadata: {
1222
- hadPotentialSideEffects,
1223
- replaySafe: !hadPotentialSideEffects
1224
- },
1225
- itemLifecycle: {
1226
- startedCount: input.activeItemCount + input.completedItemCount,
1227
- completedCount: input.completedItemCount,
1228
- activeCount: input.activeItemCount
1229
- },
1230
- yieldDetected: input.yieldDetected || false,
1231
- didSendDeterministicApprovalPrompt: input.guardianReviewCount > 0 ? false : void 0
1232
- };
1233
- const transferTtsProvenance = resolveCodexTtsProvenanceTransfer(input.runParams.hostCapabilities);
1234
- for (const toolResult of input.toolTelemetry.coreTtsToolResults ?? []) transferTtsProvenance?.(toolResult, result, toolAutoDeliveryMediaUrls ?? []);
1235
- return result;
1236
- }
1237
- //#endregion
1238
1192
  //#region extensions/codex/src/app-server/usage-limit-error.ts
1239
1193
  /**
1240
1194
  * Enriches Codex usage-limit failures with current rate-limit information and
@@ -1251,7 +1205,7 @@ function resolveCodexPromptError(source) {
1251
1205
  const usageLimitMessage = formatCodexUsageLimitErrorMessage(source);
1252
1206
  if (usageLimitMessage) return new CodexUsageLimitPromptError(usageLimitMessage);
1253
1207
  const info = source.codexErrorInfo;
1254
- let status = info === "serverOverloaded" ? 503 : info === "internalServerError" ? 500 : void 0;
1208
+ let status = info === "rateLimitExceeded" ? 429 : info === "serverOverloaded" ? 503 : info === "internalServerError" ? 500 : void 0;
1255
1209
  if (isJsonObject(info)) for (const variant of [
1256
1210
  "httpConnectionFailed",
1257
1211
  "responseStreamConnectionFailed",
@@ -1423,6 +1377,7 @@ var CodexTranscriptCheckpoint = class {
1423
1377
  this.writing = Promise.resolve();
1424
1378
  this.tainted = false;
1425
1379
  this.closed = false;
1380
+ this.abandoned = false;
1426
1381
  this.nextTimestamp = () => {
1427
1382
  this.lastTimestamp = Math.max(Date.now(), this.lastTimestamp + 1);
1428
1383
  return this.lastTimestamp;
@@ -1442,6 +1397,10 @@ var CodexTranscriptCheckpoint = class {
1442
1397
  if (this.params.sessionTarget && !this.closed) this.pending.push(entry);
1443
1398
  };
1444
1399
  }
1400
+ abandon() {
1401
+ this.closed = this.abandoned = true;
1402
+ this.pending.length = 0;
1403
+ }
1445
1404
  flush(close = false) {
1446
1405
  if (this.closed) return this.writing;
1447
1406
  this.closed = close;
@@ -1459,6 +1418,9 @@ var CodexTranscriptCheckpoint = class {
1459
1418
  });
1460
1419
  try {
1461
1420
  await codexTranscriptMirrorRuntime.mirror({
1421
+ assertWriteCurrent: () => {
1422
+ if (this.abandoned) throw new Error("Codex transcript checkpoint was retired before write");
1423
+ },
1462
1424
  ...this.params.sessionTarget,
1463
1425
  sessionId: this.params.sessionId,
1464
1426
  cwd: this.params.workspaceDir,
@@ -1482,8 +1444,9 @@ var CodexTranscriptCheckpoint = class {
1482
1444
  }
1483
1445
  };
1484
1446
  //#endregion
1485
- //#region extensions/codex/src/app-server/event-projector.ts
1486
- var CodexAppServerEventProjector = class {
1447
+ //#region extensions/codex/src/app-server/event-projector-result.ts
1448
+ /** Owns per-turn projection state and builds results from the same state. */
1449
+ var CodexTurnProjection = class {
1487
1450
  constructor(params, threadId, turnId, options = {}) {
1488
1451
  this.params = params;
1489
1452
  this.threadId = threadId;
@@ -1492,13 +1455,14 @@ var CodexAppServerEventProjector = class {
1492
1455
  this.activeItemIds = /* @__PURE__ */ new Set();
1493
1456
  this.completedItemIds = /* @__PURE__ */ new Set();
1494
1457
  this.activeCompactionItemIds = /* @__PURE__ */ new Set();
1495
- this.projectionClosed = false;
1458
+ this.projectionController = new AbortController();
1496
1459
  this.settledTurnFailureFinalizationAllowed = false;
1497
1460
  this.terminalFailure = new CodexTerminalFailureProjection();
1498
1461
  this.synthesizedMissingToolResultError = null;
1499
1462
  this.aborted = false;
1500
1463
  this.usageProjection = new CodexUsageProjection();
1501
1464
  this.completedCompactionCount = 0;
1465
+ this.settlement = new CodexProjectionSettlement(params, () => !this.projectionClosed);
1502
1466
  this.transcriptCheckpoint = new CodexTranscriptCheckpoint(params, threadId, turnId);
1503
1467
  this.asyncDeliveryProjection = new CodexAsyncDeliveryProjection(params, threadId, turnId, options);
1504
1468
  this.contextTokens = options.initialContextTokens;
@@ -1509,7 +1473,7 @@ var CodexAppServerEventProjector = class {
1509
1473
  remoteWorkspaceRoot: options.remoteWorkspaceRoot,
1510
1474
  readFile: options.readRemoteWorkspaceFile,
1511
1475
  requestTimeoutMs: options.remoteWorkspaceRequestTimeoutMs,
1512
- signal: options.runAbortSignal
1476
+ signal: options.runAbortSignal ? AbortSignal.any([options.runAbortSignal, this.projectionController.signal]) : this.projectionController.signal
1513
1477
  });
1514
1478
  this.toolProgressProjection = new CodexToolProgressProjection(params);
1515
1479
  this.toolTranscriptProjection = new CodexToolTranscriptProjection(params, threadId, turnId, this.toolProgressProjection, this.transcriptCheckpoint.nextTimestamp, {
@@ -1519,12 +1483,151 @@ var CodexAppServerEventProjector = class {
1519
1483
  checkpointMessage: this.transcriptCheckpoint.enqueue
1520
1484
  });
1521
1485
  this.eventProjection = new CodexEventProjection(threadId, turnId, (event) => this.emitAgentEvent(event), this.toolProgressProjection, this.toolTranscriptProjection, options.onNativeToolResultRecorded);
1522
- this.assistantProjection = new CodexAssistantProjection(params, (event) => this.emitAgentEvent(event), (text) => this.toolProgressProjection.matchesEcho(text), this.transcriptCheckpoint.nextTimestamp, this.transcriptCheckpoint.enqueueCommentary);
1523
- this.reasoningProjection = new CodexReasoningProjection(params, (event) => this.emitAgentEvent(event), options.onNativePlanUpdate);
1486
+ this.assistantProjection = new CodexAssistantProjection(this.settlement.params, (event) => this.emitAgentEvent(event), (text) => this.toolProgressProjection.matchesEcho(text), this.transcriptCheckpoint.nextTimestamp, this.transcriptCheckpoint.enqueueCommentary);
1487
+ this.reasoningProjection = new CodexReasoningProjection(this.settlement.params, (event) => this.emitAgentEvent(event), options.onNativePlanUpdate);
1488
+ }
1489
+ get projectionClosed() {
1490
+ return this.projectionController.signal.aborted;
1491
+ }
1492
+ buildResult(toolTelemetry, options) {
1493
+ this.eventProjection.flushPendingGuardianWarning();
1494
+ const { params: runParams, turnId, completedTurn, aborted, contextTokens, contextTokensSource, completedCompactionCount, synthesizedMissingToolResultError: previousMissingToolResultError } = this;
1495
+ const { promptError: initialPromptError, promptErrorSource: initialPromptErrorSource, providerRefusal } = this.terminalFailure;
1496
+ const upstreamUserText = this.options.upstreamUserText;
1497
+ const turnTainted = this.settlement.turnTainted;
1498
+ const activeItemCount = this.activeItemIds.size;
1499
+ const completedItemCount = this.completedItemIds.size;
1500
+ const guardianReviewCount = this.eventProjection.guardianReviewCount;
1501
+ const yieldDetected = options?.yieldDetected;
1502
+ this.nativeToolLifecycleProjector.finalizeActive();
1503
+ const assistantTexts = this.assistantProjection.collectAssistantTexts();
1504
+ const asyncMessages = this.assistantProjection.collectAsyncMessages();
1505
+ const commentaryMessages = this.assistantProjection.collectCommentaryMessages();
1506
+ const reasoningText = this.reasoningProjection.reasoningText();
1507
+ const planText = this.reasoningProjection.planText();
1508
+ const usage = this.usageProjection.usage;
1509
+ const projectedUsage = aborted && usage ? {
1510
+ ...usage,
1511
+ contextUsage: { state: "unavailable" }
1512
+ } : usage;
1513
+ const hasAssistantItemText = this.assistantProjection.hasAssistantItemTextForSynthesis();
1514
+ const legacyFailClosed = !completedTurn || completedTurn.status !== "completed" || hasAssistantItemText;
1515
+ const hasDeliverableAssistantOnCompletedTurn = completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
1516
+ const synthesizedMissingToolResultError = this.toolTranscriptProjection.synthesizeMissingToolResults({
1517
+ synthesize: legacyFailClosed,
1518
+ terminalDisposition: aborted ? "tool_error" : hasDeliverableAssistantOnCompletedTurn ? "diagnostic_only" : "prompt_error"
1519
+ });
1520
+ const storedMissingToolResultError = synthesizedMissingToolResultError ?? previousMissingToolResultError;
1521
+ let promptErrorSource = initialPromptErrorSource;
1522
+ if (synthesizedMissingToolResultError) {
1523
+ this.synthesizedMissingToolResultError = synthesizedMissingToolResultError;
1524
+ promptErrorSource = promptErrorSource ?? "prompt";
1525
+ }
1526
+ const assistantMessageOptions = {
1527
+ tokenUsage: projectedUsage,
1528
+ aborted,
1529
+ promptError: initialPromptError,
1530
+ providerRefusal
1531
+ };
1532
+ const lastAssistant = providerRefusal ? this.assistantProjection.createAssistantMessage("", assistantMessageOptions) : assistantTexts.length ? this.assistantProjection.createAssistantMessage(assistantTexts.join("\n\n"), assistantMessageOptions) : void 0;
1533
+ const currentAttemptAssistant = providerRefusal ? lastAssistant : this.assistantProjection.createCurrentAttemptAssistantMessage(assistantMessageOptions);
1534
+ const messagesSnapshot = buildCodexMessagesSnapshot({
1535
+ runParams,
1536
+ turnId,
1537
+ upstreamUserText,
1538
+ reasoningText,
1539
+ asyncMessages,
1540
+ commentaryMessages,
1541
+ toolMessages: this.toolTranscriptProjection.transcriptMessages,
1542
+ lastAssistant,
1543
+ turnTainted
1544
+ });
1545
+ const turnFailed = completedTurn?.status === "failed";
1546
+ const promptError = providerRefusal ? null : initialPromptError ?? storedMissingToolResultError ?? (turnFailed ? completedTurn?.error?.message ?? "codex app-server turn failed" : null);
1547
+ const agentHarnessResultClassification = providerRefusal ? void 0 : classifyAgentHarnessTerminalOutcome({
1548
+ assistantTexts,
1549
+ reasoningText,
1550
+ planText,
1551
+ promptError,
1552
+ turnCompleted: Boolean(completedTurn)
1553
+ });
1554
+ const toolMetas = this.toolProgressProjection.toolMetas;
1555
+ const hadPotentialSideEffects = toolTelemetry.didSendViaMessagingTool || Boolean(toolTelemetry.successfulCronAdds || toolTelemetry.acceptedSessionSpawns?.length) || this.generatedMediaProjection.hasGeneratedMedia() || this.toolProgressProjection.hasPotentialSideEffects;
1556
+ const sentMediaUrls = new Set(toolTelemetry.messagingToolSentMediaUrls.map((url) => url.trim()));
1557
+ const toolAutoDeliveryMediaUrls = toolTelemetry.toolAutoDeliveryMediaUrls?.filter((url) => !sentMediaUrls.has(url.trim()));
1558
+ const result = {
1559
+ terminal: attemptTerminal.normalize({
1560
+ aborted,
1561
+ promptError,
1562
+ promptErrorSource: promptError ? promptErrorSource || "prompt" : null
1563
+ }),
1564
+ sessionIdUsed: runParams.sessionId,
1565
+ terminalTurnId: turnId,
1566
+ ...agentHarnessResultClassification ? { agentHarnessResultClassification } : {},
1567
+ bootstrapPromptWarningSignaturesSeen: runParams.bootstrapPromptWarningSignaturesSeen,
1568
+ bootstrapPromptWarningSignature: runParams.bootstrapPromptWarningSignature,
1569
+ ...this.usageProjection.modelIterations > 0 ? { modelIterations: this.usageProjection.modelIterations } : {},
1570
+ messagesSnapshot,
1571
+ assistantTexts,
1572
+ toolMetas,
1573
+ lastAssistant,
1574
+ currentAttemptAssistant,
1575
+ ...this.toolProgressProjection.lastToolError ? { lastToolError: this.toolProgressProjection.lastToolError } : {},
1576
+ didSendViaMessagingTool: toolTelemetry.didSendViaMessagingTool,
1577
+ didDeliverSourceReplyViaMessageTool: toolTelemetry.didDeliverSourceReplyViaMessageTool === true,
1578
+ sourceReplyDelivered: toolTelemetry.sourceReplyDelivered,
1579
+ messagingToolSentTexts: toolTelemetry.messagingToolSentTexts,
1580
+ messagingToolSentMediaUrls: toolTelemetry.messagingToolSentMediaUrls,
1581
+ messagingToolSentTargets: toolTelemetry.messagingToolSentTargets,
1582
+ messagingToolSourceReplyPayloads: toolTelemetry.messagingToolSourceReplyPayloads ?? [],
1583
+ heartbeatToolResponse: toolTelemetry.heartbeatToolResponse,
1584
+ toolMediaUrls: this.generatedMediaProjection.buildToolMediaUrls(toolTelemetry),
1585
+ hostOwnedToolMediaUrls: this.generatedMediaProjection.buildHostOwnedMediaUrls(toolTelemetry),
1586
+ toolAudioAsVoice: toolTelemetry.toolAudioAsVoice,
1587
+ successfulCronAdds: toolTelemetry.successfulCronAdds,
1588
+ acceptedSessionSpawns: toolTelemetry.acceptedSessionSpawns,
1589
+ cloudCodeAssistFormatError: false,
1590
+ contextTokens,
1591
+ contextTokensSource,
1592
+ attemptUsage: projectedUsage,
1593
+ ...completedCompactionCount > 0 ? { compactionCount: completedCompactionCount } : {},
1594
+ replayMetadata: {
1595
+ hadPotentialSideEffects,
1596
+ replaySafe: !hadPotentialSideEffects
1597
+ },
1598
+ itemLifecycle: {
1599
+ startedCount: activeItemCount + completedItemCount,
1600
+ completedCount: completedItemCount,
1601
+ activeCount: activeItemCount
1602
+ },
1603
+ yieldDetected: yieldDetected || false,
1604
+ didSendDeterministicApprovalPrompt: guardianReviewCount > 0 ? false : void 0
1605
+ };
1606
+ const transferTtsProvenance = resolveCodexTtsProvenanceTransfer(runParams.hostCapabilities);
1607
+ for (const toolResult of toolTelemetry.coreTtsToolResults ?? []) transferTtsProvenance?.(toolResult, result, toolAutoDeliveryMediaUrls ?? []);
1608
+ return result;
1609
+ }
1610
+ emitAgentEvent(event) {
1611
+ if (!this.projectionClosed) emitCodexAgentEvent(this.params, event);
1524
1612
  }
1613
+ };
1614
+ //#endregion
1615
+ //#region extensions/codex/src/app-server/event-projector.ts
1616
+ var CodexAppServerEventProjector = class extends CodexTurnProjection {
1525
1617
  getCompletedTurnStatus() {
1526
1618
  return this.completedTurn?.status;
1527
1619
  }
1620
+ /** Native completion owns the answer independently of unfinished host projection. */
1621
+ recoverCompletedAnswer() {
1622
+ const completed = this.settlement.completedAnswer;
1623
+ if (!completed || this.aborted || this.terminalFailure.promptError) return false;
1624
+ this.projectionController.abort();
1625
+ this.transcriptCheckpoint.abandon();
1626
+ this.completedTurn = completed.turn;
1627
+ this.assistantProjection.recordSnapshotItem(completed.answer);
1628
+ this.assistantProjection.finalizeAnswerCandidate(completed.turn);
1629
+ return true;
1630
+ }
1528
1631
  getActiveMcpToolCall(serverName) {
1529
1632
  if (this.projectionClosed || this.aborted) return;
1530
1633
  return this.nativeToolLifecycleProjector.getActiveMcpToolCall(serverName);
@@ -1553,8 +1656,8 @@ var CodexAppServerEventProjector = class {
1553
1656
  }
1554
1657
  /** Fence delayed projections before the turn's final snapshot leaves its owner. */
1555
1658
  closeProjection() {
1556
- this.projectionClosed = true;
1557
- return this.transcriptCheckpoint.flush(true);
1659
+ this.projectionController.abort();
1660
+ return this.settlement.project("transcript/checkpoint", () => this.transcriptCheckpoint.flush(true));
1558
1661
  }
1559
1662
  /** Resolves the shared model-order position for a native tool item. */
1560
1663
  recordNativeToolOutcome(item) {
@@ -1596,11 +1699,9 @@ var CodexAppServerEventProjector = class {
1596
1699
  break;
1597
1700
  case "item/started":
1598
1701
  await this.handleItemStarted(params);
1599
- await this.transcriptCheckpoint.flush();
1600
1702
  break;
1601
1703
  case "item/completed":
1602
1704
  await this.handleItemCompleted(params);
1603
- await this.transcriptCheckpoint.flush();
1604
1705
  break;
1605
1706
  case "item/commandExecution/outputDelta":
1606
1707
  this.toolProgressProjection.handleOutputDelta(params, "bash");
@@ -1643,20 +1744,21 @@ var CodexAppServerEventProjector = class {
1643
1744
  break;
1644
1745
  case "rawResponseItem/completed":
1645
1746
  await this.handleRawResponseItemCompleted(params);
1646
- await this.transcriptCheckpoint.flush();
1647
1747
  break;
1648
1748
  case "model/rerouted":
1649
1749
  this.eventProjection.handleModelRerouted(params);
1650
1750
  break;
1651
1751
  case "error": {
1652
1752
  this.usageProjection.invalidateContext();
1653
- if (params.willRetry === true) break;
1753
+ if (params.willRetry === true) {
1754
+ this.eventProjection.handleRetry(params);
1755
+ break;
1756
+ }
1654
1757
  const codexErrorInfo = isJsonObject(params.error) ? params.error.codexErrorInfo : void 0;
1655
- const message = readCodexErrorNotificationMessage(params);
1656
1758
  const compactionFailure = codexErrorInfo === "other" && this.isCompacting();
1657
1759
  this.settledTurnFailureFinalizationAllowed = codexErrorInfo === "serverOverloaded" || compactionFailure;
1658
1760
  this.terminalFailure.record({
1659
- message,
1761
+ message: readCodexErrorNotificationMessage(params),
1660
1762
  codexErrorInfo,
1661
1763
  rateLimits: this.options.readRecentRateLimits?.(),
1662
1764
  fallbackMessage: "codex app-server error",
@@ -1677,47 +1779,23 @@ var CodexAppServerEventProjector = class {
1677
1779
  case "model/safetyBuffering/updated": break;
1678
1780
  default: this.diagnostics.warnUnknownEvent(notification, params);
1679
1781
  }
1680
- }
1681
- buildResult(toolTelemetry, options) {
1682
- this.eventProjection.flushPendingGuardianWarning();
1683
- return buildCodexAttemptResult({
1684
- runParams: this.params,
1685
- turnId: this.turnId,
1686
- upstreamUserText: this.options.upstreamUserText,
1687
- completedTurn: this.completedTurn,
1688
- promptError: this.terminalFailure.promptError,
1689
- promptErrorSource: this.terminalFailure.promptErrorSource,
1690
- providerRefusal: this.terminalFailure.providerRefusal,
1691
- synthesizedMissingToolResultError: this.synthesizedMissingToolResultError,
1692
- recordSynthesizedMissingToolResultError: (error) => {
1693
- this.synthesizedMissingToolResultError = error;
1694
- this.terminalFailure.promptErrorSource ??= "prompt";
1695
- },
1696
- aborted: this.aborted,
1697
- contextTokens: this.contextTokens,
1698
- contextTokensSource: this.contextTokensSource,
1699
- completedCompactionCount: this.completedCompactionCount,
1700
- activeItemCount: this.activeItemIds.size,
1701
- completedItemCount: this.completedItemIds.size,
1702
- guardianReviewCount: this.eventProjection.guardianReviewCount,
1703
- toolTelemetry,
1704
- yieldDetected: options?.yieldDetected,
1705
- nativeToolLifecycleProjection: this.nativeToolLifecycleProjector,
1706
- assistantProjection: this.assistantProjection,
1707
- reasoningProjection: this.reasoningProjection,
1708
- usageProjection: this.usageProjection,
1709
- toolTranscriptProjection: this.toolTranscriptProjection,
1710
- toolProgressProjection: this.toolProgressProjection,
1711
- generatedMediaProjection: this.generatedMediaProjection
1712
- });
1782
+ if (!this.projectionClosed && [
1783
+ "item/started",
1784
+ "item/completed",
1785
+ "rawResponseItem/completed"
1786
+ ].includes(notification.method)) await this.settlement.project("transcript/checkpoint", () => this.transcriptCheckpoint.flush());
1713
1787
  }
1714
1788
  recordDynamicToolCall(params) {
1715
1789
  this.toolTranscriptProjection.recordDynamicToolCall(params);
1716
1790
  }
1717
1791
  /** Projects a successful OpenClaw progress_card call through the native plan stream. */
1718
1792
  async recordDynamicProgressCardUpdate(params) {
1719
- if (isJsonObject(params)) {
1720
- const projected = { plan: Array.isArray(params.plan) ? params.plan : [] };
1793
+ const update = projectProgressCardChannelUpdate(params);
1794
+ if (update) {
1795
+ const projected = {
1796
+ plan: update.steps,
1797
+ ...update.explanation ? { explanation: update.explanation } : {}
1798
+ };
1721
1799
  await this.reasoningProjection.handleTurnPlanUpdated(projected, "openclaw");
1722
1800
  }
1723
1801
  }
@@ -1805,7 +1883,7 @@ var CodexAppServerEventProjector = class {
1805
1883
  if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
1806
1884
  if (this.projectionClosed) return;
1807
1885
  this.reasoningProjection.recordItem(item);
1808
- await this.generatedMediaProjection.recordNative(item);
1886
+ await this.settlement.project("media_projection", () => this.generatedMediaProjection.recordNative(item));
1809
1887
  if (this.projectionClosed) return;
1810
1888
  if (item?.type === "contextCompaction" && itemId) {
1811
1889
  if (!this.isCompactionProjectionActive()) return;
@@ -1897,11 +1975,16 @@ var CodexAppServerEventProjector = class {
1897
1975
  if (asyncMessage) await this.asyncDeliveryProjection.deliver(asyncMessage);
1898
1976
  if (this.projectionClosed) return;
1899
1977
  this.reasoningProjection.recordItem(item);
1900
- await this.generatedMediaProjection.recordNative(item);
1978
+ await this.settlement.project("media_projection", () => this.generatedMediaProjection.recordNative(item));
1901
1979
  if (this.projectionClosed) return;
1902
1980
  this.toolProgressProjection.recordToolMeta(item);
1903
1981
  this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
1904
- await this.emitSnapshotOnlyNativeToolProgress(item);
1982
+ await this.eventProjection.emitSnapshotOnlyNativeToolProgress({
1983
+ item,
1984
+ activeItemIds: this.activeItemIds,
1985
+ completedItemIds: this.completedItemIds,
1986
+ isActive: () => !this.projectionClosed
1987
+ });
1905
1988
  if (this.projectionClosed) return;
1906
1989
  this.toolTranscriptProjection.recordNativeToolCall(item);
1907
1990
  const details = await this.toolTranscriptProjection.prepareNativeToolResultDetails(item);
@@ -1921,39 +2004,12 @@ var CodexAppServerEventProjector = class {
1921
2004
  this.activeCompactionItemIds.clear();
1922
2005
  await this.reasoningProjection.maybeEndReasoning();
1923
2006
  }
1924
- async emitSnapshotOnlyNativeToolProgress(item) {
1925
- if (!shouldSynthesizeToolProgressForItem(item) || !matchesCodexSnapshotTurn(item, this.turnId) || this.completedItemIds.has(item.id) || itemStatus(item) === "running") return;
1926
- if (!this.activeItemIds.has(item.id)) {
1927
- this.eventProjection.emitStandardItemEvent({
1928
- phase: "start",
1929
- item
1930
- });
1931
- await this.eventProjection.emitNormalizedToolItemEvent({
1932
- phase: "start",
1933
- item
1934
- });
1935
- }
1936
- if (this.projectionClosed) return;
1937
- this.activeItemIds.delete(item.id);
1938
- this.eventProjection.emitStandardItemEvent({
1939
- phase: "end",
1940
- item
1941
- });
1942
- await this.eventProjection.emitNormalizedToolItemEvent({
1943
- phase: "result",
1944
- item
1945
- });
1946
- this.completedItemIds.add(item.id);
1947
- }
1948
2007
  async handleRawResponseItemCompleted(params) {
1949
2008
  const item = isJsonObject(params.item) ? params.item : void 0;
1950
2009
  if (!item) return;
1951
2010
  this.toolTranscriptProjection.recordRawNativeToolItem(item);
1952
2011
  this.assistantProjection.handleRawResponseItemCompleted(item, this.activeItemIds);
1953
- await this.generatedMediaProjection.recordRaw(item);
1954
- }
1955
- emitAgentEvent(event) {
1956
- if (!this.projectionClosed) emitCodexAgentEvent(this.params, event);
2012
+ await this.settlement.project("media_projection", () => this.generatedMediaProjection.recordRaw(item));
1957
2013
  }
1958
2014
  isHookNotificationForCurrentThread(params) {
1959
2015
  const threadId = readStringField(params, "threadId");
@@ -2064,6 +2120,7 @@ function createNativeMcpRuntime(params) {
2064
2120
  listResourceTemplates: async (serverName) => {
2065
2121
  return { resourceTemplates: (await loadStatuses()).find((entry) => entry.name === serverName)?.resourceTemplates ?? [] };
2066
2122
  },
2123
+ joinCleanup: async () => {},
2067
2124
  dispose: async () => {}
2068
2125
  };
2069
2126
  return runtime;
@@ -2301,9 +2358,9 @@ function createCodexUserInputBridge(params) {
2301
2358
  });
2302
2359
  },
2303
2360
  async handleElicitationRequest(request) {
2304
- if (readRawOwnString(request.params, "threadId") !== params.threadId) return;
2361
+ if (readOwnDataString(request.params, "threadId") !== params.threadId) return;
2305
2362
  const requestSnapshot = agentHarnessStructuredInput.snapshot(request.params);
2306
- if (requestSnapshot === void 0) {
2363
+ if (!agentHarnessStructuredInput.isRecord(requestSnapshot)) {
2307
2364
  const cancelValue = createCodexElicitationResponse("cancel");
2308
2365
  return await enqueue({
2309
2366
  requestId: request.id,
@@ -2319,10 +2376,10 @@ function createCodexUserInputBridge(params) {
2319
2376
  }
2320
2377
  });
2321
2378
  }
2322
- const { compileCodexOrdinaryElicitation } = await import("./elicitation-input-DMkeki8d.js");
2379
+ if (readOwnDataString(requestSnapshot, "threadId") !== params.threadId) return;
2380
+ const { compileCodexOrdinaryElicitation } = await import("./elicitation-input-DPoK8F7w.js");
2323
2381
  const compiled = compileCodexOrdinaryElicitation({
2324
- value: requestSnapshot,
2325
- threadId: params.threadId,
2382
+ snapshot: requestSnapshot,
2326
2383
  turnId: params.turnId
2327
2384
  });
2328
2385
  if (compiled.kind === "ignored") return;
@@ -2348,7 +2405,7 @@ function createCodexUserInputBridge(params) {
2348
2405
  handleNotification(notification) {
2349
2406
  if (notification.method !== "serverRequest/resolved" || !isJsonObject(notification.params)) return;
2350
2407
  const requestId = readRequestId(notification.params);
2351
- if (requestId === void 0 || readOwnString(notification.params, "threadId") !== params.threadId) return;
2408
+ if (requestId === void 0 || readOwnDataString(notification.params, "threadId") !== params.threadId) return;
2352
2409
  const job = jobs.find((candidate) => typeof candidate.requestId === typeof requestId && candidate.requestId === requestId);
2353
2410
  if (job) cancelJob(job);
2354
2411
  },
@@ -2427,11 +2484,7 @@ function readArray(record, key, maximum) {
2427
2484
  const value = readValue(record, key);
2428
2485
  return Array.isArray(value) && value.length <= maximum ? value : void 0;
2429
2486
  }
2430
- function readOwnString(record, key) {
2431
- const descriptor = Object.getOwnPropertyDescriptor(record, key);
2432
- return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : void 0;
2433
- }
2434
- function readRawOwnString(value, key) {
2487
+ function readOwnDataString(value, key) {
2435
2488
  if (!value || typeof value !== "object" || Array.isArray(value)) return;
2436
2489
  const descriptor = Object.getOwnPropertyDescriptor(value, key);
2437
2490
  return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : void 0;
@@ -2576,6 +2629,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2576
2629
  }
2577
2630
  });
2578
2631
  if (isTerminalTurnStatus(turn.turn.status)) {
2632
+ projectorRef.current.settlement.terminalReceipt = turn.turn;
2579
2633
  state.terminalTurnNotificationQueued = true;
2580
2634
  deadlines.beginSettlement(Date.now());
2581
2635
  }
@@ -2677,13 +2731,15 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2677
2731
  if (result.failedMediaCount) throw new Error(`failed to hydrate ${result.failedMediaCount} structured image attachment(s) for Codex steering`);
2678
2732
  return buildCodexUserInput(text, result.images);
2679
2733
  },
2680
- beforeConfirmConsumed: async (items) => {
2734
+ beforeSubmit: async (items) => {
2681
2735
  const transcriptItems = items.filter((item) => item.isInboundUserMessage === true || item.userTurnTranscriptRecorder !== void 0);
2682
2736
  if (transcriptItems.length === 0) return;
2683
2737
  await promptMirrorPromise;
2738
+ assertSteeringActive();
2684
2739
  const messages = activeProjector.buildSteeringTranscriptPrefix();
2685
2740
  if (params.sessionTarget && messages.length > 0) {
2686
2741
  await codexTranscriptMirrorRuntime.mirror({
2742
+ assertCurrent: assertSteeringActive,
2687
2743
  agentId: sessionAgentId,
2688
2744
  sessionKey: contextSessionKey,
2689
2745
  sessionId: params.sessionId,
@@ -2695,13 +2751,15 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2695
2751
  runMirrorIdentityPrefix: `${activeTurnId}:`,
2696
2752
  config: params.config
2697
2753
  });
2754
+ assertSteeringActive();
2698
2755
  activeProjector.markSteeringTranscriptPersisted();
2699
2756
  }
2700
2757
  for (const item of transcriptItems) {
2701
2758
  const recorder = item.userTurnTranscriptRecorder;
2702
2759
  if (!recorder) continue;
2760
+ assertSteeringActive();
2703
2761
  await recorder.persistApproved();
2704
- if (!recorder.hasPersisted()) throw new Error("Codex consumed steering before its user turn was persisted");
2762
+ if (!recorder.hasPersisted()) throw new Error("Codex steering requires a persisted user turn before submission");
2705
2763
  }
2706
2764
  }
2707
2765
  });
@@ -2721,6 +2779,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2721
2779
  kind: authorityKind,
2722
2780
  assertCurrent: injectionGuard(assertCurrent)
2723
2781
  },
2782
+ sourceRecorder: optionsLocal.userTurnTranscriptRecorder,
2724
2783
  persist: optionsLocal.userTurnTranscriptRecorder ? async () => {
2725
2784
  await optionsLocal.userTurnTranscriptRecorder?.persistApproved();
2726
2785
  } : void 0
@@ -2800,7 +2859,7 @@ function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notificatio
2800
2859
  abort: () => abortExplicitly("aborted")
2801
2860
  };
2802
2861
  params.replyOperation?.attachBackend(handle);
2803
- setActiveEmbeddedRun(params.sessionId, handle, params.sessionKey, params.sessionFile);
2862
+ setActiveEmbeddedRun(params.sessionId, handle, params.sessionKey, params.sessionFile, sessionAgentId);
2804
2863
  const freezeRunTerminalOutcome = () => {
2805
2864
  if (terminalState.terminalOutcomeFrozen) return;
2806
2865
  terminalState.terminalOutcomeFrozen = true;
@@ -2837,7 +2896,9 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
2837
2896
  const projectionClose = state.projectionClosed ? void 0 : activeTurn.activeProjector.closeProjection();
2838
2897
  state.projectionClosed = true;
2839
2898
  const checkpointCleanup = projectionClose ? runCleanupStep("codex-transcript-checkpoint", () => projectionClose) : void 0;
2840
- await state.abortCleanup.catch(() => void 0);
2899
+ if (params.oneShotCliRun) await runCleanupStep("codex-abort-cleanup", () => state.abortCleanup);
2900
+ else await state.abortCleanup?.catch(() => {});
2901
+ if (params.oneShotCliRun) await runCleanupStep("codex-one-shot-terminals", () => terminateCodexBackgroundTerminals(resourceState.client, resourceState.thread.threadId, true));
2841
2902
  try {
2842
2903
  steeringQueueRef.current?.cancel();
2843
2904
  if (params.isFinalFallbackAttempt !== false) await maybeEmitFastModeAutoResetBestEffort();
@@ -2858,8 +2919,8 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
2858
2919
  aborted: runAbortController.signal.aborted && !state.clientClosedAbort
2859
2920
  });
2860
2921
  await runCleanupStep("codex-trajectory-flush", () => trajectoryRecorder?.flush());
2861
- const retainLiveIncognitoThread = (terminalState.turnSucceeded || state.permissionChangeRestart === "confirmed" && !params.abortSignal?.aborted) && isIncognitoSessionKey(params.sessionKey);
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 () => {
2922
+ const retainLiveIncognitoThread = (terminalState.settledTurnStatus === "completed" || state.permissionChangeRestart === "confirmed" && !params.abortSignal?.aborted) && isIncognitoSessionKey(params.sessionKey);
2923
+ const retainLiveThread = ((retainLiveIncognitoThread && resourceState.thread.liveThreadEphemeralPolicy !== void 0 || terminalState.settledTurnStatus !== void 0 && !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
2924
  if (bindingStore.read(bindingIdentity)?.threadId !== resourceState.thread.threadId) return false;
2864
2925
  return await retainCodexAppServerBindingSubscription(resourceState.client, resourceState.thread.threadId, {
2865
2926
  release: resourceState.thread.liveThreadOwnership?.release,
@@ -2877,16 +2938,22 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
2877
2938
  if (!await unsubscribeCodexThreadBestEffort(resourceState.client, {
2878
2939
  threadId: resourceState.thread.threadId,
2879
2940
  timeoutMs: 5e3
2880
- })) await closeCodexStartupClientBestEffort(resourceState.client);
2941
+ })) {
2942
+ await closeCodexStartupClientBestEffort(resourceState.client);
2943
+ if (params.oneShotCliRun) await runCleanupStep("codex-one-shot-unsubscribe", async () => {
2944
+ throw new Error("Codex one-shot thread unsubscribe was not confirmed");
2945
+ });
2946
+ }
2881
2947
  }
2882
2948
  }
2883
2949
  } finally {
2884
2950
  await runCleanupStep("codex-user-input-cancel", () => userInputBridgeRef.current?.cancelPending());
2885
2951
  await runCleanupStep("codex-turn-deadline-clear", () => deadlines.dispose());
2886
2952
  await runCleanupStep("codex-dynamic-tool-cleanup", async () => {
2887
- const cleanupReason = terminalState.turnSucceeded ? "completion" : state.timeout ? "timeout" : runAbortController.signal.aborted ? "cancel" : "error";
2953
+ const cleanupReason = terminalState.settledTurnStatus === "completed" ? "completion" : state.timeout ? "timeout" : runAbortController.signal.aborted ? "cancel" : "error";
2888
2954
  const cleanups = prompt.context.attemptTools.runCleanups.splice(0);
2889
- await Promise.allSettled(cleanups.map(async (cleanup) => await cleanup(cleanupReason)));
2955
+ const errors = (await Promise.allSettled(cleanups.map(async (cleanup) => await cleanup(cleanupReason)))).filter((result) => result.status === "rejected");
2956
+ if (params.oneShotCliRun && errors.length) throw new AggregateError(errors.map((result) => result.reason), "Codex tool cleanup failed");
2890
2957
  });
2891
2958
  await runCleanupStep("codex-route-release", releaseCurrentRoute);
2892
2959
  await checkpointCleanup;
@@ -2895,7 +2962,7 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
2895
2962
  resourceState.nativeHookRelay = void 0;
2896
2963
  await runCleanupStep("codex-native-hook-relay-release", () => {
2897
2964
  if (!nativeHookRelay) return;
2898
- if (state.shouldDelayNativeHookRelayUnregister) scheduleCodexNativeHookRelayUnregister({
2965
+ if (state.shouldDelayNativeHookRelayUnregister && !params.oneShotCliRun) scheduleCodexNativeHookRelayUnregister({
2899
2966
  relay: nativeHookRelay,
2900
2967
  hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec
2901
2968
  });
@@ -3326,11 +3393,11 @@ async function prepareCodexAttemptConnection({ params, options }) {
3326
3393
  config: params.config,
3327
3394
  agentId: policyAgentId
3328
3395
  });
3329
- const agentDir = params.agentDir ?? resolveAgentDir$2(params.config ?? {}, sessionAgentId);
3396
+ const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
3330
3397
  const preparedEnvironment = params.hostCapabilities.preparedEnvironment?.();
3331
3398
  const remoteExec = isCodexRemoteExecPlacementSandbox(sandbox);
3332
3399
  const assertLocalTargetSupported = (unsupported) => {
3333
- if (preparedEnvironment?.localProcessEnv && unsupported) throw new Error("This runtime cannot target the diagnosed local installation. Use the saved prompt with a suggested external or manual handoff on this machine.");
3400
+ if (preparedEnvironment?.localProcessEnv && unsupported) throw new Error("This runtime cannot target the diagnosed local installation. Use an owned local Codex stdio process, or use the saved prompt with a suggested external or manual handoff on this machine.");
3334
3401
  };
3335
3402
  assertLocalTargetSupported(sandbox?.enabled === true || remoteExec);
3336
3403
  const preparedShellEnvironment = preparedEnvironment ? {
@@ -3341,7 +3408,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3341
3408
  const shellEnvironment = preparedShellEnvironment && Object.keys(preparedShellEnvironment).length > 0 ? preparedShellEnvironment : void 0;
3342
3409
  const disableLoginShell = remoteExec || preparedEnvironment?.localProcessEnv !== void 0 || preparedEnvironment?.managedLocalIdentity === true || preparedEnvironment !== void 0 && Object.keys(preparedEnvironment.credentialScrubEnv).length > 0;
3343
3410
  const withPreparedProcessEnv = (appServer) => {
3344
- assertLocalTargetSupported(appServer.start.transport === "websocket" || Boolean(appServer.remoteWorkspaceRoot));
3411
+ assertLocalTargetSupported(appServer.start.transport !== "stdio" || Boolean(appServer.remoteWorkspaceRoot));
3345
3412
  return shellEnvironment ? {
3346
3413
  ...appServer,
3347
3414
  start: {
@@ -3518,7 +3585,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3518
3585
  preDynamicStartupStages.mark("app-server-policy");
3519
3586
  preDynamicStartupStages.mark("native-hook-relay");
3520
3587
  const terminalState = {
3521
- turnSucceeded: false,
3588
+ settledTurnStatus: void 0,
3522
3589
  explicitCancellationObserved: false,
3523
3590
  explicitCancellationReason: void 0,
3524
3591
  terminalOutcomeFrozen: false,
@@ -3730,6 +3797,10 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
3730
3797
  sessionKey: contextSessionKey,
3731
3798
  sessionId: params.sessionId,
3732
3799
  workspaceDir: params.workspaceDir,
3800
+ ...!usesSupervisionConnection && connection.mutable.startupBinding?.preserveNativeModel !== true ? {
3801
+ modelProviderId: params.provider,
3802
+ modelId: params.modelId
3803
+ } : {},
3733
3804
  trigger: params.trigger,
3734
3805
  ...buildAgentHookContextChannelFields({
3735
3806
  sessionKey: contextSessionKey,
@@ -3789,6 +3860,17 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
3789
3860
  });
3790
3861
  const agentWorkspaceDeveloperInstructions = workspaceBootstrapContext.threadDeveloperInstructions ? connection.mutable.startupBinding?.agentWorkspaceDeveloperInstructions ?? workspaceBootstrapContext.threadDeveloperInstructions : void 0;
3791
3862
  const baseDeveloperInstructions = joinPresentSections(buildDeveloperInstructions(runtimeParams, { dynamicTools: toolBridge.availableSpecs }), agentWorkspaceDeveloperInstructions);
3863
+ const watchedSessionsContext = buildCodexWatchedSessionsContext({
3864
+ attempt: runtimeParams,
3865
+ dynamicTools: toolBridge.availableSpecs,
3866
+ sessionKey: contextSessionKey,
3867
+ sandboxed: sandbox?.enabled === true
3868
+ });
3869
+ const buildOpenClawPromptContext = (includeWorkspaceReferences) => buildCodexOpenClawPromptContext({
3870
+ params: runtimeParams,
3871
+ workspacePromptContext: includeWorkspaceReferences ? workspaceBootstrapContext.promptContext : void 0,
3872
+ watchedSessionsContext
3873
+ });
3792
3874
  return {
3793
3875
  runtime,
3794
3876
  attemptTools,
@@ -3801,16 +3883,7 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
3801
3883
  workspaceBootstrapContext,
3802
3884
  agentWorkspaceDeveloperInstructions,
3803
3885
  baseDeveloperInstructions,
3804
- openClawPromptContext: buildCodexOpenClawPromptContext({
3805
- params: runtimeParams,
3806
- workspacePromptContext: workspaceBootstrapContext.promptContext,
3807
- watchedSessionsContext: buildCodexWatchedSessionsContext({
3808
- attempt: runtimeParams,
3809
- dynamicTools: toolBridge.availableSpecs,
3810
- sessionKey: contextSessionKey,
3811
- sandboxed: sandbox?.enabled === true
3812
- })
3813
- }),
3886
+ buildOpenClawPromptContext,
3814
3887
  skillsCollaborationInstructions: renderCodexSkillsCollaborationInstructions({
3815
3888
  attempt: runtimeParams,
3816
3889
  skillsPrompt: params.skillsSnapshot?.prompt
@@ -4057,6 +4130,7 @@ function recordCodexTrajectoryCompletion(recorder, params) {
4057
4130
  yieldDetected: params.yieldDetected ?? false,
4058
4131
  aborted: terminal.aborted,
4059
4132
  promptError: normalizeCodexTrajectoryError(terminal.promptError),
4133
+ ...terminal.settlementWarning ? { settlementWarning: terminal.settlementWarning } : {},
4060
4134
  usage: params.result.attemptUsage,
4061
4135
  assistantTexts: params.result.assistantTexts,
4062
4136
  messagesSnapshot: params.result.messagesSnapshot
@@ -4107,25 +4181,25 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4107
4181
  assertCodexBindingMayBeReplaced(resourceState.thread, operation);
4108
4182
  return true;
4109
4183
  };
4110
- const { state, completion, deadlines } = turnRuntime;
4184
+ const { state, completion, deadlines, settlementExpired } = turnRuntime;
4111
4185
  const { emitLifecycleTerminal, buildLifecycleTerminalMeta } = lifecycle;
4112
4186
  const { drainNotificationQueue } = notifications;
4113
4187
  const { codexModelCallDiagnostics } = requestRuntime;
4114
4188
  const { activeTurnId, activeProjector, runtimeModelSelection, streamState, freezeRunTerminalOutcome, notifyUserMessagePersisted } = activeTurn;
4115
4189
  await completion;
4116
- const abortGraceElapsed = createDeferred();
4190
+ const drainGraceElapsed = createDeferred();
4117
4191
  let settlementPhase = "active";
4118
- let abortGraceTimer;
4119
- const beginAbortGrace = () => {
4120
- if (settlementPhase !== "active") return;
4121
- abortGraceTimer = setTimeout(() => {
4192
+ let drainGraceTimer;
4193
+ const beginDrainGrace = () => {
4194
+ if (settlementPhase !== "active" || drainGraceTimer) return;
4195
+ drainGraceTimer = setTimeout(() => {
4122
4196
  settlementPhase = "expired";
4123
- abortGraceElapsed.resolve();
4197
+ drainGraceElapsed.resolve();
4124
4198
  }, TURN_FINALIZE_DRAIN_ABORT_GRACE_MS);
4125
- abortGraceTimer.unref?.();
4199
+ drainGraceTimer.unref?.();
4126
4200
  };
4127
4201
  const abortListener = addAbortListener(runAbortController.signal, () => {
4128
- state.abortCleanup.then(beginAbortGrace, beginAbortGrace);
4202
+ state.abortCleanup.then(beginDrainGrace, beginDrainGrace);
4129
4203
  });
4130
4204
  const closeProjection = () => {
4131
4205
  state.projectionClosed = true;
@@ -4135,14 +4209,24 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4135
4209
  if (settlementPhase === "closed") return;
4136
4210
  settlementPhase = "closed";
4137
4211
  abortListener[Symbol.dispose]();
4138
- clearTimeout(abortGraceTimer);
4212
+ clearTimeout(drainGraceTimer);
4139
4213
  deadlines.dispose();
4140
4214
  };
4141
- const settlement = drainNotificationQueue().then(closeProjection);
4215
+ const settlement = drainNotificationQueue().then(async () => {
4216
+ await closeProjection();
4217
+ await activeProjector.settlement.drain();
4218
+ });
4219
+ const degradedSettlement = settlementExpired.then(() => {
4220
+ beginDrainGrace();
4221
+ });
4142
4222
  let projectionDrained = false;
4143
4223
  try {
4144
4224
  try {
4145
- projectionDrained = await Promise.race([settlement.then(() => true), abortGraceElapsed.promise.then(() => false)]);
4225
+ projectionDrained = await Promise.race([
4226
+ settlement.then(() => true),
4227
+ drainGraceElapsed.promise.then(() => false),
4228
+ degradedSettlement.then(() => false)
4229
+ ]);
4146
4230
  if (runAbortController.signal.aborted) await state.abortCleanup;
4147
4231
  } finally {
4148
4232
  if (!state.projectionClosed) await resources.runCleanupStep("codex-transcript-checkpoint", closeProjection);
@@ -4150,7 +4234,8 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4150
4234
  const result = activeProjector.buildResult(toolBridge.telemetry, { yieldDetected: toolState.yieldDetected });
4151
4235
  const projectedTerminal = attemptTerminal.project(result.terminal);
4152
4236
  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);
4237
+ const currentPromptError = (fallback) => resourceState.executionDisconnectError ?? state.clientClosedPromptError ?? (state.timeout ? `codex app-server ${state.timeout.kind === "execution" ? "execution budget" : "terminal settlement"} timed out` : fallback);
4238
+ let enrichedPromptError = currentPromptError(projectedTerminal.promptError);
4154
4239
  const enrichedPromptErrorMessage = typeof enrichedPromptError === "string" ? enrichedPromptError : enrichedPromptError instanceof Error ? enrichedPromptError.message : enrichedPromptError ? formatErrorMessage(enrichedPromptError) : void 0;
4155
4240
  if (isInvalidCodexImagePayloadError(enrichedPromptErrorMessage)) await clearCodexBindingAfterInvalidImagePayload(bindingStore, bindingIdentity, {
4156
4241
  phase: "turn_completed",
@@ -4194,7 +4279,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4194
4279
  const projectTerminalOutcome = () => {
4195
4280
  const effectiveTimedOut = state.timeout !== void 0;
4196
4281
  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);
4282
+ const finalPromptError = currentPromptError(enrichedPromptError);
4198
4283
  const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : projectedTerminal.promptErrorSource;
4199
4284
  const codexAppServerFailureKind = clientClosedPromptErrorForFinal ? "client_closed_before_turn_completed" : state.timeout?.kind === "settlement" ? "turn_settlement_timeout" : void 0;
4200
4285
  const replayBlockedReason = codexAppServerFailureKind ? resolveCodexAppServerReplayBlockedReason(result) : void 0;
@@ -4220,6 +4305,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4220
4305
  if (toolBridge.telemetry.messagingToolSentTargets.some((target) => target.sourceReplyFinal === true)) result.agentHarnessResultClassification = void 0;
4221
4306
  const attemptSucceeded = turnSucceeded && result.agentHarnessResultClassification === void 0;
4222
4307
  result.terminal = attemptTerminal.normalize({
4308
+ settlementWarning: state.settlementWarning,
4223
4309
  timedOut: effectiveTimedOut,
4224
4310
  aborted: finalAborted,
4225
4311
  promptError: finalPromptError,
@@ -4246,20 +4332,24 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4246
4332
  completedTurnStatus
4247
4333
  };
4248
4334
  };
4249
- const mirrorTerminal = projectTerminalOutcome();
4335
+ projectTerminalOutcome();
4250
4336
  const unavailableMirror = {
4251
4337
  assistantTranscriptOwned: false,
4252
4338
  mirroredMessages: []
4253
4339
  };
4254
4340
  let mirrorOutcome = unavailableMirror;
4255
- try {
4256
- if (projectionDrained && settlementPhase === "active") mirrorOutcome = await Promise.race([codexTranscriptMirrorRuntime.mirrorBestEffort({
4341
+ const mirrorFinal = () => {
4342
+ const warning = state.settlementWarning;
4343
+ const mirrorTerminal = projectTerminalOutcome();
4344
+ state.pendingSettlementStage = "transcript/mirror";
4345
+ return codexTranscriptMirrorRuntime.mirrorBestEffort({
4257
4346
  assertWriteCurrent: () => {
4258
- if (settlementPhase !== "active") throw new Error("Codex transcript settlement is no longer active");
4347
+ if (settlementPhase !== "active" || state.settlementWarning !== warning) throw new Error("Codex transcript settlement is no longer active");
4259
4348
  const current = projectTerminalOutcome();
4260
4349
  if (current.finalAborted !== mirrorTerminal.finalAborted || current.effectiveTimedOut !== mirrorTerminal.effectiveTimedOut || current.finalPromptError !== mirrorTerminal.finalPromptError) throw new Error("Codex transcript terminal outcome changed before write");
4261
4350
  },
4262
4351
  params,
4352
+ settlementWarning: warning,
4263
4353
  agentId: sessionAgentId,
4264
4354
  notifyUserMessagePersisted,
4265
4355
  result,
@@ -4267,13 +4357,47 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4267
4357
  cwd: effectiveCwd,
4268
4358
  threadId: resourceState.thread.threadId,
4269
4359
  turnId: activeTurnId
4270
- }), abortGraceElapsed.promise.then(() => unavailableMirror)]);
4360
+ });
4361
+ };
4362
+ try {
4363
+ if (projectionDrained && settlementPhase === "active" && !state.settlementWarning) mirrorOutcome = await Promise.race([
4364
+ mirrorFinal(),
4365
+ drainGraceElapsed.promise.then(() => unavailableMirror),
4366
+ degradedSettlement.then(() => unavailableMirror)
4367
+ ]);
4368
+ if (state.settlementWarning && !runAbortController.signal.aborted) {
4369
+ mirrorOutcome = await Promise.race([mirrorFinal(), drainGraceElapsed.promise.then(() => unavailableMirror)]);
4370
+ if (mirrorOutcome === unavailableMirror) trajectoryRecorder?.recordEvent("turn.settlement_persistence_unavailable", {
4371
+ pendingStage: "transcript/mirror",
4372
+ threadId: resourceState.thread.threadId,
4373
+ turnId: activeTurnId
4374
+ });
4375
+ }
4376
+ if (toolState.yieldMessage && projectTerminalOutcome().turnSucceeded) {
4377
+ state.pendingSettlementStage = "transcript/yield-context";
4378
+ await Promise.race([
4379
+ appendSessionYieldContext({
4380
+ ...activeTranscriptTarget.sessionTarget,
4381
+ agentId: activeTranscriptTarget.agentId,
4382
+ sessionId: activeTranscriptTarget.sessionId,
4383
+ sessionKey: activeTranscriptTarget.sessionKey,
4384
+ config: params.config,
4385
+ message: toolState.yieldMessage,
4386
+ assertCurrent: () => {
4387
+ connection.assertCurrent();
4388
+ if (settlementPhase !== "active" || !projectTerminalOutcome().turnSucceeded) throw new Error("Codex yield settlement is no longer active");
4389
+ }
4390
+ }),
4391
+ drainGraceElapsed.promise,
4392
+ degradedSettlement
4393
+ ]);
4394
+ }
4271
4395
  if (runAbortController.signal.aborted) await state.abortCleanup;
4272
4396
  } finally {
4273
4397
  closeSettlement();
4274
4398
  }
4275
4399
  const { effectiveTimedOut, finalPromptError, codexAppServerFailure, promptTimeoutOutcome, finalAborted, turnSucceeded, attemptSucceeded, completedTurnStatus } = projectTerminalOutcome();
4276
- terminalState.turnSucceeded = turnSucceeded;
4400
+ terminalState.settledTurnStatus = turnSucceeded ? "completed" : completedTurnStatus === "failed" && !finalAborted && !effectiveTimedOut && !state.clientClosedPromptError && !resourceState.executionDisconnectError ? "failed" : void 0;
4277
4401
  terminalState.sharedAbortAllowedAfterTerminalOutcome = shouldKeepCodexSharedAbortOpen({
4278
4402
  trigger: params.trigger,
4279
4403
  result,
@@ -4326,7 +4450,9 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4326
4450
  ctx: hookContext,
4327
4451
  hookRunner
4328
4452
  });
4453
+ const providerRefusal = result.currentAttemptAssistant?.diagnostics?.some((diagnostic) => diagnostic.type === "provider_refusal");
4329
4454
  await runCodexAgentEndHook(params, {
4455
+ skillExperienceReviewSource: providerRefusal ? void 0 : terminalAnchor,
4330
4456
  event: {
4331
4457
  messages: result.messagesSnapshot,
4332
4458
  success: !finalAborted && !finalPromptError,
@@ -4699,7 +4825,7 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
4699
4825
  });
4700
4826
  if (response && !state.projectionClosed && !runAbortController.signal.aborted && turnIdRef.current === turnId && item.success === response.success && isDeepStrictEqual(item.contentItems, response.contentItems)) acknowledgeInternalToolResult(response);
4701
4827
  }
4702
- if (item?.type === "userMessage" && typeof item.clientId === "string") await steeringQueueRef.current?.confirmConsumed(item.clientId);
4828
+ if (item?.type === "userMessage" && typeof item.clientId === "string") steeringQueueRef.current?.confirmConsumed(item.clientId);
4703
4829
  }
4704
4830
  if (isCodexTurnAbortMarkerNotification(notification, { currentPromptTexts: [turnState.codexTurnPromptText] })) state.sawCodexInterruptMarker = true;
4705
4831
  }
@@ -4740,6 +4866,8 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
4740
4866
  if (!projector || !turnId || state.projectionClosed) return;
4741
4867
  projector.recordMcpToolCallReceipt(notification);
4742
4868
  if (isTerminalTurnNotificationForTurn(notification, turnId)) {
4869
+ const completed = readCodexTurnCompletedNotification(notification.params);
4870
+ if (completed) projector.settlement.terminalReceipt = completed.turn;
4743
4871
  state.terminalTurnNotificationQueued = true;
4744
4872
  steeringQueueRef.current?.sealAdmission();
4745
4873
  deadlines.beginSettlement(receivedAtMs);
@@ -4748,7 +4876,10 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
4748
4876
  const modelToolCallId = readRawResponseToolCallId(notification);
4749
4877
  if (modelToolCallId) allocateCodexToolOutcomeOrdinal?.(modelToolCallId);
4750
4878
  const nativeItem = readCodexNotificationItem(notification.params);
4751
- if (nativeItem?.type === "webSearch") projector.recordNativeToolOutcome(nativeItem);
4879
+ if (nativeItem?.type === "webSearch") {
4880
+ projector.settlement.turnTainted ||= notification.method === "item/completed";
4881
+ projector.recordNativeToolOutcome(nativeItem);
4882
+ }
4752
4883
  }
4753
4884
  };
4754
4885
  const enqueueNotification = async (notification, scope) => {
@@ -4775,17 +4906,47 @@ function isRestrictivePromptToolsAllow(toolsAllow) {
4775
4906
  return toolsAllow !== void 0 && !toolsAllow.some((name) => name.trim() === "*");
4776
4907
  }
4777
4908
  async function prepareCodexAttemptPrompt(context) {
4778
- const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, buildActiveContextEngineRuntimeContext, baseDeveloperInstructions, openClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars, codexContinuityProjectionMaxChars } = context;
4909
+ const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, buildActiveContextEngineRuntimeContext, baseDeveloperInstructions, buildOpenClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars, codexContinuityProjectionMaxChars } = context;
4779
4910
  const { connection, buildActiveRunAttemptParams, effectiveContextTokenBudget, effectiveRuntimeModelId, effectiveRuntimeProviderId } = runtime;
4780
4911
  const { params, activeContextEngine, usesSupervisionConnection, mutable, isInactiveThreadBootstrapBinding, bindingStore, bindingIdentity, agentDir, appServer, contextSessionKey, effectiveWorkspace, sandbox } = connection;
4781
4912
  const { toolBridge } = attemptTools;
4782
- const applyFreshThreadContinuityProjection = () => {
4783
- const projection = projectContextEngineAssemblyForCodex({
4784
- assembledMessages: historyState.messages,
4913
+ let contextImages = [];
4914
+ const currentUserTurnIdempotencyKey = params.userTurnTranscriptRecorder?.message?.idempotencyKey;
4915
+ const assertProjectionCurrent = () => {
4916
+ params.hostCapabilities.assertActive();
4917
+ connection.assertCurrent();
4918
+ connection.runAbortController.signal.throwIfAborted();
4919
+ };
4920
+ const prepareFileContext = async (message, maxChars) => {
4921
+ const prepare = params.hostCapabilities.prepareContextMedia;
4922
+ if (!prepare) {
4923
+ const media = asOptionalRecord(Reflect.get(message, "__openclaw"))?.media;
4924
+ if (Array.isArray(media) && media.length || message.role === "user" && Array.isArray(message.content) && message.content.some((part) => part.type === "image")) throw new CodexContextAttachmentError("Saved attachments require a newer OpenClaw host. Update the Gateway and Codex plugin together, then retry.");
4925
+ return { images: [] };
4926
+ }
4927
+ try {
4928
+ const files = await prepare({
4929
+ message,
4930
+ maxChars
4931
+ });
4932
+ assertProjectionCurrent();
4933
+ return files;
4934
+ } catch (error) {
4935
+ assertProjectionCurrent();
4936
+ throw new CodexContextAttachmentError("Saved attachment preparation failed. Retry the request after checking the attachment source.", { cause: error });
4937
+ }
4938
+ };
4939
+ const applyContinuityProjection = async (messages) => {
4940
+ const projection = await projectContextEngineAssemblyForCodex({
4941
+ assembledMessages: messages,
4785
4942
  originalHistoryMessages: historyState.messages,
4786
4943
  prompt: params.prompt,
4787
- maxRenderedContextChars: codexContinuityProjectionMaxChars
4944
+ maxRenderedContextChars: codexContinuityProjectionMaxChars,
4945
+ prepareFileContext,
4946
+ currentUserTurnIdempotencyKey
4788
4947
  });
4948
+ assertProjectionCurrent();
4949
+ contextImages = projection.images ?? [];
4789
4950
  promptState.promptText = projection.promptText;
4790
4951
  promptState.promptContextRange = projection.promptContextRange;
4791
4952
  promptState.prePromptMessageCount = projection.prePromptMessageCount;
@@ -4814,14 +4975,6 @@ async function prepareCodexAttemptPrompt(context) {
4814
4975
  });
4815
4976
  if (!assembled) throw new Error("context engine assemble returned no result");
4816
4977
  const contextEngineProjection = readContextEngineThreadBootstrapProjection(assembled.contextProjection);
4817
- const projection = projectContextEngineAssemblyForCodex({
4818
- assembledMessages: assembled.messages,
4819
- originalHistoryMessages: historyState.messages,
4820
- prompt: params.prompt,
4821
- systemPromptAddition: assembled.systemPromptAddition,
4822
- maxRenderedContextChars: codexContextProjectionMaxChars,
4823
- toolPayloadMode: contextEngineProjection ? "preserve" : "elide"
4824
- });
4825
4978
  const projectionDecision = contextEngineProjection ? resolveContextEngineBootstrapProjectionDecision({
4826
4979
  startupBinding: decisionStartupBinding,
4827
4980
  expectedBinding: buildContextEngineBinding(buildActiveRunAttemptParams(), contextEngineProjection),
@@ -4832,6 +4985,18 @@ async function prepareCodexAttemptPrompt(context) {
4832
4985
  project: true,
4833
4986
  reason: "per-turn-projection"
4834
4987
  };
4988
+ const projection = await projectContextEngineAssemblyForCodex({
4989
+ assembledMessages: assembled.messages,
4990
+ originalHistoryMessages: historyState.messages,
4991
+ prompt: params.prompt,
4992
+ systemPromptAddition: assembled.systemPromptAddition,
4993
+ maxRenderedContextChars: codexContextProjectionMaxChars,
4994
+ toolPayloadMode: contextEngineProjection ? "preserve" : "elide",
4995
+ ...projectionDecision.project ? { prepareFileContext } : {},
4996
+ currentUserTurnIdempotencyKey
4997
+ });
4998
+ assertProjectionCurrent();
4999
+ contextImages = projectionDecision.project ? projection.images ?? [] : [];
4835
5000
  const decisionBinding = decisionStartupBinding;
4836
5001
  embeddedAgentLog.info("codex app-server context-engine projection decision", {
4837
5002
  sessionId: params.sessionId,
@@ -4859,6 +5024,8 @@ async function prepareCodexAttemptPrompt(context) {
4859
5024
  if (activeContextEngine) try {
4860
5025
  await applyActiveContextEngineProjection(runtime.nativeToolSurfaceEnabled ? mutable.startupBinding : void 0);
4861
5026
  } catch (assembleErr) {
5027
+ if (assembleErr instanceof CodexContextAttachmentError) throw assembleErr;
5028
+ assertProjectionCurrent();
4862
5029
  embeddedAgentLog.warn("context engine assemble failed; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
4863
5030
  }
4864
5031
  const codexModelInputHistoryMessages = [];
@@ -4905,8 +5072,8 @@ async function prepareCodexAttemptPrompt(context) {
4905
5072
  }
4906
5073
  };
4907
5074
  };
4908
- const decorateCodexTurnPromptText = (promptBuildResult) => {
4909
- const turnPromptText = prependCodexOpenClawPromptContext(promptBuildResult.prompt, openClawPromptContext, { preservePromptWithoutContext: params.bootstrapContextMode === "lightweight" && params.bootstrapContextRunKind === "cron" });
5075
+ const decorateCodexTurnPromptText = (promptBuildResult, includeWorkspaceReferences = true) => {
5076
+ const turnPromptText = prependCodexOpenClawPromptContext(promptBuildResult.prompt, buildOpenClawPromptContext(includeWorkspaceReferences), { preservePromptWithoutContext: params.bootstrapContextMode === "lightweight" && params.bootstrapContextRunKind === "cron" });
4910
5077
  const projectedRanges = resolveShiftedPromptContextRange(promptBuildResult.prompt, promptBuildResult.promptInputRange, turnPromptText);
4911
5078
  const preservedRange = resolveShiftedPromptInputRange(promptBuildResult.prompt, promptBuildResult.promptInputRange, turnPromptText) ?? resolveCodexDeliveryHintPreservedInputRange({
4912
5079
  prompt: promptBuildResult.prompt,
@@ -4946,28 +5113,19 @@ async function prepareCodexAttemptPrompt(context) {
4946
5113
  const selectNewerVisibleHistoryAfterBinding = (binding) => {
4947
5114
  const cutoff = Date.parse(binding.historyCoveredThrough ?? "");
4948
5115
  return historyState.messages.filter((message) => {
4949
- if (message.role !== "user" && message.role !== "assistant") return false;
5116
+ if (message.role !== "user" && message.role !== "assistant" && !isCodexDurableCustomMessage(message)) return false;
4950
5117
  const mirrorIdentity = readMirrorIdentity(message);
4951
5118
  const timestamp = typeof message.timestamp === "number" ? message.timestamp : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
4952
5119
  return !("idempotencyKey" in message && typeof message.idempotencyKey === "string" && message.idempotencyKey.startsWith("codex-app-server:")) && !hasCodexMirrorOrigin(message) && !mirrorIdentity?.startsWith("codex-app-server:") && Number.isFinite(timestamp) && timestamp > (Number.isFinite(cutoff) ? cutoff : 0);
4953
5120
  });
4954
5121
  };
4955
- const applyResumeStaleBindingContinuityProjection = (binding) => {
5122
+ const applyResumeStaleBindingContinuityProjection = async (binding) => {
4956
5123
  const newerVisibleMessages = selectNewerVisibleHistoryAfterBinding(binding);
4957
5124
  if (newerVisibleMessages.length === 0) return false;
4958
- const projection = projectContextEngineAssemblyForCodex({
4959
- assembledMessages: newerVisibleMessages,
4960
- originalHistoryMessages: historyState.messages,
4961
- prompt: params.prompt,
4962
- maxRenderedContextChars: codexContinuityProjectionMaxChars
4963
- });
4964
- promptState.promptText = projection.promptText;
4965
- promptState.promptContextRange = projection.promptContextRange;
4966
- promptState.prePromptMessageCount = projection.prePromptMessageCount;
4967
- promptState.noEngineContinuityProjectionApplied = true;
5125
+ await applyContinuityProjection(newerVisibleMessages);
4968
5126
  return true;
4969
5127
  };
4970
- const precomputeNoContextEngineStaleBindingProjection = () => {
5128
+ const precomputeNoContextEngineStaleBindingProjection = async () => {
4971
5129
  promptState.precomputedStaleBindingContinuityProjectionApplied = false;
4972
5130
  promptState.staleBindingContinuityForcedFreshStart = false;
4973
5131
  const binding = mutable.startupBinding;
@@ -4976,24 +5134,24 @@ async function prepareCodexAttemptPrompt(context) {
4976
5134
  promptState.inactiveThreadBootstrapBindingForcedFreshStart = true;
4977
5135
  return false;
4978
5136
  }
4979
- const projected = applyResumeStaleBindingContinuityProjection(binding);
5137
+ const projected = await applyResumeStaleBindingContinuityProjection(binding);
4980
5138
  promptState.precomputedStaleBindingContinuityProjectionApplied = projected;
4981
5139
  return projected;
4982
5140
  };
4983
- const applyNoContextEngineContinuityProjection = (action, binding) => {
4984
- const hasContinuity = historyState.messages.some((message) => message.role === "user" || action === "started" && (message.role === "compactionSummary" || message.role === "branchSummary"));
5141
+ const applyNoContextEngineContinuityProjection = async (action, binding) => {
5142
+ const hasContinuity = historyState.messages.some((message) => message.role === "user" || isCodexDurableCustomMessage(message) || action === "started" && (message.role === "compactionSummary" || message.role === "branchSummary"));
4985
5143
  if (activeContextEngine || !hasContinuity) return false;
4986
5144
  if (action === "resumed" && promptState.precomputedStaleBindingContinuityProjectionApplied) return true;
4987
5145
  if (action === "started" && promptState.staleBindingContinuityForcedFreshStart) return true;
4988
5146
  if (action === "started" && promptState.inactiveThreadBootstrapBindingForcedFreshStart) return false;
4989
5147
  if (action === "resumed" && binding) return applyResumeStaleBindingContinuityProjection(binding);
4990
5148
  if (action === "started") {
4991
- applyFreshThreadContinuityProjection();
5149
+ await applyContinuityProjection(historyState.messages);
4992
5150
  return true;
4993
5151
  }
4994
5152
  return false;
4995
5153
  };
4996
- if (precomputeNoContextEngineStaleBindingProjection()) await rebuildCodexPromptBuildFromCurrentProjection();
5154
+ if (await precomputeNoContextEngineStaleBindingProjection()) await rebuildCodexPromptBuildFromCurrentProjection();
4997
5155
  const rotateStartupBindingForProjectedTurn = async () => {
4998
5156
  const binding = mutable.startupBinding;
4999
5157
  if (!binding?.threadId) return;
@@ -5020,12 +5178,14 @@ async function prepareCodexAttemptPrompt(context) {
5020
5178
  if (mutable.startupBinding?.threadId) return;
5021
5179
  promptState.inactiveThreadBootstrapBindingForcedFreshStart = hadInactiveThreadBootstrapBinding;
5022
5180
  promptState.staleBindingContinuityForcedFreshStart = promptState.precomputedStaleBindingContinuityProjectionApplied && !promptState.inactiveThreadBootstrapBindingForcedFreshStart;
5023
- if (promptState.staleBindingContinuityForcedFreshStart) applyFreshThreadContinuityProjection();
5181
+ if (promptState.staleBindingContinuityForcedFreshStart) await applyContinuityProjection(historyState.messages);
5024
5182
  if (activeContextEngine) {
5025
5183
  promptState.contextEngineProjection = void 0;
5026
5184
  try {
5027
5185
  await applyActiveContextEngineProjection(void 0);
5028
5186
  } catch (assembleErr) {
5187
+ if (assembleErr instanceof CodexContextAttachmentError) throw assembleErr;
5188
+ assertProjectionCurrent();
5029
5189
  embeddedAgentLog.warn("context engine assemble failed; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
5030
5190
  }
5031
5191
  }
@@ -5039,22 +5199,36 @@ async function prepareCodexAttemptPrompt(context) {
5039
5199
  });
5040
5200
  };
5041
5201
  await rotateStartupBindingForProjectedTurn();
5202
+ const buildSystemPromptReport = (omitWorkspaceReferences = false) => buildCodexSystemPromptReport({
5203
+ attempt: params,
5204
+ sessionKey: contextSessionKey,
5205
+ workspaceDir: effectiveWorkspace,
5206
+ developerInstructions: buildRenderedCodexDeveloperInstructions(),
5207
+ workspaceBootstrapContext,
5208
+ omitWorkspaceReferences,
5209
+ skillsPrompt: skillsCollaborationInstructions ? params.skillsSnapshot?.prompt ?? "" : "",
5210
+ tools: toolBridge.availableSpecs
5211
+ });
5212
+ const systemPromptReport = buildSystemPromptReport();
5213
+ let workspaceReferencesIncluded = true;
5042
5214
  return {
5043
5215
  context,
5216
+ get contextImages() {
5217
+ return contextImages;
5218
+ },
5044
5219
  codexModelInputHistoryMessages,
5045
5220
  turnState,
5221
+ refreshWorkspaceReferences: (include) => {
5222
+ turnState.codexTurnPromptText = decorateCodexTurnPromptText(turnState.promptBuild, include);
5223
+ if (include !== workspaceReferencesIncluded) {
5224
+ Object.assign(systemPromptReport, buildSystemPromptReport(!include));
5225
+ workspaceReferencesIncluded = include;
5226
+ }
5227
+ },
5046
5228
  buildRenderedCodexDeveloperInstructions,
5047
5229
  rebuildCodexTurnPromptTextFromCurrentProjection,
5048
5230
  applyNoContextEngineContinuityProjection,
5049
- systemPromptReport: buildCodexSystemPromptReport({
5050
- attempt: params,
5051
- sessionKey: contextSessionKey,
5052
- workspaceDir: effectiveWorkspace,
5053
- developerInstructions: buildRenderedCodexDeveloperInstructions(),
5054
- workspaceBootstrapContext,
5055
- skillsPrompt: skillsCollaborationInstructions ? params.skillsSnapshot?.prompt ?? "" : "",
5056
- tools: toolBridge.availableSpecs
5057
- })
5231
+ systemPromptReport
5058
5232
  };
5059
5233
  }
5060
5234
  //#endregion
@@ -5153,10 +5327,11 @@ function prepareCodexAttemptResources(prompt) {
5153
5327
  closed: retired.closed,
5154
5328
  matchedSharedClient: retired.found
5155
5329
  });
5156
- if (retired.closed) await state.client.closeAndWait({
5330
+ const result = retired.closed ? await state.client.closeAndWait({
5157
5331
  exitTimeoutMs: 2e3,
5158
5332
  forceKillDelayMs: 250
5159
- });
5333
+ }) : void 0;
5334
+ if (params.oneShotCliRun && result?.cleanup !== "closed") throw new Error("Codex one-shot client cleanup could not be confirmed");
5160
5335
  };
5161
5336
  const releaseSandboxExecEnvironment = async () => {
5162
5337
  if (state.sandboxExecEnvironment) {
@@ -5170,10 +5345,13 @@ function prepareCodexAttemptResources(prompt) {
5170
5345
  await releaseSandboxExecEnvironment();
5171
5346
  const ownedClient = state.releaseSharedClientLease ? state.client : void 0;
5172
5347
  releaseSharedClientLeaseOnce();
5173
- await ownedClient?.closeAndWait({
5174
- exitTimeoutMs: 2e3,
5175
- forceKillDelayMs: 250
5176
- });
5348
+ if (ownedClient) {
5349
+ const result = await ownedClient.closeAndWait({
5350
+ exitTimeoutMs: 2e3,
5351
+ forceKillDelayMs: 250
5352
+ });
5353
+ if (params.oneShotCliRun && result.cleanup !== "closed") throw new Error("Codex isolated client cleanup could not be confirmed");
5354
+ }
5177
5355
  return;
5178
5356
  }
5179
5357
  releaseSharedClientLeaseOnce();
@@ -5646,10 +5824,10 @@ function createCodexDynamicToolExecutionRegistry() {
5646
5824
  }
5647
5825
  };
5648
5826
  }
5649
- function resolveCodexDynamicToolDirectNames(params, hostSystemAgentActive = false) {
5827
+ function resolveCodexDynamicToolDirectNames(params, registeredTools, hostSystemAgentActive = false) {
5650
5828
  const names = [];
5651
5829
  if (hostSystemAgentActive && isSystemAgentOnlyCodexDynamicToolAllowlist(params.toolsAllow)) names.push("openclaw");
5652
- if (params.sourceReplyDeliveryMode === "message_tool_only") names.push("message");
5830
+ if (registeredTools.some((tool) => tool.name === "message")) names.push("message");
5653
5831
  return names;
5654
5832
  }
5655
5833
  //#endregion
@@ -5922,7 +6100,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
5922
6100
  //#region extensions/codex/src/app-server/attempt-runtime-artifact.ts
5923
6101
  async function verifyStartupArtifact(params) {
5924
6102
  if (!params.request) return;
5925
- const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-Bh_gf6-t.js");
6103
+ const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-T-NwqeSH.js");
5926
6104
  const runtimeArtifact = readCodexAppServerClientRuntimeArtifact(params.client);
5927
6105
  const expected = params.request.expected;
5928
6106
  const matchesExpected = !expected || runtimeArtifact?.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint;
@@ -5934,12 +6112,7 @@ async function verifyStartupArtifact(params) {
5934
6112
  }
5935
6113
  //#endregion
5936
6114
  //#region extensions/codex/src/app-server/computer-use-health.ts
5937
- const COMPUTER_USE_HEALTH_MONITOR_STATE = Symbol.for("openclaw.codexComputerUseHealthMonitorState");
5938
- function getComputerUseHealthMonitorState() {
5939
- const globalState = globalThis;
5940
- globalState[COMPUTER_USE_HEALTH_MONITOR_STATE] ??= { monitors: /* @__PURE__ */ new WeakMap() };
5941
- return globalState[COMPUTER_USE_HEALTH_MONITOR_STATE];
5942
- }
6115
+ const getComputerUseHealthMonitorState = defineCodexBuildState("openclaw.codexComputerUseHealthMonitorState", () => ({ monitors: /* @__PURE__ */ new WeakMap() }));
5943
6116
  function startCodexComputerUseHealthMonitor(params) {
5944
6117
  const state = getComputerUseHealthMonitorState();
5945
6118
  const existing = state.monitors.get(params.client);
@@ -6516,7 +6689,7 @@ function shouldRetireCodexStartupClient(error, spawnedBy, signal) {
6516
6689
  //#region extensions/codex/src/app-server/run-attempt-start.ts
6517
6690
  async function startCodexAttemptRuntime(resources) {
6518
6691
  const { prompt, state, trajectoryRecorder, activateNativePreToolUseFailureFallback, releaseSandboxExecEnvironment, releaseSharedClientLeaseAndRetireOneShotClient, releaseCurrentRoute, runCleanupStep, startupTimeoutMs, buildNativeHookRelayFinalConfigPatch } = resources;
6519
- const { context, turnState, buildRenderedCodexDeveloperInstructions, rebuildCodexTurnPromptTextFromCurrentProjection, applyNoContextEngineContinuityProjection } = prompt;
6692
+ const { context, turnState, rebuildCodexTurnPromptTextFromCurrentProjection, applyNoContextEngineContinuityProjection } = prompt;
6520
6693
  const { runtime, attemptTools, promptState } = context;
6521
6694
  const { connection, runtimeParams, preparedAuthBinding, buildActiveRunAttemptParams, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, effectiveRuntimeModelId, sandboxExecServerEnabled } = runtime;
6522
6695
  const { toolBridge, toolState } = attemptTools;
@@ -6634,7 +6807,7 @@ async function startCodexAttemptRuntime(resources) {
6634
6807
  clientId: state.client.getInstanceId()
6635
6808
  }
6636
6809
  });
6637
- if (applyNoContextEngineContinuityProjection(state.thread.lifecycle.action, state.thread)) await rebuildCodexTurnPromptTextFromCurrentProjection();
6810
+ if (await applyNoContextEngineContinuityProjection(state.thread.lifecycle.action, state.thread)) await rebuildCodexTurnPromptTextFromCurrentProjection();
6638
6811
  trajectoryRecorder?.recordEvent("session.started", {
6639
6812
  sessionFile: params.sessionFile,
6640
6813
  threadId: state.thread.threadId,
@@ -6642,13 +6815,6 @@ async function startCodexAttemptRuntime(resources) {
6642
6815
  workspaceDir: effectiveWorkspace,
6643
6816
  toolCount: flattenCodexDynamicToolFunctions(toolBridge.specs).length
6644
6817
  });
6645
- recordCodexTrajectoryContext(trajectoryRecorder, {
6646
- attempt: params,
6647
- cwd: effectiveCwd,
6648
- developerInstructions: joinPresentSections(buildRenderedCodexDeveloperInstructions(), attemptTools.configuredMcp?.diagnosticNotice),
6649
- prompt: turnState.codexTurnPromptText,
6650
- tools: toolBridge.availableSpecs
6651
- });
6652
6818
  connection.mutable.pluginAppServer = pluginAppServer;
6653
6819
  } catch (error) {
6654
6820
  await runCleanupStep("codex-start-failure-hook-fallback", activateNativePreToolUseFailureFallback);
@@ -6758,8 +6924,9 @@ async function prepareCodexAttemptTools(runtime) {
6758
6924
  pluginConfig,
6759
6925
  profilerEnabled,
6760
6926
  ...params.cronCreatorAuthorityUnavailableReason === "queued-local-operator" && bundleMcpThreadConfig.staticServerNames.length > 0 ? { cronCreatorAuthorityUnavailableReason: "queued-local-operator-configured-mcp" } : {},
6761
- onYieldDetected: (acknowledgment) => {
6927
+ onYieldDetected: (message, acknowledgment) => {
6762
6928
  toolState.yieldDetected = true;
6929
+ toolState.yieldMessage = message;
6763
6930
  toolState.yieldAcknowledgment = acknowledgment;
6764
6931
  },
6765
6932
  claimYieldCompletion: () => runtimeYieldCompletionClaim.current?.() ?? false,
@@ -6806,9 +6973,13 @@ async function prepareCodexAttemptTools(runtime) {
6806
6973
  releaseLeasedSharedCodexAppServerClient(client);
6807
6974
  }
6808
6975
  }
6976
+ let requireExplicitMessageTarget;
6809
6977
  const tools = await buildDynamicTools({
6810
6978
  ...commonToolParams,
6811
6979
  registerRunCleanup: (cleanup) => runCleanups.push(cleanup),
6980
+ onMessageToolTargetResolved: (required) => {
6981
+ requireExplicitMessageTarget = required;
6982
+ },
6812
6983
  cronCreatorToolAllowlistRef: cronCreatorToolAllowlist,
6813
6984
  cronCreatorToolAllowlistCaptureRef,
6814
6985
  onPersistentWebSearchPolicyResolved: (allowed) => {
@@ -6831,7 +7002,7 @@ async function prepareCodexAttemptTools(runtime) {
6831
7002
  sessionId: params.sessionId,
6832
7003
  runId: params.runId,
6833
7004
  agentId: policyAgentId,
6834
- agentDir: agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId),
7005
+ agentDir: agentDir ?? resolveAgentDir$2(params.config ?? {}, sessionAgentId),
6835
7006
  agentAccountId: params.agentAccountId,
6836
7007
  messageProvider: params.messageProvider ?? params.messageChannel,
6837
7008
  messageChannel: params.messageChannel,
@@ -6981,7 +7152,7 @@ async function prepareCodexAttemptTools(runtime) {
6981
7152
  signal: runAbortController.signal,
6982
7153
  computerContextEpoch,
6983
7154
  loading: resolveCodexDynamicToolsLoadingForRuntime(pluginConfig, effectiveRuntimeModelId, { connectionClass: connection.appServer.connectionClass }),
6984
- directToolNames: resolveCodexDynamicToolDirectNames(params, isHostScopedAgentToolActive("openclaw")),
7155
+ directToolNames: resolveCodexDynamicToolDirectNames(params, registeredWithScopedMcp, isHostScopedAgentToolActive("openclaw")),
6985
7156
  hookContext
6986
7157
  });
6987
7158
  const captureCronCreatorToolAllowlist = async () => {
@@ -7046,6 +7217,7 @@ async function prepareCodexAttemptTools(runtime) {
7046
7217
  return {
7047
7218
  tools: toolsWithScopedMcp,
7048
7219
  registeredTools: registeredWithScopedMcp,
7220
+ requireExplicitMessageTarget,
7049
7221
  scopedMcpTools,
7050
7222
  configuredMcp,
7051
7223
  disposeMcpTools,
@@ -7148,12 +7320,22 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
7148
7320
  error.name = "AbortError";
7149
7321
  throw error;
7150
7322
  };
7323
+ const prepareWorkspaceReferences = () => {
7324
+ const references = prepareCodexWorkspaceReferences(resourceState.client, resourceState.thread.threadId, workspaceBootstrapContext.promptContext);
7325
+ prompt.refreshWorkspaceReferences(references.include);
7326
+ return references;
7327
+ };
7151
7328
  const startCodexTurn = async () => {
7152
7329
  const activeTurnRoute = await ensureCurrentThreadRoute();
7153
7330
  assertCodexSessionRuntimeOwnership(resourceState.thread, params.expectedSessionRuntimeOwnership);
7154
7331
  const turnAppServer = withCodexAppServerFastModeServiceTier(connection.mutable.pluginAppServer, runtimeParams);
7155
7332
  connection.mutable.pluginAppServer = turnAppServer;
7156
- const turnStartParams = buildTurnStartParams(runtimeParams, {
7333
+ const references = prepareWorkspaceReferences();
7334
+ const referencesRetained = turnState.codexTurnPromptText.includes(workspaceBootstrapContext.promptContext ?? "");
7335
+ const turnStartParams = buildTurnStartParams({
7336
+ ...runtimeParams,
7337
+ images: [...prompt.contextImages, ...runtimeParams.images ?? []]
7338
+ }, {
7157
7339
  threadId: resourceState.thread.threadId,
7158
7340
  cwd: resourceState.codexExecutionCwd,
7159
7341
  appServer: turnAppServer,
@@ -7170,9 +7352,18 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
7170
7352
  skillsCollaborationInstructions: context.skillsCollaborationInstructions,
7171
7353
  memoryCollaborationInstructions: workspaceBootstrapContext.memoryCollaborationInstructions,
7172
7354
  preserveNativeTurnSettings: usesSupervisionConnection,
7355
+ messageToolAvailable: toolBridge.availableTools.some((tool) => tool.name === "message"),
7356
+ requireExplicitMessageTarget: attemptTools.requireExplicitMessageTarget,
7173
7357
  sessionStatusAvailable: toolBridge.availableTools.some((tool) => tool.name === "session_status")
7174
7358
  });
7175
7359
  codexModelCallDiagnostics.setRequestPayloadBytes(utf8JsonByteLength(turnStartParams));
7360
+ recordCodexTrajectoryContext(resources.trajectoryRecorder, {
7361
+ attempt: params,
7362
+ cwd: connection.effectiveCwd,
7363
+ developerInstructions: joinPresentSections(buildRenderedCodexDeveloperInstructions(), attemptTools.configuredMcp?.diagnosticNotice),
7364
+ prompt: turnState.codexTurnPromptText,
7365
+ tools: toolBridge.availableSpecs
7366
+ });
7176
7367
  state.latestStartupErrorNotification = void 0;
7177
7368
  state.rateLimitsRevisionBeforeLastTurnStart = readCodexRateLimitsRevision(resourceState.client);
7178
7369
  activeTurnRoute.armTurn();
@@ -7196,6 +7387,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
7196
7387
  }));
7197
7388
  acceptedTurnId = startedTurn.turn.id;
7198
7389
  connection.assertCurrent();
7390
+ if (referencesRetained) references.accepted();
7199
7391
  throwIfTurnStartAcceptedAfterAbort();
7200
7392
  return startedTurn;
7201
7393
  } catch (error) {
@@ -7224,6 +7416,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
7224
7416
  if (await waitForActiveNativeTurnCompletion()) await resourceState.turnRoute?.drain();
7225
7417
  else if (!runAbortController.signal.aborted) embeddedAgentLog.warn("codex app-server active native turn did not complete before turn/start wait timed out", { threadId: resourceState.thread.threadId });
7226
7418
  }
7419
+ prepareWorkspaceReferences();
7227
7420
  const buildLlmInputEvent = () => ({
7228
7421
  runId: params.runId,
7229
7422
  sessionId: params.sessionId,
@@ -7232,7 +7425,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
7232
7425
  systemPrompt: buildRenderedCodexDeveloperInstructions(),
7233
7426
  prompt: turnState.codexTurnPromptText,
7234
7427
  historyMessages: prompt.codexModelInputHistoryMessages,
7235
- imagesCount: params.images?.length ?? 0,
7428
+ imagesCount: prompt.contextImages.length + (params.images?.length ?? 0),
7236
7429
  tools
7237
7430
  });
7238
7431
  return {
@@ -7541,6 +7734,8 @@ function createCodexAttemptTurnState(resources) {
7541
7734
  terminalTurnNotificationQueued: false,
7542
7735
  sawCodexInterruptMarker: false,
7543
7736
  timeout: void 0,
7737
+ settlementWarning: void 0,
7738
+ pendingSettlementStage: void 0,
7544
7739
  clientClosedPromptError: void 0,
7545
7740
  clientClosedDiagnostic: void 0,
7546
7741
  clientClosedAbort: false,
@@ -7556,6 +7751,7 @@ function createCodexAttemptTurnState(resources) {
7556
7751
  currentTurnHadNonTerminalDynamicToolResult: false
7557
7752
  };
7558
7753
  const { promise: completion, resolve: resolveCompletion } = createDeferred();
7754
+ const settlementExpired = createDeferred();
7559
7755
  const pendingOpenClawDynamicToolCompletionIds = /* @__PURE__ */ new Set();
7560
7756
  const openClawDynamicToolExecutions = createCodexDynamicToolExecutionRegistry();
7561
7757
  const activeTurnItemIds = /* @__PURE__ */ new Set();
@@ -7616,13 +7812,32 @@ function createCodexAttemptTurnState(resources) {
7616
7812
  signal: runAbortController.signal,
7617
7813
  onDeadlineChanged: params.onAttemptDeadlineChanged,
7618
7814
  onTimeout: (timeout) => {
7815
+ const pendingStage = state.pendingSettlementStage ?? projectorRef.current?.settlement.pendingStage ?? "notification_queue";
7816
+ if (timeout.kind === "settlement" && projectorRef.current?.recoverCompletedAnswer()) {
7817
+ state.settlementWarning = {
7818
+ pendingStage,
7819
+ elapsedMs: timeout.elapsedMs,
7820
+ timeoutMs: timeout.timeoutMs
7821
+ };
7822
+ state.projectionClosed = true;
7823
+ trajectoryRecorder?.recordEvent("turn.settlement_warning", {
7824
+ threadId: resourceState.thread.threadId,
7825
+ turnId: turnIdRef.current,
7826
+ ...state.settlementWarning
7827
+ });
7828
+ embeddedAgentLog.warn("codex app-server retaining completed answer after settlement expiry", state.settlementWarning);
7829
+ completeTurn();
7830
+ settlementExpired.resolve();
7831
+ return;
7832
+ }
7619
7833
  state.timeout = timeout;
7620
7834
  projectorRef.current?.markTimedOut();
7621
7835
  const error = /* @__PURE__ */ new Error(timeout.kind === "execution" ? "codex app-server execution budget timed out" : "codex app-server terminal settlement timed out");
7622
7836
  const fields = {
7623
7837
  threadId: resourceState.thread.threadId,
7624
7838
  turnId: turnIdRef.current,
7625
- ...timeout
7839
+ ...timeout,
7840
+ pendingStage
7626
7841
  };
7627
7842
  trajectoryRecorder?.recordEvent(`turn.${timeout.kind}_timeout`, fields);
7628
7843
  embeddedAgentLog.warn(error.message, fields);
@@ -7633,6 +7848,7 @@ function createCodexAttemptTurnState(resources) {
7633
7848
  return {
7634
7849
  state,
7635
7850
  completion,
7851
+ settlementExpired: settlementExpired.promise,
7636
7852
  pendingOpenClawDynamicToolCompletionIds,
7637
7853
  openClawDynamicToolExecutions,
7638
7854
  activeTurnItemIds,