@openclaw/codex 2026.8.1-beta.2 → 2026.8.1-beta.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 (59) hide show
  1. package/dist/api.js +147 -0
  2. package/dist/app-server-policy-bg5QPSVP.js +25 -0
  3. package/dist/{attempt-client-cleanup-DMLXUfa8.js → attempt-client-cleanup-URjUlCHg.js} +1 -1
  4. package/dist/{binding-connection-I5Bo-AsX.js → binding-connection-DAvZwp96.js} +15 -3
  5. package/dist/{bounded-turn-qgZmzy_4.js → bounded-turn-4BjrZEwW.js} +22 -16
  6. package/dist/{capabilities-CybGI1oz.js → capabilities-CH3K57v4.js} +1 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-B1AEz8ZA.js → command-formatters-D0nZ3qtd.js} +2 -2
  9. package/dist/{command-handlers-Db8pu_ds.js → command-handlers-DC86lgT4.js} +39 -22
  10. package/dist/command-rpc-xUIIonsO.js +90 -0
  11. package/dist/{compact-LspQaGfl.js → compact-COqgBRny.js} +35 -29
  12. package/dist/{session-binding-DPxIvMgE.js → config-CpNeo5AE.js} +28 -888
  13. package/dist/context-compaction-activity-BOeJf7yo.js +58 -0
  14. package/dist/doctor-contract-api.js +15 -14
  15. package/dist/{dynamic-tools-BVdyWkUD.js → dynamic-tools-fJZhl4CE.js} +1284 -651
  16. package/dist/{effective-mcp-catalog-DIIhAtOZ.js → effective-mcp-catalog-4YKn51aG.js} +2 -2
  17. package/dist/elicitation-input-DMkeki8d.js +71 -0
  18. package/dist/{event-projector-usage-e5huIQWu.js → event-projector-usage-CLwNEJqW.js} +16 -16
  19. package/dist/harness-DoKQcF8n.js +258 -0
  20. package/dist/harness.js +2 -226
  21. package/dist/index.js +171 -48
  22. package/dist/{isolated-completion-C58NbL40.js → isolated-completion-DPMtlH9r.js} +3 -3
  23. package/dist/managed-binary-By4FZC6i.js +212 -0
  24. package/dist/media-understanding-provider.js +2 -2
  25. package/dist/model-catalog-CmGoqVKB.js +48 -0
  26. package/dist/{models-BFlpn1Ex.js → models-CZw1wClT.js} +2 -2
  27. package/dist/{native-subagent-monitor-DyTGmTUx.js → native-subagent-monitor-GGq3RnOo.js} +185 -71
  28. package/dist/node-exec-server.runtime-Bsu1LdFZ.js +192 -0
  29. package/dist/{plugin-app-cache-key-C3H2CVp6.js → plugin-app-cache-key-DMNQ8Zi8.js} +15 -3
  30. package/dist/plugin-approval-roundtrip-C75Yiiwc.js +95 -0
  31. package/dist/{plugin-marketplace-discovery-CzrGJdCR.js → plugin-marketplace-discovery-CSWDkMrP.js} +40 -26
  32. package/dist/{plugin-metadata-cache-CNJPj4_b.js → plugin-metadata-cache-BXH5NF-4.js} +8 -5
  33. package/dist/{protocol-validators-B4F7L8Rf.js → protocol-validators-VAVyEnDp.js} +55 -2
  34. package/dist/{rate-limits-DZXmOL8-.js → rate-limits-BI1dMHDG.js} +1 -1
  35. package/dist/{request-BRl5_UfX.js → request-DSK0W6YI.js} +2 -2
  36. package/dist/{run-attempt-P8BdxC1I.js → run-attempt-BV3HzuCf.js} +1098 -666
  37. package/dist/{runtime-artifact-BVSPdd6g.js → runtime-artifact-BvyT1uyd.js} +4 -7
  38. package/dist/{sandbox-guard-Cmwc9eIk.js → sandbox-guard-C1qEeZ5C.js} +25 -19
  39. package/dist/session-binding-BTrLf9Qm.js +874 -0
  40. package/dist/{session-catalog-xwNi_SDM.js → session-catalog-ezP_UcRM.js} +1541 -1296
  41. package/dist/session-catalog-home-id-BNwAJ9D7.js +18 -0
  42. package/dist/{session-cli-7hgXZDV7.js → session-cli-B1hKvfkI.js} +20 -7
  43. package/dist/{session-retirement-DoMMJFKm.js → session-retirement-CE4iMiLh.js} +3 -3
  44. package/dist/{session-upstream-marker-CrIFX06J.js → session-upstream-marker-D_2npHlA.js} +1 -1
  45. package/dist/{settled-turn-finalizer-BRWBO4MO.js → settled-turn-finalizer-Dx1onIqg.js} +23 -19
  46. package/dist/{shared-client-kIBbGjk4.js → shared-client-Dw-rzii0.js} +755 -273
  47. package/dist/{side-question-9HAL26l9.js → side-question-DbXkJZzg.js} +52 -30
  48. package/dist/{thread-lifecycle-Bu1BTDXr.js → thread-lifecycle-DKdrnTMX.js} +310 -92
  49. package/dist/{thread-ownership-6kOQHlyC.js → thread-ownership-i2NBwDUL.js} +2 -2
  50. package/dist/{thread-resume-CPrJNQVM.js → thread-resume-CdJk2Ehf.js} +3 -3
  51. package/dist/{transcript-mirror-B9gGgnJS.js → transcript-mirror-BU0_LKAL.js} +46 -28
  52. package/dist/{transport-stdio-DIImwDVS.js → transport-stdio-DhoGy33Z.js} +2 -2
  53. package/dist/{upstream-prompt-provenance-ClRBije0.js → upstream-prompt-provenance-CFmsKwr9.js} +12 -14
  54. package/dist/{upstream-session-fork-CE-_LdnP.js → upstream-session-fork-BDVJCLAD.js} +12 -6
  55. package/dist/{usage-CHlV0e-o.js → usage-9dKJCgcy.js} +3 -3
  56. package/dist/{web-search-provider.runtime-DRw2Vl42.js → web-search-provider.runtime-DCdx4DGu.js} +3 -3
  57. package/openclaw.plugin.json +31 -1
  58. package/package.json +6 -5
  59. package/dist/app-server-policy-zcBDc1JU.js +0 -49
@@ -1,42 +1,47 @@
1
- import { C as isCodexRemoteExecPlacementSandbox, E as resolveCodexPluginsPolicy, M as isCodexAppServerApprovalPolicyAllowedByRequirements, N as resolveOpenClawExecPolicyForCodexAppServer, S as withMcpElicitationsApprovalPolicy, T as readCodexPluginConfig, c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, h as resolveCodexAppServerHomeScope, i as createCodexSessionGenerationSupersededError, j as resolveCodexModelBackedReviewerPolicyContext, l as resolveCodexRunSessionBindingAuthority, u as scopeCodexRunBindingStore, v as resolveCodexComputerUseConfig, w as isCodexSandboxExecServerEnabled, x as shouldAutoApproveCodexAppServerApprovals } from "./session-binding-DPxIvMgE.js";
2
- import { $ as resolveCodexAppServerAuthProfileId, A as isCodexAppServerApprovalRequest, C as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, D as resolveCodexTurnTerminalIdleTimeoutMs, E as resolveCodexTurnCompletionIdleTimeoutMs, G as protectCodexAppServerLiveThread, H as ensureCodexAppServerClientRuntime, I as isCodexAppServerRequestTimeoutError, M as isCodexAppServerConnectionClosedError, N as isCodexAppServerIndeterminateRequestCancellationError, O as withCodexStartupTimeout, P as isCodexAppServerIndeterminateTransportError, Q as resolveCodexAppServerAuthAccountCacheKey, R as resolveCodexAppServerClientInstanceId, T as resolveCodexTurnAssistantCompletionIdleTimeoutMs, X as readRecentCodexRateLimits, Y as readCodexRateLimitsRevision, Z as rememberCodexRateLimitsRead, a as getLeasedSharedCodexAppServerClient, b as CodexAppServerStartupError, ct as isJsonObject, et as resolveCodexAppServerAuthProfileIdForAgent, f as retainSharedCodexAppServerClientIfCurrent, g as withAbortableTimeout, j as isCodexAppServerBrokenPipeError, k as getCodexAppServerClientInstanceId, l as releaseLeasedSharedCodexAppServerClient, n as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, nt as resolveCodexAppServerPreparedApiKeyCacheKey, o as getSharedCodexAppServerClient, p as retireSharedCodexAppServerClientIfCurrent, q as retainCodexAppServerLiveThread, rt as resolveCodexAppServerPreparedAuthHandoff, s as isCodexAppServerStartSelectionChangedError, st as flattenCodexDynamicToolFunctions, t as clearSharedCodexAppServerClientIfCurrent, tt as resolveCodexAppServerFallbackApiKeyCacheKey, ut as resolveCodexAppServerHomeDir, w as resolveCodexStartupTimeoutMs, x as isCodexAppServerStartupError, y as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, z as CodexAppServerRpcError } from "./shared-client-kIBbGjk4.js";
3
- import { A as shouldSynthesizeToolProgressForItem, B as readNullableString, E as itemStatus, F as readItem, I as readItemString, N as readCodexErrorNotificationMessage, O as shouldClearTerminalPresentationForNativeItem, T as itemName, V as splitPlanText, a as closeCodexStartupClientBestEffort, d as unsubscribeCodexThreadBestEffort, f as CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS, g as readCodexNotificationThreadId, h as isCodexNotificationForTurn, j as extractRawAssistantText, l as retireCodexAppServerClientAfterTimedOutTurn, m as CodexProjectionDiagnostics, o as interruptCodexTurnAndWaitBestEffort, p as getCodexAppServerTurnRouter, r as CodexAppServerUnsafeSubscriptionError, t as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS, u as retireUnsafeCodexTurnClientBestEffort, z as readNonNegativeInteger } from "./attempt-client-cleanup-DMLXUfa8.js";
4
- import { C as readRawResponseToolCallId, E as updateActiveTurnItemIds, S as readNotificationItemId, T as updateActiveCompletionBlockerItemIds, _ as isReasoningItemCompletionNotification, a as codexExecutionToolName, b as isTerminalTurnStatus, c as isAssistantCompletionReleaseNotification, d as isNativeToolProgressNotification, f as isPendingOpenClawDynamicToolCompletionNotification, g as isRawToolOutputCompletionNotification, h as isRawReasoningCompletionNotification, l as isCodexTurnAbortMarkerNotification, m as isRawFunctionToolOutputCompletionNotification, o as describeNotificationActivity, p as isRawAssistantProgressNotification, r as projectCodexThreadUsageUpdate, s as isAssistantCommentaryCompletionNotification, t as CodexResponseCompletionProjection, u as isFileChangePatchUpdatedNotification, v as isReasoningProgressNotification, w as shouldDisarmAssistantCompletionIdleWatch, x as readCodexNotificationItem, y as isRetryableErrorNotification } from "./event-projector-usage-e5huIQWu.js";
5
- import { l as readCodexTurn, o as assertCodexTurnStartResponse, s as readCodexDynamicToolCallParams, u as readCodexTurnCompletedNotification } from "./protocol-validators-B4F7L8Rf.js";
6
- import { i as defaultCodexAppInventoryCache, n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-C3H2CVp6.js";
7
- import { A as resolveCodexDynamicToolsLoadingForRuntime, B as buildCodexPluginThreadConfigInputFingerprint, C as codexLegacyDynamicToolsFingerprint, D as isSystemAgentOnlyCodexDynamicToolAllowlist, F as projectContextEngineAssemblyForCodex, G as shouldBuildCodexPluginThreadConfig, I as resolveCodexContextEngineProjectionMaxChars, L as resolveCodexContextEngineProjectionReserveTokens, M as isContextEngineBindingCompatible, N as fitCodexProjectedContextForTurnStart, P as neutralizeCodexExplicitMentionSigils, R as buildCodexPluginAppsConfigPatchFromPolicyContext, S as codexDynamicToolsFingerprint, U as buildPluginAppPolicyContext, V as buildCodexPluginThreadConfigTimeoutFallback, W as mergeCodexThreadConfigs, Z as resolveRecoverableCodexPluginConfigKeys, _ as resolveCodexAppServerThreadModelSelection, a as isCodexAppServerProfilerEnabled, f as resolveCodexWebSearchPlan, i as startOrResumeThread, j as buildContextEngineBinding, n as buildTurnStartParams, p as buildDeveloperInstructions, r as buildCodexUserInput, t as buildTurnCollaborationMode, w as filterCodexDynamicTools, x as areCodexDynamicToolFingerprintsCompatible, z as buildCodexPluginThreadConfig } from "./thread-lifecycle-Bu1BTDXr.js";
1
+ import { A as resolveOpenClawExecPolicyForCodexAppServer, C as parseAllowedApprovalPoliciesFromCodexRequirements, D as selectGuardianApprovalPolicy, E as readCodexRequirementsToml, O as selectGuardianApprovalsReviewer, S as resolveCodexModelBackedReviewerPolicyContext, T as parseAllowedSandboxModesFromCodexRequirements, b as canUseCodexModelBackedApprovalsReviewerForModel, d as withMcpElicitationsApprovalPolicy, f as isCodexPairedNodeRemoteExecPlacementSandbox, g as resolveCodexPluginsPolicy, h as readCodexPluginConfig, j as selectGuardianSandbox, k as selectUserApprovalsReviewer, l as resolveCodexAppServerNetworkProxy, m as isCodexSandboxExecServerEnabled, o as resolveCodexComputerUseConfig, p as isCodexRemoteExecPlacementSandbox, r as resolveCodexAppServerHomeScope, u as shouldAutoApproveCodexAppServerApprovals, w as parseAllowedApprovalsReviewersFromCodexRequirements } from "./config-CpNeo5AE.js";
2
+ import { $ as rememberCodexRateLimitsRead, A as isCodexAppServerApprovalRequest, B as CodexAppServerRpcError, C as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, D as resolveCodexTurnTerminalIdleTimeoutMs, E as resolveCodexTurnCompletionIdleTimeoutMs, I as isCodexAppServerRequestTimeoutError, M as isCodexAppServerConnectionClosedError, N as isCodexAppServerIndeterminateRequestCancellationError, O as withCodexStartupTimeout, P as isCodexAppServerIndeterminateTransportError, Q as readRecentCodexRateLimits, R as resolveCodexAppServerClientInstanceId, T as resolveCodexTurnAssistantCompletionIdleTimeoutMs, V as createCodexElicitationResponse, W as ensureCodexAppServerClientRuntime, Y as retainCodexAppServerLiveThread, Z as readCodexRateLimitsRevision, a as getLeasedSharedCodexAppServerClient, at as resolveCodexAppServerPreparedAuthHandoff, b as CodexAppServerStartupError, et as resolveCodexAppServerAuthAccountCacheKey, f as retainSharedCodexAppServerClientIfCurrent, ft as resolveCodexAppServerHomeDir, g as withAbortableTimeout, i as createIsolatedCodexAppServerClient, it as resolveCodexAppServerPreparedApiKeyCacheKey, j as isCodexAppServerBrokenPipeError, k as getCodexAppServerClientInstanceId, l as releaseLeasedSharedCodexAppServerClient, lt as flattenCodexDynamicToolFunctions, n as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, nt as resolveCodexAppServerAuthProfileIdForAgent, o as getSharedCodexAppServerClient, p as retireSharedCodexAppServerClientIfCurrent, q as protectCodexAppServerLiveThread, rt as resolveCodexAppServerFallbackApiKeyCacheKey, s as isCodexAppServerStartSelectionChangedError, t as clearSharedCodexAppServerClientIfCurrent, tt as resolveCodexAppServerAuthProfileId, ut as isJsonObject, w as resolveCodexStartupTimeoutMs, x as isCodexAppServerStartupError, y as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS } from "./shared-client-Dw-rzii0.js";
3
+ import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, i as createCodexSessionGenerationSupersededError, l as resolveCodexRunSessionBindingAuthority, u as scopeCodexRunBindingStore } from "./session-binding-BTrLf9Qm.js";
4
+ import { A as shouldSynthesizeToolProgressForItem, B as readNullableString, E as itemStatus, F as readItem, I as readItemString, N as readCodexErrorNotificationMessage, O as shouldClearTerminalPresentationForNativeItem, T as itemName, V as splitPlanText, a as closeCodexStartupClientBestEffort, d as unsubscribeCodexThreadBestEffort, f as CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS, g as readCodexNotificationThreadId, h as isCodexNotificationForTurn, j as extractRawAssistantText, l as retireCodexAppServerClientAfterTimedOutTurn, m as CodexProjectionDiagnostics, o as interruptCodexTurnAndWaitBestEffort, p as getCodexAppServerTurnRouter, r as CodexAppServerUnsafeSubscriptionError, t as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS, u as retireUnsafeCodexTurnClientBestEffort, z as readNonNegativeInteger } from "./attempt-client-cleanup-URjUlCHg.js";
5
+ import { C as readRawResponseToolCallId, E as updateActiveTurnItemIds, S as readNotificationItemId, T as updateActiveCompletionBlockerItemIds, _ as isReasoningItemCompletionNotification, a as codexExecutionToolName, b as isTerminalTurnStatus, c as isAssistantCompletionReleaseNotification, d as isNativeToolProgressNotification, f as isPendingOpenClawDynamicToolCompletionNotification, g as isRawToolOutputCompletionNotification, h as isRawReasoningCompletionNotification, l as isCodexTurnAbortMarkerNotification, m as isRawFunctionToolOutputCompletionNotification, o as describeNotificationActivity, p as isRawAssistantProgressNotification, r as projectCodexThreadUsageUpdate, s as isAssistantCommentaryCompletionNotification, t as CodexResponseCompletionProjection, u as isFileChangePatchUpdatedNotification, v as isReasoningProgressNotification, w as shouldDisarmAssistantCompletionIdleWatch, x as readCodexNotificationItem, y as isRetryableErrorNotification } from "./event-projector-usage-CLwNEJqW.js";
6
+ import { l as readCodexTurn, o as assertCodexTurnStartResponse, s as readCodexDynamicToolCallParams, u as readCodexTurnCompletedNotification } from "./protocol-validators-VAVyEnDp.js";
7
+ import { n as buildCodexAppServerRuntimeFingerprint, o as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-DMNQ8Zi8.js";
8
+ import { B as neutralizeCodexExplicitMentionSigils, D as codexLegacyDynamicToolsFingerprint, E as codexDynamicToolsFingerprint, F as resolveCodexDynamicToolsLoadingForRuntime, G as buildCodexPluginAppsConfigPatchFromPolicyContext, H as resolveCodexContextEngineProjectionMaxChars, I as buildContextEngineBinding, J as buildCodexPluginThreadConfigTimeoutFallback, K as buildCodexPluginThreadConfig, L as isContextEngineBindingCompatible, M as isSystemAgentOnlyCodexDynamicToolAllowlist, O as filterCodexDynamicTools, Q as shouldBuildCodexPluginThreadConfig, R as buildCodexContinuityCalibration, T as areCodexDynamicToolFingerprintsCompatible, U as resolveCodexContextEngineProjectionReserveTokens, V as projectContextEngineAssemblyForCodex, W as resolveCodexContinuityProjectionMaxChars, X as buildPluginAppPolicyContext, Z as mergeCodexThreadConfigs, a as isCodexAppServerProfilerEnabled, f as resolveCodexWebSearchPlan, i as startOrResumeThread, it as resolveRecoverableCodexPluginConfigKeys, j as isMessageOnlyCodexSourceReply, n as buildTurnStartParams, p as buildDeveloperInstructions, q as buildCodexPluginThreadConfigInputFingerprint, r as buildCodexUserInput, t as buildTurnCollaborationMode, v as resolveCodexAppServerThreadModelSelection, z as fitCodexProjectedContextForTurnStart } from "./thread-lifecycle-DKdrnTMX.js";
8
9
  import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
9
- import { i as readUpstreamUserText, n as attachUpstreamUserText, r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-ClRBije0.js";
10
- import { a as buildCodexUserPromptMessage, c as readCodexMirrorSourceFingerprint, i as mirrorPromptAtTurnStartBestEffort, l as serializeCodexMirrorSourceEvidence, n as createCodexAppServerUserMessagePersistenceNotifier, o as promptSnapshot, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-B9gGgnJS.js";
11
- import { t as CODEX_CONTROL_METHODS } from "./capabilities-CybGI1oz.js";
12
- import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-DZXmOL8-.js";
13
- import { r as formatCodexDisplayText } from "./command-formatters-B1AEz8ZA.js";
14
- import { n as resolveCodexAppServerForOpenClawToolPolicy, t as resolveCodexAppServerForModelProvider } from "./app-server-policy-zcBDc1JU.js";
15
- import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-I5Bo-AsX.js";
10
+ import { i as readUpstreamUserText, n as attachUpstreamUserText, r as readMirrorIdentity, t as attachCodexMirrorIdentity } from "./upstream-prompt-provenance-CFmsKwr9.js";
11
+ import { a as buildCodexUserPromptMessage, c as readCodexMirrorSourceFingerprint, i as mirrorPromptAtTurnStartBestEffort, l as serializeCodexMirrorSourceEvidence, n as createCodexAppServerUserMessagePersistenceNotifier, o as promptSnapshot, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-BU0_LKAL.js";
12
+ import { t as CODEX_CONTROL_METHODS } from "./capabilities-CH3K57v4.js";
13
+ import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-BI1dMHDG.js";
14
+ import { r as formatCodexDisplayText } from "./command-formatters-D0nZ3qtd.js";
15
+ import { t as resolveCodexAppServerForModelProvider } from "./app-server-policy-bg5QPSVP.js";
16
+ import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-DAvZwp96.js";
16
17
  import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-B4FfbcCg.js";
17
- import { t as resolveCodexLocalRuntimeAttribution } from "./local-runtime-attribution-B_2mnqhb.js";
18
+ import { t as persistCodexContextCompactionActivity } from "./context-compaction-activity-BOeJf7yo.js";
18
19
  import { n as createAssistantMessage, r as createAssistantMirrorMessage, t as createAssistantCommentaryMessage } from "./event-projector-assistant-message-BwxV4d6N.js";
19
- import { a as CodexToolProgressProjection, c as isCodexCommandBearingToolCall, d as sanitizeCodexToolResponse, i as readCodexMirroredSessionHistoryMessages, l as resolveCodexToolProgressDetailMode, n as CodexEventProjection, o as shouldEmitTranscriptToolProgress, r as CodexToolTranscriptProjection, s as inferCodexDynamicToolMeta, t as codexNativeSubagentMonitorRuntime, u as sanitizeCodexToolArguments } from "./native-subagent-monitor-DyTGmTUx.js";
20
- import { A as buildCodexNativeHookRelayDisabledConfig, B as resolveDynamicToolCallTimeoutMs, C as shouldWarnCodexDynamicToolBuildStageSummary, E as CodexNativeToolLifecycleProjector, F as scheduleCodexNativeHookRelayUnregister, G as toCodexDynamicToolProtocolResponse, H as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, I as handleDynamicToolCallWithTimeout, K as resolveCodexToolAbortTerminalReason, L as hasPendingDynamicToolTerminalDiagnostic, M as emitCodexNativePreToolUseFailureDiagnostic, N as resolveCodexNativeHookRelayEvents, O as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, P as resolveCodexNativeHookRelayTtlMs, R as isDynamicToolTerminalDiagnosticEvent, S as shouldRequireCodexSandboxExecServerEnvironment, T as readBoundedCodexRemoteWorkspaceFile, U as shouldReleaseTurnAfterTerminalDynamicTool, V as resolveTerminalDynamicToolBatchAction, W as toCodexDynamicToolProgressResponse, _ as resolveCodexAppServerHookChannelId, a as emitDynamicToolStartedDiagnostic, b as resolveCodexSandboxEnvironmentSelection, c as resolveCodexProviderWebSearchSupport, d as releaseCodexSandboxExecServerEnvironment, f as buildDynamicTools, g as resolveCodexAppServerExecutionCwd, h as formatCodexDynamicToolBuildStageSummary, i as emitDynamicToolErrorDiagnostic, j as createCodexNativeHookRelay, k as buildCodexNativeHookRelayConfig, m as disableCodexPluginThreadConfig, n as projectCodexExecutableDynamicTools, o as emitDynamicToolTerminalDiagnostic, p as createCodexDynamicToolBuildStageTracker, r as handleCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, u as ensureCodexSandboxExecServerEnvironment, v as resolveCodexExternalSandboxPolicyForOpenClawSandbox, x as shouldEnableCodexAppServerNativeToolSurface, y as resolveCodexMessageToolProvider, z as isMatchingDynamicToolTerminalDiagnostic } from "./dynamic-tools-BVdyWkUD.js";
21
- import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, o as killStaleComputerUseMcpChildren, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-CNJPj4_b.js";
20
+ import { a as CodexToolProgressProjection, c as isCodexCommandBearingToolCall, d as sanitizeCodexToolResponse, i as readCodexMirroredSessionHistoryMessages, l as resolveCodexToolProgressDetailMode, n as CodexEventProjection, o as shouldEmitTranscriptToolProgress, r as CodexToolTranscriptProjection, s as inferCodexDynamicToolMeta, t as codexNativeSubagentMonitorRuntime, u as sanitizeCodexToolArguments } from "./native-subagent-monitor-GGq3RnOo.js";
21
+ import { A as buildCodexNativeHookRelayConfig, B as isMatchingDynamicToolTerminalDiagnostic, C as shouldRequireCodexSandboxExecServerEnvironment, D as CodexNativeToolLifecycleProjector, E as readBoundedCodexRemoteWorkspaceFile, F as resolveCodexNativeHookRelayTtlMs, G as toCodexDynamicToolProgressResponse, H as resolveTerminalDynamicToolBatchAction, I as scheduleCodexNativeHookRelayUnregister, K as toCodexDynamicToolProtocolResponse, L as handleDynamicToolCallWithTimeout, M as createCodexNativeHookRelay, N as emitCodexNativePreToolUseFailureDiagnostic, P as resolveCodexNativeHookRelayEvents, R as hasPendingDynamicToolTerminalDiagnostic, S as shouldEnableCodexAppServerNativeToolSurface, U as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, V as resolveDynamicToolCallTimeoutMs, W as shouldReleaseTurnAfterTerminalDynamicTool, _ as resolveCodexAppServerHookChannelId, a as emitDynamicToolStartedDiagnostic, c as resolveCodexProviderWebSearchSupport, d as releaseCodexSandboxExecServerEnvironment, f as buildDynamicTools, g as resolveCodexAppServerExecutionCwd, h as formatCodexDynamicToolBuildStageSummary, i as emitDynamicToolErrorDiagnostic, j as buildCodexNativeHookRelayDisabledConfig, k as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, m as disableCodexPluginThreadConfig, n as projectCodexExecutableDynamicTools, o as emitDynamicToolTerminalDiagnostic, p as createCodexDynamicToolBuildStageTracker, q as resolveCodexToolAbortTerminalReason, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, u as ensureCodexSandboxExecServerEnvironment, v as resolveCodexExternalSandboxPolicyForOpenClawSandbox, w as shouldWarnCodexDynamicToolBuildStageSummary, x as resolveCodexSandboxEnvironmentSelection, y as resolveCodexMessageToolProvider, z as isDynamicToolTerminalDiagnosticEvent } from "./dynamic-tools-fJZhl4CE.js";
22
+ import { a as runCodexComputerUseLiveTest, n as ensureCodexComputerUse, o as killStaleComputerUseMcpChildren, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-BXH5NF-4.js";
22
23
  import { asBoolean, asFiniteNumber, asOptionalRecord, hasNonEmptyString, normalizeOptionalString, readNonBlankString, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
23
24
  import fs from "node:fs/promises";
24
25
  import path from "node:path";
25
26
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
26
27
  import { asDateTimestampMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
27
- import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, agentHarnessAttemptTerminal, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildAgentHarnessUserInputAnswers, buildBootstrapContextForFiles, buildHarnessContextEngineRuntimeContext, buildWatchedSessionsHarnessContext, callGatewayTool, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, deliverAgentHarnessUserInputPrompt, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, getBeforeToolCallPolicyDiagnosticState, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, prepareHarnessNativeMcpAppPreview, projectAgentHarnessTranscriptMessageForDisplay, resolveAgentDir, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveSessionAgentIds, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessGatewayQuestion, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
28
+ import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, agentHarnessAttemptTerminal, agentHarnessStructuredInput, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildBootstrapContextForFiles, buildHarnessContextEngineRuntimeContext, buildWatchedSessionsHarnessContext, callGatewayTool, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, prepareHarnessNativeMcpAppPreview, projectAgentHarnessTranscriptMessageForDisplay, resolveAgentDir, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveSessionAgentIds, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
28
29
  import crypto, { createHash } from "node:crypto";
30
+ import { hostname } from "node:os";
29
31
  import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
30
32
  import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
31
33
  import { parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
32
- import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
34
+ import { truncateUtf16Safe, truncateUtf8Prefix } from "openclaw/plugin-sdk/text-utility-runtime";
35
+ import { isPathInside, isPathStrictlyInside, root } from "openclaw/plugin-sdk/file-access-runtime";
33
36
  import { captureFinalCodexCronCreatorToolAllowlist, materializeStaticMcpToolsForScheduledHarnessRun, resolveCodexMcpToolOverridesForAgent } from "openclaw/plugin-sdk/codex-mcp-projection";
34
37
  import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
38
+ import { Buffer as Buffer$1 } from "node:buffer";
35
39
  import { prepareMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
40
+ import { isSilentReplyPayloadText } from "openclaw/plugin-sdk/reply-chunking";
36
41
  import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
37
42
  import { resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generation-runtime";
38
43
  import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
39
- import { root } from "openclaw/plugin-sdk/file-access-runtime";
44
+ import { stripInvisibleUnicode } from "openclaw/plugin-sdk/web-content-extractor";
40
45
  import { MESSAGE_TOOL_DELIVERY_HINTS } from "openclaw/plugin-sdk/message-tool-delivery-hints";
41
46
  //#region extensions/codex/src/app-server/attempt-steering.ts
42
47
  /**
@@ -173,10 +178,12 @@ function createCodexSteeringQueue(params) {
173
178
  acceptance: "open",
174
179
  text,
175
180
  images: options?.images,
181
+ isInboundUserMessage: options?.isInboundUserMessage,
176
182
  onQueueAccepted: options?.onQueueAccepted,
177
183
  resolve: resolveDelivery,
178
184
  reject: rejectDelivery,
179
- settled: false
185
+ settled: false,
186
+ userTurnTranscriptRecorder: options?.userTurnTranscriptRecorder
180
187
  };
181
188
  pendingMessages.add(item);
182
189
  return {
@@ -193,19 +200,6 @@ function createCodexSteeringQueue(params) {
193
200
  options?.onQueueAccepted?.(false);
194
201
  throw unavailableError;
195
202
  }
196
- const pendingUserInput = options?.isInboundUserMessage === true ? params.claimPendingUserInput() : void 0;
197
- if (pendingUserInput) {
198
- if (!options?.images?.length) {
199
- const answered = pendingUserInput.answer(text);
200
- options?.onQueueAccepted?.(answered);
201
- if (!answered) throw new Error("codex pending user input rejected the answer");
202
- return;
203
- }
204
- flushBatch().catch(() => void 0);
205
- const { item, delivery } = createPendingMessage(text, options);
206
- await Promise.all([enqueueSend([item]).finally(() => pendingUserInput.cancel()), delivery]);
207
- return;
208
- }
209
203
  const { item, delivery } = createPendingMessage(text, options);
210
204
  batchedMessages.push(item);
211
205
  clearBatchTimer();
@@ -221,8 +215,21 @@ function createCodexSteeringQueue(params) {
221
215
  const batch = dispatchedBatches.get(clientUserMessageId);
222
216
  if (!batch) return false;
223
217
  dispatchedBatches.delete(clientUserMessageId);
224
- for (const item of batch.items) resolveItem(item);
225
- return true;
218
+ for (const item of batch.items) reportItemAcceptance(item, true);
219
+ const resolveBatch = () => {
220
+ for (const item of batch.items) resolveItem(item);
221
+ return true;
222
+ };
223
+ const rejectBatch = (error) => {
224
+ for (const item of batch.items) rejectItem(item, error);
225
+ return true;
226
+ };
227
+ if (!params.beforeConfirmConsumed) return resolveBatch();
228
+ try {
229
+ return params.beforeConfirmConsumed(batch.items).then(resolveBatch, rejectBatch);
230
+ } catch (error) {
231
+ return rejectBatch(error);
232
+ }
226
233
  },
227
234
  sealAdmission: sealQueueAdmission,
228
235
  cancel: cancelQueue
@@ -253,6 +260,8 @@ var CodexAssistantProjection = class {
253
260
  this.rawPromotedAssistantItemIds = /* @__PURE__ */ new Set();
254
261
  this.assistantStarted = false;
255
262
  this.streamedPartialAssistantItemReplaceable = false;
263
+ this.persistableAssistantBarrier = 0;
264
+ this.persistableAssistantBarrierItemIds = /* @__PURE__ */ new Set();
256
265
  }
257
266
  hasCompletedTerminalAssistantText(completedItemIds) {
258
267
  const latestCompletedItemId = this.latestCompletedTerminalAssistantItemId;
@@ -322,6 +331,7 @@ var CodexAssistantProjection = class {
322
331
  if (knownFinalAnswer && !replaceable) await this.params.onPartialReply?.(streamPayload);
323
332
  }
324
333
  recordItemStarted(item, itemId) {
334
+ this.noteNativeWorkBarrier(item);
325
335
  if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
326
336
  this.rememberAssistantPhase(item);
327
337
  if (item?.type === "agentMessage" && itemId) this.rememberAssistantItem(itemId);
@@ -331,6 +341,7 @@ var CodexAssistantProjection = class {
331
341
  }
332
342
  }
333
343
  recordItemCompleted(item, itemId, activeItemIds) {
344
+ this.noteNativeWorkBarrier(item);
334
345
  if (item?.type === "agentMessage" && itemId && itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
335
346
  if (itemId) this.latestCompletedItemId = itemId;
336
347
  this.rememberAssistantPhase(item);
@@ -403,8 +414,14 @@ var CodexAssistantProjection = class {
403
414
  else this.markLatestTerminalAssistantCandidate(itemId, activeItemIds, { canReleaseAfterToolHandoff: isIdlessTerminalAssistantAfterCompletedWork });
404
415
  }
405
416
  collectAssistantTexts() {
406
- const finalText = this.resolveFinalAssistantTextItem()?.text;
407
- return finalText ? [finalText] : [];
417
+ const afterHandoff = this.collectPersistableAssistantTexts(this.persistableAssistantBarrier);
418
+ const audibleAfterHandoff = afterHandoff.filter((text) => !isSilentReplyPayloadText(text));
419
+ if (audibleAfterHandoff.length > 0) return audibleAfterHandoff;
420
+ if (afterHandoff.length > 0) return afterHandoff.slice(-1);
421
+ const recoveredAudible = this.collectPersistableAssistantTexts(0).filter((text) => !isSilentReplyPayloadText(text));
422
+ if (recoveredAudible.length > 0) return recoveredAudible.slice(-1);
423
+ const recovered = this.resolveFinalAssistantTextItem()?.text;
424
+ return recovered ? [recovered] : [];
408
425
  }
409
426
  collectCommentaryMessages() {
410
427
  return this.assistantItemOrder.flatMap((itemId) => {
@@ -560,6 +577,34 @@ var CodexAssistantProjection = class {
560
577
  };
561
578
  }
562
579
  }
580
+ collectPersistableAssistantTexts(minIndex) {
581
+ let texts = [];
582
+ let replaceable = false;
583
+ for (let index = minIndex; index < this.assistantItemOrder.length; index += 1) {
584
+ const itemId = this.assistantItemOrder[index];
585
+ if (!itemId || this.assistantPhaseByItem.get(itemId) === "commentary") continue;
586
+ const text = this.assistantTextByItem.get(itemId)?.trim();
587
+ if (!text || this.isToolProgressEchoText(itemId, text)) continue;
588
+ if (isSilentReplyPayloadText(text)) {
589
+ texts.push(text);
590
+ continue;
591
+ }
592
+ const isTerminalFinal = this.assistantPhaseByItem.get(itemId) === "final_answer";
593
+ if (!isTerminalFinal || replaceable) {
594
+ texts = [text];
595
+ replaceable = !isTerminalFinal;
596
+ continue;
597
+ }
598
+ texts.push(text);
599
+ }
600
+ return texts;
601
+ }
602
+ noteNativeWorkBarrier(item) {
603
+ if (!item || !shouldAdvancePersistableAssistantBarrier(item)) return;
604
+ if (item.id && this.persistableAssistantBarrierItemIds.has(item.id)) return;
605
+ if (item.id) this.persistableAssistantBarrierItemIds.add(item.id);
606
+ this.persistableAssistantBarrier = this.assistantItemOrder.length;
607
+ }
563
608
  rememberAssistantItem(itemId) {
564
609
  if (!itemId || this.assistantItemOrder.includes(itemId)) return;
565
610
  this.assistantItemOrder.push(itemId);
@@ -569,6 +614,9 @@ var CodexAssistantProjection = class {
569
614
  return this.rawPromotedAssistantItemIds.has(itemId) && this.matchesToolProgressEcho(text);
570
615
  }
571
616
  };
617
+ function shouldAdvancePersistableAssistantBarrier(item) {
618
+ return shouldClearTerminalPresentationForNativeItem(item) || item.type === "dynamicToolCall" || item.type === "sleep";
619
+ }
572
620
  //#endregion
573
621
  //#region extensions/codex/src/app-server/event-projector-media.ts
574
622
  const GENERATED_IMAGE_MEDIA_SUBDIR = "tool-image-generation";
@@ -739,9 +787,10 @@ function isBase64WhitespaceCode(code) {
739
787
  //#endregion
740
788
  //#region extensions/codex/src/app-server/event-projector-reasoning.ts
741
789
  var CodexReasoningProjection = class {
742
- constructor(params, emitAgentEvent) {
790
+ constructor(params, emitAgentEvent, onNativePlanUpdate) {
743
791
  this.params = params;
744
792
  this.emitAgentEvent = emitAgentEvent;
793
+ this.onNativePlanUpdate = onNativePlanUpdate;
745
794
  this.reasoningTextByGroup = /* @__PURE__ */ new Map();
746
795
  this.reasoningItemOrder = /* @__PURE__ */ new Map();
747
796
  this.planTextByItem = /* @__PURE__ */ new Map();
@@ -782,7 +831,7 @@ var CodexReasoningProjection = class {
782
831
  }))
783
832
  });
784
833
  }
785
- handleTurnPlanUpdated(params, source = "codex-app-server") {
834
+ async handleTurnPlanUpdated(params, source = "codex-app-server") {
786
835
  const explanation = readNullableString(params, "explanation");
787
836
  const plan = Array.isArray(params.plan) ? params.plan.flatMap((entry) => {
788
837
  if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
@@ -796,6 +845,10 @@ var CodexReasoningProjection = class {
796
845
  }) : void 0;
797
846
  const planText = [explanation, ...(plan ?? []).map(({ step, status }) => `- [${status}] ${step}`)].filter((part) => Boolean(part)).join("\n");
798
847
  if (planText) this.turnPlanText = planText;
848
+ if (source === "codex-app-server" && plan) await this.onNativePlanUpdate?.({
849
+ ...typeof explanation === "string" ? { markdown: explanation } : {},
850
+ steps: plan
851
+ });
799
852
  this.emitPlanUpdate({
800
853
  explanation,
801
854
  steps: plan
@@ -825,7 +878,7 @@ var CodexReasoningProjection = class {
825
878
  return this.turnPlanText ?? [...this.planTextByItem.values()].filter((text) => text.trim().length > 0).join("\n\n");
826
879
  }
827
880
  emitPlanUpdate(params, source = "codex-app-server") {
828
- if (!params.explanation && (!params.steps || params.steps.length === 0)) return;
881
+ if (!params.explanation && params.steps === void 0) return;
829
882
  this.emitAgentEvent({
830
883
  stream: "plan",
831
884
  data: {
@@ -833,7 +886,7 @@ var CodexReasoningProjection = class {
833
886
  title: "Plan updated",
834
887
  source,
835
888
  ...params.explanation ? { explanation: params.explanation } : {},
836
- ...params.steps && params.steps.length > 0 ? { steps: params.steps } : {}
889
+ ...params.steps ? { steps: params.steps } : {}
837
890
  }
838
891
  });
839
892
  }
@@ -858,9 +911,9 @@ function reasoningMethodOrder(method) {
858
911
  const attemptTerminal = agentHarnessAttemptTerminal;
859
912
  //#endregion
860
913
  //#region extensions/codex/src/app-server/event-projector-snapshot.ts
914
+ const CODEX_META_KEY$1 = "__openclaw";
861
915
  function readTurnTaintMetadata(message) {
862
- const metadata = message["__openclaw"];
863
- return metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : void 0;
916
+ return asOptionalRecord(CODEX_META_KEY$1 in message ? message[CODEX_META_KEY$1] : void 0);
864
917
  }
865
918
  function applyStickyTurnTaint(messages) {
866
919
  let tainted = false;
@@ -900,8 +953,12 @@ function buildCodexAttemptResult(input) {
900
953
  const commentaryMessages = input.assistantProjection.collectCommentaryMessages();
901
954
  const reasoningText = input.reasoningProjection.reasoningText();
902
955
  const planText = input.reasoningProjection.planText();
903
- const completedUsage = input.responseCompletions.usage ?? input.tokenUsage;
904
- const projectedUsage = input.aborted ? input.tokenUsage : completedUsage;
956
+ const unavailableThreadUsage = input.tokenUsage ? {
957
+ ...input.tokenUsage,
958
+ contextUsage: { state: "unavailable" }
959
+ } : void 0;
960
+ const completedUsage = input.responseCompletions.usage ?? (input.responseCompletions.modelIterations > 0 ? unavailableThreadUsage : input.tokenUsage);
961
+ const projectedUsage = input.aborted ? unavailableThreadUsage : completedUsage;
905
962
  const hasAssistantItemText = input.assistantProjection.hasAssistantItemTextForSynthesis();
906
963
  const legacyFailClosed = !input.completedTurn || input.completedTurn.status !== "completed" || hasAssistantItemText;
907
964
  const hasDeliverableAssistantOnCompletedTurn = input.completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
@@ -976,6 +1033,7 @@ function buildCodexAttemptResult(input) {
976
1033
  acceptedSessionSpawns: input.toolTelemetry.acceptedSessionSpawns,
977
1034
  cloudCodeAssistFormatError: false,
978
1035
  contextTokens: input.contextTokens,
1036
+ contextTokensSource: input.contextTokensSource,
979
1037
  attemptUsage: projectedUsage,
980
1038
  ...input.completedCompactionCount > 0 ? { compactionCount: input.completedCompactionCount } : {},
981
1039
  replayMetadata: {
@@ -1148,6 +1206,7 @@ var CodexAppServerEventProjector = class {
1148
1206
  this.completedCompactionCount = 0;
1149
1207
  this.lastTranscriptTimestamp = 0;
1150
1208
  this.contextTokens = options.initialContextTokens;
1209
+ this.contextTokensSource = options.initialContextTokens === void 0 ? void 0 : "resolved";
1151
1210
  this.diagnostics = new CodexProjectionDiagnostics(threadId, turnId);
1152
1211
  this.nativeToolLifecycleProjector = new CodexNativeToolLifecycleProjector(params, threadId, turnId, { runAbortSignal: options.runAbortSignal });
1153
1212
  this.generatedMediaProjection = new CodexGeneratedMediaProjection(params.config, {
@@ -1164,7 +1223,7 @@ var CodexAppServerEventProjector = class {
1164
1223
  });
1165
1224
  this.eventProjection = new CodexEventProjection(threadId, turnId, (event) => this.emitAgentEvent(event), this.toolProgressProjection, this.toolTranscriptProjection, options.onNativeToolResultRecorded);
1166
1225
  this.assistantProjection = new CodexAssistantProjection(params, (event) => this.emitAgentEvent(event), (text) => this.toolProgressProjection.matchesEcho(text), () => this.nextTranscriptTimestamp());
1167
- this.reasoningProjection = new CodexReasoningProjection(params, (event) => this.emitAgentEvent(event));
1226
+ this.reasoningProjection = new CodexReasoningProjection(params, (event) => this.emitAgentEvent(event), options.onNativePlanUpdate);
1168
1227
  }
1169
1228
  nextTranscriptTimestamp() {
1170
1229
  this.lastTranscriptTimestamp = Math.max(Date.now(), this.lastTranscriptTimestamp + 1);
@@ -1173,6 +1232,20 @@ var CodexAppServerEventProjector = class {
1173
1232
  getCompletedTurnStatus() {
1174
1233
  return this.completedTurn?.status;
1175
1234
  }
1235
+ buildSteeringTranscriptPrefix() {
1236
+ const commentaryMessages = this.assistantProjection.collectCommentaryMessages().filter(({ itemId }) => this.completedItemIds.has(itemId));
1237
+ return buildCodexMessagesSnapshot({
1238
+ runParams: this.params,
1239
+ turnId: this.turnId,
1240
+ upstreamUserText: this.options.upstreamUserText,
1241
+ reasoningText: void 0,
1242
+ planText: void 0,
1243
+ commentaryMessages,
1244
+ toolMessages: this.toolTranscriptProjection.transcriptMessages,
1245
+ lastAssistant: void 0,
1246
+ createAssistantMirrorMessage: (title, text) => this.assistantProjection.createAssistantMirrorMessage(title, text)
1247
+ }).filter((message) => message.role !== "user");
1248
+ }
1176
1249
  hasCompletedTerminalAssistantText() {
1177
1250
  return this.assistantProjection.hasCompletedTerminalAssistantText(this.completedItemIds);
1178
1251
  }
@@ -1199,8 +1272,9 @@ var CodexAppServerEventProjector = class {
1199
1272
  const ordinal = this.params.allocateToolOutcomeOrdinal?.(item.id);
1200
1273
  if (ordinal !== void 0) this.nativeToolOutcomeOrdinals.set(item.id, ordinal);
1201
1274
  }
1202
- recordNativeToolApprovalFailure(toolCallId, disposition) {
1275
+ recordNativeToolApprovalFailure(toolCallId, disposition, approvalKind) {
1203
1276
  this.nativeToolLifecycleProjector.recordApprovalFailureDisposition(toolCallId, disposition);
1277
+ if (disposition === "timed_out" && approvalKind) this.toolProgressProjection.approvalTimeoutKinds.set(toolCallId, approvalKind);
1204
1278
  }
1205
1279
  recordNativeToolPreToolUseFailure(failure) {
1206
1280
  this.nativeToolLifecycleProjector.recordPreToolUseFailure(failure);
@@ -1213,6 +1287,7 @@ var CodexAppServerEventProjector = class {
1213
1287
  } else if (notification.method === "guardianWarning") {
1214
1288
  if (readCodexNotificationThreadId(params) !== this.threadId) return;
1215
1289
  } else if (!isCodexNotificationForTurn(params, this.threadId, this.turnId)) return;
1290
+ if (notification.method !== "guardianWarning" && notification.method !== "item/autoApprovalReview/started" && notification.method !== "item/autoApprovalReview/completed") this.eventProjection.flushPendingGuardianWarning();
1216
1291
  this.nativeToolLifecycleProjector.handleNotification(notification);
1217
1292
  this.assistantProjection.handleNotification(notification.method, params);
1218
1293
  switch (notification.method) {
@@ -1227,7 +1302,7 @@ var CodexAppServerEventProjector = class {
1227
1302
  this.reasoningProjection.handlePlanDelta(params);
1228
1303
  break;
1229
1304
  case "turn/plan/updated":
1230
- this.reasoningProjection.handleTurnPlanUpdated(params);
1305
+ await this.reasoningProjection.handleTurnPlanUpdated(params);
1231
1306
  break;
1232
1307
  case "item/started":
1233
1308
  await this.handleItemStarted(params);
@@ -1251,7 +1326,10 @@ var CodexAppServerEventProjector = class {
1251
1326
  break;
1252
1327
  case "thread/tokenUsage/updated":
1253
1328
  projectCodexThreadUsageUpdate(params, this.tokenUsage, (usage) => this.tokenUsage = usage, (data) => {
1254
- this.contextTokens = data.modelContextWindow ?? this.contextTokens;
1329
+ if (data.modelContextWindow !== void 0) {
1330
+ this.contextTokens = data.modelContextWindow;
1331
+ this.contextTokensSource = this.params.authoredContextTokenCap === void 0 ? "runtime" : "runtime-configured";
1332
+ }
1255
1333
  this.emitAgentEvent({
1256
1334
  stream: "codex_app_server.usage",
1257
1335
  data
@@ -1267,13 +1345,16 @@ var CodexAppServerEventProjector = class {
1267
1345
  case "rawResponseItem/completed":
1268
1346
  await this.handleRawResponseItemCompleted(params);
1269
1347
  break;
1270
- case "error":
1348
+ case "error": {
1271
1349
  this.responseCompletions.clear();
1272
1350
  if (params.willRetry === true) break;
1273
- this.settledTurnFailureFinalizationAllowed = (isJsonObject(params.error) ? params.error.codexErrorInfo : void 0) === "serverOverloaded";
1351
+ const codexErrorInfo = isJsonObject(params.error) ? params.error.codexErrorInfo : void 0;
1352
+ const compactionFailure = codexErrorInfo === "other" && this.isCompacting();
1353
+ this.settledTurnFailureFinalizationAllowed = codexErrorInfo === "serverOverloaded" || compactionFailure;
1274
1354
  this.promptError = this.formatCodexErrorMessage(params) ?? "codex app-server error";
1275
- this.promptErrorSource = "prompt";
1355
+ this.promptErrorSource = compactionFailure ? "compaction" : "prompt";
1276
1356
  break;
1357
+ }
1277
1358
  case "thread/compacted":
1278
1359
  case "turn/started":
1279
1360
  case "turn/diff/updated":
@@ -1292,6 +1373,7 @@ var CodexAppServerEventProjector = class {
1292
1373
  }
1293
1374
  }
1294
1375
  buildResult(toolTelemetry, options) {
1376
+ this.eventProjection.flushPendingGuardianWarning();
1295
1377
  return buildCodexAttemptResult({
1296
1378
  runParams: this.params,
1297
1379
  turnId: this.turnId,
@@ -1307,6 +1389,7 @@ var CodexAppServerEventProjector = class {
1307
1389
  aborted: this.aborted,
1308
1390
  tokenUsage: this.tokenUsage,
1309
1391
  contextTokens: this.contextTokens,
1392
+ contextTokensSource: this.contextTokensSource,
1310
1393
  completedCompactionCount: this.completedCompactionCount,
1311
1394
  activeItemCount: this.activeItemIds.size,
1312
1395
  completedItemCount: this.completedItemIds.size,
@@ -1325,9 +1408,12 @@ var CodexAppServerEventProjector = class {
1325
1408
  recordDynamicToolCall(params) {
1326
1409
  this.toolTranscriptProjection.recordDynamicToolCall(params);
1327
1410
  }
1328
- /** Projects a successful OpenClaw update_plan call through the native plan stream. */
1329
- recordDynamicPlanUpdate(params) {
1330
- if (isJsonObject(params)) this.reasoningProjection.handleTurnPlanUpdated(params, "openclaw");
1411
+ /** Projects a successful OpenClaw progress_card call through the native plan stream. */
1412
+ async recordDynamicProgressCardUpdate(params) {
1413
+ if (isJsonObject(params)) {
1414
+ const projected = { plan: Array.isArray(params.plan) ? params.plan : [] };
1415
+ await this.reasoningProjection.handleTurnPlanUpdated(projected, "openclaw");
1416
+ }
1331
1417
  }
1332
1418
  recordDynamicToolResult(params) {
1333
1419
  this.toolProgressProjection.recordDynamicToolResult(params);
@@ -1415,7 +1501,7 @@ var CodexAppServerEventProjector = class {
1415
1501
  if (item?.type === "contextCompaction" && itemId) {
1416
1502
  this.activeCompactionItemIds.delete(itemId);
1417
1503
  this.completedCompactionCount += 1;
1418
- this.options.onContextCompacted?.();
1504
+ await this.options.onContextCompacted?.();
1419
1505
  await runAgentHarnessAfterCompactionHook({
1420
1506
  sessionFile: this.params.sessionFile,
1421
1507
  messages: await this.toolTranscriptProjection.readMirroredSessionMessages(),
@@ -1431,17 +1517,17 @@ var CodexAppServerEventProjector = class {
1431
1517
  channelId: this.params.messageChannel ?? this.params.messageProvider ?? void 0
1432
1518
  }
1433
1519
  });
1434
- this.emitAgentEvent({
1435
- stream: "compaction",
1436
- data: {
1437
- phase: "end",
1438
- backend: "codex-app-server",
1439
- completed: true,
1440
- threadId: this.threadId,
1441
- turnId: this.turnId,
1442
- itemId
1443
- }
1520
+ await persistCodexContextCompactionActivity({
1521
+ sessionTarget: this.params.sessionTarget,
1522
+ config: this.params.config,
1523
+ cwd: this.params.workspaceDir,
1524
+ runId: this.params.runId,
1525
+ threadId: this.threadId,
1526
+ turnId: this.turnId,
1527
+ itemId,
1528
+ timestamp: this.nextTranscriptTimestamp()
1444
1529
  });
1530
+ this.emitCompactionEnd(itemId, true);
1445
1531
  }
1446
1532
  this.toolProgressProjection.recordToolMeta(item);
1447
1533
  this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
@@ -1470,7 +1556,8 @@ var CodexAppServerEventProjector = class {
1470
1556
  const turn = readCodexTurn(params.turn);
1471
1557
  if (!turn || turn.id !== this.turnId) return;
1472
1558
  this.completedTurn = turn;
1473
- this.settledTurnFailureFinalizationAllowed = turn.status === "failed" && turn.error?.codexErrorInfo === "serverOverloaded";
1559
+ const compactionFailure = turn.status === "failed" && (this.promptErrorSource === "compaction" || turn.error?.codexErrorInfo === "other" && this.isCompacting());
1560
+ this.settledTurnFailureFinalizationAllowed = turn.status === "failed" && (turn.error?.codexErrorInfo === "serverOverloaded" || compactionFailure);
1474
1561
  if (turn.status !== "completed") this.responseCompletions.clear();
1475
1562
  if (turn.status === "failed") {
1476
1563
  const usageLimitMessage = formatCodexUsageLimitErrorMessage({
@@ -1479,7 +1566,15 @@ var CodexAppServerEventProjector = class {
1479
1566
  rateLimits: this.options.readRecentRateLimits?.()
1480
1567
  });
1481
1568
  this.promptError = usageLimitMessage ? createCodexUsageLimitPromptError(usageLimitMessage) : turn.error?.message ?? "codex app-server turn failed";
1482
- this.promptErrorSource = "prompt";
1569
+ this.promptErrorSource = compactionFailure ? "compaction" : "prompt";
1570
+ }
1571
+ if (compactionFailure) {
1572
+ const failedCompactionItemIds = [...this.activeCompactionItemIds];
1573
+ for (const itemId of failedCompactionItemIds) {
1574
+ this.activeItemIds.delete(itemId);
1575
+ this.activeCompactionItemIds.delete(itemId);
1576
+ this.emitCompactionEnd(itemId, false);
1577
+ }
1483
1578
  }
1484
1579
  const turnItems = turn.items ?? [];
1485
1580
  for (let index = turnItems.length - 1; index >= 0; index -= 1) {
@@ -1505,10 +1600,24 @@ var CodexAppServerEventProjector = class {
1505
1600
  this.toolProgressProjection.emitToolResultSummary(item);
1506
1601
  this.toolProgressProjection.emitToolResultOutput(item);
1507
1602
  }
1603
+ this.toolProgressProjection.approvalTimeoutKinds.clear();
1508
1604
  this.assistantProjection.finalizeAnswerCandidate(turn);
1509
1605
  this.activeCompactionItemIds.clear();
1510
1606
  await this.reasoningProjection.maybeEndReasoning();
1511
1607
  }
1608
+ emitCompactionEnd(itemId, completed) {
1609
+ this.emitAgentEvent({
1610
+ stream: "compaction",
1611
+ data: {
1612
+ phase: "end",
1613
+ backend: "codex-app-server",
1614
+ completed,
1615
+ threadId: this.threadId,
1616
+ turnId: this.turnId,
1617
+ itemId
1618
+ }
1619
+ });
1620
+ }
1512
1621
  async emitSnapshotOnlyNativeToolProgress(item) {
1513
1622
  if (!shouldSynthesizeToolProgressForItem(item) || !this.isCurrentTurnSnapshotItem(item) || this.completedItemIds.has(item.id) || itemStatus(item) === "running") return;
1514
1623
  if (!this.activeItemIds.has(item.id)) {
@@ -1708,184 +1817,347 @@ function createCodexNativeMcpAppResultDetailsPreparer(params) {
1708
1817
  };
1709
1818
  }
1710
1819
  //#endregion
1820
+ //#region extensions/codex/src/app-server/plan-compaction-state.ts
1821
+ const RESTORED_PLAN_PREAMBLE = "OpenClaw restored the session progress card after context compaction. This is application state, not a new user request. Continue the current task and call progress_card whenever the status meaningfully changes.";
1822
+ const PROGRESS_CARD_MAX_STEPS = 50;
1823
+ const PROGRESS_CARD_MAX_STEP_UTF8_BYTES = 512;
1824
+ const PROGRESS_CARD_MAX_UTF8_BYTES = 8 * 1024;
1825
+ const RESTORED_PLAN_MAX_MARKDOWN_BYTES = 2 * 1024;
1826
+ const RESTORED_PLAN_MAX_PAYLOAD_BYTES = 32 * 1024;
1827
+ const RESTORED_PLAN_TRUNCATION_SUFFIX = "…";
1828
+ function canonicalizeNativeProgressCardInput(input) {
1829
+ const markdown = input.markdown === void 0 ? void 0 : truncateUtf8(stripInvisibleUnicode(input.markdown), PROGRESS_CARD_MAX_UTF8_BYTES);
1830
+ const plan = [];
1831
+ let hasInProgressStep = false;
1832
+ for (const step of input.steps.slice(0, PROGRESS_CARD_MAX_STEPS)) {
1833
+ const text = truncateUtf8(stripInvisibleUnicode(step.step), PROGRESS_CARD_MAX_STEP_UTF8_BYTES);
1834
+ if (!text.trim()) continue;
1835
+ let status = step.status;
1836
+ if (status === "in_progress") if (hasInProgressStep) status = "pending";
1837
+ else hasInProgressStep = true;
1838
+ plan.push({
1839
+ step: text,
1840
+ status
1841
+ });
1842
+ }
1843
+ return {
1844
+ ...markdown !== void 0 ? { markdown } : {},
1845
+ plan
1846
+ };
1847
+ }
1848
+ /** Retains the latest projected plan so Codex compaction cannot discard it. */
1849
+ var CodexCompactionPlanState = class {
1850
+ record(event) {
1851
+ if (event.stream !== "plan") return;
1852
+ const plan = readBoundedPlan(event.data.explanation, event.data.steps);
1853
+ this.latestPlan = plan;
1854
+ }
1855
+ /** Retains markdown that migration-only plan events intentionally omit. */
1856
+ recordProgressCardInput(value) {
1857
+ if (!isJsonObject(value)) return;
1858
+ this.latestPlan = readBoundedPlan(value.markdown, value.plan);
1859
+ }
1860
+ async restore(params) {
1861
+ if (!this.latestPlan) return;
1862
+ await params.client.request("thread/inject_items", {
1863
+ threadId: params.threadId,
1864
+ items: [{
1865
+ type: "message",
1866
+ role: "user",
1867
+ content: [{
1868
+ type: "input_text",
1869
+ text: `${RESTORED_PLAN_PREAMBLE}\n${serializePlan(this.latestPlan)}`
1870
+ }]
1871
+ }]
1872
+ }, {
1873
+ timeoutMs: params.timeoutMs,
1874
+ signal: params.signal
1875
+ });
1876
+ }
1877
+ };
1878
+ function readBoundedPlan(markdownValue, stepsValue) {
1879
+ const canonical = canonicalizeNativeProgressCardInput({
1880
+ ...typeof markdownValue === "string" ? { markdown: markdownValue } : {},
1881
+ steps: readPlanSteps(stepsValue)
1882
+ });
1883
+ const markdown = canonical.markdown === void 0 ? void 0 : truncateUtf8(canonical.markdown, RESTORED_PLAN_MAX_MARKDOWN_BYTES);
1884
+ const steps = [];
1885
+ for (const step of canonical.plan) {
1886
+ const candidate = {
1887
+ ...markdown?.trim() ? { markdown } : {},
1888
+ steps: [...steps, step]
1889
+ };
1890
+ if (Buffer$1.byteLength(serializePlan(candidate), "utf8") > RESTORED_PLAN_MAX_PAYLOAD_BYTES) break;
1891
+ steps.push(step);
1892
+ }
1893
+ return markdown?.trim() || steps.length > 0 ? {
1894
+ ...markdown?.trim() ? { markdown } : {},
1895
+ steps
1896
+ } : void 0;
1897
+ }
1898
+ function serializePlan(plan) {
1899
+ return JSON.stringify({
1900
+ markdown: plan.markdown,
1901
+ plan: plan.steps
1902
+ });
1903
+ }
1904
+ function truncateUtf8(value, maxBytes) {
1905
+ if (Buffer$1.byteLength(value, "utf8") <= maxBytes) return value;
1906
+ return `${truncateUtf8Prefix(value, maxBytes - Buffer$1.byteLength(RESTORED_PLAN_TRUNCATION_SUFFIX, "utf8"))}${RESTORED_PLAN_TRUNCATION_SUFFIX}`;
1907
+ }
1908
+ function readPlanSteps(value) {
1909
+ if (!Array.isArray(value)) return [];
1910
+ return value.flatMap((entry) => {
1911
+ if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
1912
+ const { step, status } = entry;
1913
+ if (typeof step !== "string" || !isPlanStatus(status)) return [];
1914
+ return [{
1915
+ step,
1916
+ status
1917
+ }];
1918
+ });
1919
+ }
1920
+ function isPlanStatus(value) {
1921
+ return value === "pending" || value === "in_progress" || value === "completed";
1922
+ }
1923
+ //#endregion
1711
1924
  //#region extensions/codex/src/app-server/user-input-bridge.ts
1712
- /** Bridges Codex request_user_input calls to gateway questions and secret text prompts. */
1925
+ /** Owns per-turn Codex request_user_input and ordinary MCP elicitation lifecycles. */
1713
1926
  const DEFAULT_USER_INPUT_TIMEOUT_MS = 15 * 6e4;
1714
1927
  const NONBLOCKING_USER_INPUT_TIMEOUT_MS = 12e4;
1715
- /** Creates a per-turn bridge for pending Codex user-input requests. */
1928
+ const MAX_USER_INPUT_QUESTIONS = 3;
1929
+ const MAX_USER_INPUT_OPTIONS = 4;
1930
+ const MAX_USER_INPUT_ID = 256;
1931
+ const MAX_USER_INPUT_HEADER = 64;
1932
+ const MAX_USER_INPUT_TEXT = 4096;
1933
+ /** Creates the single per-turn owner for Codex operator input. */
1716
1934
  function createCodexUserInputBridge(params) {
1717
- let sensitiveInput;
1718
- let pendingGateway;
1719
1935
  const gatewayCall = params.gatewayCall ?? callGatewayTool;
1720
- const resolveSecret = (value) => {
1721
- const current = sensitiveInput;
1722
- if (!current) return;
1723
- sensitiveInput = void 0;
1724
- current.cleanup();
1725
- current.resolve(value);
1726
- };
1727
- const resolveSecretIfCurrent = (current, value) => {
1728
- if (sensitiveInput !== current) return false;
1729
- resolveSecret(value);
1730
- return true;
1936
+ const jobs = [];
1937
+ let activeCompletion;
1938
+ const inputSessionKey = params.paramsForRun.sessionKey ?? params.paramsForRun.sessionId;
1939
+ const pump = () => {
1940
+ const job = jobs[0];
1941
+ if (activeCompletion || !job) return;
1942
+ activeCompletion = job.run(job.abort.signal).catch((error) => {
1943
+ embeddedAgentLog.warn("failed to bridge codex operator input", { error });
1944
+ return job.abort.signal.aborted ? job.cancelValue : job.failureValue;
1945
+ }).then((value) => {
1946
+ job.resolve(job.abort.signal.aborted ? job.cancelValue : value ?? job.failureValue);
1947
+ }).finally(() => {
1948
+ if (jobs[0] === job) jobs.shift();
1949
+ activeCompletion = void 0;
1950
+ pump();
1951
+ });
1731
1952
  };
1732
- const cancelGateway = () => {
1733
- pendingGateway?.abort.abort(/* @__PURE__ */ new Error("Codex user input request cancelled"));
1953
+ const enqueue = (definition) => {
1954
+ if (params.signal?.aborted) return Promise.resolve(definition.cancelValue);
1955
+ return new Promise((resolve) => {
1956
+ jobs.push({
1957
+ ...definition,
1958
+ resolve
1959
+ });
1960
+ pump();
1961
+ });
1734
1962
  };
1963
+ const cancelJob = (job) => {
1964
+ const index = jobs.indexOf(job);
1965
+ if (index < 0) return;
1966
+ if (index === 0) {
1967
+ job.abort.abort(/* @__PURE__ */ new Error("Codex operator input request cancelled"));
1968
+ return;
1969
+ }
1970
+ jobs.splice(index, 1);
1971
+ job.resolve(job.cancelValue);
1972
+ };
1973
+ const cancelPending = async () => {
1974
+ const pendingCompletion = activeCompletion;
1975
+ const queuedJobs = jobs.splice(1);
1976
+ for (const job of queuedJobs) job.resolve(job.cancelValue);
1977
+ jobs[0]?.abort.abort(/* @__PURE__ */ new Error("Codex operator input request cancelled"));
1978
+ await pendingCompletion;
1979
+ };
1980
+ const execute = (input, timeoutMs, signal) => agentHarnessStructuredInput.run({
1981
+ input,
1982
+ sessionKey: inputSessionKey,
1983
+ agentId: params.paramsForRun.agentId,
1984
+ runId: params.paramsForRun.runId,
1985
+ timeoutMs,
1986
+ gatewayCall,
1987
+ delivery: params.paramsForRun,
1988
+ signal,
1989
+ promptOptions: {
1990
+ formatText: formatCodexDisplayText,
1991
+ unsupportedIntro: "Codex input request could not be shown:",
1992
+ urlIntro: "Codex needs confirmation:"
1993
+ }
1994
+ });
1995
+ params.signal?.addEventListener("abort", () => void cancelPending(), { once: true });
1735
1996
  return {
1736
1997
  async handleRequest(request) {
1737
1998
  const requestParams = readUserInputParams(request.params);
1738
- if (!requestParams) return;
1739
- if (requestParams.threadId !== params.threadId || requestParams.turnId !== params.turnId) return;
1999
+ if (!requestParams || requestParams.threadId !== params.threadId || requestParams.turnId !== params.turnId) return;
1740
2000
  if (requestParams.questions.length === 0) return emptyUserInputResponse();
1741
- resolveSecret(emptyUserInputResponse());
1742
- cancelGateway();
1743
- if (requestParams.questions.some((question) => question.isSecret)) return new Promise((resolve) => {
1744
- const abortListener = () => resolveSecret(emptyUserInputResponse());
1745
- const timeout = requestParams.isBlocking ? void 0 : setTimeout(() => resolveSecret(emptyUserInputResponse()), NONBLOCKING_USER_INPUT_TIMEOUT_MS);
1746
- timeout?.unref?.();
1747
- const cleanup = () => {
1748
- params.signal?.removeEventListener("abort", abortListener);
1749
- if (timeout) clearTimeout(timeout);
1750
- };
1751
- const current = {
1752
- requestId: request.id,
1753
- threadId: requestParams.threadId,
1754
- questions: requestParams.questions,
1755
- claimed: false,
1756
- resolve,
1757
- cleanup
1758
- };
1759
- sensitiveInput = current;
1760
- params.signal?.addEventListener("abort", abortListener, { once: true });
1761
- if (params.signal?.aborted) {
1762
- resolveSecret(emptyUserInputResponse());
1763
- return;
2001
+ const timeoutMs = requestParams.isBlocking ? params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS : NONBLOCKING_USER_INPUT_TIMEOUT_MS;
2002
+ const input = compileUserInputQuestions(requestParams.questions);
2003
+ const cancelValue = emptyUserInputResponse();
2004
+ return await enqueue({
2005
+ requestId: request.id,
2006
+ abort: new AbortController(),
2007
+ cancelValue,
2008
+ failureValue: cancelValue,
2009
+ run: async (signal) => {
2010
+ const result = await execute(input, timeoutMs, signal);
2011
+ return result.status === "answered" ? gatewayAnswersToCodexResponse(result.answers) : cancelValue;
1764
2012
  }
1765
- deliverAgentHarnessUserInputPrompt(params.paramsForRun, requestParams.questions, {
1766
- formatText: formatCodexDisplayText,
1767
- intro: "Codex needs input:"
1768
- }).catch((error) => {
1769
- embeddedAgentLog.warn("failed to deliver secret codex user input prompt", { error });
1770
- resolveSecretIfCurrent(current, emptyUserInputResponse());
1771
- });
1772
2013
  });
1773
- const abort = new AbortController();
1774
- const abortFromRun = () => abort.abort(params.signal?.reason);
1775
- params.signal?.addEventListener("abort", abortFromRun, { once: true });
1776
- if (params.signal?.aborted) abortFromRun();
1777
- pendingGateway = {
1778
- requestId: request.id,
1779
- threadId: requestParams.threadId,
1780
- abort
1781
- };
1782
- try {
1783
- const result = await runAgentHarnessGatewayQuestion({
1784
- questions: requestParams.questions,
1785
- sessionKey: params.paramsForRun.sessionKey ?? params.paramsForRun.sessionId,
1786
- agentId: params.paramsForRun.agentId,
1787
- runId: params.paramsForRun.runId,
1788
- timeoutMs: requestParams.isBlocking ? params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS : NONBLOCKING_USER_INPUT_TIMEOUT_MS,
1789
- gatewayCall,
1790
- delivery: params.paramsForRun,
1791
- promptOptions: {
1792
- formatText: formatCodexDisplayText,
1793
- intro: "Codex needs input:"
1794
- },
1795
- signal: abort.signal
2014
+ },
2015
+ async handleElicitationRequest(request) {
2016
+ if (readRawOwnString(request.params, "threadId") !== params.threadId) return;
2017
+ const requestSnapshot = agentHarnessStructuredInput.snapshot(request.params);
2018
+ if (requestSnapshot === void 0) {
2019
+ const cancelValue = createCodexElicitationResponse("cancel");
2020
+ return await enqueue({
2021
+ requestId: request.id,
2022
+ abort: new AbortController(),
2023
+ cancelValue,
2024
+ failureValue: declineElicitation("OpenClaw could not handle this elicitation."),
2025
+ run: async (signal) => {
2026
+ const result = await execute({
2027
+ kind: "unsupported",
2028
+ message: "OpenClaw declined a malformed or over-limit MCP elicitation request."
2029
+ }, params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS, signal);
2030
+ return result.status === "unsupported" ? declineElicitation(result.message) : cancelValue;
2031
+ }
1796
2032
  });
1797
- return result.status === "answered" ? gatewayAnswersToCodexResponse(result.answers.answers) : emptyUserInputResponse();
1798
- } catch (error) {
1799
- embeddedAgentLog.warn("failed to bridge codex user input through gateway", { error });
1800
- return emptyUserInputResponse();
1801
- } finally {
1802
- params.signal?.removeEventListener("abort", abortFromRun);
1803
- if (pendingGateway?.abort === abort) pendingGateway = void 0;
1804
2033
  }
1805
- },
1806
- claimPendingRequest() {
1807
- const current = sensitiveInput;
1808
- if (!current || current.claimed) return;
1809
- current.claimed = true;
1810
- return {
1811
- answer: (text) => resolveSecretIfCurrent(current, buildUserInputResponse(current.questions, text)),
1812
- cancel: () => resolveSecretIfCurrent(current, emptyUserInputResponse())
1813
- };
2034
+ const { compileCodexOrdinaryElicitation } = await import("./elicitation-input-DMkeki8d.js");
2035
+ const compiled = compileCodexOrdinaryElicitation({
2036
+ value: requestSnapshot,
2037
+ threadId: params.threadId,
2038
+ turnId: params.turnId
2039
+ });
2040
+ if (compiled.kind === "ignored") return;
2041
+ const cancelValue = createCodexElicitationResponse("cancel");
2042
+ const timeoutMs = params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS;
2043
+ return await enqueue({
2044
+ requestId: request.id,
2045
+ abort: new AbortController(),
2046
+ cancelValue,
2047
+ failureValue: declineElicitation("OpenClaw could not handle this elicitation."),
2048
+ run: async (signal) => {
2049
+ const result = await execute(compiled.input, timeoutMs, signal);
2050
+ if (result.status === "answered") return createCodexElicitationResponse("accept", compiled.input.kind === "ready" && compiled.input.plan.kind === "url" ? null : result.content);
2051
+ if (result.status === "declined") return declineElicitation(result.message);
2052
+ if (result.status === "unsupported") return declineElicitation(result.message);
2053
+ return cancelValue;
2054
+ }
2055
+ });
1814
2056
  },
1815
2057
  handleNotification(notification) {
1816
- if (notification.method !== "serverRequest/resolved") return;
1817
- const notificationParams = isJsonObject(notification.params) ? notification.params : void 0;
1818
- const requestId = notificationParams ? readRequestId(notificationParams) : void 0;
1819
- if (!notificationParams || requestId === void 0) return;
1820
- if (sensitiveInput && readStringField(notificationParams, "threadId") === sensitiveInput.threadId && String(requestId) === String(sensitiveInput.requestId)) resolveSecret(emptyUserInputResponse());
1821
- if (pendingGateway && readStringField(notificationParams, "threadId") === pendingGateway.threadId && String(requestId) === String(pendingGateway.requestId)) pendingGateway.abort.abort(/* @__PURE__ */ new Error("Codex server request resolved"));
2058
+ if (notification.method !== "serverRequest/resolved" || !isJsonObject(notification.params)) return;
2059
+ const requestId = readRequestId(notification.params);
2060
+ if (requestId === void 0 || readOwnString(notification.params, "threadId") !== params.threadId) return;
2061
+ const job = jobs.find((candidate) => typeof candidate.requestId === typeof requestId && candidate.requestId === requestId);
2062
+ if (job) cancelJob(job);
1822
2063
  },
1823
- cancelPending() {
1824
- resolveSecret(emptyUserInputResponse());
1825
- cancelGateway();
1826
- }
2064
+ cancelPending
1827
2065
  };
1828
2066
  }
2067
+ function compileUserInputQuestions(questions) {
2068
+ return agentHarnessStructuredInput.compileQuestions({
2069
+ questions,
2070
+ intro: "Codex needs input:"
2071
+ });
2072
+ }
1829
2073
  function readUserInputParams(value) {
1830
- if (!isJsonObject(value)) return;
1831
- const threadId = readStringField(value, "threadId");
1832
- const turnId = readStringField(value, "turnId");
1833
- const itemId = readStringField(value, "itemId");
1834
- const questionsRaw = value.questions;
1835
- if (!threadId || !turnId || !itemId || !Array.isArray(questionsRaw)) return;
2074
+ const snapshot = agentHarnessStructuredInput.snapshot(value);
2075
+ if (!agentHarnessStructuredInput.isRecord(snapshot)) return;
2076
+ const threadId = readBoundedUserInputText(snapshot, "threadId", MAX_USER_INPUT_ID);
2077
+ const turnId = readBoundedUserInputText(snapshot, "turnId", MAX_USER_INPUT_ID);
2078
+ const itemId = readBoundedUserInputText(snapshot, "itemId", MAX_USER_INPUT_ID);
2079
+ const questions = readArray(snapshot, "questions", MAX_USER_INPUT_QUESTIONS);
2080
+ if (!threadId || !turnId || !itemId || !questions) return;
2081
+ const parsed = [];
2082
+ for (const questionValue of questions) {
2083
+ const question = readQuestion(questionValue);
2084
+ if (!question) return;
2085
+ parsed.push(question);
2086
+ }
1836
2087
  return {
1837
2088
  threadId,
1838
2089
  turnId,
1839
- itemId,
1840
- questions: questionsRaw.map((rawQuestion) => {
1841
- const question = readQuestion(rawQuestion);
1842
- if (question && isJsonObject(rawQuestion) && rawQuestion.multiSelect === true) question.multiSelect = true;
1843
- return question;
1844
- }).filter((question) => Boolean(question)),
1845
- isBlocking: value.isBlocking !== false
2090
+ questions: parsed,
2091
+ isBlocking: readValue(snapshot, "isBlocking") !== false
1846
2092
  };
1847
2093
  }
1848
2094
  function readQuestion(value) {
1849
- if (!isJsonObject(value)) return;
1850
- const id = readStringField(value, "id");
1851
- const header = readStringField(value, "header");
1852
- const question = readStringField(value, "question");
2095
+ if (!agentHarnessStructuredInput.isRecord(value)) return;
2096
+ const id = readBoundedUserInputText(value, "id", MAX_USER_INPUT_ID);
2097
+ const header = readBoundedUserInputText(value, "header", MAX_USER_INPUT_HEADER);
2098
+ const question = readBoundedUserInputText(value, "question", MAX_USER_INPUT_TEXT);
1853
2099
  if (!id || !header || !question) return;
2100
+ const options = readOptions(readValue(value, "options"));
2101
+ if (options === void 0) return;
1854
2102
  return {
1855
2103
  id,
1856
2104
  header,
1857
2105
  question,
1858
- isOther: value.isOther === true,
1859
- isSecret: value.isSecret === true,
1860
- options: readOptions(value.options)
2106
+ isOther: readValue(value, "isOther") === true,
2107
+ isSecret: readValue(value, "isSecret") === true,
2108
+ ...readValue(value, "multiSelect") === true ? { multiSelect: true } : {},
2109
+ options
1861
2110
  };
1862
2111
  }
1863
2112
  function readOptions(value) {
1864
- if (!Array.isArray(value)) return null;
1865
- const options = value.map(readOption).filter((option) => Boolean(option));
1866
- return options.length > 0 ? options : null;
1867
- }
1868
- function readOption(value) {
1869
- if (!isJsonObject(value)) return;
1870
- const label = readStringField(value, "label");
1871
- const description = readStringField(value, "description") ?? "";
1872
- return label ? {
1873
- label,
1874
- description
1875
- } : void 0;
2113
+ if (value === void 0 || value === null) return null;
2114
+ if (!Array.isArray(value) || value.length > MAX_USER_INPUT_OPTIONS) return;
2115
+ const options = [];
2116
+ for (const entry of value) {
2117
+ if (!agentHarnessStructuredInput.isRecord(entry)) return;
2118
+ const label = readBoundedUserInputText(entry, "label", MAX_USER_INPUT_ID);
2119
+ const description = readBoundedUserInputText(entry, "description", MAX_USER_INPUT_TEXT, true);
2120
+ if (!label) return;
2121
+ options.push({
2122
+ label,
2123
+ ...description ? { description } : {}
2124
+ });
2125
+ }
2126
+ return options;
2127
+ }
2128
+ function readValue(record, key) {
2129
+ return Object.hasOwn(record, key) ? record[key] : void 0;
2130
+ }
2131
+ function readBoundedUserInputText(record, key, maximum, allowEmpty = false) {
2132
+ const value = readValue(record, key);
2133
+ return typeof value === "string" && value.length <= maximum && (allowEmpty || value.length > 0) ? value : void 0;
1876
2134
  }
1877
- function buildUserInputResponse(questions, inputText) {
1878
- return buildAgentHarnessUserInputAnswers(questions, inputText);
2135
+ function readArray(record, key, maximum) {
2136
+ const value = readValue(record, key);
2137
+ return Array.isArray(value) && value.length <= maximum ? value : void 0;
2138
+ }
2139
+ function readOwnString(record, key) {
2140
+ const descriptor = Object.getOwnPropertyDescriptor(record, key);
2141
+ return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : void 0;
2142
+ }
2143
+ function readRawOwnString(value, key) {
2144
+ if (!value || typeof value !== "object" || Array.isArray(value)) return;
2145
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
2146
+ return descriptor && "value" in descriptor && typeof descriptor.value === "string" ? descriptor.value : void 0;
2147
+ }
2148
+ function readRequestId(record) {
2149
+ const descriptor = Object.getOwnPropertyDescriptor(record, "requestId");
2150
+ const value = descriptor && "value" in descriptor ? descriptor.value : void 0;
2151
+ return typeof value === "string" || typeof value === "number" ? value : void 0;
1879
2152
  }
1880
2153
  function gatewayAnswersToCodexResponse(answers) {
1881
2154
  return { answers: Object.fromEntries(Object.entries(answers).map(([questionId, values]) => [questionId, { answers: values }])) };
1882
2155
  }
1883
2156
  function emptyUserInputResponse() {
1884
- return emptyAgentHarnessUserInputAnswers();
2157
+ return { ...emptyAgentHarnessUserInputAnswers() };
1885
2158
  }
1886
- function readRequestId(record) {
1887
- const value = record.requestId;
1888
- return typeof value === "string" || typeof value === "number" ? value : void 0;
2159
+ function declineElicitation(message) {
2160
+ return createCodexElicitationResponse("decline", null, message ? { message } : null);
1889
2161
  }
1890
2162
  //#endregion
1891
2163
  //#region extensions/codex/src/app-server/run-attempt-active-turn.ts
@@ -1894,12 +2166,14 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
1894
2166
  const { context, turnState } = prompt;
1895
2167
  const { runtime, attemptTools } = context;
1896
2168
  const { connection } = runtime;
1897
- const { params, runAbortController, terminalState, abortExplicitly, abortFromUpstream, bindingStore, bindingIdentity, sessionAgentId, sandboxSessionKey, effectiveCwd } = connection;
1898
- const { dynamicToolParams, computerContextEpoch, toolBridge } = attemptTools;
2169
+ const { params, runAbortController, terminalState, abortExplicitly, abortFromUpstream, bindingStore, bindingIdentity, sessionAgentId, sandboxSessionKey, contextSessionKey, effectiveCwd } = connection;
2170
+ const { dynamicToolParams, compactionPlanState, computerContextEpoch, toolBridge } = attemptTools;
1899
2171
  const { state, userInputBridgeRef, steeringQueueRef, turnWatches, completeTurn, interruptTurn } = turnRuntime;
1900
2172
  const { emitExecutionPhaseOnce, emitLifecycleStart, maybeAnnounceFastModeAutoOff } = lifecycle;
1901
2173
  const { enqueueNotification } = notifications;
1902
2174
  const activeTurnId = turn.turn.id;
2175
+ const progressCardTool = toolBridge.availableTools.find((tool) => tool.name === "progress_card");
2176
+ let nativePlanUpdateOrdinal = 0;
1903
2177
  const prepareNativeMcpAppResultDetails = createCodexNativeMcpAppResultDetailsPreparer({
1904
2178
  client: resourceState.client,
1905
2179
  threadId: resourceState.thread.threadId,
@@ -1948,12 +2222,39 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
1948
2222
  trajectoryRecorder,
1949
2223
  resolveDynamicToolResultContentSource: toolBridge.resultContentSourceForTool,
1950
2224
  onNativeToolResultRecorded: maybeAnnounceFastModeAutoOff,
2225
+ ...progressCardTool ? { onNativePlanUpdate: async (update) => {
2226
+ nativePlanUpdateOrdinal += 1;
2227
+ try {
2228
+ const input = canonicalizeNativeProgressCardInput(update);
2229
+ await progressCardTool.execute(`codex-native-plan:${activeTurnId}:${nativePlanUpdateOrdinal}`, input, runAbortController.signal);
2230
+ } catch (error) {
2231
+ embeddedAgentLog.warn("failed to persist native Codex plan to progress card", {
2232
+ runId: params.runId,
2233
+ threadId: resourceState.thread.threadId,
2234
+ error: formatErrorMessage(error)
2235
+ });
2236
+ }
2237
+ } } : {},
1951
2238
  ...prepareNativeMcpAppResultDetails ? { prepareNativeMcpAppResultDetails } : {},
1952
2239
  upstreamUserText: turnState.codexTurnPromptText,
1953
- onContextCompacted: () => {
2240
+ onContextCompacted: async () => {
1954
2241
  computerContextEpoch.value += 1;
1955
2242
  delete computerContextEpoch.frameToolCallId;
1956
2243
  delete computerContextEpoch.frameImageIdentity;
2244
+ try {
2245
+ await compactionPlanState.restore({
2246
+ client: resourceState.client,
2247
+ threadId: resourceState.thread.threadId,
2248
+ timeoutMs: connection.appServer.requestTimeoutMs,
2249
+ signal: runAbortController.signal
2250
+ });
2251
+ } catch (error) {
2252
+ embeddedAgentLog.warn("failed to restore Codex plan state after compaction", {
2253
+ runId: params.runId,
2254
+ threadId: resourceState.thread.threadId,
2255
+ error: formatErrorMessage(error)
2256
+ });
2257
+ }
1957
2258
  }
1958
2259
  });
1959
2260
  if (isTerminalTurnStatus(turn.turn.status)) state.terminalTurnNotificationQueued = true;
@@ -1974,24 +2275,61 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
1974
2275
  throw error;
1975
2276
  }
1976
2277
  }
1977
- if (!state.completed && isTerminalTurnStatus(turn.turn.status)) await enqueueNotification({
1978
- method: "turn/completed",
1979
- params: {
2278
+ if (!state.completed && isTerminalTurnStatus(turn.turn.status)) {
2279
+ if (!isJsonObject(turn.turn)) throw new Error("Codex turn completion payload is not a JSON object");
2280
+ await enqueueNotification({
2281
+ method: "turn/completed",
2282
+ params: {
2283
+ threadId: resourceState.thread.threadId,
2284
+ turnId: activeTurnId,
2285
+ turn: turn.turn
2286
+ }
2287
+ }, {
1980
2288
  threadId: resourceState.thread.threadId,
1981
- turnId: activeTurnId,
1982
- turn: turn.turn
1983
- }
1984
- }, {
2289
+ turnId: activeTurnId
2290
+ });
2291
+ }
2292
+ const notifyUserMessagePersisted = createCodexAppServerUserMessagePersistenceNotifier(params);
2293
+ const promptMirrorPromise = mirrorPromptAtTurnStartBestEffort({
2294
+ params,
2295
+ agentId: sessionAgentId,
2296
+ notifyUserMessagePersisted,
2297
+ sessionKey: sandboxSessionKey,
2298
+ cwd: effectiveCwd,
1985
2299
  threadId: resourceState.thread.threadId,
1986
- turnId: activeTurnId
2300
+ turnId: activeTurnId,
2301
+ upstreamUserText: turnState.codexTurnPromptText
1987
2302
  });
1988
2303
  const activeSteeringQueue = createCodexSteeringQueue({
1989
2304
  client: resourceState.client,
1990
2305
  threadId: resourceState.thread.threadId,
1991
2306
  turnId: activeTurnId,
1992
2307
  requestTimeoutMs: connection.appServer.requestTimeoutMs,
1993
- claimPendingUserInput: () => userInputBridgeRef.current?.claimPendingRequest(),
1994
- signal: runAbortController.signal
2308
+ signal: runAbortController.signal,
2309
+ beforeConfirmConsumed: async (items) => {
2310
+ const inboundItems = items.filter((item) => item.isInboundUserMessage === true);
2311
+ if (inboundItems.length === 0) return;
2312
+ await promptMirrorPromise;
2313
+ const messages = activeProjector.buildSteeringTranscriptPrefix();
2314
+ if (params.sessionTarget && messages.length > 0) await codexTranscriptMirrorRuntime.mirror({
2315
+ agentId: sessionAgentId,
2316
+ sessionKey: contextSessionKey,
2317
+ sessionId: params.sessionId,
2318
+ storePath: params.sessionTarget.storePath,
2319
+ cwd: effectiveCwd,
2320
+ messages,
2321
+ idempotencyScope: `codex-app-server:${resourceState.thread.threadId}`,
2322
+ runId: params.runId,
2323
+ runMirrorIdentityPrefix: `${activeTurnId}:`,
2324
+ config: params.config
2325
+ });
2326
+ for (const item of inboundItems) {
2327
+ const recorder = item.userTurnTranscriptRecorder;
2328
+ if (!recorder) continue;
2329
+ await recorder.persistApproved();
2330
+ if (!recorder.hasPersisted()) throw new Error("Codex consumed steering before its user turn was persisted");
2331
+ }
2332
+ }
1995
2333
  });
1996
2334
  steeringQueueRef.current = activeSteeringQueue;
1997
2335
  const claimPendingUserInputAnswer = async (text, optionsLocal) => {
@@ -2058,17 +2396,6 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
2058
2396
  terminalState.terminalOutcomeFrozen = true;
2059
2397
  params.abortSignal?.removeEventListener("abort", abortFromUpstream);
2060
2398
  };
2061
- const notifyUserMessagePersisted = createCodexAppServerUserMessagePersistenceNotifier(params);
2062
- mirrorPromptAtTurnStartBestEffort({
2063
- params,
2064
- agentId: sessionAgentId,
2065
- notifyUserMessagePersisted,
2066
- sessionKey: sandboxSessionKey,
2067
- cwd: effectiveCwd,
2068
- threadId: resourceState.thread.threadId,
2069
- turnId: activeTurnId,
2070
- upstreamUserText: turnState.codexTurnPromptText
2071
- });
2072
2399
  const abortListener = () => {
2073
2400
  if (state.timedOut) {
2074
2401
  (async () => {
@@ -2252,6 +2579,105 @@ async function runCodexAgentEndHook(params, hookParams) {
2252
2579
  runAgentEndSideEffects(sideEffectParams);
2253
2580
  }
2254
2581
  //#endregion
2582
+ //#region extensions/codex/src/app-server/session-permission-policy.ts
2583
+ function tupleForMode(mode, canUseAutoReview) {
2584
+ switch (mode) {
2585
+ case "read-only": return {
2586
+ sandbox: "read-only",
2587
+ approvalPolicy: "on-request",
2588
+ approvalsReviewer: "user"
2589
+ };
2590
+ case "guarded": return {
2591
+ sandbox: "workspace-write",
2592
+ approvalPolicy: "on-request",
2593
+ approvalsReviewer: "user"
2594
+ };
2595
+ case "workspace": return {
2596
+ sandbox: "workspace-write",
2597
+ approvalPolicy: "on-request",
2598
+ approvalsReviewer: canUseAutoReview ? "auto_review" : "user"
2599
+ };
2600
+ case "full": return {
2601
+ sandbox: "danger-full-access",
2602
+ approvalPolicy: "never",
2603
+ approvalsReviewer: "user"
2604
+ };
2605
+ }
2606
+ return mode;
2607
+ }
2608
+ function requirementsAllowTuple(tuple, allowed) {
2609
+ return (allowed.sandboxes === void 0 || allowed.sandboxes.has(tuple.sandbox)) && (allowed.approvalPolicies === void 0 || allowed.approvalPolicies.has(tuple.approvalPolicy)) && (allowed.reviewers === void 0 || allowed.reviewers.has(tuple.approvalsReviewer));
2610
+ }
2611
+ function tightenTupleForExecMode(tuple, execMode) {
2612
+ switch (execMode) {
2613
+ case "deny":
2614
+ case "allowlist": return {
2615
+ sandbox: "read-only",
2616
+ approvalPolicy: "on-request",
2617
+ approvalsReviewer: "user"
2618
+ };
2619
+ case "ask": return {
2620
+ ...tuple,
2621
+ approvalPolicy: "on-request",
2622
+ approvalsReviewer: "user"
2623
+ };
2624
+ case "auto":
2625
+ case "full":
2626
+ case void 0: return tuple;
2627
+ }
2628
+ return execMode;
2629
+ }
2630
+ function clampSessionPermissionTuple(params) {
2631
+ if (!params.requirementsToml) return params.requested;
2632
+ const allowed = {
2633
+ sandboxes: parseAllowedSandboxModesFromCodexRequirements(params.requirementsToml, params.hostName ?? hostname()),
2634
+ approvalPolicies: parseAllowedApprovalPoliciesFromCodexRequirements(params.requirementsToml),
2635
+ reviewers: parseAllowedApprovalsReviewersFromCodexRequirements(params.requirementsToml)
2636
+ };
2637
+ if (requirementsAllowTuple(params.requested, allowed)) return params.requested;
2638
+ const userReviewRequired = params.mode === "read-only" || params.mode === "guarded" || params.mode === "workspace" && !params.canUseAutoReview;
2639
+ return {
2640
+ sandbox: selectGuardianSandbox(allowed.sandboxes),
2641
+ approvalPolicy: selectGuardianApprovalPolicy(allowed.approvalPolicies, userReviewRequired ? "ask" : "auto"),
2642
+ approvalsReviewer: userReviewRequired ? selectUserApprovalsReviewer(allowed.reviewers) : selectGuardianApprovalsReviewer(allowed.reviewers, "auto")
2643
+ };
2644
+ }
2645
+ /** Applies one complete session-mode tuple without mixing requirements-clamped fields. */
2646
+ function applyCodexSessionPermissionPolicy(params) {
2647
+ if (!params.permissionMode) return params.appServer;
2648
+ const sessionRoot = params.sessionRoot?.trim();
2649
+ if (!sessionRoot) throw new Error("Codex session permission mode requires a recorded session root");
2650
+ if (params.policyLocked) return {
2651
+ ...params.appServer,
2652
+ sessionRoot
2653
+ };
2654
+ const requested = tightenTupleForExecMode(tupleForMode(params.permissionMode, params.canUseAutoReview), params.execMode);
2655
+ const tuple = params.appServer.start.transport === "stdio" ? clampSessionPermissionTuple({
2656
+ mode: params.permissionMode,
2657
+ requested,
2658
+ requirementsToml: params.requirementsToml,
2659
+ hostName: params.hostName,
2660
+ canUseAutoReview: params.canUseAutoReview
2661
+ }) : requested;
2662
+ const networkProxy = params.appServer.networkProxy ? resolveCodexAppServerNetworkProxy(params.pluginConfig.appServer?.networkProxy, tuple.sandbox).networkProxy : void 0;
2663
+ const resolved = {
2664
+ ...params.appServer,
2665
+ ...tuple,
2666
+ sessionRoot
2667
+ };
2668
+ if (networkProxy) resolved.networkProxy = networkProxy;
2669
+ else delete resolved.networkProxy;
2670
+ return resolved;
2671
+ }
2672
+ /** Keeps relative execution inside the prepared root without filesystem rediscovery. */
2673
+ function resolveCodexSessionPermissionCwd(params) {
2674
+ if (!params.permissionMode) return params.requestedCwd ?? params.fallbackCwd;
2675
+ const sessionRoot = params.sessionRoot?.trim();
2676
+ if (!sessionRoot) throw new Error("Codex session permission mode requires a recorded session root");
2677
+ const requestedCwd = params.requestedCwd?.trim();
2678
+ return requestedCwd && isPathInside(sessionRoot, requestedCwd) ? requestedCwd : sessionRoot;
2679
+ }
2680
+ //#endregion
2255
2681
  //#region extensions/codex/src/app-server/startup-binding.ts
2256
2682
  const CODEX_APP_SERVER_NATIVE_THREAD_FALLBACK_MAX_TOKENS = 3e5;
2257
2683
  const CODEX_APP_SERVER_NATIVE_THREAD_DEFAULT_RESERVE_TOKENS = 2e4;
@@ -2295,10 +2721,7 @@ async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codex
2295
2721
  path.join(resolvedAgentDir, "agent", "codex-home", "sessions"),
2296
2722
  path.join(path.dirname(resolvedAgentDir), "codex-home", "sessions")
2297
2723
  ];
2298
- const rolloutRoot = rolloutPath ? roots.find((root) => {
2299
- const relativePath = path.relative(root, rolloutPath);
2300
- return relativePath !== "" && relativePath !== ".." && !relativePath.startsWith(`..${path.sep}`) && !path.isAbsolute(relativePath);
2301
- }) : void 0;
2724
+ const rolloutRoot = rolloutPath ? roots.find((root) => isPathStrictlyInside(root, rolloutPath)) : void 0;
2302
2725
  if (rolloutPath && rolloutRoot && path.isAbsolute(rolloutPath) && path.extname(rolloutPath) === ".jsonl" && path.basename(rolloutPath).includes(threadId)) try {
2303
2726
  const opened = await (await root(rolloutRoot, {
2304
2727
  hardlinks: "reject",
@@ -2555,14 +2978,6 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
2555
2978
  }
2556
2979
  //#endregion
2557
2980
  //#region extensions/codex/src/app-server/run-attempt-connection.ts
2558
- function applyStoredBindingPermissions(params) {
2559
- if (params.execPolicyTouched || params.binding?.connectionScope === "supervision") return params.appServer;
2560
- return {
2561
- ...params.appServer,
2562
- approvalPolicy: params.binding?.approvalPolicy ?? params.appServer.approvalPolicy,
2563
- sandbox: params.binding?.sandbox ?? params.appServer.sandbox
2564
- };
2565
- }
2566
2981
  async function prepareCodexAttemptConnection({ params, options }) {
2567
2982
  const attemptStartedAt = Date.now();
2568
2983
  const profilerEnabled = isCodexAppServerProfilerEnabled(params.config);
@@ -2575,16 +2990,15 @@ async function prepareCodexAttemptConnection({ params, options }) {
2575
2990
  resetAnnounced: false
2576
2991
  };
2577
2992
  const preDynamicStartupStages = createCodexDynamicToolBuildStageTracker({ enabled: profilerEnabled });
2578
- const attemptClientFactory = options.clientFactory ?? getLeasedSharedCodexAppServerClient;
2579
2993
  const runtimeArtifactRequest = params.captureRuntimeArtifact || params.expectedRuntimeArtifact ? params.expectedRuntimeArtifact ? { expected: params.expectedRuntimeArtifact } : {} : void 0;
2580
2994
  const pluginConfig = readCodexPluginConfig(options.pluginConfig);
2995
+ const requirementsToml = readCodexRequirementsToml({});
2581
2996
  const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig });
2582
2997
  const { sessionAgentId } = resolveSessionAgentIds({
2583
2998
  sessionKey: params.sessionKey,
2584
2999
  config: params.config,
2585
3000
  agentId: params.agentId
2586
3001
  });
2587
- const beforeToolCallPolicy = getBeforeToolCallPolicyDiagnosticState();
2588
3002
  preDynamicStartupStages.mark("config");
2589
3003
  const resolvedWorkspace = resolveUserPath(params.workspaceDir);
2590
3004
  await ensureCodexWorkspaceDirOnce(resolvedWorkspace);
@@ -2596,14 +3010,36 @@ async function prepareCodexAttemptConnection({ params, options }) {
2596
3010
  sessionKey: sandboxSessionKey,
2597
3011
  workspaceDir: resolvedWorkspace
2598
3012
  });
3013
+ const attemptClientFactory = options.clientFactory ?? (isCodexPairedNodeRemoteExecPlacementSandbox(sandbox) ? createIsolatedCodexAppServerClient : getLeasedSharedCodexAppServerClient);
2599
3014
  preDynamicStartupStages.mark("sandbox");
2600
3015
  const execPolicy = resolveOpenClawExecPolicyForCodexAppServer({
3016
+ permissionMode: params.permissionMode,
2601
3017
  execOverrides: params.execOverrides,
2602
- approvals: loadExecApprovals(),
3018
+ approvals: params.permissionMode === "full" ? void 0 : loadExecApprovals(),
2603
3019
  config: params.config,
2604
3020
  agentId: sessionAgentId
2605
3021
  });
2606
3022
  const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
3023
+ const preparedEnvironment = params.hostCapabilities.preparedEnvironment?.();
3024
+ const remoteExec = isCodexRemoteExecPlacementSandbox(sandbox);
3025
+ const preparedShellEnvironment = preparedEnvironment ? {
3026
+ ...preparedEnvironment.credentialScrubEnv,
3027
+ ...!remoteExec ? preparedEnvironment.localIdentityEnv : void 0
3028
+ } : void 0;
3029
+ const shellEnvironment = preparedShellEnvironment && Object.keys(preparedShellEnvironment).length > 0 ? preparedShellEnvironment : void 0;
3030
+ const disableLoginShell = remoteExec || preparedEnvironment?.managedLocalIdentity === true || preparedEnvironment !== void 0 && Object.keys(preparedEnvironment.credentialScrubEnv).length > 0;
3031
+ const withPreparedProcessEnv = (appServer) => {
3032
+ return shellEnvironment ? {
3033
+ ...appServer,
3034
+ start: {
3035
+ ...appServer.start,
3036
+ env: {
3037
+ ...appServer.start.env,
3038
+ ...shellEnvironment
3039
+ }
3040
+ }
3041
+ } : appServer;
3042
+ };
2607
3043
  let bindingIdentity = sessionBindingIdentity({
2608
3044
  sessionId: params.sessionId,
2609
3045
  sessionKey: params.sessionKey,
@@ -2650,21 +3086,20 @@ async function prepareCodexAttemptConnection({ params, options }) {
2650
3086
  const usesSupervisionConnection = startupBinding?.connectionScope === "supervision";
2651
3087
  if (usesSupervisionConnection) activeContextEngine = void 0;
2652
3088
  if (usesSupervisionConnection && pluginConfig.supervision?.enabled !== true) throw new Error("Codex supervision is disabled; refusing to open a native user-home supervised session");
2653
- const resolveRuntimeOptionsForBinding = (selection) => applyStoredBindingPermissions({
2654
- appServer: resolveCodexBindingAppServerConnection({
2655
- binding: startupBinding,
2656
- pluginConfig,
2657
- execPolicy,
2658
- modelProvider: selection.modelProvider,
2659
- model: selection.model,
2660
- config: params.config,
2661
- agentDir,
2662
- openClawSandboxActive: sandbox?.enabled === true
2663
- }).appServer,
2664
- binding: startupBinding,
2665
- execPolicyTouched: execPolicy.touched
2666
- });
3089
+ const resolveRuntimeOptionsForBinding = (binding, selection) => resolveCodexBindingAppServerConnection({
3090
+ binding,
3091
+ pluginConfig,
3092
+ execPolicy,
3093
+ modelProvider: selection.modelProvider,
3094
+ model: selection.model,
3095
+ config: params.config,
3096
+ agentDir,
3097
+ requirementsToml,
3098
+ openClawSandboxActive: sandbox?.enabled === true,
3099
+ sessionPermissionMode: params.permissionMode
3100
+ }).appServer;
2667
3101
  const initialStartupBindingHadInactiveThreadBootstrap = isInactiveThreadBootstrapBinding(startupBinding);
3102
+ const appServerHomeScope = resolveCodexAppServerHomeScope({ appServer: pluginConfig.appServer });
2668
3103
  const preparedAuthRoute = usesSupervisionConnection ? void 0 : params.runtimePlan?.auth.modelRoute;
2669
3104
  const startupAuthProfileCandidate = usesSupervisionConnection ? void 0 : preparedAuthRoute ? params.runtimePlan?.auth.forwardedAuthProfileId : params.runtimePlan?.auth.forwardedAuthProfileId ?? params.authProfileId ?? startupBinding?.authProfileId;
2670
3105
  const resolvedStartupAuthProfileId = usesSupervisionConnection ? void 0 : preparedAuthRoute ? startupAuthProfileCandidate : params.authProfileStore ? resolveCodexAppServerAuthProfileId({
@@ -2686,13 +3121,13 @@ async function prepareCodexAttemptConnection({ params, options }) {
2686
3121
  authProfileId: resolvedStartupAuthProfileId,
2687
3122
  authProfileStore: params.authProfileStore,
2688
3123
  agentDir,
2689
- homeScope: resolveCodexAppServerHomeScope({ appServer: pluginConfig.appServer }),
3124
+ homeScope: appServerHomeScope,
2690
3125
  requirePreparedAuth: isCodexRemoteExecPlacementSandbox(sandbox),
2691
3126
  config: params.config,
2692
3127
  subscriptionProfileRequiredError: "Prepared Codex subscription route requires a forwarded OpenAI OAuth or token profile.",
2693
3128
  subscriptionProfileUnusableError: "Prepared Codex subscription auth profile is unusable."
2694
3129
  });
2695
- const startupClientAuthProfileId = usesSupervisionConnection || startupPreparedAuth?.kind === "api-key" ? null : startupAuthProfileId;
3130
+ const startupClientAuthProfileId = usesSupervisionConnection || appServerHomeScope === "user" || startupPreparedAuth?.kind === "api-key" ? null : startupAuthProfileId;
2696
3131
  const resolveReviewerPolicyContext = (binding) => {
2697
3132
  const nativeModelOwned = binding?.preserveNativeModel === true;
2698
3133
  return resolveCodexModelBackedReviewerPolicyContext({
@@ -2705,41 +3140,56 @@ async function prepareCodexAttemptConnection({ params, options }) {
2705
3140
  };
2706
3141
  let reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
2707
3142
  preDynamicStartupStages.mark("auth-profile");
2708
- let configuredAppServer = resolveRuntimeOptionsForBinding({
3143
+ let configuredAppServer = resolveRuntimeOptionsForBinding(startupBinding, {
2709
3144
  modelProvider: reviewerPolicyContext.modelProvider,
2710
3145
  model: reviewerPolicyContext.model
2711
3146
  });
2712
3147
  const effectiveWorkspace = sandbox?.enabled ? sandbox.workspaceAccess === "rw" ? resolvedWorkspace : sandbox.workspaceDir : resolvedWorkspace;
2713
3148
  const requestedCwd = params.cwd ? resolveUserPath(params.cwd) : void 0;
2714
3149
  if (sandbox?.enabled && requestedCwd && requestedCwd !== resolvedWorkspace) throw new Error("cwd override is not supported for sandboxed Codex app-server runs; omit cwd or use the agent workspace as cwd");
2715
- const effectiveCwd = sandbox?.enabled ? effectiveWorkspace : requestedCwd ?? effectiveWorkspace;
3150
+ const sessionPermissionCwd = resolveCodexSessionPermissionCwd({
3151
+ permissionMode: params.permissionMode,
3152
+ sessionRoot: params.sessionRoot,
3153
+ requestedCwd,
3154
+ fallbackCwd: effectiveWorkspace
3155
+ });
3156
+ const effectiveCwd = sandbox?.enabled ? effectiveWorkspace : sessionPermissionCwd;
2716
3157
  if (effectiveWorkspace !== resolvedWorkspace) await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
2717
3158
  preDynamicStartupStages.mark("effective-workspace");
2718
- const shouldPromoteApprovalPolicy = beforeToolCallPolicy.hasBeforeToolCallHook || beforeToolCallPolicy.trustedToolPolicies.length > 0;
2719
- const resolvePolicyAppServer = () => resolveCodexAppServerForOpenClawToolPolicy({
2720
- appServer: configuredAppServer,
3159
+ const applySessionPermissionPolicy = (appServer, selection) => applyCodexSessionPermissionPolicy({
3160
+ appServer,
3161
+ permissionMode: params.permissionMode,
3162
+ sessionRoot: params.sessionRoot,
2721
3163
  pluginConfig,
2722
- env: process.env,
2723
- shouldPromote: shouldPromoteApprovalPolicy,
2724
- execPolicy,
2725
- canUseUntrustedApprovalPolicy: shouldPromoteApprovalPolicy && configuredAppServer.approvalPolicy === "never" && (configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted"))
2726
- });
2727
- let policyAppServer = resolvePolicyAppServer();
2728
- let appServer = resolveCodexAppServerForModelProvider({
2729
- appServer: policyAppServer,
2730
- provider: reviewerPolicyContext.modelProvider,
2731
- model: reviewerPolicyContext.model,
2732
- config: params.config,
2733
- env: process.env,
2734
- agentDir
2735
- });
2736
- let approvalPolicyPromotedForOpenClawToolPolicy = configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted";
2737
- if (approvalPolicyPromotedForOpenClawToolPolicy) embeddedAgentLog.info("codex app-server approval policy promoted for OpenClaw tool policy", {
2738
- from: "never",
2739
- to: "untrusted",
2740
- beforeToolCallHook: beforeToolCallPolicy.hasBeforeToolCallHook,
2741
- trustedToolPolicies: beforeToolCallPolicy.trustedToolPolicies
3164
+ canUseAutoReview: canUseCodexModelBackedApprovalsReviewerForModel({
3165
+ modelProvider: selection.modelProvider,
3166
+ model: selection.model,
3167
+ config: params.config,
3168
+ env: process.env,
3169
+ agentDir,
3170
+ homeScope: appServer.start.homeScope
3171
+ }),
3172
+ requirementsToml,
3173
+ policyLocked: startupBinding?.connectionScope === "supervision",
3174
+ execMode: execPolicy.mode
2742
3175
  });
3176
+ const resolveFinalAppServer = (configured, selection) => {
3177
+ const session = applySessionPermissionPolicy(configured, selection);
3178
+ const trusted = resolveCodexAppServerForModelProvider({
3179
+ appServer: session,
3180
+ provider: selection.modelProvider,
3181
+ model: selection.model,
3182
+ config: params.config,
3183
+ env: process.env,
3184
+ agentDir
3185
+ });
3186
+ return {
3187
+ session,
3188
+ appServer: withPreparedProcessEnv(trusted)
3189
+ };
3190
+ };
3191
+ let resolvedAppServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
3192
+ let appServer = resolvedAppServer.appServer;
2743
3193
  preDynamicStartupStages.mark("app-server-policy");
2744
3194
  preDynamicStartupStages.mark("native-hook-relay");
2745
3195
  const terminalState = {
@@ -2787,20 +3237,12 @@ async function prepareCodexAttemptConnection({ params, options }) {
2787
3237
  preDynamicStartupStages.mark("rotate-binding");
2788
3238
  if (startupBinding !== startupBindingBeforeRotation) {
2789
3239
  reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
2790
- configuredAppServer = resolveRuntimeOptionsForBinding({
3240
+ configuredAppServer = resolveRuntimeOptionsForBinding(startupBinding, {
2791
3241
  modelProvider: reviewerPolicyContext.modelProvider,
2792
3242
  model: reviewerPolicyContext.model
2793
3243
  });
2794
- policyAppServer = resolvePolicyAppServer();
2795
- appServer = resolveCodexAppServerForModelProvider({
2796
- appServer: policyAppServer,
2797
- provider: reviewerPolicyContext.modelProvider,
2798
- model: reviewerPolicyContext.model,
2799
- config: params.config,
2800
- env: process.env,
2801
- agentDir
2802
- });
2803
- approvalPolicyPromotedForOpenClawToolPolicy = configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted";
3244
+ resolvedAppServer = resolveFinalAppServer(configuredAppServer, reviewerPolicyContext);
3245
+ appServer = resolvedAppServer.appServer;
2804
3246
  }
2805
3247
  const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
2806
3248
  configuredEvents: options.nativeHookRelay?.events,
@@ -2809,22 +3251,10 @@ async function prepareCodexAttemptConnection({ params, options }) {
2809
3251
  const mutable = {
2810
3252
  startupBinding,
2811
3253
  startupContextTokens: startupBindingResolution.startupContextTokens,
2812
- pluginAppServer: appServer
3254
+ pluginAppServer: appServer,
3255
+ continuityCalibration: startupBindingBeforeRotation?.continuityCalibration
2813
3256
  };
2814
- const resolveRuntimeOptionsForCurrentBinding = (selection) => applyStoredBindingPermissions({
2815
- appServer: resolveCodexBindingAppServerConnection({
2816
- binding: mutable.startupBinding,
2817
- pluginConfig,
2818
- execPolicy,
2819
- modelProvider: selection.modelProvider,
2820
- model: selection.model,
2821
- config: params.config,
2822
- agentDir,
2823
- openClawSandboxActive: sandbox?.enabled === true
2824
- }).appServer,
2825
- binding: mutable.startupBinding,
2826
- execPolicyTouched: execPolicy.touched
2827
- });
3257
+ const resolveRuntimeOptionsForCurrentBinding = (selection) => resolveFinalAppServer(resolveRuntimeOptionsForBinding(mutable.startupBinding, selection), selection).appServer;
2828
3258
  return {
2829
3259
  params,
2830
3260
  options,
@@ -2846,6 +3276,8 @@ async function prepareCodexAttemptConnection({ params, options }) {
2846
3276
  contextSessionKey,
2847
3277
  sandbox,
2848
3278
  agentDir,
3279
+ shellEnvironment,
3280
+ disableLoginShell,
2849
3281
  bindingIdentity,
2850
3282
  bindingStore,
2851
3283
  activeContextEngine,
@@ -2858,7 +3290,6 @@ async function prepareCodexAttemptConnection({ params, options }) {
2858
3290
  effectiveWorkspace,
2859
3291
  effectiveCwd,
2860
3292
  appServer,
2861
- approvalPolicyPromotedForOpenClawToolPolicy,
2862
3293
  nativeHookRelayEvents,
2863
3294
  runAbortController,
2864
3295
  terminalState,
@@ -2951,10 +3382,12 @@ function resolveContextEngineBootstrapProjectionDecision(params) {
2951
3382
  */
2952
3383
  async function buildCodexWorkspaceBootstrapContext(params) {
2953
3384
  try {
3385
+ const inheritsAgentWorkspace = (params.executionWorkspace ?? params.resolvedWorkspace) !== params.resolvedWorkspace;
3386
+ const promptWorkspace = inheritsAgentWorkspace ? params.resolvedWorkspace : params.effectiveWorkspace;
2954
3387
  const memoryToolsAvailable = params.memoryToolNames.length > 0 && canRouteCodexWorkspaceMemoryThroughTools({
2955
3388
  config: params.params.config,
2956
3389
  agentId: params.params.agentId ?? params.sessionAgentId,
2957
- workspaceDir: params.effectiveWorkspace
3390
+ workspaceDir: inheritsAgentWorkspace ? params.resolvedWorkspace : params.effectiveWorkspace
2958
3391
  });
2959
3392
  const bootstrapFiles = await resolveBootstrapFilesForRun({
2960
3393
  workspaceDir: params.resolvedWorkspace,
@@ -2974,7 +3407,7 @@ async function buildCodexWorkspaceBootstrapContext(params) {
2974
3407
  const memoryReferenceFiles = memoryToolRoutedBootstrapFiles.map((file) => remapCodexContextFilePath({
2975
3408
  file: toCodexEmbeddedContextFile(file),
2976
3409
  sourceWorkspaceDir: params.resolvedWorkspace,
2977
- targetWorkspaceDir: params.effectiveWorkspace
3410
+ targetWorkspaceDir: promptWorkspace
2978
3411
  }));
2979
3412
  const contextFiles = buildBootstrapContextForFiles(memoryToolsAvailable ? bootstrapFiles.filter((file) => !isCodexWorkspaceRootMemoryBootstrapFile({
2980
3413
  file,
@@ -2986,23 +3419,33 @@ async function buildCodexWorkspaceBootstrapContext(params) {
2986
3419
  }).map((file) => remapCodexContextFilePath({
2987
3420
  file,
2988
3421
  sourceWorkspaceDir: params.resolvedWorkspace,
2989
- targetWorkspaceDir: params.effectiveWorkspace
3422
+ targetWorkspaceDir: promptWorkspace
2990
3423
  }));
2991
3424
  const promptContextFiles = selectCodexWorkspacePromptContextFiles(contextFiles, {
2992
3425
  excludeMemory: memoryToolsAvailable,
2993
3426
  memoryWorkspaceDir: params.effectiveWorkspace
2994
3427
  });
2995
- const turnScopedDeveloperInstructionFiles = shouldInjectCodexOpenClawPromptContext(params.params) ? selectCodexWorkspaceTurnScopedDeveloperInstructionFiles(contextFiles) : [];
3428
+ const injectOpenClawContext = shouldInjectCodexOpenClawPromptContext(params.params);
3429
+ const restrictedProjectDocNeedsOpenClawCarrier = params.params.pluginHarnessToolPolicyRestricted === true && !params.params.disableTools && !isMessageOnlyCodexSourceReply(params.params) && params.params.bootstrapContextMode !== "lightweight";
3430
+ const threadDeveloperInstructionFiles = injectOpenClawContext && !params.ringZeroActive && (inheritsAgentWorkspace || restrictedProjectDocNeedsOpenClawCarrier) ? selectCodexWorkspaceAgentProjectInstructionFiles(contextFiles, params.resolvedWorkspace) : [];
3431
+ const turnScopedDeveloperInstructionFiles = injectOpenClawContext ? selectCodexWorkspaceTurnScopedDeveloperInstructionFiles(contextFiles) : [];
2996
3432
  return {
2997
3433
  bootstrapFiles,
2998
3434
  contextFiles,
3435
+ inheritsAgentWorkspace,
2999
3436
  promptContextFiles,
3437
+ threadDeveloperInstructionFiles,
3000
3438
  turnScopedDeveloperInstructionFiles,
3001
3439
  memoryReferenceFiles,
3002
3440
  memoryToolRoutedBootstrapFiles,
3003
3441
  memoryToolNames: [...params.memoryToolNames],
3004
3442
  memoryToolRouted: memoryToolsAvailable,
3005
3443
  promptContext: renderCodexWorkspaceBootstrapPromptContext(promptContextFiles),
3444
+ threadDeveloperInstructions: renderCodexWorkspaceDeveloperInstructions({
3445
+ files: threadDeveloperInstructionFiles,
3446
+ header: "## OpenClaw Agent Workspace Instructions",
3447
+ preamble: "OpenClaw loaded this bounded snapshot from the configured agent workspace."
3448
+ }),
3006
3449
  turnScopedDeveloperInstructions: renderCodexWorkspaceCollaborationDeveloperInstructions(turnScopedDeveloperInstructionFiles),
3007
3450
  memoryCollaborationInstructions: shouldInjectCodexOpenClawPromptContext(params.params) ? await renderCodexWorkspaceMemoryCollaborationInstructions({
3008
3451
  files: memoryReferenceFiles,
@@ -3018,7 +3461,8 @@ async function buildCodexWorkspaceBootstrapContext(params) {
3018
3461
  embeddedAgentLog.warn("failed to load codex workspace bootstrap instructions", { error });
3019
3462
  return {
3020
3463
  bootstrapFiles: [],
3021
- contextFiles: []
3464
+ contextFiles: [],
3465
+ inheritsAgentWorkspace: false
3022
3466
  };
3023
3467
  }
3024
3468
  }
@@ -3051,7 +3495,7 @@ function buildCodexSystemPromptReport(params) {
3051
3495
  injectedWorkspaceFiles: buildCodexBootstrapInjectionStats({
3052
3496
  bootstrapFiles: params.workspaceBootstrapContext.bootstrapFiles,
3053
3497
  injectedFiles: params.workspaceBootstrapContext.promptContextFiles ?? [],
3054
- developerInstructionFiles: params.workspaceBootstrapContext.turnScopedDeveloperInstructionFiles ?? [],
3498
+ developerInstructionFiles: [...params.workspaceBootstrapContext.threadDeveloperInstructionFiles ?? [], ...params.workspaceBootstrapContext.turnScopedDeveloperInstructionFiles ?? []],
3055
3499
  memoryToolRoutedBootstrapFiles: params.workspaceBootstrapContext.memoryToolRoutedBootstrapFiles ?? [],
3056
3500
  memoryToolRouted: params.workspaceBootstrapContext.memoryToolRouted === true
3057
3501
  }),
@@ -3132,12 +3576,17 @@ function buildCodexBootstrapInjectionStats(params) {
3132
3576
  const rawChars = file.missing ? 0 : (file.content ?? "").trimEnd().length;
3133
3577
  const memoryToolRoutedFile = baseName === CODEX_MEMORY_CONTEXT_BASENAME && params.memoryToolRouted === true && memoryToolRoutedPaths.has(normalizeCodexContextFilePath(pathValue));
3134
3578
  const injected = memoryToolRoutedFile ? void 0 : readCodexIndexedContextFileContent(injectedIndex, pathValue, fileName) ?? readCodexIndexedContextFileContent(developerInstructionIndex, pathValue, fileName);
3135
- let injectedChars = memoryToolRoutedFile ? 0 : injected?.length ?? 0;
3136
- let truncated = memoryToolRoutedFile ? false : !file.missing && injectedChars < rawChars;
3137
- if (injected === void 0 && CODEX_NATIVE_PROJECT_DOC_BASENAMES.has(baseName)) {
3138
- injectedChars = rawChars;
3139
- truncated = false;
3140
- }
3579
+ if (!file.missing && injected === void 0 && CODEX_NATIVE_PROJECT_DOC_BASENAMES.has(baseName)) return {
3580
+ name: displayName,
3581
+ path: pathValue,
3582
+ missing: false,
3583
+ rawChars,
3584
+ injectionStatus: "native_unverified",
3585
+ injectedChars: null,
3586
+ truncated: null
3587
+ };
3588
+ const injectedChars = memoryToolRoutedFile ? 0 : injected?.length ?? 0;
3589
+ const truncated = memoryToolRoutedFile ? false : !file.missing && injectedChars < rawChars;
3141
3590
  return {
3142
3591
  name: displayName,
3143
3592
  path: pathValue,
@@ -3272,7 +3721,7 @@ function renderCodexWorkspaceBootstrapPromptContext(contextFiles) {
3272
3721
  const files = contextFiles;
3273
3722
  if (files.length === 0) return;
3274
3723
  const lines = [
3275
- "OpenClaw loaded these user-editable workspace files for the current turn. Codex loads AGENTS.md natively. SOUL.md, IDENTITY.md, and USER.md are provided as turn-scoped collaboration instructions so native Codex subagents do not inherit them. Those files are not repeated here.",
3724
+ "OpenClaw loaded these user-editable workspace files for the current turn. Codex loads project-local AGENTS.md natively. When execution uses another folder, OpenClaw supplies the agent workspace AGENTS.md as thread-level developer instructions. SOUL.md, IDENTITY.md, and USER.md remain turn-scoped collaboration instructions. Those files are not repeated here.",
3276
3725
  "",
3277
3726
  "# Project Context",
3278
3727
  "",
@@ -3295,6 +3744,10 @@ function selectCodexWorkspacePromptContextFiles(contextFiles, options = {}) {
3295
3744
  function selectCodexWorkspaceTurnScopedDeveloperInstructionFiles(contextFiles) {
3296
3745
  return selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, CODEX_TURN_SCOPED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES);
3297
3746
  }
3747
+ function selectCodexWorkspaceAgentProjectInstructionFiles(contextFiles, agentWorkspaceDir) {
3748
+ const agentProjectDocPath = path.join(path.resolve(agentWorkspaceDir), "AGENTS.md");
3749
+ return selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, CODEX_NATIVE_PROJECT_DOC_BASENAMES).filter((file) => path.resolve(file.path) === agentProjectDocPath);
3750
+ }
3298
3751
  function selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, basenames) {
3299
3752
  return contextFiles.filter((file) => {
3300
3753
  const baseName = getCodexContextFileBasename(file.path);
@@ -3428,34 +3881,131 @@ function remapCodexContextFilePath(params) {
3428
3881
  path: targetUsesPosixSeparators ? path.posix.join(params.targetWorkspaceDir, normalizedRelativePath) : path.win32.join(params.targetWorkspaceDir, normalizedRelativePath)
3429
3882
  };
3430
3883
  }
3431
- function compareCodexContextFiles(left, right) {
3432
- const leftPath = normalizeCodexContextFilePath(left.path);
3433
- const rightPath = normalizeCodexContextFilePath(right.path);
3434
- const leftBase = getCodexContextFileBasename(left.path);
3435
- const rightBase = getCodexContextFileBasename(right.path);
3436
- const leftOrder = CODEX_BOOTSTRAP_CONTEXT_ORDER.get(leftBase) ?? Number.MAX_SAFE_INTEGER;
3437
- const rightOrder = CODEX_BOOTSTRAP_CONTEXT_ORDER.get(rightBase) ?? Number.MAX_SAFE_INTEGER;
3438
- if (leftOrder !== rightOrder) return leftOrder - rightOrder;
3439
- if (leftBase !== rightBase) return leftBase.localeCompare(rightBase);
3440
- return leftPath.localeCompare(rightPath);
3884
+ function compareCodexContextFiles(left, right) {
3885
+ const leftPath = normalizeCodexContextFilePath(left.path);
3886
+ const rightPath = normalizeCodexContextFilePath(right.path);
3887
+ const leftBase = getCodexContextFileBasename(left.path);
3888
+ const rightBase = getCodexContextFileBasename(right.path);
3889
+ const leftOrder = CODEX_BOOTSTRAP_CONTEXT_ORDER.get(leftBase) ?? Number.MAX_SAFE_INTEGER;
3890
+ const rightOrder = CODEX_BOOTSTRAP_CONTEXT_ORDER.get(rightBase) ?? Number.MAX_SAFE_INTEGER;
3891
+ if (leftOrder !== rightOrder) return leftOrder - rightOrder;
3892
+ if (leftBase !== rightBase) return leftBase.localeCompare(rightBase);
3893
+ return leftPath.localeCompare(rightPath);
3894
+ }
3895
+ function compareCodexBootstrapFiles(left, right) {
3896
+ return compareCodexContextFiles(toCodexEmbeddedContextFile(left), toCodexEmbeddedContextFile(right));
3897
+ }
3898
+ function normalizeCodexContextFilePath(filePath) {
3899
+ return filePath.trim().replaceAll("\\", "/").toLowerCase();
3900
+ }
3901
+ function getCodexContextFileDisplayBasename(filePath) {
3902
+ return filePath.trim().replaceAll("\\", "/").split("/").pop()?.trim() ?? "";
3903
+ }
3904
+ function getCodexContextFileBasename(filePath) {
3905
+ return normalizeCodexContextFilePath(filePath).split("/").pop() ?? "";
3906
+ }
3907
+ function normalizeCodexDynamicToolName(name) {
3908
+ return name.trim().toLowerCase();
3909
+ }
3910
+ function isNonEmptyString$1(value) {
3911
+ return typeof value === "string" && value.length > 0;
3912
+ }
3913
+ //#endregion
3914
+ //#region extensions/codex/src/app-server/run-attempt-state.ts
3915
+ async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields) {
3916
+ const currentBinding = await bindingStore.read(identity);
3917
+ const expectedThreadId = fields.threadId ?? currentBinding?.threadId;
3918
+ if (!expectedThreadId) return;
3919
+ if (currentBinding && currentBinding.threadId !== expectedThreadId) {
3920
+ embeddedAgentLog.warn("codex app-server image payload error detected for unbound thread; preserving thread binding", {
3921
+ ...fields,
3922
+ boundThreadId: currentBinding.threadId
3923
+ });
3924
+ return;
3925
+ }
3926
+ if (currentBinding?.connectionScope === "supervision") {
3927
+ embeddedAgentLog.warn("codex app-server image payload error detected for supervised thread; preserving native binding", fields);
3928
+ return;
3929
+ }
3930
+ embeddedAgentLog.warn("codex app-server image payload error detected; clearing thread binding", fields);
3931
+ await bindingStore.mutate(identity, {
3932
+ kind: "clear",
3933
+ threadId: expectedThreadId
3934
+ });
3935
+ }
3936
+ async function markCodexAppServerBindingCoveredThroughTurn(params) {
3937
+ await params.bindingStore.mutate(params.identity, {
3938
+ kind: "patch",
3939
+ threadId: params.threadId,
3940
+ patch: {
3941
+ historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString(),
3942
+ ...params.continuityCalibration ? { continuityCalibration: params.continuityCalibration } : {}
3943
+ }
3944
+ });
3945
+ }
3946
+ function isNonEmptyString(value) {
3947
+ return typeof value === "string" && value.length > 0;
3441
3948
  }
3442
- function compareCodexBootstrapFiles(left, right) {
3443
- return compareCodexContextFiles(toCodexEmbeddedContextFile(left), toCodexEmbeddedContextFile(right));
3949
+ function shouldUseFreshCodexThreadAfterContextEngineOverflow(params) {
3950
+ if (!params.contextEngineActive || params.thread.lifecycle.action !== "resumed") return false;
3951
+ const message = formatErrorMessage(params.error);
3952
+ return /ran out of room in the model'?s context window/iu.test(message) || /context window/iu.test(message) || /context length/iu.test(message) || /maximum context/iu.test(message) || /too many tokens/iu.test(message);
3444
3953
  }
3445
- function normalizeCodexContextFilePath(filePath) {
3446
- return filePath.trim().replaceAll("\\", "/").toLowerCase();
3954
+ function isCodexActiveCompactTurnError(error) {
3955
+ if (!(error instanceof CodexAppServerRpcError)) return false;
3956
+ const data = isJsonObject(error.data) ? error.data : void 0;
3957
+ const codexErrorInfo = isJsonObject(data?.codexErrorInfo) ? data.codexErrorInfo : void 0;
3958
+ return (isJsonObject(codexErrorInfo?.activeTurnNotSteerable) ? codexErrorInfo.activeTurnNotSteerable : void 0)?.turnKind === "compact";
3447
3959
  }
3448
- function getCodexContextFileDisplayBasename(filePath) {
3449
- return filePath.trim().replaceAll("\\", "/").split("/").pop()?.trim() ?? "";
3960
+ function readCodexFinalizationHookNotification(notification, threadId, turnId) {
3961
+ if (notification.method !== "hook/started" && notification.method !== "hook/completed") return;
3962
+ const params = isJsonObject(notification.params) ? notification.params : void 0;
3963
+ const run = params && isJsonObject(params.run) ? params.run : void 0;
3964
+ if (params?.threadId !== threadId || params.turnId !== turnId || run?.eventName !== "stop" && run?.eventName !== "subagentStop" || typeof run.id !== "string" || !run.id) return;
3965
+ if (notification.method === "hook/started") return {
3966
+ phase: "started",
3967
+ runId: run.id
3968
+ };
3969
+ return {
3970
+ phase: "completed",
3971
+ runId: run.id,
3972
+ status: typeof run.status === "string" ? run.status : void 0
3973
+ };
3450
3974
  }
3451
- function getCodexContextFileBasename(filePath) {
3452
- return normalizeCodexContextFilePath(filePath).split("/").pop() ?? "";
3975
+ function joinPresentSections(...sections) {
3976
+ return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
3453
3977
  }
3454
- function normalizeCodexDynamicToolName(name) {
3455
- return name.trim().toLowerCase();
3978
+ function prependCurrentInboundContext(prompt, context) {
3979
+ const text = context?.text.trim();
3980
+ return text ? [neutralizeCodexExplicitMentionSigils(text), prompt].filter(Boolean).join("\n\n") : prompt;
3456
3981
  }
3457
- function isNonEmptyString$1(value) {
3458
- return typeof value === "string" && value.length > 0;
3982
+ function buildCodexAppServerTimeoutDiagnostics(params) {
3983
+ const readNonBlankDetailString = (key) => {
3984
+ const value = params.details?.[key];
3985
+ return hasNonEmptyString(value) ? value : void 0;
3986
+ };
3987
+ const activeAppServerTurnRequests = asFiniteNumber(params.details?.activeAppServerTurnRequests);
3988
+ const activeTurnItemCount = asFiniteNumber(params.details?.activeTurnItemCount);
3989
+ const terminalTurnNotificationQueued = asBoolean(params.details?.terminalTurnNotificationQueued);
3990
+ const completionIdleWatchArmed = asBoolean(params.details?.completionIdleWatchArmed);
3991
+ const assistantCompletionIdleWatchArmed = asBoolean(params.details?.assistantCompletionIdleWatchArmed);
3992
+ const terminalIdleWatchArmed = asBoolean(params.details?.terminalIdleWatchArmed);
3993
+ return {
3994
+ ...params.idleMs !== void 0 ? { idleMs: params.idleMs } : {},
3995
+ ...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
3996
+ ...params.lastActivityReason ? { lastActivityReason: params.lastActivityReason } : {},
3997
+ ...readNonBlankDetailString("lastNotificationMethod") ? { lastNotificationMethod: readNonBlankDetailString("lastNotificationMethod") } : {},
3998
+ ...readNonBlankDetailString("lastNotificationItemId") ? { lastNotificationItemId: readNonBlankDetailString("lastNotificationItemId") } : {},
3999
+ ...readNonBlankDetailString("lastNotificationItemType") ? { lastNotificationItemType: readNonBlankDetailString("lastNotificationItemType") } : {},
4000
+ ...readNonBlankDetailString("lastNotificationItemRole") ? { lastNotificationItemRole: readNonBlankDetailString("lastNotificationItemRole") } : {},
4001
+ ...readNonBlankDetailString("lastAssistantTextPreview") ? { lastAssistantTextPreview: readNonBlankDetailString("lastAssistantTextPreview") } : {},
4002
+ ...activeAppServerTurnRequests !== void 0 ? { activeAppServerTurnRequests } : {},
4003
+ ...activeTurnItemCount !== void 0 ? { activeTurnItemCount } : {},
4004
+ ...terminalTurnNotificationQueued !== void 0 ? { terminalTurnNotificationQueued } : {},
4005
+ ...completionIdleWatchArmed !== void 0 ? { completionIdleWatchArmed } : {},
4006
+ ...assistantCompletionIdleWatchArmed !== void 0 ? { assistantCompletionIdleWatchArmed } : {},
4007
+ ...terminalIdleWatchArmed !== void 0 ? { terminalIdleWatchArmed } : {}
4008
+ };
3459
4009
  }
3460
4010
  //#endregion
3461
4011
  //#region extensions/codex/src/app-server/run-attempt-context.ts
@@ -3527,16 +4077,20 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
3527
4077
  });
3528
4078
  historyState.messages = await readFencedHistory() ?? historyState.messages;
3529
4079
  }
4080
+ const memoryToolNames = getCodexWorkspaceMemoryToolNames(toolBridge.availableSpecs);
3530
4081
  const workspaceBootstrapContext = await buildCodexWorkspaceBootstrapContext({
3531
4082
  params: runtimeParams,
3532
- resolvedWorkspace,
4083
+ resolvedWorkspace: runtimeParams.bootstrapWorkspaceDir ?? resolvedWorkspace,
4084
+ executionWorkspace: resolvedWorkspace,
3533
4085
  effectiveWorkspace,
3534
4086
  sessionKey: contextSessionKey,
3535
4087
  sessionAgentId,
3536
- memoryToolNames: getCodexWorkspaceMemoryToolNames(toolBridge.availableSpecs),
4088
+ memoryToolNames,
4089
+ ringZeroActive: isHostScopedAgentToolActive("openclaw") && isSystemAgentOnlyCodexDynamicToolAllowlist(runtimeParams.toolsAllow),
3537
4090
  sandboxed: sandbox?.enabled === true
3538
4091
  });
3539
- const baseDeveloperInstructions = buildDeveloperInstructions(runtimeParams, { dynamicTools: toolBridge.availableSpecs });
4092
+ const agentWorkspaceDeveloperInstructions = workspaceBootstrapContext.threadDeveloperInstructions ? connection.mutable.startupBinding?.agentWorkspaceDeveloperInstructions ?? workspaceBootstrapContext.threadDeveloperInstructions : void 0;
4093
+ const baseDeveloperInstructions = joinPresentSections(buildDeveloperInstructions(runtimeParams, { dynamicTools: toolBridge.availableSpecs }), agentWorkspaceDeveloperInstructions);
3540
4094
  return {
3541
4095
  runtime,
3542
4096
  attemptTools,
@@ -3547,6 +4101,7 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
3547
4101
  hookRunner,
3548
4102
  buildActiveContextEngineRuntimeContext,
3549
4103
  workspaceBootstrapContext,
4104
+ agentWorkspaceDeveloperInstructions,
3550
4105
  baseDeveloperInstructions,
3551
4106
  openClawPromptContext: buildCodexOpenClawPromptContext({
3552
4107
  params: runtimeParams,
@@ -3570,11 +4125,16 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
3570
4125
  contextEngineProjection: void 0,
3571
4126
  precomputedStaleBindingContinuityProjectionApplied: false,
3572
4127
  staleBindingContinuityForcedFreshStart: false,
4128
+ noEngineContinuityProjectionApplied: false,
3573
4129
  inactiveThreadBootstrapBindingForcedFreshStart: initialInactiveThreadBootstrapBindingForcedFreshStart
3574
4130
  },
3575
4131
  codexContextProjectionMaxChars: resolveCodexContextEngineProjectionMaxChars({
3576
4132
  contextTokenBudget: effectiveContextTokenBudget,
3577
4133
  reserveTokens: resolveCodexContextEngineProjectionReserveTokens()
4134
+ }),
4135
+ codexContinuityProjectionMaxChars: resolveCodexContinuityProjectionMaxChars({
4136
+ contextTokenBudget: effectiveContextTokenBudget,
4137
+ calibration: connection.mutable.continuityCalibration
3578
4138
  })
3579
4139
  };
3580
4140
  }
@@ -3785,105 +4345,6 @@ function isInvalidCodexImagePayloadError(message) {
3785
4345
  return /\b(?:invalid|malformed)\b[\s\S]{0,120}\b(?:image|image url|base64)\b/iu.test(normalizedMessage) || /\b(?:image|image url|base64)\b[\s\S]{0,120}\b(?:invalid|malformed)\b/iu.test(normalizedMessage);
3786
4346
  }
3787
4347
  //#endregion
3788
- //#region extensions/codex/src/app-server/run-attempt-state.ts
3789
- async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields) {
3790
- const currentBinding = await bindingStore.read(identity);
3791
- const expectedThreadId = fields.threadId ?? currentBinding?.threadId;
3792
- if (!expectedThreadId) return;
3793
- if (currentBinding && currentBinding.threadId !== expectedThreadId) {
3794
- embeddedAgentLog.warn("codex app-server image payload error detected for unbound thread; preserving thread binding", {
3795
- ...fields,
3796
- boundThreadId: currentBinding.threadId
3797
- });
3798
- return;
3799
- }
3800
- if (currentBinding?.connectionScope === "supervision") {
3801
- embeddedAgentLog.warn("codex app-server image payload error detected for supervised thread; preserving native binding", fields);
3802
- return;
3803
- }
3804
- embeddedAgentLog.warn("codex app-server image payload error detected; clearing thread binding", fields);
3805
- await bindingStore.mutate(identity, {
3806
- kind: "clear",
3807
- threadId: expectedThreadId
3808
- });
3809
- }
3810
- async function markCodexAppServerBindingCoveredThroughTurn(params) {
3811
- await params.bindingStore.mutate(params.identity, {
3812
- kind: "patch",
3813
- threadId: params.threadId,
3814
- patch: { historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString() }
3815
- });
3816
- }
3817
- function isNonEmptyString(value) {
3818
- return typeof value === "string" && value.length > 0;
3819
- }
3820
- function shouldUseFreshCodexThreadAfterContextEngineOverflow(params) {
3821
- if (!params.contextEngineActive || params.thread.lifecycle.action !== "resumed") return false;
3822
- const message = formatErrorMessage(params.error);
3823
- return /ran out of room in the model'?s context window/iu.test(message) || /context window/iu.test(message) || /context length/iu.test(message) || /maximum context/iu.test(message) || /too many tokens/iu.test(message);
3824
- }
3825
- function isCodexActiveCompactTurnError(error) {
3826
- if (!(error instanceof CodexAppServerRpcError)) return false;
3827
- const data = isJsonObject(error.data) ? error.data : void 0;
3828
- const codexErrorInfo = isJsonObject(data?.codexErrorInfo) ? data.codexErrorInfo : void 0;
3829
- return (isJsonObject(codexErrorInfo?.activeTurnNotSteerable) ? codexErrorInfo.activeTurnNotSteerable : void 0)?.turnKind === "compact";
3830
- }
3831
- function readCodexFinalizationHookNotification(notification, threadId, turnId) {
3832
- if (notification.method !== "hook/started" && notification.method !== "hook/completed") return;
3833
- const params = isJsonObject(notification.params) ? notification.params : void 0;
3834
- const run = params && isJsonObject(params.run) ? params.run : void 0;
3835
- if (params?.threadId !== threadId || params.turnId !== turnId || run?.eventName !== "stop" && run?.eventName !== "subagentStop" || typeof run.id !== "string" || !run.id) return;
3836
- if (notification.method === "hook/started") return {
3837
- phase: "started",
3838
- runId: run.id
3839
- };
3840
- return {
3841
- phase: "completed",
3842
- runId: run.id,
3843
- status: typeof run.status === "string" ? run.status : void 0
3844
- };
3845
- }
3846
- function joinPresentSections(...sections) {
3847
- return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
3848
- }
3849
- function prependCurrentInboundContext(prompt, context) {
3850
- const text = context?.text.trim();
3851
- return text ? [neutralizeCodexExplicitMentionSigils(text), prompt].filter(Boolean).join("\n\n") : prompt;
3852
- }
3853
- function waitForCodexNotificationDispatchTurn() {
3854
- return new Promise((resolve) => {
3855
- setImmediate(resolve);
3856
- });
3857
- }
3858
- function buildCodexAppServerTimeoutDiagnostics(params) {
3859
- const readNonBlankDetailString = (key) => {
3860
- const value = params.details?.[key];
3861
- return hasNonEmptyString(value) ? value : void 0;
3862
- };
3863
- const activeAppServerTurnRequests = asFiniteNumber(params.details?.activeAppServerTurnRequests);
3864
- const activeTurnItemCount = asFiniteNumber(params.details?.activeTurnItemCount);
3865
- const terminalTurnNotificationQueued = asBoolean(params.details?.terminalTurnNotificationQueued);
3866
- const completionIdleWatchArmed = asBoolean(params.details?.completionIdleWatchArmed);
3867
- const assistantCompletionIdleWatchArmed = asBoolean(params.details?.assistantCompletionIdleWatchArmed);
3868
- const terminalIdleWatchArmed = asBoolean(params.details?.terminalIdleWatchArmed);
3869
- return {
3870
- ...params.idleMs !== void 0 ? { idleMs: params.idleMs } : {},
3871
- ...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
3872
- ...params.lastActivityReason ? { lastActivityReason: params.lastActivityReason } : {},
3873
- ...readNonBlankDetailString("lastNotificationMethod") ? { lastNotificationMethod: readNonBlankDetailString("lastNotificationMethod") } : {},
3874
- ...readNonBlankDetailString("lastNotificationItemId") ? { lastNotificationItemId: readNonBlankDetailString("lastNotificationItemId") } : {},
3875
- ...readNonBlankDetailString("lastNotificationItemType") ? { lastNotificationItemType: readNonBlankDetailString("lastNotificationItemType") } : {},
3876
- ...readNonBlankDetailString("lastNotificationItemRole") ? { lastNotificationItemRole: readNonBlankDetailString("lastNotificationItemRole") } : {},
3877
- ...readNonBlankDetailString("lastAssistantTextPreview") ? { lastAssistantTextPreview: readNonBlankDetailString("lastAssistantTextPreview") } : {},
3878
- ...activeAppServerTurnRequests !== void 0 ? { activeAppServerTurnRequests } : {},
3879
- ...activeTurnItemCount !== void 0 ? { activeTurnItemCount } : {},
3880
- ...terminalTurnNotificationQueued !== void 0 ? { terminalTurnNotificationQueued } : {},
3881
- ...completionIdleWatchArmed !== void 0 ? { completionIdleWatchArmed } : {},
3882
- ...assistantCompletionIdleWatchArmed !== void 0 ? { assistantCompletionIdleWatchArmed } : {},
3883
- ...terminalIdleWatchArmed !== void 0 ? { terminalIdleWatchArmed } : {}
3884
- };
3885
- }
3886
- //#endregion
3887
4348
  //#region extensions/codex/src/app-server/settled-turn-context.ts
3888
4349
  function collectUniqueMessageIdentities(messages) {
3889
4350
  const identities = /* @__PURE__ */ new Map();
@@ -3973,100 +4434,13 @@ async function captureCodexSettledTurnFinalizationContext(params) {
3973
4434
  }
3974
4435
  //#endregion
3975
4436
  //#region extensions/codex/src/app-server/trajectory.ts
3976
- const SENSITIVE_FIELD_RE = /(?:authorization|cookie|credential|key|password|passwd|secret|token)/iu;
3977
- const PRIVATE_PAYLOAD_FIELD_RE = /(?:image|screenshot|attachment|fileData|dataUri)/iu;
3978
- const AUTHORIZATION_VALUE_RE = /\b(Bearer|Basic)\s+[A-Za-z0-9+/._~=-]{8,}/giu;
3979
- const JWT_VALUE_RE = /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/gu;
3980
- const COOKIE_PAIR_RE = /\b([A-Za-z][A-Za-z0-9_.-]{1,64})=([A-Za-z0-9+/._~%=-]{16,})(?=;|\s|$)/gu;
3981
- const TRAJECTORY_RUNTIME_EVENT_MAX_BYTES = 256 * 1024;
3982
- const TRAJECTORY_RUNTIME_OVERSIZE_PRESERVED_DATA_KEYS = ["usage", "promptCache"];
3983
- function boundedTrajectoryEvent(event) {
3984
- const line = JSON.stringify(event);
3985
- const bytes = Buffer.byteLength(line, "utf8");
3986
- if (bytes <= TRAJECTORY_RUNTIME_EVENT_MAX_BYTES) return event;
3987
- const originalData = event.data && typeof event.data === "object" && !Array.isArray(event.data) ? event.data : {};
3988
- const originalDataKeys = Object.keys(originalData);
3989
- const preservedDataKeys = /* @__PURE__ */ new Set();
3990
- const baseData = {
3991
- truncated: true,
3992
- originalBytes: bytes,
3993
- limitBytes: TRAJECTORY_RUNTIME_EVENT_MAX_BYTES,
3994
- reason: "trajectory-event-size-limit"
3995
- };
3996
- const buildTruncatedEvent = (includeDroppedFields) => {
3997
- const data = { ...baseData };
3998
- for (const key of TRAJECTORY_RUNTIME_OVERSIZE_PRESERVED_DATA_KEYS) if (preservedDataKeys.has(key)) data[key] = originalData[key];
3999
- if (includeDroppedFields) {
4000
- const droppedFields = originalDataKeys.filter((key) => !preservedDataKeys.has(key));
4001
- if (droppedFields.length > 0) data.droppedFields = droppedFields;
4002
- }
4003
- const truncatedEvent = {
4004
- ...event,
4005
- data
4006
- };
4007
- const truncated = JSON.stringify(truncatedEvent);
4008
- if (Buffer.byteLength(truncated, "utf8") <= TRAJECTORY_RUNTIME_EVENT_MAX_BYTES) return truncatedEvent;
4009
- };
4010
- let best = buildTruncatedEvent(true) ?? buildTruncatedEvent(false);
4011
- if (!best) return;
4012
- for (const key of TRAJECTORY_RUNTIME_OVERSIZE_PRESERVED_DATA_KEYS) {
4013
- if (!Object.hasOwn(originalData, key)) continue;
4014
- preservedDataKeys.add(key);
4015
- const next = buildTruncatedEvent(true) ?? buildTruncatedEvent(false);
4016
- if (next) {
4017
- best = next;
4018
- continue;
4019
- }
4020
- preservedDataKeys.delete(key);
4021
- }
4022
- return best;
4023
- }
4024
- function createCodexHostTrajectorySink(params) {
4025
- return {
4026
- write: (event) => {
4027
- params.recorder.recordEvent(event.type, event.data);
4028
- },
4029
- flush: async () => {
4030
- await params.recorder.flush();
4031
- }
4032
- };
4033
- }
4034
- /** Creates a trajectory recorder when trajectory capture is enabled for the environment. */
4437
+ /** Creates a trajectory recorder when the host exposes its capture capability. */
4035
4438
  function createCodexTrajectoryRecorder(params) {
4036
- if (!parseTrajectoryEnabled(params.env ?? process.env)) return null;
4037
- if (!params.trajectoryRecorder) {
4038
- params.warn?.("codex trajectory capture requires the SQLite host recorder", {
4039
- sessionId: params.attempt.sessionId,
4040
- reason: "sqlite-recorder-unavailable"
4041
- });
4042
- return null;
4043
- }
4044
- const sink = createCodexHostTrajectorySink({ recorder: params.trajectoryRecorder });
4045
- let seq = 0;
4046
- const attribution = resolveCodexLocalRuntimeAttribution(params.attempt);
4439
+ if (!params.trajectory) return null;
4440
+ const trajectory = params.trajectory;
4047
4441
  return {
4048
- recordEvent: (type, data) => {
4049
- const event = boundedTrajectoryEvent({
4050
- traceSchema: "openclaw-trajectory",
4051
- schemaVersion: 1,
4052
- traceId: params.attempt.sessionId,
4053
- source: "runtime",
4054
- type,
4055
- ts: (/* @__PURE__ */ new Date()).toISOString(),
4056
- seq: seq += 1,
4057
- sourceSeq: seq,
4058
- sessionId: params.attempt.sessionId,
4059
- sessionKey: params.attempt.sessionKey,
4060
- runId: params.attempt.runId,
4061
- workspaceDir: params.cwd,
4062
- provider: attribution.provider,
4063
- modelId: params.attempt.modelId,
4064
- modelApi: attribution.api,
4065
- data: data ? sanitizeValue(data) : void 0
4066
- });
4067
- if (event) sink.write(event);
4068
- },
4069
- flush: sink.flush
4442
+ recordEvent: trajectory.recordEvent,
4443
+ flush: trajectory.flush
4070
4444
  };
4071
4445
  }
4072
4446
  /** Records compiled prompt/tool context at the start of a Codex runtime attempt. */
@@ -4095,12 +4469,6 @@ function recordCodexTrajectoryCompletion(recorder, params) {
4095
4469
  messagesSnapshot: params.result.messagesSnapshot
4096
4470
  });
4097
4471
  }
4098
- function parseTrajectoryEnabled(env) {
4099
- const value = env.OPENCLAW_TRAJECTORY?.trim().toLowerCase();
4100
- if (value === "1" || value === "true" || value === "yes" || value === "on") return true;
4101
- if (value === "0" || value === "false" || value === "no" || value === "off") return false;
4102
- return true;
4103
- }
4104
4472
  function toTrajectoryToolDefinitions(tools) {
4105
4473
  if (!tools || tools.length === 0) return;
4106
4474
  return flattenCodexDynamicToolFunctions(tools).flatMap((tool) => {
@@ -4109,31 +4477,10 @@ function toTrajectoryToolDefinitions(tools) {
4109
4477
  return [{
4110
4478
  name,
4111
4479
  description: tool.description,
4112
- parameters: sanitizeValue(tool.inputSchema)
4480
+ parameters: tool.inputSchema
4113
4481
  }];
4114
4482
  }).toSorted((left, right) => left.name.localeCompare(right.name));
4115
4483
  }
4116
- function sanitizeValue(value, depth = 0, key = "") {
4117
- if (value == null || typeof value === "boolean" || typeof value === "number") return value;
4118
- if (typeof value === "string") {
4119
- if (SENSITIVE_FIELD_RE.test(key)) return "<redacted>";
4120
- if (value.startsWith("data:") && value.length > 256) return `<redacted data-uri ${value.slice(0, value.indexOf(",")).length} chars>`;
4121
- if (PRIVATE_PAYLOAD_FIELD_RE.test(key) && value.length > 256) return "<redacted payload>";
4122
- const redacted = redactSensitiveString(value);
4123
- return redacted.length > 2e4 ? `${truncateUtf16Safe(redacted, 2e4)}…` : redacted;
4124
- }
4125
- if (depth >= 6) return "<truncated>";
4126
- if (Array.isArray(value)) return value.slice(0, 100).map((entry) => sanitizeValue(entry, depth + 1, key));
4127
- if (typeof value === "object") {
4128
- const next = {};
4129
- for (const [keyLocal, child] of Object.entries(value).slice(0, 100)) next[keyLocal] = sanitizeValue(child, depth + 1, keyLocal);
4130
- return next;
4131
- }
4132
- return JSON.stringify(value);
4133
- }
4134
- function redactSensitiveString(value) {
4135
- return value.replace(AUTHORIZATION_VALUE_RE, "$1 <redacted>").replace(JWT_VALUE_RE, "<redacted-jwt>").replace(COOKIE_PAIR_RE, "$1=<redacted>");
4136
- }
4137
4484
  /** Converts arbitrary prompt errors into trajectory-safe text. */
4138
4485
  function normalizeCodexTrajectoryError(value) {
4139
4486
  if (!value) return null;
@@ -4186,9 +4533,9 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4186
4533
  const projectedTerminal = attemptTerminal.project(result.terminal);
4187
4534
  const effectiveTimedOut = state.timedOut && !recoveredTurnWatchTimeout;
4188
4535
  const effectiveTurnCompletionIdleTimedOut = state.turnCompletionIdleTimedOut && !recoveredTurnWatchTimeout;
4189
- const isFinalAborted = () => projectedTerminal.aborted || terminalState.explicitCancellationObserved || runAbortController.signal.aborted && !state.clientClosedAbort && !recoveredTurnWatchTimeout;
4536
+ const isFinalAborted = () => terminalState.explicitCancellationObserved || !resourceState.executionDisconnectError && (projectedTerminal.aborted || runAbortController.signal.aborted && !state.clientClosedAbort && !recoveredTurnWatchTimeout);
4190
4537
  const clientClosedPromptErrorForFinal = state.clientClosedPromptError && hasRecoverableCompletedAssistant ? void 0 : state.clientClosedPromptError;
4191
- let finalPromptError = clientClosedPromptErrorForFinal ?? (effectiveTurnCompletionIdleTimedOut ? state.turnCompletionIdleTimeoutMessage : effectiveTimedOut ? "codex app-server attempt timed out" : projectedTerminal.promptError);
4538
+ let finalPromptError = resourceState.executionDisconnectError ?? clientClosedPromptErrorForFinal ?? (effectiveTurnCompletionIdleTimedOut ? state.turnCompletionIdleTimeoutMessage : effectiveTimedOut ? "codex app-server attempt timed out" : projectedTerminal.promptError);
4192
4539
  const finalPromptErrorMessage = typeof finalPromptError === "string" ? finalPromptError : finalPromptError instanceof Error ? finalPromptError.message : finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
4193
4540
  if (isInvalidCodexImagePayloadError(finalPromptErrorMessage)) await clearCodexBindingAfterInvalidImagePayload(bindingStore, bindingIdentity, {
4194
4541
  phase: "turn_completed",
@@ -4229,6 +4576,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4229
4576
  authProfileId: startupAuthProfileId,
4230
4577
  rateLimits: readRecentCodexRateLimits(resourceState.client)
4231
4578
  });
4579
+ finalPromptError = resourceState.executionDisconnectError ?? finalPromptError;
4232
4580
  const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : projectedTerminal.promptErrorSource;
4233
4581
  const codexAppServerFailureKind = clientClosedPromptErrorForFinal ? "client_closed_before_turn_completed" : effectiveTurnCompletionIdleTimedOut ? "turn_completion_idle_timeout" : void 0;
4234
4582
  const replayBlockedReason = codexAppServerFailureKind ? resolveCodexAppServerReplayBlockedReason(result) : void 0;
@@ -4354,7 +4702,11 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4354
4702
  await markCodexAppServerBindingCoveredThroughTurn({
4355
4703
  bindingStore,
4356
4704
  identity: bindingIdentity,
4357
- threadId: resourceState.thread.threadId
4705
+ threadId: resourceState.thread.threadId,
4706
+ continuityCalibration: context.promptState.noEngineContinuityProjectionApplied ? buildCodexContinuityCalibration({
4707
+ promptChars: prompt.turnState.codexTurnPromptText.length,
4708
+ inputTokens: (result.attemptUsage?.input ?? 0) + (result.attemptUsage?.cacheRead ?? 0) + (result.attemptUsage?.cacheWrite ?? 0)
4709
+ }) : void 0
4358
4710
  });
4359
4711
  } catch (error) {
4360
4712
  if (resourceState.thread.connectionScope === "supervision") throw error;
@@ -4407,6 +4759,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4407
4759
  });
4408
4760
  const finalizedResult = {
4409
4761
  ...result,
4762
+ ...toolState.yieldAcknowledgment ? { yieldAcknowledgment: toolState.yieldAcknowledgment } : {},
4410
4763
  terminal: attemptTerminal.normalize({
4411
4764
  timedOut: effectiveTimedOut,
4412
4765
  aborted: finalAborted,
@@ -4420,6 +4773,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4420
4773
  ...terminalAnchor ? { contextEngineTerminalAnchor: terminalAnchor } : {},
4421
4774
  ...settledTurnFinalizationContext ? { settledTurnFinalizationContext } : {},
4422
4775
  ...resourceState.runtimeArtifact ? { runtimeArtifact: resourceState.runtimeArtifact } : {},
4776
+ ...resourceState.runtimeContinuationStarted ? { runtimeContinuationStarted: true } : {},
4423
4777
  ...!finalAborted && !effectiveTimedOut && !finalPromptError && preparedAuthBinding ? { authBindingFingerprint: preparedAuthBinding.fingerprint } : {},
4424
4778
  systemPromptReport
4425
4779
  };
@@ -4764,7 +5118,7 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
4764
5118
  state.turnCrossedToolHandoff = notificationState.turnCrossedToolHandoff;
4765
5119
  if (notificationState.isCurrentTurnNotification && notification.method === "item/completed") {
4766
5120
  const item = readCodexNotificationItem(notification.params);
4767
- if (item?.type === "userMessage" && typeof item.clientId === "string") steeringQueue?.confirmConsumed(item.clientId);
5121
+ if (item?.type === "userMessage" && typeof item.clientId === "string") await steeringQueue?.confirmConsumed(item.clientId);
4768
5122
  }
4769
5123
  if (notificationState.isTurnAbortMarker) state.sawCodexInterruptMarker = true;
4770
5124
  const hookNotification = readCodexFinalizationHookNotification(notification, resourceState.thread.threadId, turnId);
@@ -4775,7 +5129,6 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
4775
5129
  }
4776
5130
  if (notificationState.isTurnTerminal) state.terminalTurnNotificationQueued = true;
4777
5131
  try {
4778
- await waitForCodexNotificationDispatchTurn();
4779
5132
  await projector.handleNotification(notification);
4780
5133
  const canRelease = isAssistantCompletionReleaseNotification(notification, state.turnCrossedToolHandoff) || notificationState.isCurrentTurnNotification && state.turnCrossedToolHandoff && notification.method === "rawResponseItem/completed" && projector.canReleaseLatestTerminalAssistantAfterToolHandoff();
4781
5134
  if (notificationState.isCurrentTurnNotification && canRelease) {
@@ -4871,11 +5224,12 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
4871
5224
  }
4872
5225
  //#endregion
4873
5226
  //#region extensions/codex/src/app-server/run-attempt-prompt.ts
5227
+ const CODEX_META_KEY = "__openclaw";
4874
5228
  function isRestrictivePromptToolsAllow(toolsAllow) {
4875
5229
  return toolsAllow !== void 0 && !toolsAllow.some((name) => name.trim() === "*");
4876
5230
  }
4877
5231
  async function prepareCodexAttemptPrompt(context) {
4878
- const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, buildActiveContextEngineRuntimeContext, baseDeveloperInstructions, openClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars } = context;
5232
+ const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, buildActiveContextEngineRuntimeContext, baseDeveloperInstructions, openClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars, codexContinuityProjectionMaxChars } = context;
4879
5233
  const { connection, buildActiveRunAttemptParams, effectiveContextTokenBudget, effectiveRuntimeModelId, effectiveRuntimeProviderId } = runtime;
4880
5234
  const { params, activeContextEngine, usesSupervisionConnection, mutable, isInactiveThreadBootstrapBinding, bindingStore, bindingIdentity, agentDir, appServer, contextSessionKey, effectiveWorkspace, sandbox } = connection;
4881
5235
  const { toolBridge } = attemptTools;
@@ -4884,11 +5238,12 @@ async function prepareCodexAttemptPrompt(context) {
4884
5238
  assembledMessages: historyState.messages,
4885
5239
  originalHistoryMessages: historyState.messages,
4886
5240
  prompt: params.prompt,
4887
- maxRenderedContextChars: codexContextProjectionMaxChars
5241
+ maxRenderedContextChars: codexContinuityProjectionMaxChars
4888
5242
  });
4889
5243
  promptState.promptText = projection.promptText;
4890
5244
  promptState.promptContextRange = projection.promptContextRange;
4891
5245
  promptState.prePromptMessageCount = projection.prePromptMessageCount;
5246
+ promptState.noEngineContinuityProjectionApplied = true;
4892
5247
  };
4893
5248
  const applyActiveContextEngineProjection = async (decisionStartupBinding) => {
4894
5249
  if (!activeContextEngine) return;
@@ -4962,15 +5317,21 @@ async function prepareCodexAttemptPrompt(context) {
4962
5317
  }
4963
5318
  const codexModelInputHistoryMessages = [];
4964
5319
  const buildPromptFromCurrentInputs = async () => {
4965
- const result = await resolveAgentHarnessBeforePromptBuildResult({
5320
+ return await resolveAgentHarnessBeforePromptBuildResult({
4966
5321
  prompt: prependCurrentInboundContext(promptState.promptText, params.currentInboundContext),
4967
- developerInstructions: promptState.developerInstructions,
5322
+ developerInstructions: { build: ({ toolsAllow }) => {
5323
+ if (isRestrictivePromptToolsAllow(toolsAllow)) throw new Error("Codex app-server cannot enforce before_prompt_build toolsAllow; use the embedded or Copilot runtime for turn-scoped tool policy.");
5324
+ return promptState.developerInstructions;
5325
+ } },
4968
5326
  messages: structuredClone(historyState.messages),
4969
5327
  ctx: hookContext,
4970
- bootstrapContextRunKind: params.bootstrapContextRunKind
5328
+ bootstrapContextRunKind: params.bootstrapContextRunKind,
5329
+ toolAuthority: {
5330
+ fingerprint: params.toolAuthorityFingerprint,
5331
+ activeToolNames: () => flattenCodexDynamicToolFunctions(toolBridge.availableSpecs).map((tool) => tool.name).filter(isNonEmptyString),
5332
+ assertActive: params.hostCapabilities.assertActive
5333
+ }
4971
5334
  });
4972
- if (isRestrictivePromptToolsAllow(result.toolsAllow)) throw new Error("Codex app-server cannot enforce before_prompt_build toolsAllow; use the embedded or Copilot runtime for turn-scoped tool policy.");
4973
- return result;
4974
5335
  };
4975
5336
  const resolveShiftedPromptInputRange = (prompt, promptInputRange, turnPromptText) => {
4976
5337
  if (!promptInputRange || promptInputRange.start < 0 || promptInputRange.end < promptInputRange.start || promptInputRange.end > prompt.length || !turnPromptText.endsWith(prompt)) return;
@@ -5040,12 +5401,11 @@ async function prepareCodexAttemptPrompt(context) {
5040
5401
  const cutoff = Date.parse(binding.historyCoveredThrough ?? "");
5041
5402
  return historyState.messages.filter((message) => {
5042
5403
  if (message.role !== "user" && message.role !== "assistant") return false;
5043
- const record = message;
5044
- const meta = record["__openclaw"];
5404
+ const meta = CODEX_META_KEY in message ? message[CODEX_META_KEY] : void 0;
5045
5405
  const mirrorIdentity = meta && typeof meta === "object" && !Array.isArray(meta) ? meta.mirrorIdentity : void 0;
5046
5406
  const mirrorOrigin = meta && typeof meta === "object" && !Array.isArray(meta) ? meta.mirrorOrigin : void 0;
5047
5407
  const timestamp = typeof message.timestamp === "number" ? message.timestamp : typeof message.timestamp === "string" ? Date.parse(message.timestamp) : NaN;
5048
- return !(typeof record.idempotencyKey === "string" && record.idempotencyKey.startsWith("codex-app-server:")) && mirrorOrigin !== "codex-app-server" && !(typeof mirrorIdentity === "string" && mirrorIdentity.startsWith("codex-app-server:")) && Number.isFinite(timestamp) && timestamp > (Number.isFinite(cutoff) ? cutoff : 0);
5408
+ return !("idempotencyKey" in message && typeof message.idempotencyKey === "string" && message.idempotencyKey.startsWith("codex-app-server:")) && mirrorOrigin !== "codex-app-server" && !(typeof mirrorIdentity === "string" && mirrorIdentity.startsWith("codex-app-server:")) && Number.isFinite(timestamp) && timestamp > (Number.isFinite(cutoff) ? cutoff : 0);
5049
5409
  });
5050
5410
  };
5051
5411
  const applyResumeStaleBindingContinuityProjection = (binding) => {
@@ -5055,11 +5415,12 @@ async function prepareCodexAttemptPrompt(context) {
5055
5415
  assembledMessages: newerVisibleMessages,
5056
5416
  originalHistoryMessages: historyState.messages,
5057
5417
  prompt: params.prompt,
5058
- maxRenderedContextChars: codexContextProjectionMaxChars
5418
+ maxRenderedContextChars: codexContinuityProjectionMaxChars
5059
5419
  });
5060
5420
  promptState.promptText = projection.promptText;
5061
5421
  promptState.promptContextRange = projection.promptContextRange;
5062
5422
  promptState.prePromptMessageCount = projection.prePromptMessageCount;
5423
+ promptState.noEngineContinuityProjectionApplied = true;
5063
5424
  return true;
5064
5425
  };
5065
5426
  const precomputeNoContextEngineStaleBindingProjection = () => {
@@ -5171,15 +5532,13 @@ function prepareCodexAttemptResources(prompt) {
5171
5532
  const { connection, hookChannelId } = runtime;
5172
5533
  const { appServer, params, effectiveCwd, sessionAgentId, sandboxSessionKey, runAbortController, sandbox, options, nativeHookRelayEvents } = connection;
5173
5534
  const { toolBridge } = attemptTools;
5174
- const hostTrajectoryRecorder = params.trajectoryRecorder;
5175
5535
  const trajectoryRecorder = createCodexTrajectoryRecorder({
5176
5536
  attempt: params,
5177
5537
  cwd: effectiveCwd,
5178
5538
  developerInstructions: buildRenderedCodexDeveloperInstructions(),
5179
5539
  prompt: turnState.codexTurnPromptText,
5180
- trajectoryRecorder: hostTrajectoryRecorder,
5181
- tools: toolBridge.availableSpecs,
5182
- warn: (message, fields) => embeddedAgentLog.warn(message, fields)
5540
+ trajectory: params.hostCapabilities.trajectory,
5541
+ tools: toolBridge.availableSpecs
5183
5542
  });
5184
5543
  const state = {
5185
5544
  client: void 0,
@@ -5192,12 +5551,14 @@ function prepareCodexAttemptResources(prompt) {
5192
5551
  trajectoryEndRecorded: false,
5193
5552
  nativeHookRelay: void 0,
5194
5553
  nativeSubagentMonitor: void 0,
5554
+ runtimeContinuationStarted: false,
5195
5555
  nativePreToolUseFailureFallbackActive: false,
5196
5556
  nativePreToolUseFailureFallbackTerminalReason: void 0,
5197
5557
  releaseSharedClientLease: void 0,
5198
5558
  startupClientUnsafe: false,
5199
5559
  sharedCodexClientRetiredForOneShotCleanup: false,
5200
- sandboxExecEnvironmentAcquired: false,
5560
+ sandboxExecEnvironment: void 0,
5561
+ executionDisconnectError: void 0,
5201
5562
  codexEnvironmentSelection: void 0,
5202
5563
  codexExecutionCwd: effectiveCwd,
5203
5564
  codexSandboxPolicy: void 0,
@@ -5236,7 +5597,7 @@ function prepareCodexAttemptResources(prompt) {
5236
5597
  if (params.cleanupBundleMcpOnRunEnd !== true || state.sharedCodexClientRetiredForOneShotCleanup) return;
5237
5598
  state.sharedCodexClientRetiredForOneShotCleanup = true;
5238
5599
  const retired = clearSharedCodexAppServerClientIfCurrentAndUnclaimed(state.client);
5239
- embeddedAgentLog.info("codex app-server one-shot cleanup checked shared client retirement", {
5600
+ embeddedAgentLog.debug("codex app-server one-shot cleanup checked shared client retirement", {
5240
5601
  runId: params.runId,
5241
5602
  sessionId: params.sessionId,
5242
5603
  sessionKey: params.sessionKey,
@@ -5250,16 +5611,27 @@ function prepareCodexAttemptResources(prompt) {
5250
5611
  forceKillDelayMs: 250
5251
5612
  });
5252
5613
  };
5614
+ const releaseSandboxExecEnvironment = async () => {
5615
+ if (state.sandboxExecEnvironment) {
5616
+ const environment = state.sandboxExecEnvironment;
5617
+ state.sandboxExecEnvironment = void 0;
5618
+ await releaseCodexSandboxExecServerEnvironment(sandbox, environment);
5619
+ }
5620
+ };
5253
5621
  const releaseSharedClientLeaseAndRetireOneShotClient = async () => {
5622
+ if (connection.attemptClientFactory === createIsolatedCodexAppServerClient) {
5623
+ await releaseSandboxExecEnvironment();
5624
+ const ownedClient = state.releaseSharedClientLease ? state.client : void 0;
5625
+ releaseSharedClientLeaseOnce();
5626
+ await ownedClient?.closeAndWait({
5627
+ exitTimeoutMs: 2e3,
5628
+ forceKillDelayMs: 250
5629
+ });
5630
+ return;
5631
+ }
5254
5632
  releaseSharedClientLeaseOnce();
5255
5633
  await retireSharedCodexClientForOneShotCleanup();
5256
5634
  };
5257
- const releaseSandboxExecEnvironment = async () => {
5258
- if (state.sandboxExecEnvironmentAcquired) {
5259
- state.sandboxExecEnvironmentAcquired = false;
5260
- await releaseCodexSandboxExecServerEnvironment(sandbox);
5261
- }
5262
- };
5263
5635
  const runCleanupStep = (step, operation) => runAgentCleanupStep({
5264
5636
  runId: params.runId,
5265
5637
  sessionId: params.sessionId,
@@ -5284,7 +5656,10 @@ function prepareCodexAttemptResources(prompt) {
5284
5656
  retainClient: () => retainSharedCodexAppServerClientIfCurrent(state.client),
5285
5657
  retainParentThread: (protectedThreadId) => protectCodexAppServerLiveThread(state.client, protectedThreadId),
5286
5658
  claimDirectChild: (childThreadId) => state.nativeHookRelay?.claimDirectChild(childThreadId),
5287
- rejectPendingDirectChild: (childThreadId, reason) => state.nativeHookRelay?.rejectPendingDirectChild(childThreadId, reason)
5659
+ rejectPendingDirectChild: (childThreadId, reason) => state.nativeHookRelay?.rejectPendingDirectChild(childThreadId, reason),
5660
+ ...params.sessionKey && params.agentHarnessTaskRuntimeScope ? { onDirectChildAccepted: () => {
5661
+ state.runtimeContinuationStarted = true;
5662
+ } } : {}
5288
5663
  });
5289
5664
  };
5290
5665
  const releaseCurrentRoute = () => {
@@ -5347,8 +5722,7 @@ function prepareCodexAttemptResources(prompt) {
5347
5722
  configPatch: state.nativeHookRelay ? buildCodexNativeHookRelayConfig({
5348
5723
  relay: state.nativeHookRelay,
5349
5724
  events: nativeHookRelayEvents,
5350
- hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec,
5351
- loopDetectionPreToolUseRelay: appServer.loopDetectionPreToolUseRelay
5725
+ hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec
5352
5726
  }) : options.nativeHookRelay?.enabled === false ? buildCodexNativeHookRelayDisabledConfig() : void 0,
5353
5727
  nativeHookRelayGeneration: state.nativeHookRelay?.generation
5354
5728
  };
@@ -5783,8 +6157,8 @@ async function prepareCodexAttemptRuntime(connection) {
5783
6157
  const effectiveContextWindowInfo = usesSupervisionConnection ? void 0 : params.contextWindowInfo;
5784
6158
  const effectiveContextTokenBudget = usesSupervisionConnection ? void 0 : params.contextTokenBudget;
5785
6159
  const effectiveRuntimeProviderId = usesSupervisionConnection ? mutable.startupBinding?.modelProvider ?? "codex" : params.provider;
5786
- const effectiveRuntimeModelId = usesSupervisionConnection ? mutable.startupBinding?.model ?? "codex-native" : params.modelId;
5787
- const { authProfileId: _outerAuthProfileId, contextWindowInfo: _outerContextWindowInfo, contextTokenBudget: _outerContextTokenBudget, model: _outerModel, modelId: _outerModelId, provider: _outerProvider, runtimePlan: _outerRuntimePlan, requestedModelId: _outerRequestedModelId, fallbackReason: _outerFallbackReason, degradedReason: _outerDegradedReason, thinkLevel: _outerThinkLevel, fastMode: _outerFastMode, ...paramsWithoutOuterNativeOwnership } = params;
6160
+ const effectiveRuntimeModelId = usesSupervisionConnection ? mutable.startupBinding?.model ?? "codex-native" : connection.options.runtimeModelId ?? params.modelId;
6161
+ const { authProfileId: _outerAuthProfileId, authoredContextTokenCap: _outerAuthoredContextTokenCap, contextWindowInfo: _outerContextWindowInfo, contextTokenBudget: _outerContextTokenBudget, model: _outerModel, modelId: _outerModelId, provider: _outerProvider, runtimePlan: _outerRuntimePlan, requestedModelId: _outerRequestedModelId, fallbackReason: _outerFallbackReason, degradedReason: _outerDegradedReason, thinkLevel: _outerThinkLevel, fastMode: _outerFastMode, ...paramsWithoutOuterNativeOwnership } = params;
5788
6162
  const supervisedRuntimeModel = {
5789
6163
  id: effectiveRuntimeModelId,
5790
6164
  name: effectiveRuntimeModelId,
@@ -6017,18 +6391,23 @@ function resolveCodexDynamicToolDirectNames(params, hostSystemAgentActive = fals
6017
6391
  const names = [];
6018
6392
  if (hostSystemAgentActive && isSystemAgentOnlyCodexDynamicToolAllowlist(params.toolsAllow)) names.push("openclaw");
6019
6393
  if (params.sourceReplyDeliveryMode === "message_tool_only") names.push("message");
6020
- if (params.pluginHarnessToolPolicyRestricted === true) names.push("update_plan");
6394
+ names.push("progress_card");
6021
6395
  return names;
6022
6396
  }
6023
6397
  //#endregion
6024
6398
  //#region extensions/codex/src/app-server/run-attempt-server-requests.ts
6399
+ const DYNAMIC_TOOL_TERMINAL_DIAGNOSTIC_TYPES = [
6400
+ "tool.execution.completed",
6401
+ "tool.execution.error",
6402
+ "tool.execution.blocked"
6403
+ ];
6025
6404
  function createCodexAttemptServerRequestController(resources, turnRuntime, lifecycle) {
6026
6405
  const { prompt, state: resourceState, projectorRef, trajectoryRecorder } = resources;
6027
6406
  const { context } = prompt;
6028
6407
  const { runtime, attemptTools } = context;
6029
6408
  const { connection } = runtime;
6030
- const { params, computerUseConfig, runAbortController, appServer, approvalPolicyPromotedForOpenClawToolPolicy, sessionAgentId } = connection;
6031
- const { toolBridge, toolOutcomeOrdinals, suppressedDynamicToolOutcomeOrdinals, allocateCodexToolOutcomeOrdinal } = attemptTools;
6409
+ const { params, computerUseConfig, runAbortController, appServer, sessionAgentId } = connection;
6410
+ const { compactionPlanState, toolBridge, toolOutcomeOrdinals, suppressedDynamicToolOutcomeOrdinals, allocateCodexToolOutcomeOrdinal } = attemptTools;
6032
6411
  const { state, turnIdRef, userInputBridgeRef, openClawDynamicToolExecutions, pendingOpenClawDynamicToolCompletionIds, postToolRawAssistantCompletionIdleTimeoutMs, turnWatches } = turnRuntime;
6033
6412
  const { emitExecutionPhaseOnce, scheduleTurnReleaseAfterTerminalDynamicTool, scheduleTerminalDynamicToolReleaseCheck } = lifecycle;
6034
6413
  const handleServerRequest = async (request, scope, requestSignal = new AbortController().signal) => {
@@ -6054,7 +6433,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6054
6433
  armCompletionWatchOnResponse = true;
6055
6434
  markCurrentTurnRequestProgress();
6056
6435
  }
6057
- return await handleCodexAppServerElicitationRequest({
6436
+ const approvalResult = await routeCodexAppServerElicitationRequest({
6058
6437
  requestParams: request.params,
6059
6438
  paramsForRun: params,
6060
6439
  threadId: resourceState.thread.threadId,
@@ -6063,6 +6442,11 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6063
6442
  ...computerUseConfig.enabled ? { computerUseMcpServerName: computerUseConfig.mcpServerName } : {},
6064
6443
  signal
6065
6444
  });
6445
+ if (approvalResult.kind === "handled") return approvalResult.response;
6446
+ return await userInputBridgeRef.current?.handleElicitationRequest({
6447
+ id: request.id,
6448
+ params: request.params
6449
+ });
6066
6450
  }
6067
6451
  if (request.method === "item/tool/requestUserInput") {
6068
6452
  if (scope.turnId === turnId) {
@@ -6088,9 +6472,8 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6088
6472
  turnId,
6089
6473
  nativeHookRelay: resourceState.nativeHookRelay,
6090
6474
  autoApprove: shouldAutoApproveCodexAppServerApprovals(appServer),
6091
- autoApproveOpenClawToolPolicy: approvalPolicyPromotedForOpenClawToolPolicy,
6092
6475
  signal,
6093
- onNativeToolFailureDisposition: (itemId, disposition) => projector?.recordNativeToolApprovalFailure(itemId, disposition)
6476
+ onNativeToolFailureDisposition: (itemId, disposition, approvalKind) => projector?.recordNativeToolApprovalFailure(itemId, disposition, approvalKind)
6094
6477
  });
6095
6478
  }
6096
6479
  return;
@@ -6126,13 +6509,6 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6126
6509
  tool: call.tool,
6127
6510
  toolCallId: call.callId
6128
6511
  });
6129
- emitDynamicToolStartedDiagnostic({
6130
- call,
6131
- agentId: sessionAgentId,
6132
- runId: params.runId,
6133
- sessionId: params.sessionId,
6134
- sessionKey: params.sessionKey
6135
- });
6136
6512
  const toolMeta = inferCodexDynamicToolMeta(call, resolveCodexToolProgressDetailMode(params.toolProgressDetail));
6137
6513
  const toolArgs = sanitizeCodexToolArguments(call.arguments);
6138
6514
  const commandBearing = isCodexCommandBearingToolCall(call.tool, toolArgs);
@@ -6162,30 +6538,39 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6162
6538
  sessionId: params.sessionId,
6163
6539
  sessionKey: params.sessionKey
6164
6540
  })) terminalDiagnosticObserved = true;
6165
- });
6541
+ }, { include: DYNAMIC_TOOL_TERMINAL_DIAGNOSTIC_TYPES });
6166
6542
  try {
6167
- const { execution } = openClawDynamicToolExecutions.claim(call, () => handleDynamicToolCallWithTimeout({
6168
- call,
6169
- toolBridge,
6170
- signal,
6171
- timeoutMs: dynamicToolTimeoutMs,
6172
- toolMeta,
6173
- toolCallOrdinal,
6174
- onAgentToolResult: params.onAgentToolResult,
6175
- observeToolTerminal: params.observeToolTerminal,
6176
- onFallbackSelected: () => {
6177
- if (toolCallOrdinal !== void 0) suppressedDynamicToolOutcomeOrdinals.add(toolCallOrdinal);
6178
- },
6179
- onTimeout: () => {
6180
- trajectoryRecorder?.recordEvent("tool.timeout", {
6181
- threadId: call.threadId,
6182
- turnId: call.turnId,
6183
- toolCallId: call.callId,
6184
- name: call.tool,
6185
- timeoutMs: dynamicToolTimeoutMs
6186
- });
6187
- }
6188
- }));
6543
+ const { execution } = openClawDynamicToolExecutions.claim(call, () => {
6544
+ emitDynamicToolStartedDiagnostic({
6545
+ call,
6546
+ agentId: sessionAgentId,
6547
+ runId: params.runId,
6548
+ sessionId: params.sessionId,
6549
+ sessionKey: params.sessionKey
6550
+ });
6551
+ return handleDynamicToolCallWithTimeout({
6552
+ call,
6553
+ toolBridge,
6554
+ signal,
6555
+ timeoutMs: dynamicToolTimeoutMs,
6556
+ toolMeta,
6557
+ toolCallOrdinal,
6558
+ onAgentToolResult: params.onAgentToolResult,
6559
+ observeToolTerminal: params.observeToolTerminal,
6560
+ onFallbackSelected: () => {
6561
+ if (toolCallOrdinal !== void 0) suppressedDynamicToolOutcomeOrdinals.add(toolCallOrdinal);
6562
+ },
6563
+ onTimeout: () => {
6564
+ trajectoryRecorder?.recordEvent("tool.timeout", {
6565
+ threadId: call.threadId,
6566
+ turnId: call.turnId,
6567
+ toolCallId: call.callId,
6568
+ name: call.tool,
6569
+ timeoutMs: dynamicToolTimeoutMs
6570
+ });
6571
+ }
6572
+ });
6573
+ });
6189
6574
  const response = await execution;
6190
6575
  const protocolResponse = toCodexDynamicToolProtocolResponse(response);
6191
6576
  if (!protocolResponse.success && toolCallOrdinal !== void 0) {
@@ -6209,7 +6594,11 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6209
6594
  contentItems: protocolResponse.contentItems
6210
6595
  });
6211
6596
  recordCodexDynamicToolResult(projector, call, response, protocolResponse);
6212
- if (protocolResponse.success && call.tool === "update_plan") projector?.recordDynamicPlanUpdate(response.executedArguments ?? call.arguments);
6597
+ if (protocolResponse.success && call.tool === "progress_card") {
6598
+ const progressCardInput = response.executedArguments ?? call.arguments;
6599
+ await projector?.recordDynamicProgressCardUpdate(progressCardInput);
6600
+ compactionPlanState.recordProgressCardInput(progressCardInput);
6601
+ }
6213
6602
  if (shouldEmitDynamicToolProgress) {
6214
6603
  const progressResponse = toCodexDynamicToolProgressResponse(response, protocolResponse);
6215
6604
  emitCodexAppServerEvent(params, {
@@ -6289,6 +6678,20 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
6289
6678
  return { handleServerRequest };
6290
6679
  }
6291
6680
  //#endregion
6681
+ //#region extensions/codex/src/app-server/attempt-runtime-artifact.ts
6682
+ async function verifyStartupArtifact(params) {
6683
+ if (!params.request) return;
6684
+ const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-BvyT1uyd.js");
6685
+ const runtimeArtifact = readCodexAppServerClientRuntimeArtifact(params.client);
6686
+ const expected = params.request.expected;
6687
+ const matchesExpected = !expected || runtimeArtifact?.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint;
6688
+ if (!runtimeArtifact || !matchesExpected || !await validateCodexAppServerRuntimeArtifact(runtimeArtifact, params.signal)) {
6689
+ retireSharedCodexAppServerClientIfCurrent(params.client);
6690
+ throw new Error(expected ? "Codex app-server runtime artifact does not match verified inference" : "Codex app-server runtime artifact is unavailable or stale");
6691
+ }
6692
+ return runtimeArtifact;
6693
+ }
6694
+ //#endregion
6292
6695
  //#region extensions/codex/src/app-server/computer-use-health.ts
6293
6696
  const COMPUTER_USE_HEALTH_MONITOR_STATE = Symbol.for("openclaw.codexComputerUseHealthMonitorState");
6294
6697
  function getComputerUseHealthMonitorState() {
@@ -6575,24 +6978,19 @@ async function startCodexAttemptThread(params) {
6575
6978
  startupClientLease = () => {
6576
6979
  if (startupClientLeaseReleased) return;
6577
6980
  startupClientLeaseReleased = true;
6578
- releaseLeasedSharedCodexAppServerClient(activeStartupClient);
6981
+ if (params.attemptClientFactory === createIsolatedCodexAppServerClient) activeStartupClient.close();
6982
+ else releaseLeasedSharedCodexAppServerClient(activeStartupClient);
6579
6983
  };
6580
6984
  releaseSharedClientLease = startupClientLease;
6581
6985
  attemptedClient = activeStartupClient;
6582
6986
  startupClientForAbandonedRequestCleanup = activeStartupClient;
6583
6987
  if (startupAbandoned) throw new CodexAppServerStartupError("timed_out");
6584
6988
  if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
6585
- let runtimeArtifact;
6586
- if (params.runtimeArtifactRequest) {
6587
- const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-BVSPdd6g.js");
6588
- runtimeArtifact = readCodexAppServerClientRuntimeArtifact(activeStartupClient);
6589
- const expected = params.runtimeArtifactRequest.expected;
6590
- const matchesExpected = !expected || Boolean(runtimeArtifact && runtimeArtifact.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint);
6591
- if (!runtimeArtifact || !matchesExpected || !await validateCodexAppServerRuntimeArtifact(runtimeArtifact, startupAbandonController.signal)) {
6592
- retireSharedCodexAppServerClientIfCurrent(activeStartupClient);
6593
- throw new Error(expected ? "Codex app-server runtime artifact does not match verified inference" : "Codex app-server runtime artifact is unavailable or stale");
6594
- }
6595
- }
6989
+ const runtimeArtifact = await verifyStartupArtifact({
6990
+ client: activeStartupClient,
6991
+ request: params.runtimeArtifactRequest,
6992
+ signal: startupAbandonController.signal
6993
+ });
6596
6994
  ensureCodexAppServerClientRuntime(activeStartupClient, {
6597
6995
  agentDir: params.agentDir,
6598
6996
  authProfileId: startupRuntimeAuthProfileId,
@@ -6652,7 +7050,7 @@ async function startCodexAttemptThread(params) {
6652
7050
  const releaseStartupSandboxEnvironment = async () => {
6653
7051
  if (startupSandboxEnvironmentAcquired) {
6654
7052
  startupSandboxEnvironmentAcquired = false;
6655
- await releaseCodexSandboxExecServerEnvironment(params.sandbox);
7053
+ await releaseCodexSandboxExecServerEnvironment(params.sandbox, startupSandboxEnvironment);
6656
7054
  }
6657
7055
  };
6658
7056
  releaseStartupResourcesOnTimeout = releaseStartupSandboxEnvironment;
@@ -6665,9 +7063,11 @@ async function startCodexAttemptThread(params) {
6665
7063
  startupSandboxEnvironment = sandboxEnvironmentRequired ? await ensureCodexSandboxExecServerEnvironment({
6666
7064
  client: activeStartupClient,
6667
7065
  sandbox: params.sandbox ?? null,
7066
+ runtime: params.runtime,
6668
7067
  appServerStartOptions: params.appServer.start,
6669
7068
  timeoutMs: params.appServer.requestTimeoutMs,
6670
- signal: startupAbandonController.signal
7069
+ signal: AbortSignal.any([params.signal, startupAbandonController.signal]),
7070
+ onExecutionDisconnect: params.onExecutionDisconnect
6671
7071
  }) : void 0;
6672
7072
  startupSandboxEnvironmentAcquired = Boolean(startupSandboxEnvironment);
6673
7073
  if (startupAbandonController.signal.aborted) {
@@ -6711,14 +7111,19 @@ async function startCodexAttemptThread(params) {
6711
7111
  reserveResumeThread,
6712
7112
  bindingStore: params.bindingStore,
6713
7113
  params: params.buildAttemptParams(),
7114
+ runtimeModelId: params.runtimeModelId,
6714
7115
  agentId: params.sessionAgentId,
7116
+ agentDir: params.agentDir,
6715
7117
  cwd: startupExecutionCwd,
6716
7118
  dynamicTools: params.dynamicTools,
6717
7119
  persistentWebSearchAllowed: params.persistentWebSearchAllowed,
6718
7120
  webSearchAllowed: params.webSearchAllowed,
6719
7121
  appServer: pluginAppServer,
6720
7122
  developerInstructions: params.developerInstructions,
7123
+ agentWorkspaceDeveloperInstructions: params.agentWorkspaceDeveloperInstructions,
6721
7124
  config: threadConfig,
7125
+ shellEnvironment: params.shellEnvironment,
7126
+ disableLoginShell: params.disableLoginShell,
6722
7127
  finalConfigPatch: params.finalConfigPatch,
6723
7128
  buildFinalConfigPatch: params.buildFinalConfigPatch,
6724
7129
  nativeHookRelayGeneration: params.nativeHookRelayGeneration,
@@ -6886,7 +7291,7 @@ async function startCodexAttemptRuntime(resources) {
6886
7291
  const { prompt, state, trajectoryRecorder, activateNativePreToolUseFailureFallback, releaseSandboxExecEnvironment, releaseSharedClientLeaseAndRetireOneShotClient, releaseCurrentRoute, runCleanupStep, startupTimeoutMs, buildNativeHookRelayFinalConfigPatch } = resources;
6887
7292
  const { context, turnState, buildRenderedCodexDeveloperInstructions, rebuildCodexTurnPromptTextFromCurrentProjection, applyNoContextEngineContinuityProjection } = prompt;
6888
7293
  const { runtime, attemptTools, promptState } = context;
6889
- const { connection, runtimeParams, preparedAuthBinding, buildActiveRunAttemptParams, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, sandboxExecServerEnabled } = runtime;
7294
+ const { connection, runtimeParams, preparedAuthBinding, buildActiveRunAttemptParams, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, effectiveRuntimeModelId, sandboxExecServerEnabled } = runtime;
6890
7295
  const { toolBridge, toolState } = attemptTools;
6891
7296
  const developerInstructions = joinPresentSections(turnState.promptBuild.developerInstructions, attemptTools.scheduledConfiguredMcp?.diagnosticNotice);
6892
7297
  const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, startupAuthRequirement, abortFromUpstream } = connection;
@@ -6899,6 +7304,7 @@ async function startCodexAttemptRuntime(resources) {
6899
7304
  const startupResult = await startCodexAttemptThread({
6900
7305
  attemptClientFactory,
6901
7306
  bindingStore,
7307
+ runtime: connection.options.runtime,
6902
7308
  appServer: pluginAppServer,
6903
7309
  pluginConfig,
6904
7310
  computerUseConfig,
@@ -6911,7 +7317,10 @@ async function startCodexAttemptRuntime(resources) {
6911
7317
  startupEnvApiKeyCacheKey,
6912
7318
  agentDir,
6913
7319
  config: params.config,
7320
+ shellEnvironment: connection.shellEnvironment,
7321
+ disableLoginShell: connection.disableLoginShell,
6914
7322
  buildAttemptParams: buildActiveRunAttemptParams,
7323
+ ...effectiveRuntimeModelId !== runtimeParams.modelId ? { runtimeModelId: effectiveRuntimeModelId } : {},
6915
7324
  sessionAgentId,
6916
7325
  effectiveWorkspace,
6917
7326
  effectiveCwd,
@@ -6919,6 +7328,7 @@ async function startCodexAttemptRuntime(resources) {
6919
7328
  persistentWebSearchAllowed: toolState.persistentWebSearchAllowed,
6920
7329
  webSearchAllowed: toolState.webSearchAllowed,
6921
7330
  developerInstructions,
7331
+ agentWorkspaceDeveloperInstructions: context.agentWorkspaceDeveloperInstructions,
6922
7332
  buildFinalConfigPatch: buildNativeHookRelayFinalConfigPatch,
6923
7333
  bundleMcpThreadConfig,
6924
7334
  configuredMcpOwnershipVersion: attemptTools.configuredMcpOwnershipVersion,
@@ -6930,6 +7340,11 @@ async function startCodexAttemptRuntime(resources) {
6930
7340
  startupTimeoutMs,
6931
7341
  signal: runAbortController.signal,
6932
7342
  onStartupTimeout: () => runAbortController.abort("codex_startup_timeout"),
7343
+ onExecutionDisconnect: (error) => {
7344
+ state.executionDisconnectError = error;
7345
+ embeddedAgentLog.warn(error.message);
7346
+ runAbortController.abort("client_closed");
7347
+ },
6933
7348
  spawnedBy: params.spawnedBy
6934
7349
  });
6935
7350
  state.client = startupResult.client;
@@ -6937,7 +7352,7 @@ async function startCodexAttemptRuntime(resources) {
6937
7352
  state.runtimeArtifact = startupResult.runtimeArtifact;
6938
7353
  state.turnRouter = startupResult.turnRouter;
6939
7354
  state.turnRoute = startupResult.turnRoute;
6940
- state.sandboxExecEnvironmentAcquired = Boolean(startupResult.sandboxEnvironment);
7355
+ state.sandboxExecEnvironment = startupResult.sandboxEnvironment;
6941
7356
  state.releaseSharedClientLease = startupResult.releaseSharedClientLease;
6942
7357
  state.restartContextEngineCodexThread = startupResult.restartContextEngineCodexThread;
6943
7358
  pluginAppServer = startupResult.pluginAppServer;
@@ -7011,7 +7426,7 @@ async function startCodexAttemptRuntime(resources) {
7011
7426
  await runCleanupStep("codex-start-failure-sandbox-release", releaseSandboxExecEnvironment);
7012
7427
  await runCleanupStep("codex-start-failure-shared-client-release", releaseSharedClientLeaseAndRetireOneShotClient);
7013
7428
  await runCleanupStep("codex-start-failure-abort-listener", () => params.abortSignal?.removeEventListener("abort", abortFromUpstream));
7014
- throw error;
7429
+ throw state.executionDisconnectError ?? error;
7015
7430
  }
7016
7431
  }
7017
7432
  //#endregion
@@ -7035,6 +7450,7 @@ async function prepareCodexAttemptTools(runtime) {
7035
7450
  });
7036
7451
  const toolState = {
7037
7452
  yieldDetected: false,
7453
+ yieldAcknowledgment: void 0,
7038
7454
  persistentWebSearchAllowed: void 0,
7039
7455
  webSearchAllowed: false
7040
7456
  };
@@ -7052,11 +7468,16 @@ async function prepareCodexAttemptTools(runtime) {
7052
7468
  if (toolCallId) toolOutcomeOrdinals.set(toolCallId, ordinal);
7053
7469
  return ordinal;
7054
7470
  } : void 0;
7055
- const dynamicToolParams = allocateCodexToolOutcomeOrdinal || onCodexToolOutcome ? {
7471
+ const compactionPlanState = new CodexCompactionPlanState();
7472
+ const dynamicToolParams = {
7056
7473
  ...runtimeParams,
7474
+ onAgentEvent: (event) => {
7475
+ compactionPlanState.record(event);
7476
+ return runtimeParams.onAgentEvent?.(event);
7477
+ },
7057
7478
  ...allocateCodexToolOutcomeOrdinal ? { allocateToolOutcomeOrdinal: allocateCodexToolOutcomeOrdinal } : {},
7058
7479
  ...onCodexToolOutcome ? { onToolOutcome: onCodexToolOutcome } : {}
7059
- } : runtimeParams;
7480
+ };
7060
7481
  const computerContextEpoch = { value: 0 };
7061
7482
  const cronCreatorToolAllowlist = [];
7062
7483
  const cronCreatorToolAllowlistCaptureRef = {};
@@ -7080,6 +7501,7 @@ async function prepareCodexAttemptTools(runtime) {
7080
7501
  let toolBridge;
7081
7502
  let creatorAuthorityPromise;
7082
7503
  let resolveCreatorAuthorityImpl;
7504
+ const runtimeYieldCompletionClaim = {};
7083
7505
  const commonToolParams = {
7084
7506
  params: dynamicToolParams,
7085
7507
  resolvedWorkspace,
@@ -7094,9 +7516,11 @@ async function prepareCodexAttemptTools(runtime) {
7094
7516
  pluginConfig,
7095
7517
  profilerEnabled,
7096
7518
  ...params.cronCreatorAuthorityUnavailableReason === "queued-local-operator" && bundleMcpThreadConfig.staticServerNames.length > 0 ? { cronCreatorAuthorityUnavailableReason: "queued-local-operator-configured-mcp" } : {},
7097
- onYieldDetected: () => {
7519
+ onYieldDetected: (acknowledgment) => {
7098
7520
  toolState.yieldDetected = true;
7521
+ toolState.yieldAcknowledgment = acknowledgment;
7099
7522
  },
7523
+ claimYieldCompletion: () => runtimeYieldCompletionClaim.current?.() ?? false,
7100
7524
  onCodexAppServerEvent: (event) => {
7101
7525
  emitCodexAppServerEvent(params, event);
7102
7526
  },
@@ -7333,13 +7757,15 @@ async function prepareCodexAttemptTools(runtime) {
7333
7757
  cronCreatorToolAllowlistCaptureRef,
7334
7758
  scheduledAppAuthoritySourceRef,
7335
7759
  dynamicToolParams,
7760
+ compactionPlanState,
7336
7761
  computerContextEpoch,
7337
7762
  toolBridge,
7338
7763
  toolState,
7339
7764
  toolOutcomeOrdinals,
7340
7765
  suppressedDynamicToolOutcomeOrdinals,
7341
7766
  onCodexToolOutcome,
7342
- allocateCodexToolOutcomeOrdinal
7767
+ allocateCodexToolOutcomeOrdinal,
7768
+ runtimeYieldCompletionClaim
7343
7769
  };
7344
7770
  } catch (error) {
7345
7771
  await scopedMcpTools?.dispose();
@@ -7457,7 +7883,7 @@ async function prepareCodexAttemptTurnRequest(resources, turnRuntime, ensureCurr
7457
7883
  data: {
7458
7884
  phase: "turn_starting",
7459
7885
  threadId: resourceState.thread.threadId,
7460
- model: turnStartParams.model,
7886
+ model: params.modelId,
7461
7887
  effort: turnStartParams.effort,
7462
7888
  collaborationEffort: turnStartParams.collaborationMode?.settings.reasoning_effort,
7463
7889
  serviceTier: turnStartParams.serviceTier
@@ -8179,11 +8605,14 @@ function createCodexAttemptTurnState(resources) {
8179
8605
  //#endregion
8180
8606
  //#region extensions/codex/src/app-server/run-attempt.ts
8181
8607
  async function runCodexAppServerAttempt(params, options) {
8182
- const runtime = await prepareCodexAttemptRuntime(await prepareCodexAttemptConnection({
8608
+ const connection = await prepareCodexAttemptConnection({
8183
8609
  params,
8184
8610
  options
8185
- }));
8186
- const resources = prepareCodexAttemptResources(await prepareCodexAttemptPrompt(await prepareCodexAttemptContext(runtime, await prepareCodexAttemptTools(runtime))));
8611
+ });
8612
+ const runtime = await prepareCodexAttemptRuntime(connection);
8613
+ const attemptTools = await prepareCodexAttemptTools(runtime);
8614
+ const resources = prepareCodexAttemptResources(await prepareCodexAttemptPrompt(await prepareCodexAttemptContext(runtime, attemptTools)));
8615
+ attemptTools.runtimeYieldCompletionClaim.current = () => resources.state.nativeHookRelay?.hasClaimedDirectChild() ?? false;
8187
8616
  await startCodexAttemptRuntime(resources);
8188
8617
  const turnRuntime = createCodexAttemptTurnState(resources);
8189
8618
  const lifecycle = createCodexAttemptLifecycleController(resources, turnRuntime);
@@ -8193,11 +8622,14 @@ async function runCodexAppServerAttempt(params, options) {
8193
8622
  const turnStart = await startCodexAttemptTurn(resources, turnRuntime, notifications, turnRequest);
8194
8623
  if ("result" in turnStart) return turnStart.result;
8195
8624
  const activeTurn = await activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notifications, turnStart.turn);
8625
+ let finalizedResult;
8196
8626
  try {
8197
- return await finalizeCodexAttempt(resources, turnRuntime, lifecycle, notifications, turnRequest, activeTurn);
8627
+ finalizedResult = await finalizeCodexAttempt(resources, turnRuntime, lifecycle, notifications, turnRequest, activeTurn);
8198
8628
  } finally {
8199
8629
  await cleanupCodexAttempt(resources, turnRuntime, lifecycle, turnRequest, activeTurn);
8200
8630
  }
8631
+ if (resources.state.executionDisconnectError && !connection.terminalState.explicitCancellationObserved) throw resources.state.executionDisconnectError;
8632
+ return finalizedResult;
8201
8633
  }
8202
8634
  //#endregion
8203
8635
  export { runCodexAppServerAttempt };