@openclaw/codex 2026.7.2-beta.4 → 2026.7.2-beta.7

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 (40) hide show
  1. package/dist/{app-server-policy-BO3jYBkv.js → app-server-policy-BSaO2JIT.js} +1 -1
  2. package/dist/{attempt-notifications-DdmnBMUp.js → attempt-notifications-AP-a-Q5k.js} +1 -1
  3. package/dist/{bounded-turn-CaQL96kg.js → bounded-turn-D2ZAgZVz.js} +54 -24
  4. package/dist/{capabilities-CLICvTxf.js → capabilities-BFDTVYr4.js} +1 -1
  5. package/dist/cli-metadata.js +1 -1
  6. package/dist/{command-formatters-DgADqnHa.js → command-formatters-C336eRVS.js} +2 -2
  7. package/dist/{command-handlers-l_lVPNlB.js → command-handlers-DAHUSry9.js} +1233 -1222
  8. package/dist/{compact-CC5KhBzX.js → compact-D_uvHurS.js} +8 -8
  9. package/dist/{computer-use-Ip1-QGa-.js → computer-use-CYEc8U3w.js} +123 -115
  10. package/dist/{conversation-control-sNPsbTCP.js → conversation-control-xsIeXbo4.js} +6 -6
  11. package/dist/doctor-contract-api.js +24 -86
  12. package/dist/{dynamic-tools-CQI3UwqY.js → dynamic-tools-D2gYkSBO.js} +482 -91
  13. package/dist/effective-mcp-catalog-Bbd98Inw.js +114 -0
  14. package/dist/{event-projector-usage-D6tE7_qD.js → event-projector-usage-Xp4AlR2k.js} +20 -3
  15. package/dist/harness.js +19 -14
  16. package/dist/index.js +292 -328
  17. package/dist/media-understanding-provider.js +6 -1
  18. package/dist/{models-BNeMlHgg.js → models-BBMKU4jA.js} +2 -2
  19. package/dist/{notification-correlation-BGLixv5_.js → notification-correlation-CU6_AnOb.js} +3 -3
  20. package/dist/{plugin-app-cache-key-CvzvmBRz.js → plugin-app-cache-key-DztPafOA.js} +135 -42
  21. package/dist/{rate-limits-D0IJT-a6.js → rate-limits-CU-gVCCS.js} +1 -1
  22. package/dist/{request-BTccUTD3.js → request-qKh331yu.js} +3 -3
  23. package/dist/{run-attempt--858NXDl.js → run-attempt-CY9WlDLc.js} +1060 -402
  24. package/dist/{runtime-artifact-C2ITXdhM.js → runtime-artifact-CmtG_t1L.js} +90 -24
  25. package/dist/{sandbox-guard-D1Wky__S.js → sandbox-guard-NuhpXmPB.js} +4 -0
  26. package/dist/{session-binding-ZSMX1omP.js → session-binding-BXpo9ymA.js} +1006 -891
  27. package/dist/{session-catalog-DsKaezgR.js → session-catalog-DyOgR4WH.js} +289 -56
  28. package/dist/{session-cli-CYJTfRLG.js → session-cli-2PZaFLRh.js} +2 -2
  29. package/dist/{session-upstream-marker-D7XlI9us.js → session-upstream-marker-B6U7tLw5.js} +1 -1
  30. package/dist/{settled-turn-finalizer-DHltNgtF.js → settled-turn-finalizer-CXY2Z9dT.js} +19 -6
  31. package/dist/{shared-client-wmgNFNYp.js → shared-client-DTbvH-XV.js} +1993 -1720
  32. package/dist/{side-question-BfFZCsJ-.js → side-question-_ulBk1AL.js} +12 -10
  33. package/dist/{thread-lifecycle-cqrOlJkq.js → thread-lifecycle-DF53ogiA.js} +980 -346
  34. package/dist/{transcript-mirror-2p7kl6e4.js → transcript-mirror-DzsdNCf5.js} +80 -41
  35. package/dist/{upstream-session-fork-vPjwkT1i.js → upstream-session-fork-Dy4Xvuoj.js} +3 -3
  36. package/dist/{usage-DM_I3mPT.js → usage-CQ6GhD5-.js} +3 -3
  37. package/dist/{web-search-provider.runtime-Bx6HAc_k.js → web-search-provider.runtime-CCFhg2z5.js} +3 -3
  38. package/package.json +6 -8
  39. package/npm-shrinkwrap.json +0 -202
  40. package/dist/{auth-binding-C1czuHPA.js → auth-binding-B4FfbcCg.js} +1 -1
@@ -1,35 +1,36 @@
1
- import { A as isCodexAppServerStartupError, B as isCodexAppServerApprovalRequest, C as resolveCodexAppServerFallbackApiKeyCacheKey, D as resolveCodexAppServerHomeDir, F as resolveCodexTurnCompletionIdleTimeoutMs, H as isCodexAppServerConnectionClosedError, I as resolveCodexTurnTerminalIdleTimeoutMs, K as isCodexAppServerRequestTimeoutError, L as withCodexStartupTimeout, M as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, N as resolveCodexStartupTimeoutMs, O as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, P as resolveCodexTurnAssistantCompletionIdleTimeoutMs, Q as isJsonObject, R as CodexAppServerRpcError, S as resolveCodexAppServerAuthProfileIdForAgent, T as resolveCodexAppServerPreparedAuthHandoff, V as isCodexAppServerBrokenPipeError, Z as flattenCodexDynamicToolFunctions, _ as readCodexRateLimitsRevision, a as getLeasedSharedCodexAppServerClient, b as resolveCodexAppServerAuthAccountCacheKey, c as releaseLeasedSharedCodexAppServerClient, d as retireSharedCodexAppServerClientIfCurrent, g as ensureCodexAppServerClientRuntime, k as CodexAppServerStartupError, n as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, o as isCodexAppServerStartSelectionChangedError, t as clearSharedCodexAppServerClientIfCurrent, u as retainSharedCodexAppServerClientIfCurrent, v as readRecentCodexRateLimits, w as resolveCodexAppServerPreparedApiKeyCacheKey, x as resolveCodexAppServerAuthProfileId, y as rememberCodexRateLimitsRead } from "./shared-client-wmgNFNYp.js";
2
- import { S as updateActiveTurnItemIds, _ as readCodexNotificationItem, a as isCodexTurnAbortMarkerNotification, b as shouldDisarmAssistantCompletionIdleWatch, c as isPendingOpenClawDynamicToolCompletionNotification, d as isRawReasoningCompletionNotification, f as isRawToolOutputCompletionNotification, g as isTerminalTurnStatus, h as isRetryableErrorNotification, i as isAssistantCompletionReleaseNotification, l as isRawAssistantProgressNotification, m as isReasoningProgressNotification, n as describeNotificationActivity, o as isFileChangePatchUpdatedNotification, p as isReasoningItemCompletionNotification, r as isAssistantCommentaryCompletionNotification, s as isNativeToolProgressNotification, t as codexExecutionToolName, u as isRawFunctionToolOutputCompletionNotification, v as readNotificationItemId, x as updateActiveCompletionBlockerItemIds, y as readRawResponseToolCallId } from "./attempt-notifications-DdmnBMUp.js";
3
- import { A as withMcpElicitationsApprovalPolicy, E as resolveCodexPluginsPolicy, O as resolveOpenClawExecPolicyForCodexAppServer, T as resolveCodexModelBackedReviewerPolicyContext, _ as isCodexAppServerApprovalPolicyAllowedByRequirements, b as readCodexPluginConfig, c as reclaimCurrentCodexSessionGeneration, i as createCodexSessionGenerationSupersededError, k as shouldAutoApproveCodexAppServerApprovals, l as sessionBindingIdentity, w as resolveCodexComputerUseConfig, y as isCodexSandboxExecServerEnabled } from "./session-binding-ZSMX1omP.js";
4
- import { $ as shouldBuildCodexPluginThreadConfig, B as codexDynamicToolsFingerprint, F as closeCodexStartupClientBestEffort, G as projectContextEngineAssemblyForCodex, H as buildContextEngineBinding, I as interruptCodexTurnBestEffort, K as resolveCodexContextEngineProjectionMaxChars, L as retireCodexAppServerClientAfterTimedOutTurn, M as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS, N as CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS, O as isSystemAgentOnlyCodexDynamicToolAllowlist, P as CodexAppServerUnsafeSubscriptionError, Q as mergeCodexThreadConfigs, R as unsubscribeCodexThreadBestEffort, T as filterCodexDynamicTools, U as isContextEngineBindingCompatible, V as codexLegacyDynamicToolsFingerprint, W as fitCodexProjectedContextForTurnStart, X as buildCodexPluginThreadConfigInputFingerprint, Y as buildCodexPluginThreadConfig, Z as buildCodexPluginThreadConfigTimeoutFallback, a as sanitizeCodexHistoryImagePayloads, at as readCodexErrorNotificationMessage, b as resolveCodexAppServerThreadModelSelection, ct as readItemString, dt as readNonNegativeInteger, ft as readNullableString$1, g as buildDeveloperInstructions, h as resolveCodexWebSearchPlan, ht as splitPlanText, it as normalizeNonEmptyString, j as resolveCodexDynamicToolsLoadingForRuntime, lt as readNonEmptyString$1, mt as readString$5, n as buildTurnStartParams, nt as resolveRecoverableCodexPluginConfigKeys, ot as readHookOutputEntries, pt as readNumber, q as resolveCodexContextEngineProjectionReserveTokens, r as buildCodexUserInput, rt as extractRawAssistantText, s as startOrResumeThread, st as readItem, t as buildTurnCollaborationMode, ut as readNonEmptyStringArray, w as isCodexAppServerProfilerEnabled, z as areCodexDynamicToolFingerprintsCompatible } from "./thread-lifecycle-cqrOlJkq.js";
5
- import { n as projectCodexThreadUsageUpdate, t as normalizeCodexResponseTokenUsage } from "./event-projector-usage-D6tE7_qD.js";
6
- import { C as readCodexTurnCompletedNotification, S as readCodexTurn, d as attachCodexMirrorIdentity, f as readMirrorIdentity, i as mirrorPromptAtTurnStartBestEffort, n as createCodexAppServerUserMessagePersistenceNotifier, o as buildCodexUserPromptMessage, s as promptSnapshot, t as codexTranscriptMirrorRuntime, u as serializeCodexMirrorSourceEvidence, v as assertCodexTurnStartResponse, y as readCodexDynamicToolCallParams } from "./transcript-mirror-2p7kl6e4.js";
7
- import { i as defaultCodexAppInventoryCache, n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-CvzvmBRz.js";
1
+ import { $ as resolveCodexTurnAssistantCompletionIdleTimeoutMs, A as retainCodexAppServerLiveThread, D as resolveCodexAppServerClientInstanceId, E as isCodexAppServerRequestTimeoutError, F as resolveCodexAppServerAuthProfileId, I as resolveCodexAppServerAuthProfileIdForAgent, J as CodexAppServerStartupError, K as resolveCodexAppServerHomeDir, L as resolveCodexAppServerFallbackApiKeyCacheKey, M as readRecentCodexRateLimits, N as rememberCodexRateLimitsRead, P as resolveCodexAppServerAuthAccountCacheKey, Q as resolveCodexStartupTimeoutMs, R as resolveCodexAppServerPreparedApiKeyCacheKey, S as isCodexAppServerConnectionClosedError, U as flattenCodexDynamicToolFunctions, W as isJsonObject, Y as isCodexAppServerStartupError, Z as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, a as getLeasedSharedCodexAppServerClient, b as isCodexAppServerApprovalRequest, et as resolveCodexTurnCompletionIdleTimeoutMs, f as retainSharedCodexAppServerClientIfCurrent, j as readCodexRateLimitsRevision, k as ensureCodexAppServerClientRuntime, l as releaseLeasedSharedCodexAppServerClient, n as clearSharedCodexAppServerClientIfCurrentAndUnclaimed, nt as withCodexStartupTimeout, o as getSharedCodexAppServerClient, p as retireSharedCodexAppServerClientIfCurrent, q as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, s as isCodexAppServerStartSelectionChangedError, t as clearSharedCodexAppServerClientIfCurrent, tt as resolveCodexTurnTerminalIdleTimeoutMs, v as CodexAppServerRpcError, x as isCodexAppServerBrokenPipeError, y as getCodexAppServerClientInstanceId, z as resolveCodexAppServerPreparedAuthHandoff } from "./shared-client-DTbvH-XV.js";
2
+ import { A as resolveOpenClawExecPolicyForCodexAppServer, D as isCodexSandboxExecServerEnabled, E as isCodexAppServerApprovalPolicyAllowedByRequirements, O as readCodexPluginConfig, S as withMcpElicitationsApprovalPolicy, T as resolveCodexModelBackedReviewerPolicyContext, c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, h as resolveCodexAppServerHomeScope, i as createCodexSessionGenerationSupersededError, k as resolveCodexPluginsPolicy, l as resolveCodexRunSessionBindingAuthority, u as scopeCodexRunBindingStore, v as resolveCodexComputerUseConfig, x as shouldAutoApproveCodexAppServerApprovals } from "./session-binding-BXpo9ymA.js";
3
+ import { $ as readCodexErrorNotificationMessage, B as resolveCodexContextEngineProjectionReserveTokens, F as buildContextEngineBinding, G as mergeCodexThreadConfigs, H as buildCodexPluginThreadConfig, I as isContextEngineBindingCompatible, K as shouldBuildCodexPluginThreadConfig, L as fitCodexProjectedContextForTurnStart, M as areCodexDynamicToolFingerprintsCompatible, N as codexDynamicToolsFingerprint, O as isSystemAgentOnlyCodexDynamicToolAllowlist, P as codexLegacyDynamicToolsFingerprint, Q as normalizeNonEmptyString, R as projectContextEngineAssemblyForCodex, T as filterCodexDynamicTools, U as buildCodexPluginThreadConfigInputFingerprint, W as buildCodexPluginThreadConfigTimeoutFallback, X as resolveRecoverableCodexPluginConfigKeys, Z as extractRawAssistantText, _ as buildDeveloperInstructions, _t as unsubscribeCodexThreadBestEffort, a as sanitizeCodexHistoryImagePayloads, at as readNonNegativeInteger, c as isCodexAppServerProfilerEnabled, ct as readString$6, dt as CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS, et as readHookOutputEntries, ft as CodexAppServerUnsafeSubscriptionError, g as resolveCodexWebSearchPlan, gt as retireCodexAppServerClientAfterTimedOutTurn, ht as interruptCodexTurnBestEffort, it as readNonEmptyStringArray, j as resolveCodexDynamicToolsLoadingForRuntime, lt as splitPlanText, n as buildTurnStartParams, nt as readItemString, ot as readNullableString$1, pt as closeCodexStartupClientBestEffort, r as buildCodexUserInput, rt as readNonEmptyString$1, s as startOrResumeThread, st as readNumber, t as buildTurnCollaborationMode, tt as readItem, ut as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS, x as resolveCodexAppServerThreadModelSelection, z as resolveCodexContextEngineProjectionMaxChars } from "./thread-lifecycle-DF53ogiA.js";
4
+ import { S as updateActiveTurnItemIds, _ as readCodexNotificationItem, a as isCodexTurnAbortMarkerNotification, b as shouldDisarmAssistantCompletionIdleWatch, c as isPendingOpenClawDynamicToolCompletionNotification, d as isRawReasoningCompletionNotification, f as isRawToolOutputCompletionNotification, g as isTerminalTurnStatus, h as isRetryableErrorNotification, i as isAssistantCompletionReleaseNotification, l as isRawAssistantProgressNotification, m as isReasoningProgressNotification, n as describeNotificationActivity, o as isFileChangePatchUpdatedNotification, p as isReasoningItemCompletionNotification, r as isAssistantCommentaryCompletionNotification, s as isNativeToolProgressNotification, t as codexExecutionToolName, u as isRawFunctionToolOutputCompletionNotification, v as readNotificationItemId, x as updateActiveCompletionBlockerItemIds, y as readRawResponseToolCallId } from "./attempt-notifications-AP-a-Q5k.js";
5
+ import { r as projectCodexThreadUsageUpdate, t as CodexResponseCompletionProjection } from "./event-projector-usage-Xp4AlR2k.js";
6
+ import { C as readCodexTurnCompletedNotification, S as readCodexTurn, d as attachCodexMirrorIdentity, f as readMirrorIdentity, i as mirrorPromptAtTurnStartBestEffort, n as createCodexAppServerUserMessagePersistenceNotifier, o as buildCodexUserPromptMessage, s as promptSnapshot, t as codexTranscriptMirrorRuntime, u as serializeCodexMirrorSourceEvidence, v as assertCodexTurnStartResponse, y as readCodexDynamicToolCallParams } from "./transcript-mirror-DzsdNCf5.js";
7
+ import { i as defaultCodexAppInventoryCache, n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-DztPafOA.js";
8
8
  import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
9
- import { t as CODEX_CONTROL_METHODS } from "./capabilities-CLICvTxf.js";
10
- import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-D0IJT-a6.js";
11
- import { r as formatCodexDisplayText } from "./command-formatters-DgADqnHa.js";
12
- import { n as resolveCodexAppServerForOpenClawToolPolicy, t as resolveCodexAppServerForModelProvider } from "./app-server-policy-BO3jYBkv.js";
13
- import { a as resolveCodexBindingAppServerConnection, n as readCodexNotificationThreadId, r as readCodexNotificationTurnId, t as isCodexNotificationForTurn } from "./notification-correlation-BGLixv5_.js";
14
- import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-C1czuHPA.js";
9
+ import { t as CODEX_CONTROL_METHODS } from "./capabilities-BFDTVYr4.js";
10
+ import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-CU-gVCCS.js";
11
+ import { r as formatCodexDisplayText } from "./command-formatters-C336eRVS.js";
12
+ import { n as resolveCodexAppServerForOpenClawToolPolicy, t as resolveCodexAppServerForModelProvider } from "./app-server-policy-BSaO2JIT.js";
13
+ import { a as resolveCodexBindingAppServerConnection, n as readCodexNotificationThreadId, r as readCodexNotificationTurnId, t as isCodexNotificationForTurn } from "./notification-correlation-CU6_AnOb.js";
14
+ import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-B4FfbcCg.js";
15
15
  import { i as resolveCodexLocalRuntimeAttribution, n as createAssistantMessage, r as createAssistantMirrorMessage, t as createAssistantCommentaryMessage } from "./event-projector-assistant-message-DTgnPPVF.js";
16
- import { $ as shouldSynthesizeToolProgressForItem, A as resolveCodexNativeHookRelayEvents, B as shouldReleaseTurnAfterTerminalDynamicTool, C as CodexNativeToolLifecycleProjector, D as buildCodexNativeHookRelayDisabledConfig, E as buildCodexNativeHookRelayConfig, F as isDynamicToolTerminalDiagnosticEvent, G as isNonSuccessItemStatus, H as toCodexDynamicToolProtocolResponse, I as isMatchingDynamicToolTerminalDiagnostic, J as itemName, K as isSideEffectingNativeToolItem, L as resolveDynamicToolCallTimeoutMs, M as scheduleCodexNativeHookRelayUnregister, N as handleDynamicToolCallWithTimeout, O as createCodexNativeHookRelay, P as hasPendingDynamicToolTerminalDiagnostic, Q as shouldRecordNativeToolTranscript, R as resolveTerminalDynamicToolBatchAction, T as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, U as resolveCodexToolAbortTerminalReason, V as toCodexDynamicToolProgressResponse, W as isMutatingNativeToolItem, X as itemTitle, Y as itemStatus, Z as shouldClearTerminalPresentationForNativeItem, _ as resolveCodexMessageToolProvider, a as emitDynamicToolStartedDiagnostic, b as shouldRequireCodexSandboxExecServerEnvironment, d as createCodexDynamicToolBuildStageTracker, et as unknownItemStatus, f as disableCodexPluginThreadConfig, g as resolveCodexExternalSandboxPolicyForOpenClawSandbox, h as resolveCodexAppServerHookChannelId, i as emitDynamicToolErrorDiagnostic, j as resolveCodexNativeHookRelayTtlMs, k as emitCodexNativePreToolUseFailureDiagnostic, l as settleCodexSourceReplyFinality, m as resolveCodexAppServerExecutionCwd, n as handleCodexAppServerApprovalRequest, o as emitDynamicToolTerminalDiagnostic, p as formatCodexDynamicToolBuildStageSummary, q as itemKind, r as handleCodexAppServerElicitationRequest, s as resolveCodexProviderWebSearchSupport, t as createCodexDynamicToolBridge, u as buildDynamicTools, v as resolveCodexSandboxEnvironmentSelection, x as shouldWarnCodexDynamicToolBuildStageSummary, y as shouldEnableCodexAppServerNativeToolSurface, z as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult } from "./dynamic-tools-CQI3UwqY.js";
17
- import { a as runCodexComputerUseLiveTest, r as killStaleComputerUseMcpChildren, t as ensureCodexComputerUse } from "./computer-use-Ip1-QGa-.js";
16
+ import { $ as shouldClearTerminalPresentationForNativeItem, A as createCodexNativeHookRelay, B as resolveTerminalDynamicToolBatchAction, D as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, F as handleDynamicToolCallWithTimeout, G as resolveCodexToolAbortTerminalReason, H as shouldReleaseTurnAfterTerminalDynamicTool, I as hasPendingDynamicToolTerminalDiagnostic, J as isSideEffectingNativeToolItem, K as isMutatingNativeToolItem, L as isDynamicToolTerminalDiagnosticEvent, M as resolveCodexNativeHookRelayEvents, N as resolveCodexNativeHookRelayTtlMs, O as buildCodexNativeHookRelayConfig, P as scheduleCodexNativeHookRelayUnregister, Q as itemTitle, R as isMatchingDynamicToolTerminalDiagnostic, S as shouldWarnCodexDynamicToolBuildStageSummary, T as CodexNativeToolLifecycleProjector, U as toCodexDynamicToolProgressResponse, V as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, W as toCodexDynamicToolProtocolResponse, X as itemName, Y as itemKind, Z as itemStatus, _ as resolveCodexExternalSandboxPolicyForOpenClawSandbox, a as emitDynamicToolStartedDiagnostic, b as shouldEnableCodexAppServerNativeToolSurface, d as buildDynamicTools, et as shouldRecordNativeToolTranscript, f as createCodexDynamicToolBuildStageTracker, g as resolveCodexAppServerHookChannelId, h as resolveCodexAppServerExecutionCwd, i as emitDynamicToolErrorDiagnostic, j as emitCodexNativePreToolUseFailureDiagnostic, k as buildCodexNativeHookRelayDisabledConfig, l as buildCodexHookRequester, m as formatCodexDynamicToolBuildStageSummary, n as handleCodexAppServerApprovalRequest, nt as unknownItemStatus, o as emitDynamicToolTerminalDiagnostic, p as disableCodexPluginThreadConfig, q as isNonSuccessItemStatus, r as handleCodexAppServerElicitationRequest, s as resolveCodexProviderWebSearchSupport, t as createCodexDynamicToolBridge, tt as shouldSynthesizeToolProgressForItem, u as settleCodexSourceReplyFinality, v as resolveCodexMessageToolProvider, w as readBoundedCodexRemoteWorkspaceFile, x as shouldRequireCodexSandboxExecServerEnvironment, y as resolveCodexSandboxEnvironmentSelection, z as resolveDynamicToolCallTimeoutMs } from "./dynamic-tools-D2gYkSBO.js";
17
+ import { a as killStaleComputerUseMcpChildren, i as runCodexComputerUseLiveTest, t as ensureCodexComputerUse } from "./computer-use-CYEc8U3w.js";
18
18
  import fs from "node:fs/promises";
19
19
  import path, { posix } from "node:path";
20
20
  import { asDateTimestampMs, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
21
- import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
21
+ import { AgentHarnessPreflightError, CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, TOOL_PROGRESS_OUTPUT_MAX_CHARS, agentHarnessAttemptTerminal, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildAgentHarnessUserInputAnswers, buildBootstrapContextForFiles, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, buildWatchedSessionsHarnessContext, callGatewayTool, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, deliverAgentHarnessUserInputPrompt, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, finalizeHarnessContextEngineTurn, formatErrorMessage, formatFastModeAutoProgressText, formatToolAggregate, formatToolProgressOutput, getAgentHarnessHookRunner, getBeforeToolCallPolicyDiagnosticState, inferToolMetaFromArgs, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, prepareHarnessNativeMcpAppPreview, projectAgentHarnessTranscriptMessageForDisplay, resolveAgentDir, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveSessionAgentIds, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessGatewayQuestion, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
22
22
  import { createHash, randomUUID } from "node:crypto";
23
- import { markAuthProfileBlockedUntil, resolveAgentDir, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
23
+ import { markAuthProfileBlockedUntil, resolveAgentDir as resolveAgentDir$1, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
24
24
  import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
25
25
  import { asFiniteNumber, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
26
- import { CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, TOOL_PROGRESS_OUTPUT_MAX_CHARS, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildAgentHarnessUserInputAnswers, buildBootstrapContextForFiles, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, callGatewayTool, cancelPendingAgentQuestionForSession, claimPendingAgentQuestionAnswer, classifyAgentHarnessTerminalOutcome, clearActiveEmbeddedRun, deliverAgentHarnessUserInputPrompt, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, finalizeHarnessContextEngineTurn, formatErrorMessage, formatFastModeAutoProgressText, formatToolAggregate, formatToolProgressOutput, getAgentHarnessHookRunner, getBeforeToolCallPolicyDiagnosticState, inferToolMetaFromArgs, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, projectAgentHarnessTranscriptMessageForDisplay, resolveAgentDir as resolveAgentDir$1, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveSessionAgentIds as resolveSessionAgentIds$1, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessAfterCompactionHook, runAgentHarnessAfterToolCallHook, runAgentHarnessBeforeCompactionHook, runAgentHarnessGatewayQuestion, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
26
+ import { SsrFBlockedError, isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
27
+ import { getSessionEntry, parseSqliteSessionFileMarker, resolveTranscriptSessionKeyBySessionId } from "openclaw/plugin-sdk/session-store-runtime";
27
28
  import { spawn } from "node:child_process";
29
+ import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
28
30
  import { once } from "node:events";
29
31
  import { isIP } from "node:net";
30
32
  import { WebSocketServer } from "ws";
31
- import { listSessionEntries, parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
32
- import { fileURLToPath } from "node:url";
33
+ import { fileURLToPath, pathToFileURL } from "node:url";
33
34
  import { redactSensitiveFieldValue, redactSensitiveText, redactToolPayloadText } from "openclaw/plugin-sdk/logging-core";
34
35
  import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
35
36
  import { readSessionTranscriptEvents } from "openclaw/plugin-sdk/session-transcript-runtime";
@@ -37,10 +38,11 @@ import { prepareMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
37
38
  import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
38
39
  import { buildSessionContext, migrateSessionEntries, parseSessionEntries } from "openclaw/plugin-sdk/agent-sessions";
39
40
  import { generatedImageAssetFromBase64 } from "openclaw/plugin-sdk/image-generation";
41
+ import { resolveGeneratedMediaMaxBytes } from "openclaw/plugin-sdk/media-generation-runtime";
40
42
  import { saveMediaBuffer } from "openclaw/plugin-sdk/media-store";
43
+ import { root } from "openclaw/plugin-sdk/file-access-runtime";
41
44
  import { MESSAGE_TOOL_DELIVERY_HINTS } from "openclaw/plugin-sdk/message-tool-delivery-hints";
42
45
  import { createAgentHarnessTaskRuntime, deliverAgentHarnessTaskCompletion, isDurableAgentHarnessCompletionDelivery } from "openclaw/plugin-sdk/agent-harness-task-runtime";
43
- import { SsrFBlockedError, isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
44
46
  //#region extensions/codex/src/app-server/attempt-steering.ts
45
47
  /**
46
48
  * Debounced steering queue for forwarding user messages to an active Codex
@@ -201,6 +203,9 @@ function normalizeCodexSteerDebounceMs(value) {
201
203
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : CODEX_STEER_ALL_DEBOUNCE_MS;
202
204
  }
203
205
  //#endregion
206
+ //#region extensions/codex/src/app-server/attempt-terminal.ts
207
+ const attemptTerminal = agentHarnessAttemptTerminal;
208
+ //#endregion
204
209
  //#region extensions/codex/src/app-server/event-projector-assistant.ts
205
210
  var CodexAssistantProjection = class {
206
211
  constructor(params, emitAgentEvent, matchesToolProgressEcho, nextTranscriptTimestamp) {
@@ -244,8 +249,8 @@ var CodexAssistantProjection = class {
244
249
  return this.latestTerminalAssistantCandidateCanReleaseAfterToolHandoff && this.hasLatestTerminalAssistantCandidateText();
245
250
  }
246
251
  async handleAssistantDelta(params) {
247
- const itemId = readString$5(params, "itemId") ?? "assistant";
248
- const delta = readString$5(params, "delta") ?? "";
252
+ const itemId = readString$6(params, "itemId") ?? "assistant";
253
+ const delta = readString$6(params, "delta") ?? "";
249
254
  if (!delta) return;
250
255
  if (itemId !== this.pendingRawTerminalAssistantEchoItemId) this.pendingRawTerminalAssistantEchoItemId = void 0;
251
256
  const isCommentary = this.isCommentaryAssistantItem(itemId);
@@ -327,9 +332,9 @@ var CodexAssistantProjection = class {
327
332
  }
328
333
  }
329
334
  handleRawResponseItemCompleted(item, activeItemIds) {
330
- const role = readString$5(item, "role");
331
- const phase = readString$5(item, "phase");
332
- const rawItemId = readString$5(item, "id");
335
+ const role = readString$6(item, "role");
336
+ const phase = readString$6(item, "phase");
337
+ const rawItemId = readString$6(item, "id");
333
338
  const candidateWasSupersededBeforeRaw = this.latestTerminalAssistantCandidateSuperseded;
334
339
  const pendingTerminalAssistantEchoItemId = this.pendingRawTerminalAssistantEchoItemId;
335
340
  const isPendingTerminalAssistantEcho = role === "assistant" && phase !== "commentary" && pendingTerminalAssistantEchoItemId !== void 0 && (rawItemId === void 0 || rawItemId === pendingTerminalAssistantEchoItemId);
@@ -388,7 +393,11 @@ var CodexAssistantProjection = class {
388
393
  return;
389
394
  }
390
395
  const turnItems = turn.items ?? [];
391
- const authoritativeIndex = turnItems.findLastIndex((item) => item.type === "agentMessage" && readItemString(item, "phase") === "final_answer" && typeof item.text === "string" && item.text.trim().length > 0);
396
+ const authoritativeIndex = turnItems.findLastIndex((item) => {
397
+ if (item.type !== "agentMessage" || typeof item.text !== "string" || item.text.trim().length === 0) return false;
398
+ const phase = readItemString(item, "phase");
399
+ return phase === "final_answer" || phase === void 0;
400
+ });
392
401
  const authoritative = authoritativeIndex >= 0 ? turnItems[authoritativeIndex] : void 0;
393
402
  if (turnItems.slice(authoritativeIndex + 1).some(shouldClearTerminalPresentationForNativeItem) || authoritative?.id === this.latestTerminalAssistantCandidateItemId && this.latestTerminalAssistantCandidateSuperseded) {
394
403
  this.supersedeVisibleAnswerCandidate();
@@ -652,7 +661,7 @@ function collectDynamicToolContentText(contentItems) {
652
661
  if (!Array.isArray(contentItems)) return "";
653
662
  return contentItems.flatMap((entry) => {
654
663
  if (!isJsonObject(entry)) return [];
655
- const text = readString$5(entry, "text");
664
+ const text = readString$6(entry, "text");
656
665
  return text ? [text] : [];
657
666
  }).join("\n");
658
667
  }
@@ -1043,8 +1052,8 @@ var CodexToolProgressProjection = class {
1043
1052
  if (params.sideEffectEvidence === true) this.sideEffectingDynamicIds.add(params.callId);
1044
1053
  }
1045
1054
  handleOutputDelta(params, toolName) {
1046
- const itemId = readString$5(params, "itemId");
1047
- const delta = readString$5(params, "delta");
1055
+ const itemId = readString$6(params, "itemId");
1056
+ const delta = readString$6(params, "delta");
1048
1057
  if (!itemId || !delta) return;
1049
1058
  const storedOutput = this.output.append(itemId, delta);
1050
1059
  this.rememberEcho(itemId, {
@@ -1310,17 +1319,19 @@ async function readCodexMirroredSessionEntries(target) {
1310
1319
  }
1311
1320
  function resolveSqliteMarkerSessionKey(target, marker) {
1312
1321
  const explicitSessionKey = target.sessionKey?.trim();
1313
- if (explicitSessionKey) return explicitSessionKey;
1314
- const entries = listSessionEntries({
1322
+ if (explicitSessionKey) {
1323
+ const explicitEntry = getSessionEntry({
1324
+ agentId: marker.agentId,
1325
+ sessionKey: explicitSessionKey,
1326
+ storePath: marker.storePath
1327
+ });
1328
+ if (explicitEntry) return explicitEntry.sessionId === marker.sessionId ? explicitSessionKey : void 0;
1329
+ }
1330
+ return resolveTranscriptSessionKeyBySessionId({
1315
1331
  agentId: marker.agentId,
1316
- readOnly: true,
1332
+ sessionId: marker.sessionId,
1317
1333
  storePath: marker.storePath
1318
1334
  });
1319
- return (entries.find(({ entry }) => {
1320
- return entry.sessionId === marker.sessionId && entry.sessionFile === target.sessionFile;
1321
- }) ?? entries.find(({ entry }) => {
1322
- return entry.sessionId === marker.sessionId;
1323
- }))?.sessionKey;
1324
1335
  }
1325
1336
  //#endregion
1326
1337
  //#region extensions/codex/src/app-server/event-projector-tool-transcript.ts
@@ -1339,6 +1350,35 @@ const ZERO_USAGE = {
1339
1350
  }
1340
1351
  };
1341
1352
  const MISSING_TOOL_RESULT_ERROR = "OpenClaw recorded a native Codex tool.call without a matching tool.result before the turn completed.";
1353
+ const NATIVE_PATCH_REJECTION_RE = /^\s*patch rejected:\s*writing outside of the project;\s*rejected by user approval settings\s*$/iu;
1354
+ const CODE_MODE_NATIVE_PATCH_SOURCE_RE = /^\s*(?:\/\/[^\r\n]*\r?\n\s*)?(?:const|let)\s+([A-Za-z_$][\w$]*)\s*=\s*await\s+tools\.apply_patch\(\s*("(?:\\[\s\S]|[^"\\])*")\s*\)\s*;?\s*text\(\s*\1\s*\)\s*;?\s*$/u;
1355
+ const CODE_MODE_NATIVE_PATCH_RESULT_RE = /^\s*Script (completed|failed)\s*\r?\nWall time\s+\d+(?:\.\d+)?\s+seconds\s*\r?\nOutput:\s*([\s\S]*?)\s*$/iu;
1356
+ function readCodeModeNativePatchInput(source) {
1357
+ if (typeof source !== "string") return;
1358
+ const match = CODE_MODE_NATIVE_PATCH_SOURCE_RE.exec(source);
1359
+ if (!match?.[2]) return;
1360
+ try {
1361
+ const patch = JSON.parse(match[2]);
1362
+ return typeof patch === "string" && /^\*\*\* Begin Patch\r?\n[\s\S]*\r?\n\*\*\* End Patch(?:\r?\n)?$/u.test(patch) ? patch : void 0;
1363
+ } catch {
1364
+ return;
1365
+ }
1366
+ }
1367
+ function readInterceptedNativePatchInput(command) {
1368
+ if (typeof command !== "string") return;
1369
+ const lines = command.replace(/\r\n?/gu, "\n").split("\n");
1370
+ const patchStart = lines.indexOf("*** Begin Patch");
1371
+ const invocation = /^[\t ]*(?:cd[\t ]+(?:'([^'\n]+)'|([A-Za-z0-9_./-]+))[\t ]+&&[\t ]+)?apply_patch[\t ]*<<-?[\t ]*'([^'\n]+)'[\t ]*$/u.exec(lines[0] ?? "");
1372
+ if (!invocation || patchStart !== 1) return;
1373
+ const patchEnd = lines.indexOf("*** End Patch", patchStart + 1);
1374
+ const cwd = invocation[1] ?? invocation[2];
1375
+ const delimiter = invocation[3];
1376
+ if (patchEnd < 0 || lines[patchEnd + 1] !== delimiter || lines.slice(patchEnd + 2).some((line) => line.trim().length > 0)) return;
1377
+ return {
1378
+ input: `${lines.slice(patchStart, patchEnd + 1).join("\n")}\n`,
1379
+ ...cwd ? { cwd } : {}
1380
+ };
1381
+ }
1342
1382
  var CodexToolTranscriptProjection = class {
1343
1383
  constructor(params, threadId, turnId, progress, nextTranscriptTimestamp, options = {}) {
1344
1384
  this.params = params;
@@ -1356,6 +1396,10 @@ var CodexToolTranscriptProjection = class {
1356
1396
  this.trajectoryNamesById = /* @__PURE__ */ new Map();
1357
1397
  this.trajectoryItemsById = /* @__PURE__ */ new Map();
1358
1398
  this.afterToolCallObservedItemIds = /* @__PURE__ */ new Set();
1399
+ this.nativeMcpAppResultDetails = /* @__PURE__ */ new Map();
1400
+ this.nativeMcpAppResultDetailsAttempted = /* @__PURE__ */ new Set();
1401
+ this.rawNativeToolOutputByCallId = /* @__PURE__ */ new Map();
1402
+ this.codeModeNativePatchInputsByCallId = /* @__PURE__ */ new Map();
1359
1403
  }
1360
1404
  get transcriptMessages() {
1361
1405
  return this.messages;
@@ -1367,12 +1411,14 @@ var CodexToolTranscriptProjection = class {
1367
1411
  arguments: sanitizeCodexToolArguments(params.arguments)
1368
1412
  });
1369
1413
  }
1370
- recordDynamicToolResult(params) {
1414
+ recordDynamicToolResult(params, resultContentSource) {
1371
1415
  this.recordToolResult({
1372
1416
  id: params.callId,
1373
1417
  name: params.tool,
1374
1418
  text: collectDynamicToolContentText(params.contentItems),
1375
- isError: !params.success
1419
+ isError: !params.success,
1420
+ details: params.details,
1421
+ ...resultContentSource ? { resultContentSource } : {}
1376
1422
  });
1377
1423
  }
1378
1424
  recordNativeToolCall(item) {
@@ -1384,15 +1430,117 @@ var CodexToolTranscriptProjection = class {
1384
1430
  arguments: itemToolArgs(item)
1385
1431
  });
1386
1432
  }
1387
- recordNativeToolResult(item) {
1433
+ recordNativeToolResult(item, details) {
1388
1434
  if (!item || !shouldRecordNativeToolTranscript(item)) return;
1389
1435
  const name = itemName(item);
1390
1436
  if (name) this.recordToolResult({
1391
1437
  id: item.id,
1392
1438
  name,
1393
- text: itemTranscriptResultText(item, this.progress.outputTextByItem),
1394
- isError: isNonSuccessItemStatus(itemStatus(item))
1395
- });
1439
+ text: this.rawNativeToolOutputByCallId.get(item.id) ?? itemTranscriptResultText(item, this.progress.outputTextByItem),
1440
+ isError: isNonSuccessItemStatus(itemStatus(item)),
1441
+ details,
1442
+ ...item.type === "webSearch" ? { resultContentSource: "network" } : {}
1443
+ });
1444
+ }
1445
+ recordRawNativeToolItem(item) {
1446
+ const type = typeof item.type === "string" ? item.type : void 0;
1447
+ const callId = typeof item.call_id === "string" ? item.call_id : typeof item.callId === "string" ? item.callId : void 0;
1448
+ if (!callId) return;
1449
+ if ((type === "custom_tool_call" || type === "function_call") && (item.name === "apply_patch" || item.name === "exec_command" || item.name === "exec")) {
1450
+ let args;
1451
+ if (type === "custom_tool_call" && item.name === "apply_patch" && typeof item.input === "string") args = { input: item.input };
1452
+ else if (type === "custom_tool_call" && item.name === "exec") {
1453
+ const input = readCodeModeNativePatchInput(item.input);
1454
+ if (input) this.codeModeNativePatchInputsByCallId.set(callId, input);
1455
+ return;
1456
+ } else if (type === "function_call" && typeof item.arguments === "string") try {
1457
+ const parsed = JSON.parse(item.arguments);
1458
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
1459
+ const parsedArguments = parsed;
1460
+ if (item.name === "apply_patch") args = parsedArguments;
1461
+ else {
1462
+ const patch = readInterceptedNativePatchInput(typeof parsedArguments.cmd === "string" ? parsedArguments.cmd : typeof parsedArguments.command === "string" ? parsedArguments.command : void 0);
1463
+ if (patch) {
1464
+ const workdir = typeof parsedArguments.workdir === "string" ? parsedArguments.workdir : typeof parsedArguments.cwd === "string" ? parsedArguments.cwd : void 0;
1465
+ const cwd = patch.cwd ? workdir && !path.isAbsolute(patch.cwd) ? path.join(workdir, patch.cwd) : patch.cwd : workdir;
1466
+ args = {
1467
+ input: patch.input,
1468
+ ...cwd ? { cwd } : {}
1469
+ };
1470
+ }
1471
+ }
1472
+ }
1473
+ } catch {
1474
+ return;
1475
+ }
1476
+ if (args) this.recordToolCall({
1477
+ id: callId,
1478
+ name: "apply_patch",
1479
+ arguments: args
1480
+ });
1481
+ return;
1482
+ }
1483
+ if (type !== "custom_tool_call_output" && type !== "function_call_output" || this.namesById.get(callId) !== "apply_patch" && !this.codeModeNativePatchInputsByCallId.has(callId)) return;
1484
+ const text = typeof item.output === "string" ? item.output : Array.isArray(item.output) ? collectDynamicToolContentText(item.output) : "";
1485
+ if (!text.trim()) return;
1486
+ const codeModePatchInput = this.codeModeNativePatchInputsByCallId.get(callId);
1487
+ if (codeModePatchInput) {
1488
+ this.codeModeNativePatchInputsByCallId.delete(callId);
1489
+ const execution = CODE_MODE_NATIVE_PATCH_RESULT_RE.exec(text);
1490
+ if (execution?.[1]?.toLowerCase() === "completed" && execution[2]?.trim() === "{}") return;
1491
+ if (execution?.[1]?.toLowerCase() === "failed") {
1492
+ const failure = execution[2]?.replace(/^Script error:\s*/iu, "").trim() || text;
1493
+ this.recordToolCall({
1494
+ id: callId,
1495
+ name: "apply_patch",
1496
+ arguments: { input: codeModePatchInput }
1497
+ });
1498
+ this.recordToolResult({
1499
+ id: callId,
1500
+ name: "apply_patch",
1501
+ text: failure,
1502
+ isError: true
1503
+ });
1504
+ }
1505
+ return;
1506
+ }
1507
+ this.rawNativeToolOutputByCallId.set(callId, text);
1508
+ const result = this.messages.find((message) => message.role === "toolResult" && message.toolCallId === callId);
1509
+ if (!result) {
1510
+ if (NATIVE_PATCH_REJECTION_RE.test(text)) this.recordToolResult({
1511
+ id: callId,
1512
+ name: "apply_patch",
1513
+ text,
1514
+ isError: true
1515
+ });
1516
+ return;
1517
+ }
1518
+ result.content = this.createToolResultMessage({
1519
+ id: callId,
1520
+ name: "apply_patch",
1521
+ text,
1522
+ isError: result.isError === true
1523
+ }).content;
1524
+ }
1525
+ async recordNativeToolResultWithDetails(item) {
1526
+ this.recordNativeToolResult(item, await this.prepareNativeMcpAppResultDetails(item));
1527
+ }
1528
+ async prepareNativeMcpAppResultDetails(item) {
1529
+ if (!item || item.type !== "mcpToolCall" || itemStatus(item) === "running") return;
1530
+ if (this.nativeMcpAppResultDetails.has(item.id)) return this.nativeMcpAppResultDetails.get(item.id);
1531
+ if (this.nativeMcpAppResultDetailsAttempted.has(item.id) || !this.options.prepareNativeMcpAppResultDetails) return;
1532
+ this.nativeMcpAppResultDetailsAttempted.add(item.id);
1533
+ try {
1534
+ const details = await this.options.prepareNativeMcpAppResultDetails(item);
1535
+ if (details !== void 0) this.nativeMcpAppResultDetails.set(item.id, details);
1536
+ return details;
1537
+ } catch (error) {
1538
+ embeddedAgentLog.debug("codex native MCP App preview preparation failed", {
1539
+ itemId: item.id,
1540
+ error
1541
+ });
1542
+ return;
1543
+ }
1396
1544
  }
1397
1545
  recordTrajectoryEvent(params) {
1398
1546
  if (params.phase === "start") {
@@ -1489,10 +1637,11 @@ var CodexToolTranscriptProjection = class {
1489
1637
  output: text
1490
1638
  });
1491
1639
  }
1492
- if (!params.recordPromptError) {
1640
+ if (params.terminalDisposition === "tool_error") {
1493
1641
  this.recordMissingToolError(missingTranscriptIds, missingTrajectoryIds);
1494
1642
  return;
1495
1643
  }
1644
+ if (params.terminalDisposition === "diagnostic_only") return;
1496
1645
  const missingCount = (/* @__PURE__ */ new Set([...missingTranscriptIds, ...missingTrajectoryIds])).size;
1497
1646
  return missingCount === 1 ? MISSING_TOOL_RESULT_ERROR : `${MISSING_TOOL_RESULT_ERROR} missingToolResultCount=${missingCount}`;
1498
1647
  }
@@ -1578,6 +1727,8 @@ var CodexToolTranscriptProjection = class {
1578
1727
  content: text,
1579
1728
  text
1580
1729
  }],
1730
+ ...params.details !== void 0 ? { details: params.details } : {},
1731
+ ...params.resultContentSource ? { __openclaw: { resultContentSource: params.resultContentSource } } : {},
1581
1732
  timestamp: this.nextTranscriptTimestamp()
1582
1733
  };
1583
1734
  }
@@ -1616,14 +1767,14 @@ var CodexEventProjection = class {
1616
1767
  data: {
1617
1768
  method,
1618
1769
  phase: method.endsWith("/started") ? "started" : "completed",
1619
- reviewId: readString$5(params, "reviewId"),
1770
+ reviewId: readString$6(params, "reviewId"),
1620
1771
  targetItemId: readNullableString$1(params, "targetItemId"),
1621
- decisionSource: readString$5(params, "decisionSource"),
1622
- status: review ? readString$5(review, "status") : void 0,
1623
- riskLevel: review ? readString$5(review, "riskLevel") : void 0,
1624
- userAuthorization: review ? readString$5(review, "userAuthorization") : void 0,
1772
+ decisionSource: readString$6(params, "decisionSource"),
1773
+ status: review ? readString$6(review, "status") : void 0,
1774
+ riskLevel: review ? readString$6(review, "riskLevel") : void 0,
1775
+ userAuthorization: review ? readString$6(review, "userAuthorization") : void 0,
1625
1776
  rationale: review ? readNullableString$1(review, "rationale") : void 0,
1626
- actionType: action ? readString$5(action, "type") : void 0
1777
+ actionType: action ? readString$6(action, "type") : void 0
1627
1778
  }
1628
1779
  });
1629
1780
  }
@@ -1632,7 +1783,7 @@ var CodexEventProjection = class {
1632
1783
  stream: "codex_app_server.guardian",
1633
1784
  data: {
1634
1785
  phase: "warning",
1635
- message: readString$5(params, "message")
1786
+ message: readString$6(params, "message")
1636
1787
  }
1637
1788
  });
1638
1789
  }
@@ -1648,14 +1799,14 @@ var CodexEventProjection = class {
1648
1799
  phase: method === "hook/started" ? "started" : "completed",
1649
1800
  threadId: this.threadId,
1650
1801
  turnId: hookTurnId === void 0 ? this.turnId : hookTurnId,
1651
- hookRunId: readString$5(run, "id"),
1652
- eventName: readString$5(run, "eventName"),
1653
- handlerType: readString$5(run, "handlerType"),
1654
- executionMode: readString$5(run, "executionMode"),
1655
- scope: readString$5(run, "scope"),
1656
- source: readString$5(run, "source"),
1657
- sourcePath: readString$5(run, "sourcePath"),
1658
- status: readString$5(run, "status"),
1802
+ hookRunId: readString$6(run, "id"),
1803
+ eventName: readString$6(run, "eventName"),
1804
+ handlerType: readString$6(run, "handlerType"),
1805
+ executionMode: readString$6(run, "executionMode"),
1806
+ scope: readString$6(run, "scope"),
1807
+ source: readString$6(run, "source"),
1808
+ sourcePath: readString$6(run, "sourcePath"),
1809
+ status: readString$6(run, "status"),
1659
1810
  statusMessage: readNullableString$1(run, "statusMessage"),
1660
1811
  ...durationMs !== void 0 ? { durationMs } : {},
1661
1812
  ...entries.length > 0 ? { entries } : {}
@@ -1736,59 +1887,128 @@ var CodexEventProjection = class {
1736
1887
  //#endregion
1737
1888
  //#region extensions/codex/src/app-server/event-projector-media.ts
1738
1889
  const GENERATED_IMAGE_MEDIA_SUBDIR = "tool-image-generation";
1739
- const BYTES_PER_MB = 1024 * 1024;
1740
- const DEFAULT_GENERATED_IMAGE_MAX_BYTES = 6 * BYTES_PER_MB;
1741
1890
  var CodexGeneratedMediaProjection = class {
1742
- constructor(config) {
1891
+ constructor(config, remote) {
1743
1892
  this.config = config;
1893
+ this.remote = remote;
1744
1894
  this.itemIds = /* @__PURE__ */ new Set();
1745
1895
  this.urlsByItemId = /* @__PURE__ */ new Map();
1896
+ this.gatewayMaterializedItemIds = /* @__PURE__ */ new Set();
1897
+ this.pendingMaterializationsByItemId = /* @__PURE__ */ new Map();
1746
1898
  }
1747
1899
  hasGeneratedMedia() {
1748
1900
  return this.itemIds.size > 0;
1749
1901
  }
1750
- recordNative(item) {
1902
+ async recordNative(item) {
1751
1903
  if (item?.type !== "imageGeneration") return;
1904
+ this.itemIds.add(item.id);
1905
+ const result = readItemString(item, "result");
1906
+ if (result) {
1907
+ await this.recordImage({
1908
+ itemId: item.id,
1909
+ result,
1910
+ revisedPrompt: readItemString(item, "revisedPrompt"),
1911
+ source: "native"
1912
+ });
1913
+ return;
1914
+ }
1752
1915
  const savedPath = readItemString(item, "savedPath")?.trim();
1753
- if (savedPath) this.recordUrl({
1754
- itemId: item.id,
1755
- mediaUrl: savedPath
1756
- });
1916
+ if (savedPath) {
1917
+ if (this.remote?.remoteWorkspaceRoot) {
1918
+ if (!this.remote.readFile) {
1919
+ embeddedAgentLog.warn("codex remote image has no app-server file transfer", { itemId: item.id });
1920
+ return;
1921
+ }
1922
+ try {
1923
+ const response = await this.remote.readFile({
1924
+ path: savedPath,
1925
+ maxBytes: resolveGeneratedMediaMaxBytes(this.config, "image"),
1926
+ signal: this.remote.signal,
1927
+ timeoutMs: this.remote.requestTimeoutMs
1928
+ });
1929
+ if (!response || typeof response.dataBase64 !== "string" || !response.dataBase64) {
1930
+ embeddedAgentLog.warn("codex remote image file returned no inline bytes", { itemId: item.id });
1931
+ return;
1932
+ }
1933
+ await this.recordImage({
1934
+ itemId: item.id,
1935
+ result: response.dataBase64,
1936
+ revisedPrompt: readItemString(item, "revisedPrompt"),
1937
+ source: "native"
1938
+ });
1939
+ } catch (error) {
1940
+ embeddedAgentLog.warn("codex app-server remote image file read failed", {
1941
+ itemId: item.id,
1942
+ error
1943
+ });
1944
+ }
1945
+ return;
1946
+ }
1947
+ this.recordUrl({
1948
+ itemId: item.id,
1949
+ mediaUrl: savedPath
1950
+ });
1951
+ }
1757
1952
  }
1758
1953
  async recordRaw(item) {
1759
- if (readString$5(item, "type") !== "image_generation_call") return;
1760
- const result = readString$5(item, "result");
1954
+ if (readString$6(item, "type") !== "image_generation_call") return;
1955
+ const result = readString$6(item, "result");
1761
1956
  if (!result) return;
1762
- const itemId = readString$5(item, "id") ?? `raw-image-${this.itemIds.size}`;
1763
- this.itemIds.add(itemId);
1764
- const maxBytes = resolveGeneratedImageMaxBytes(this.config);
1765
- const estimatedDecodedBytes = estimateBase64DecodedBytes(result);
1957
+ const itemId = readString$6(item, "id") ?? `raw-image-${this.itemIds.size}`;
1958
+ await this.recordImage({
1959
+ itemId,
1960
+ result,
1961
+ revisedPrompt: readString$6(item, "revised_prompt") ?? readString$6(item, "revisedPrompt"),
1962
+ source: "raw"
1963
+ });
1964
+ }
1965
+ async recordImage(params) {
1966
+ this.itemIds.add(params.itemId);
1967
+ if (this.gatewayMaterializedItemIds.has(params.itemId)) return;
1968
+ let pending = this.pendingMaterializationsByItemId.get(params.itemId);
1969
+ while (pending) {
1970
+ await pending;
1971
+ if (this.gatewayMaterializedItemIds.has(params.itemId)) return;
1972
+ pending = this.pendingMaterializationsByItemId.get(params.itemId);
1973
+ }
1974
+ const materialization = this.materializeImage(params);
1975
+ this.pendingMaterializationsByItemId.set(params.itemId, materialization);
1976
+ try {
1977
+ await materialization;
1978
+ } finally {
1979
+ if (this.pendingMaterializationsByItemId.get(params.itemId) === materialization) this.pendingMaterializationsByItemId.delete(params.itemId);
1980
+ }
1981
+ }
1982
+ async materializeImage(params) {
1983
+ const maxBytes = resolveGeneratedMediaMaxBytes(this.config, "image");
1984
+ const estimatedDecodedBytes = estimateBase64DecodedBytes(params.result);
1766
1985
  if (estimatedDecodedBytes !== void 0 && estimatedDecodedBytes > maxBytes) {
1767
- embeddedAgentLog.warn("codex app-server raw image generation result exceeds media limit", {
1768
- itemId,
1986
+ embeddedAgentLog.warn(`codex app-server ${params.source} image generation result exceeds media limit`, {
1987
+ itemId: params.itemId,
1769
1988
  estimatedDecodedBytes,
1770
1989
  maxBytes
1771
1990
  });
1772
1991
  return;
1773
1992
  }
1774
1993
  const asset = generatedImageAssetFromBase64({
1775
- base64: result,
1994
+ base64: params.result,
1776
1995
  index: this.itemIds.size,
1777
- revisedPrompt: readString$5(item, "revised_prompt") ?? readString$5(item, "revisedPrompt"),
1996
+ revisedPrompt: params.revisedPrompt,
1778
1997
  fileNamePrefix: "codex-image-generation",
1779
1998
  sniffMimeType: true
1780
1999
  });
1781
2000
  if (!asset) return;
1782
2001
  try {
1783
2002
  const saved = await saveMediaBuffer(asset.buffer, asset.mimeType, GENERATED_IMAGE_MEDIA_SUBDIR, maxBytes, asset.fileName);
2003
+ this.gatewayMaterializedItemIds.add(params.itemId);
1784
2004
  this.recordUrl({
1785
- itemId,
2005
+ itemId: params.itemId,
1786
2006
  mediaUrl: saved.path,
1787
2007
  replaceExisting: true
1788
2008
  });
1789
2009
  } catch (error) {
1790
- embeddedAgentLog.warn("codex app-server raw image generation result save failed", {
1791
- itemId,
2010
+ embeddedAgentLog.warn(`codex app-server ${params.source} image generation result save failed`, {
2011
+ itemId: params.itemId,
1792
2012
  error
1793
2013
  });
1794
2014
  }
@@ -1831,11 +2051,6 @@ function estimateBase64DecodedBytes(base64) {
1831
2051
  function isBase64WhitespaceCode(code) {
1832
2052
  return code === 32 || code === 9 || code === 10 || code === 13;
1833
2053
  }
1834
- function resolveGeneratedImageMaxBytes(config) {
1835
- const configured = config?.agents?.defaults?.mediaMaxMb;
1836
- if (typeof configured === "number" && Number.isFinite(configured) && configured > 0) return Math.floor(configured * BYTES_PER_MB);
1837
- return DEFAULT_GENERATED_IMAGE_MAX_BYTES;
1838
- }
1839
2054
  //#endregion
1840
2055
  //#region extensions/codex/src/app-server/event-projector-reasoning.ts
1841
2056
  var CodexReasoningProjection = class {
@@ -1849,8 +2064,8 @@ var CodexReasoningProjection = class {
1849
2064
  this.reasoningEnded = false;
1850
2065
  }
1851
2066
  async handleReasoningDelta(method, params) {
1852
- const itemId = readString$5(params, "itemId") ?? "reasoning";
1853
- const delta = readString$5(params, "delta") ?? "";
2067
+ const itemId = readString$6(params, "itemId") ?? "reasoning";
2068
+ const delta = readString$6(params, "delta") ?? "";
1854
2069
  if (!delta) return;
1855
2070
  this.reasoningStarted = true;
1856
2071
  if (!this.reasoningItemOrder.has(itemId)) this.reasoningItemOrder.set(itemId, this.reasoningItemOrder.size);
@@ -1869,8 +2084,8 @@ var CodexReasoningProjection = class {
1869
2084
  });
1870
2085
  }
1871
2086
  handlePlanDelta(params) {
1872
- const itemId = readString$5(params, "itemId") ?? "plan";
1873
- const delta = readString$5(params, "delta") ?? "";
2087
+ const itemId = readString$6(params, "itemId") ?? "plan";
2088
+ const delta = readString$6(params, "delta") ?? "";
1874
2089
  if (!delta) return;
1875
2090
  const text = `${this.planTextByItem.get(itemId) ?? ""}${delta}`;
1876
2091
  this.planTextByItem.set(itemId, text);
@@ -1887,11 +2102,11 @@ var CodexReasoningProjection = class {
1887
2102
  const plan = Array.isArray(params.plan) ? params.plan.flatMap((entry) => {
1888
2103
  if (!entry || typeof entry !== "object" || Array.isArray(entry)) return [];
1889
2104
  const record = entry;
1890
- const step = readString$5(record, "step");
2105
+ const step = readString$6(record, "step");
1891
2106
  if (!step) return [];
1892
2107
  return [{
1893
2108
  step,
1894
- status: normalizePlanStepStatus(readString$5(record, "status"))
2109
+ status: normalizePlanStepStatus(readString$6(record, "status"))
1895
2110
  }];
1896
2111
  }) : void 0;
1897
2112
  const planText = [explanation, ...(plan ?? []).map(({ step, status }) => `- [${status}] ${step}`)].filter((part) => Boolean(part)).join("\n");
@@ -1955,6 +2170,28 @@ function reasoningMethodOrder(method) {
1955
2170
  }
1956
2171
  //#endregion
1957
2172
  //#region extensions/codex/src/app-server/event-projector-snapshot.ts
2173
+ function readTurnTaintMetadata(message) {
2174
+ const metadata = message["__openclaw"];
2175
+ return metadata && typeof metadata === "object" && !Array.isArray(metadata) ? metadata : void 0;
2176
+ }
2177
+ function applyStickyTurnTaint(messages) {
2178
+ let tainted = false;
2179
+ return messages.map((message) => {
2180
+ if (message.role === "user") {
2181
+ tainted = false;
2182
+ return message;
2183
+ }
2184
+ const metadata = readTurnTaintMetadata(message);
2185
+ tainted ||= metadata?.turnTainted === true || metadata?.resultContentSource === "network";
2186
+ return message.role === "assistant" && tainted ? {
2187
+ ...message,
2188
+ __openclaw: {
2189
+ ...metadata,
2190
+ turnTainted: true
2191
+ }
2192
+ } : message;
2193
+ });
2194
+ }
1958
2195
  function buildCodexMessagesSnapshot(params) {
1959
2196
  const messages = promptSnapshot(params.runParams, params.turnId, params.upstreamUserText);
1960
2197
  if (params.reasoningText) messages.push(attachCodexMirrorIdentity(params.createAssistantMirrorMessage("Codex reasoning", params.reasoningText), `${params.turnId}:reasoning`));
@@ -1962,7 +2199,7 @@ function buildCodexMessagesSnapshot(params) {
1962
2199
  const visibleWorkMessages = [...params.runParams.config?.ui?.prefs?.chatPersistCommentary === false ? [] : params.commentaryMessages.map(({ itemId, message }) => attachCodexMirrorIdentity(message, `${params.turnId}:commentary:${itemId}`)), ...params.toolMessages].toSorted((left, right) => (asDateTimestampMs(left.timestamp) ?? 0) - (asDateTimestampMs(right.timestamp) ?? 0));
1963
2200
  messages.push(...visibleWorkMessages);
1964
2201
  if (params.lastAssistant) messages.push(attachCodexMirrorIdentity(params.lastAssistant, `${params.turnId}:assistant`));
1965
- return messages.map((message) => projectAgentHarnessTranscriptMessageForDisplay({
2202
+ return applyStickyTurnTaint(messages).map((message) => projectAgentHarnessTranscriptMessageForDisplay({
1966
2203
  hidden: params.runParams.trigger === "memory",
1967
2204
  message
1968
2205
  }));
@@ -2086,7 +2323,7 @@ function readCodexErrorNotification(notification) {
2086
2323
  if (notification?.method !== "error" || !isJsonObject(notification.params)) return;
2087
2324
  const error = notification.params.error;
2088
2325
  return isJsonObject(error) ? {
2089
- message: readString$4(error, "message"),
2326
+ message: readString$5(error, "message"),
2090
2327
  codexErrorInfo: error.codexErrorInfo
2091
2328
  } : void 0;
2092
2329
  }
@@ -2098,12 +2335,12 @@ function readCodexErrorPayload(error) {
2098
2335
  const nestedError = isJsonObject(data.error) ? data.error : data;
2099
2336
  const rateLimits = nestedError.rateLimits ?? data.rateLimits;
2100
2337
  return {
2101
- message: readString$4(nestedError, "message") ?? message,
2338
+ message: readString$5(nestedError, "message") ?? message,
2102
2339
  codexErrorInfo: nestedError.codexErrorInfo,
2103
2340
  rateLimits
2104
2341
  };
2105
2342
  }
2106
- function readString$4(record, key) {
2343
+ function readString$5(record, key) {
2107
2344
  const value = record[key];
2108
2345
  return typeof value === "string" ? value : void 0;
2109
2346
  }
@@ -2123,14 +2360,21 @@ var CodexAppServerEventProjector = class {
2123
2360
  this.promptErrorSource = null;
2124
2361
  this.synthesizedMissingToolResultError = null;
2125
2362
  this.aborted = false;
2363
+ this.responseCompletions = new CodexResponseCompletionProjection();
2126
2364
  this.completedCompactionCount = 0;
2127
2365
  this.lastTranscriptTimestamp = 0;
2128
2366
  this.diagnostics = new CodexProjectionDiagnostics(threadId, turnId);
2129
2367
  this.nativeToolLifecycleProjector = new CodexNativeToolLifecycleProjector(params, threadId, turnId, { runAbortSignal: options.runAbortSignal });
2130
- this.generatedMediaProjection = new CodexGeneratedMediaProjection(params.config);
2368
+ this.generatedMediaProjection = new CodexGeneratedMediaProjection(params.config, {
2369
+ remoteWorkspaceRoot: options.remoteWorkspaceRoot,
2370
+ readFile: options.readRemoteWorkspaceFile,
2371
+ requestTimeoutMs: options.remoteWorkspaceRequestTimeoutMs,
2372
+ signal: options.runAbortSignal
2373
+ });
2131
2374
  this.toolProgressProjection = new CodexToolProgressProjection(params);
2132
2375
  this.toolTranscriptProjection = new CodexToolTranscriptProjection(params, threadId, turnId, this.toolProgressProjection, () => this.nextTranscriptTimestamp(), {
2133
2376
  nativePostToolUseRelayEnabled: options.nativePostToolUseRelayEnabled,
2377
+ prepareNativeMcpAppResultDetails: options.prepareNativeMcpAppResultDetails,
2134
2378
  trajectoryRecorder: options.trajectoryRecorder
2135
2379
  });
2136
2380
  this.eventProjection = new CodexEventProjection(threadId, turnId, (event) => this.emitAgentEvent(event), this.toolProgressProjection, this.toolTranscriptProjection, options.onNativeToolResultRecorded);
@@ -2229,13 +2473,13 @@ var CodexAppServerEventProjector = class {
2229
2473
  await this.handleTurnCompleted(params);
2230
2474
  break;
2231
2475
  case "rawResponse/completed":
2232
- this.handleRawResponseCompleted(params);
2476
+ this.responseCompletions.record(params);
2233
2477
  break;
2234
2478
  case "rawResponseItem/completed":
2235
2479
  await this.handleRawResponseItemCompleted(params);
2236
2480
  break;
2237
2481
  case "error":
2238
- this.responseUsage = void 0;
2482
+ this.responseCompletions.clear();
2239
2483
  if (params.willRetry === true) break;
2240
2484
  this.promptError = this.formatCodexErrorMessage(params) ?? "codex app-server error";
2241
2485
  this.promptErrorSource = "prompt";
@@ -2263,13 +2507,14 @@ var CodexAppServerEventProjector = class {
2263
2507
  const commentaryMessages = this.assistantProjection.collectCommentaryMessages();
2264
2508
  const reasoningText = this.reasoningProjection.reasoningText();
2265
2509
  const planText = this.reasoningProjection.planText();
2266
- const projectedUsage = this.aborted ? this.tokenUsage : this.responseUsage ?? this.tokenUsage;
2510
+ const completedUsage = this.responseCompletions.usage ?? this.tokenUsage;
2511
+ const projectedUsage = this.aborted ? this.tokenUsage : completedUsage;
2267
2512
  const hasAssistantItemText = this.assistantProjection.hasAssistantItemTextForSynthesis();
2268
2513
  const legacyFailClosed = !this.completedTurn || this.completedTurn.status !== "completed" || hasAssistantItemText;
2269
2514
  const hasDeliverableAssistantOnCompletedTurn = this.completedTurn?.status === "completed" && assistantTexts.some((text) => text.trim().length > 0);
2270
2515
  const synthesizedMissingToolResultError = this.toolTranscriptProjection.synthesizeMissingToolResults({
2271
2516
  synthesize: legacyFailClosed,
2272
- recordPromptError: legacyFailClosed && !hasDeliverableAssistantOnCompletedTurn && !this.aborted
2517
+ terminalDisposition: this.aborted ? "tool_error" : hasDeliverableAssistantOnCompletedTurn ? "diagnostic_only" : "prompt_error"
2273
2518
  });
2274
2519
  if (synthesizedMissingToolResultError) {
2275
2520
  this.synthesizedMissingToolResultError = synthesizedMissingToolResultError;
@@ -2305,18 +2550,16 @@ var CodexAppServerEventProjector = class {
2305
2550
  const toolMetas = this.toolProgressProjection.toolMetas;
2306
2551
  const hadPotentialSideEffects = toolTelemetry.didSendViaMessagingTool || (toolTelemetry.successfulCronAdds ?? 0) > 0 || this.generatedMediaProjection.hasGeneratedMedia() || this.toolProgressProjection.hasPotentialSideEffects;
2307
2552
  return {
2308
- aborted: this.aborted,
2309
- externalAbort: false,
2310
- timedOut: false,
2311
- idleTimedOut: false,
2312
- timedOutDuringCompaction: false,
2313
- timedOutDuringToolExecution: false,
2314
- promptError,
2315
- promptErrorSource: promptError ? this.promptErrorSource || "prompt" : null,
2553
+ terminal: attemptTerminal.normalize({
2554
+ aborted: this.aborted,
2555
+ promptError,
2556
+ promptErrorSource: promptError ? this.promptErrorSource || "prompt" : null
2557
+ }),
2316
2558
  sessionIdUsed: this.params.sessionId,
2317
2559
  ...agentHarnessResultClassification ? { agentHarnessResultClassification } : {},
2318
2560
  bootstrapPromptWarningSignaturesSeen: this.params.bootstrapPromptWarningSignaturesSeen,
2319
2561
  bootstrapPromptWarningSignature: this.params.bootstrapPromptWarningSignature,
2562
+ ...this.responseCompletions.modelIterations > 0 ? { modelIterations: this.responseCompletions.modelIterations } : {},
2320
2563
  messagesSnapshot,
2321
2564
  assistantTexts,
2322
2565
  toolMetas,
@@ -2355,7 +2598,8 @@ var CodexAppServerEventProjector = class {
2355
2598
  }
2356
2599
  recordDynamicToolResult(params) {
2357
2600
  this.toolProgressProjection.recordDynamicToolResult(params);
2358
- this.toolTranscriptProjection.recordDynamicToolResult(params);
2601
+ const source = this.options.resolveDynamicToolResultContentSource?.(params.tool);
2602
+ this.toolTranscriptProjection.recordDynamicToolResult(params, source);
2359
2603
  }
2360
2604
  markTimedOut() {
2361
2605
  this.aborted = true;
@@ -2364,14 +2608,14 @@ var CodexAppServerEventProjector = class {
2364
2608
  }
2365
2609
  markAborted() {
2366
2610
  this.aborted = true;
2367
- this.responseUsage = void 0;
2611
+ this.responseCompletions.clear();
2368
2612
  }
2369
2613
  isCompacting() {
2370
2614
  return this.activeCompactionItemIds.size > 0;
2371
2615
  }
2372
2616
  async handleItemStarted(params) {
2373
2617
  const item = readItem(params.item);
2374
- const itemId = item?.id ?? readString$5(params, "itemId");
2618
+ const itemId = item?.id ?? readString$6(params, "itemId");
2375
2619
  this.assistantProjection.recordItemStarted(item, itemId);
2376
2620
  if (itemId) this.activeItemIds.add(itemId);
2377
2621
  this.recordNativeToolOutcome(item);
@@ -2427,14 +2671,14 @@ var CodexAppServerEventProjector = class {
2427
2671
  this.diagnostics.warnUnknownItemStatus(item);
2428
2672
  this.recordNativeToolOutcome(item);
2429
2673
  this.clearTerminalPresentationForNativeItem(item);
2430
- const itemId = item?.id ?? readString$5(params, "itemId");
2674
+ const itemId = item?.id ?? readString$6(params, "itemId");
2431
2675
  if (itemId) {
2432
2676
  this.activeItemIds.delete(itemId);
2433
2677
  this.completedItemIds.add(itemId);
2434
2678
  }
2435
2679
  this.assistantProjection.recordItemCompleted(item, itemId, this.activeItemIds);
2436
2680
  this.reasoningProjection.recordItem(item);
2437
- this.generatedMediaProjection.recordNative(item);
2681
+ await this.generatedMediaProjection.recordNative(item);
2438
2682
  if (item?.type === "contextCompaction" && itemId) {
2439
2683
  this.activeCompactionItemIds.delete(itemId);
2440
2684
  this.completedCompactionCount += 1;
@@ -2477,7 +2721,7 @@ var CodexAppServerEventProjector = class {
2477
2721
  item
2478
2722
  });
2479
2723
  this.toolTranscriptProjection.recordNativeToolCall(item);
2480
- this.toolTranscriptProjection.recordNativeToolResult(item);
2724
+ await this.toolTranscriptProjection.recordNativeToolResultWithDetails(item);
2481
2725
  this.toolProgressProjection.emitToolResultSummary(item);
2482
2726
  this.toolProgressProjection.emitToolResultOutput(item);
2483
2727
  this.emitAgentEvent({
@@ -2489,15 +2733,11 @@ var CodexAppServerEventProjector = class {
2489
2733
  }
2490
2734
  });
2491
2735
  }
2492
- handleRawResponseCompleted(params) {
2493
- const usage = isJsonObject(params.usage) ? params.usage : void 0;
2494
- this.responseUsage = usage ? normalizeCodexResponseTokenUsage(usage) : void 0;
2495
- }
2496
2736
  async handleTurnCompleted(params) {
2497
2737
  const turn = readCodexTurn(params.turn);
2498
2738
  if (!turn || turn.id !== this.turnId) return;
2499
2739
  this.completedTurn = turn;
2500
- if (turn.status !== "completed") this.responseUsage = void 0;
2740
+ if (turn.status !== "completed") this.responseCompletions.clear();
2501
2741
  if (turn.status === "failed") {
2502
2742
  const usageLimitMessage = formatCodexUsageLimitErrorMessage({
2503
2743
  message: turn.error?.message,
@@ -2521,12 +2761,12 @@ var CodexAppServerEventProjector = class {
2521
2761
  this.diagnostics.warnUnknownItemStatus(item);
2522
2762
  this.assistantProjection.recordSnapshotItem(item);
2523
2763
  this.reasoningProjection.recordItem(item);
2524
- this.generatedMediaProjection.recordNative(item);
2764
+ await this.generatedMediaProjection.recordNative(item);
2525
2765
  this.toolProgressProjection.recordToolMeta(item);
2526
2766
  this.toolProgressProjection.rememberCommandAggregateOutputEcho(item);
2527
2767
  await this.emitSnapshotOnlyNativeToolProgress(item);
2528
2768
  this.toolTranscriptProjection.recordNativeToolCall(item);
2529
- this.toolTranscriptProjection.recordNativeToolResult(item);
2769
+ await this.toolTranscriptProjection.recordNativeToolResultWithDetails(item);
2530
2770
  this.toolTranscriptProjection.emitAfterToolCallObservation(item);
2531
2771
  this.toolProgressProjection.emitToolResultSummary(item);
2532
2772
  this.toolProgressProjection.emitToolResultOutput(item);
@@ -2565,6 +2805,7 @@ var CodexAppServerEventProjector = class {
2565
2805
  async handleRawResponseItemCompleted(params) {
2566
2806
  const item = isJsonObject(params.item) ? params.item : void 0;
2567
2807
  if (!item) return;
2808
+ this.toolTranscriptProjection.recordRawNativeToolItem(item);
2568
2809
  this.assistantProjection.handleRawResponseItemCompleted(item, this.activeItemIds);
2569
2810
  await this.generatedMediaProjection.recordRaw(item);
2570
2811
  }
@@ -2584,7 +2825,7 @@ var CodexAppServerEventProjector = class {
2584
2825
  formatCodexErrorMessage(params) {
2585
2826
  const error = isJsonObject(params.error) ? params.error : void 0;
2586
2827
  const usageLimitMessage = formatCodexUsageLimitErrorMessage({
2587
- message: error ? readString$5(error, "message") : void 0,
2828
+ message: error ? readString$6(error, "message") : void 0,
2588
2829
  codexErrorInfo: error?.codexErrorInfo,
2589
2830
  rateLimits: this.options.readRecentRateLimits?.()
2590
2831
  });
@@ -2616,7 +2857,7 @@ var CodexAppServerEventProjector = class {
2616
2857
  return threadId === this.threadId && turnId === this.turnId;
2617
2858
  }
2618
2859
  isHookNotificationForCurrentThread(params) {
2619
- const threadId = readString$5(params, "threadId");
2860
+ const threadId = readString$6(params, "threadId");
2620
2861
  const turnId = params.turnId;
2621
2862
  return threadId === this.threadId && (turnId === this.turnId || turnId === null);
2622
2863
  }
@@ -2625,6 +2866,128 @@ function isHookNotificationMethod(method) {
2625
2866
  return method === "hook/started" || method === "hook/completed";
2626
2867
  }
2627
2868
  //#endregion
2869
+ //#region extensions/codex/src/app-server/native-mcp-app.ts
2870
+ function asRecord(value) {
2871
+ return value && typeof value === "object" && !Array.isArray(value) ? value : void 0;
2872
+ }
2873
+ function readString$4(value) {
2874
+ return typeof value === "string" && value.trim() ? value.trim() : void 0;
2875
+ }
2876
+ function readMcpAppResourceUri(item) {
2877
+ const uri = readString$4(asRecord(item.appContext)?.resourceUri) ?? readString$4(item.mcpAppResourceUri);
2878
+ return uri?.startsWith("ui://") ? uri : void 0;
2879
+ }
2880
+ function readMcpToolResult(item) {
2881
+ const result = asRecord(item.result);
2882
+ if (!result || !Array.isArray(result.content)) return;
2883
+ const resultMeta = asRecord(result["_meta"]);
2884
+ return {
2885
+ content: result.content,
2886
+ ...result.structuredContent !== void 0 ? { structuredContent: result.structuredContent } : {},
2887
+ ...result.isError === true ? { isError: true } : {},
2888
+ ...resultMeta ? { _meta: resultMeta } : {}
2889
+ };
2890
+ }
2891
+ function statusTools(status) {
2892
+ return Object.entries(status.tools).map(([name, value]) => Object.assign({}, asRecord(value), { name }));
2893
+ }
2894
+ function createNativeMcpRuntime(params) {
2895
+ let catalog = null;
2896
+ let statuses;
2897
+ const createdAt = Date.now();
2898
+ const loadStatuses = async () => {
2899
+ if (statuses) return statuses;
2900
+ statuses = (await params.client.request("mcpServerStatus/list", {
2901
+ threadId: params.threadId,
2902
+ detail: "full"
2903
+ })).data;
2904
+ return statuses;
2905
+ };
2906
+ const getCatalog = async () => {
2907
+ if (catalog) return catalog;
2908
+ const loaded = await loadStatuses();
2909
+ catalog = {
2910
+ version: 1,
2911
+ generatedAt: Date.now(),
2912
+ servers: Object.fromEntries(loaded.map((status) => [status.name, {
2913
+ serverName: status.name,
2914
+ launchSummary: "Codex native MCP connection",
2915
+ toolCount: Object.keys(status.tools).length
2916
+ }])),
2917
+ tools: loaded.flatMap((status) => statusTools(status).map((tool) => ({
2918
+ serverName: status.name,
2919
+ safeServerName: status.name,
2920
+ toolName: String(tool.name),
2921
+ inputSchema: asRecord(tool.inputSchema) ?? { type: "object" },
2922
+ fallbackDescription: readString$4(tool.description) ?? String(tool.name)
2923
+ })))
2924
+ };
2925
+ return catalog;
2926
+ };
2927
+ const runtime = {
2928
+ sessionId: params.attempt.sessionId,
2929
+ sessionKey: params.attempt.sessionKey,
2930
+ workspaceDir: params.attempt.workspaceDir,
2931
+ configFingerprint: `${getCodexAppServerClientInstanceId(params.client)}:${params.threadId}`,
2932
+ mcpAppsEnabled: true,
2933
+ createdAt,
2934
+ lastUsedAt: createdAt,
2935
+ acquireLease: () => retainSharedCodexAppServerClientIfCurrent(params.client) ?? (() => {}),
2936
+ getCatalog,
2937
+ peekCatalog: () => catalog,
2938
+ markUsed: () => {
2939
+ runtime.lastUsedAt = Date.now();
2940
+ },
2941
+ callTool: async (serverName, toolName, input) => await params.client.request("mcpServer/tool/call", {
2942
+ threadId: params.threadId,
2943
+ server: serverName,
2944
+ tool: toolName,
2945
+ arguments: asRecord(input) ?? {}
2946
+ }),
2947
+ listTools: async (serverName) => {
2948
+ const status = (await loadStatuses()).find((entry) => entry.name === serverName);
2949
+ return { tools: status ? statusTools(status) : [] };
2950
+ },
2951
+ readResource: async (serverName, uri) => await params.client.request("mcpServer/resource/read", {
2952
+ threadId: params.threadId,
2953
+ server: serverName,
2954
+ uri
2955
+ }),
2956
+ listResources: async (serverName) => {
2957
+ return { resources: (await loadStatuses()).find((entry) => entry.name === serverName)?.resources ?? [] };
2958
+ },
2959
+ listResourceTemplates: async (serverName) => {
2960
+ return { resourceTemplates: (await loadStatuses()).find((entry) => entry.name === serverName)?.resourceTemplates ?? [] };
2961
+ },
2962
+ dispose: async () => {}
2963
+ };
2964
+ return runtime;
2965
+ }
2966
+ function createCodexNativeMcpAppResultDetailsPreparer(params) {
2967
+ if (params.attempt.config?.mcp?.apps?.enabled !== true) return;
2968
+ const runtime = createNativeMcpRuntime(params);
2969
+ return async (item) => {
2970
+ const serverName = readString$4(item.server);
2971
+ const toolName = readString$4(item.tool);
2972
+ const uiResourceUri = readMcpAppResourceUri(item);
2973
+ const toolResult = readMcpToolResult(item);
2974
+ if (!serverName || !toolName || !uiResourceUri || !toolResult) return;
2975
+ const allowedAppToolNames = new Set((await runtime.getCatalog()).tools.filter((tool) => tool.serverName === serverName).map((tool) => tool.toolName));
2976
+ if (allowedAppToolNames.size === 0) return;
2977
+ return await prepareHarnessNativeMcpAppPreview({
2978
+ runtime,
2979
+ serverName,
2980
+ toolName,
2981
+ uiResourceUri,
2982
+ toolCallId: item.id,
2983
+ toolInput: item.arguments ?? {},
2984
+ toolResult,
2985
+ allowedAppToolNames,
2986
+ ...toolResult["_meta"] !== void 0 ? { resultMetaState: "unavailable" } : {}
2987
+ });
2988
+ };
2989
+ }
2990
+ //#endregion
2628
2991
  //#region extensions/codex/src/app-server/user-input-bridge.ts
2629
2992
  /** Bridges Codex request_user_input calls to gateway questions and secret text prompts. */
2630
2993
  const DEFAULT_USER_INPUT_TIMEOUT_MS = 15 * 6e4;
@@ -2693,6 +3056,7 @@ function createCodexUserInputBridge(params) {
2693
3056
  questions: requestParams.questions,
2694
3057
  sessionKey: params.paramsForRun.sessionKey ?? params.paramsForRun.sessionId,
2695
3058
  agentId: params.paramsForRun.agentId,
3059
+ runId: params.paramsForRun.runId,
2696
3060
  timeoutMs: requestParams.autoResolutionMs ?? params.paramsForRun.timeoutMs ?? DEFAULT_USER_INPUT_TIMEOUT_MS,
2697
3061
  gatewayCall,
2698
3062
  delivery: params.paramsForRun,
@@ -2807,11 +3171,16 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
2807
3171
  const { runtime, attemptTools } = context;
2808
3172
  const { connection } = runtime;
2809
3173
  const { params, runAbortController, terminalState, abortExplicitly, abortFromUpstream, bindingStore, bindingIdentity, sessionAgentId, sandboxSessionKey, effectiveCwd } = connection;
2810
- const { dynamicToolParams, computerContextEpoch } = attemptTools;
3174
+ const { dynamicToolParams, computerContextEpoch, toolBridge } = attemptTools;
2811
3175
  const { state, userInputBridgeRef, steeringQueueRef, turnWatches } = turnRuntime;
2812
3176
  const { emitExecutionPhaseOnce, emitLifecycleStart, maybeAnnounceFastModeAutoOff } = lifecycle;
2813
3177
  const { enqueueNotification } = notifications;
2814
3178
  const activeTurnId = turn.turn.id;
3179
+ const prepareNativeMcpAppResultDetails = createCodexNativeMcpAppResultDetailsPreparer({
3180
+ client: resourceState.client,
3181
+ threadId: resourceState.thread.threadId,
3182
+ attempt: dynamicToolParams
3183
+ });
2815
3184
  const streamState = {
2816
3185
  eventEmitted: false,
2817
3186
  needsTerminalSnapshot: false
@@ -2842,8 +3211,19 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
2842
3211
  nativePostToolUseRelayEnabled: resourceState.nativeHookRelay?.allowedEvents.includes("post_tool_use") === true && resourceState.nativeHookRelay.shouldRelayEvent("post_tool_use"),
2843
3212
  readRecentRateLimits: () => readRecentCodexRateLimits(resourceState.client),
2844
3213
  runAbortSignal: runAbortController.signal,
3214
+ remoteWorkspaceRoot: connection.appServer.remoteWorkspaceRoot,
3215
+ remoteWorkspaceRequestTimeoutMs: connection.appServer.requestTimeoutMs,
3216
+ readRemoteWorkspaceFile: ({ path, maxBytes, signal, timeoutMs }) => readBoundedCodexRemoteWorkspaceFile({
3217
+ client: resourceState.client,
3218
+ path,
3219
+ maxBytes,
3220
+ signal,
3221
+ timeoutMs
3222
+ }),
2845
3223
  trajectoryRecorder,
3224
+ resolveDynamicToolResultContentSource: toolBridge.resultContentSourceForTool,
2846
3225
  onNativeToolResultRecorded: maybeAnnounceFastModeAutoOff,
3226
+ ...prepareNativeMcpAppResultDetails ? { prepareNativeMcpAppResultDetails } : {},
2847
3227
  upstreamUserText: turnState.codexTurnPromptText,
2848
3228
  onContextCompacted: () => {
2849
3229
  computerContextEpoch.value += 1;
@@ -2909,6 +3289,7 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
2909
3289
  await activeSteeringQueue.queue(text, optionsLocal);
2910
3290
  },
2911
3291
  isStreaming: () => !state.completed && !runAbortController.signal.aborted,
3292
+ isAborted: () => runAbortController.signal.aborted,
2912
3293
  isStopped: () => state.completed || state.timedOut || runAbortController.signal.aborted,
2913
3294
  isAbortable: () => !terminalState.terminalOutcomeFrozen || terminalState.sharedAbortAllowedAfterTerminalOutcome,
2914
3295
  isCompacting: () => projectorRef.current?.isCompacting() ?? false,
@@ -3006,15 +3387,27 @@ async function cleanupCodexAttempt(resources, turnRuntime, lifecycle, requestRun
3006
3387
  });
3007
3388
  if (!state.timedOut && !runAbortController.signal.aborted) await steeringQueueRef.current?.flushPending();
3008
3389
  const retainLiveIncognitoThread = terminalState.turnSucceeded && isIncognitoSessionKey(params.sessionKey);
3390
+ const retainedPersistentThread = terminalState.turnSucceeded && !isIncognitoSessionKey(params.sessionKey) && params.cleanupBundleMcpOnRunEnd !== true && !params.contextEngine && resourceState.thread.liveThreadConfigFingerprint !== void 0 && resourceState.thread.clientId === resolveCodexAppServerClientInstanceId(resourceState.client) && resourceState.thread.preserveNativeModel !== true && resourceState.thread.connectionScope !== "supervision" && !resourceState.thread.ringZeroConfigFingerprint && !resourceState.thread.contextEngine ? await retainCodexAppServerLiveThread(resourceState.client, resourceState.thread.threadId, async (previousThreadId) => {
3391
+ if (!await unsubscribeCodexThreadBestEffort(resourceState.client, {
3392
+ threadId: previousThreadId,
3393
+ timeoutMs: 5e3
3394
+ })) {
3395
+ await closeCodexStartupClientBestEffort(resourceState.client);
3396
+ throw new CodexAppServerUnsafeSubscriptionError(`Codex retained thread subscription could not be released: ${previousThreadId}`);
3397
+ }
3398
+ }, resourceState.thread.liveThreadConfigFingerprint) : void 0;
3399
+ const retainLiveThread = retainLiveIncognitoThread || retainedPersistentThread !== void 0;
3009
3400
  const bindingReleased = isIncognitoSessionKey(params.sessionKey) && !retainLiveIncognitoThread ? await bindingStore.mutate(bindingIdentity, {
3010
3401
  kind: "clear",
3011
3402
  threadId: resourceState.thread.threadId
3012
3403
  }) : true;
3013
- if (!state.timedOut && !retainLiveIncognitoThread) {
3014
- if (bindingReleased) await unsubscribeCodexThreadBestEffort(resourceState.client, {
3015
- threadId: resourceState.thread.threadId,
3016
- timeoutMs: CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS
3017
- });
3404
+ if (!state.timedOut && !retainLiveThread) {
3405
+ if (bindingReleased) {
3406
+ if (!await unsubscribeCodexThreadBestEffort(resourceState.client, {
3407
+ threadId: resourceState.thread.threadId,
3408
+ timeoutMs: 5e3
3409
+ })) await closeCodexStartupClientBestEffort(resourceState.client);
3410
+ }
3018
3411
  }
3019
3412
  userInputBridgeRef.current?.cancelPending();
3020
3413
  turnWatches.clearAllTimers();
@@ -3049,7 +3442,8 @@ const codexWorkspaceDirCache = /* @__PURE__ */ new Set();
3049
3442
  //#region extensions/codex/src/app-server/run-attempt-lifecycle.ts
3050
3443
  const CODEX_APP_SERVER_PROJECTED_CHARS_PER_TOKEN = 4;
3051
3444
  function shouldKeepCodexSharedAbortOpen(params) {
3052
- if (params.explicitCancellationObserved || params.result.aborted || params.result.externalAbort) return false;
3445
+ const terminal = attemptTerminal.project(params.result.terminal);
3446
+ if (params.explicitCancellationObserved || terminal.aborted || terminal.externalAbort) return false;
3053
3447
  return params.trigger === "memory" || !params.attemptSucceeded;
3054
3448
  }
3055
3449
  function withCodexAppServerFastModeServiceTier(appServer, params) {
@@ -3071,14 +3465,7 @@ function estimateCodexAppServerProjectedTurnTokens(params) {
3071
3465
  }
3072
3466
  async function ensureCodexWorkspaceDirOnce(workspaceDir) {
3073
3467
  const normalized = path.resolve(workspaceDir);
3074
- if (codexWorkspaceDirCache.has(normalized)) {
3075
- try {
3076
- if ((await fs.stat(normalized)).isDirectory()) return;
3077
- } catch (error) {
3078
- if ((typeof error === "object" && error ? error.code : void 0) !== "ENOENT") throw error;
3079
- }
3080
- codexWorkspaceDirCache.delete(normalized);
3081
- }
3468
+ if (codexWorkspaceDirCache.has(normalized)) return;
3082
3469
  await fs.mkdir(normalized, { recursive: true });
3083
3470
  codexWorkspaceDirCache.add(normalized);
3084
3471
  }
@@ -3119,6 +3506,7 @@ const CODEX_APP_SERVER_NATIVE_THREAD_FALLBACK_MAX_TOKENS = 3e5;
3119
3506
  const CODEX_APP_SERVER_NATIVE_THREAD_DEFAULT_RESERVE_TOKENS = 2e4;
3120
3507
  const CODEX_APP_SERVER_NATIVE_THREAD_MIN_PROMPT_BUDGET_TOKENS = 8e3;
3121
3508
  const CODEX_APP_SERVER_NATIVE_THREAD_MIN_PROMPT_BUDGET_RATIO = .5;
3509
+ const CODEX_APP_SERVER_ROLLOUT_TAIL_READ_BYTES = 64 * 1024;
3122
3510
  const CODEX_APP_SERVER_BYTE_UNITS = {
3123
3511
  b: 1,
3124
3512
  k: 1024,
@@ -3147,7 +3535,7 @@ function parseCodexAppServerByteLimit(value) {
3147
3535
  if (multiplier === void 0) return;
3148
3536
  return Math.max(1, Math.round(amount * multiplier));
3149
3537
  }
3150
- async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codexHome) {
3538
+ async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codexHome, rolloutPath) {
3151
3539
  const resolvedAgentDir = path.resolve(agentDir);
3152
3540
  const resolvedCodexHome = codexHome?.trim() ? path.resolve(codexHome) : resolveCodexAppServerHomeDir(resolvedAgentDir);
3153
3541
  const roots = [
@@ -3156,6 +3544,22 @@ async function listCodexAppServerRolloutFilesForThread(agentDir, threadId, codex
3156
3544
  path.join(resolvedAgentDir, "agent", "codex-home", "sessions"),
3157
3545
  path.join(path.dirname(resolvedAgentDir), "codex-home", "sessions")
3158
3546
  ];
3547
+ const rolloutRoot = rolloutPath ? roots.find((root) => {
3548
+ const relativePath = path.relative(root, rolloutPath);
3549
+ return relativePath !== "" && relativePath !== ".." && !relativePath.startsWith(`..${path.sep}`) && !path.isAbsolute(relativePath);
3550
+ }) : void 0;
3551
+ if (rolloutPath && rolloutRoot && path.isAbsolute(rolloutPath) && path.extname(rolloutPath) === ".jsonl" && path.basename(rolloutPath).includes(threadId)) try {
3552
+ const opened = await (await root(rolloutRoot, {
3553
+ hardlinks: "reject",
3554
+ maxBytes: Number.MAX_SAFE_INTEGER,
3555
+ symlinks: "reject"
3556
+ })).open(path.relative(rolloutRoot, rolloutPath));
3557
+ return [{
3558
+ path: opened.realPath,
3559
+ bytes: opened.stat.size,
3560
+ handle: opened.handle
3561
+ }];
3562
+ } catch {}
3159
3563
  const files = [];
3160
3564
  const visited = /* @__PURE__ */ new Set();
3161
3565
  for (const root of roots) {
@@ -3234,23 +3638,48 @@ async function readCodexSessionRecordForSessionFile(sessionFile) {
3234
3638
  function isSqliteSessionFileMarker(sessionFile) {
3235
3639
  return parseSqliteSessionFileMarker(sessionFile) !== void 0;
3236
3640
  }
3237
- async function readCodexAppServerRolloutTokenSnapshot(file) {
3238
- let handle;
3239
- try {
3641
+ async function readCodexAppServerRolloutTokenSnapshot(file, openedHandle) {
3642
+ let handle = openedHandle;
3643
+ if (!handle) try {
3240
3644
  handle = await fs.open(file, "r");
3241
3645
  } catch {
3242
3646
  return;
3243
3647
  }
3244
3648
  let snapshot;
3245
3649
  try {
3246
- for await (const line of handle.readLines()) {
3650
+ let position = (await handle.stat()).size;
3651
+ const partialLineFragments = [];
3652
+ const applySnapshotLine = (line) => {
3247
3653
  const lineSnapshot = readCodexAppServerRolloutTokenSnapshotLine(line);
3248
- if (lineSnapshot !== void 0) {
3249
- snapshot ??= {};
3250
- if (lineSnapshot.totalTokens !== void 0) snapshot.totalTokens = lineSnapshot.totalTokens;
3251
- if (lineSnapshot.modelContextWindow !== void 0) snapshot.modelContextWindow = lineSnapshot.modelContextWindow;
3654
+ if (lineSnapshot === void 0) return false;
3655
+ snapshot ??= {};
3656
+ snapshot.totalTokens ??= lineSnapshot.totalTokens;
3657
+ snapshot.modelContextWindow ??= lineSnapshot.modelContextWindow;
3658
+ return snapshot.totalTokens !== void 0 && snapshot.modelContextWindow !== void 0;
3659
+ };
3660
+ while (position > 0) {
3661
+ const bytesToRead = Math.min(position, CODEX_APP_SERVER_ROLLOUT_TAIL_READ_BYTES);
3662
+ const nextPosition = position - bytesToRead;
3663
+ const chunk = Buffer.allocUnsafe(bytesToRead);
3664
+ let bytesRead = 0;
3665
+ while (bytesRead < bytesToRead) {
3666
+ const result = await handle.read(chunk, bytesRead, bytesToRead - bytesRead, nextPosition + bytesRead);
3667
+ if (result.bytesRead === 0) return snapshot;
3668
+ bytesRead += result.bytesRead;
3669
+ }
3670
+ let lineEnd = bytesRead;
3671
+ for (let index = bytesRead - 1; index >= 0; index -= 1) {
3672
+ if (chunk[index] !== 10) continue;
3673
+ const lineFragment = chunk.subarray(index + 1, lineEnd);
3674
+ const line = partialLineFragments.length === 0 ? lineFragment.toString("utf8") : Buffer.concat([lineFragment, ...partialLineFragments.toReversed()]).toString("utf8");
3675
+ partialLineFragments.length = 0;
3676
+ if (applySnapshotLine(line)) return snapshot;
3677
+ lineEnd = index;
3252
3678
  }
3679
+ if (lineEnd > 0) partialLineFragments.push(chunk.subarray(0, lineEnd));
3680
+ position = nextPosition;
3253
3681
  }
3682
+ if (partialLineFragments.length > 0) applySnapshotLine(Buffer.concat(partialLineFragments.toReversed()).toString("utf8"));
3254
3683
  } finally {
3255
3684
  await handle.close();
3256
3685
  }
@@ -3308,31 +3737,36 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
3308
3737
  if (!binding?.threadId) return binding;
3309
3738
  if (binding.connectionScope === "supervision") return binding;
3310
3739
  const sessionRecord = await readCodexSessionRecordForSessionFile(params.sessionFile);
3311
- const rolloutFiles = await listCodexAppServerRolloutFilesForThread(params.agentDir, binding.threadId, params.codexHome);
3312
- const compaction = readCompactionConfig(params.config);
3313
- const shouldDeferByteGuard = compaction?.truncateAfterCompaction === true && params.contextEngineActive === true && hasContextEngineThreadBootstrapProjection(binding);
3314
- if (compaction?.truncateAfterCompaction === true && !shouldDeferByteGuard) {
3315
- const maxBytes = parseCodexAppServerByteLimit(compaction.maxActiveTranscriptBytes);
3316
- if (maxBytes !== void 0) {
3317
- const oversizedFiles = rolloutFiles.filter((file) => file.bytes >= maxBytes);
3318
- if (oversizedFiles.length > 0) {
3319
- embeddedAgentLog.warn("codex app-server native transcript exceeded active byte limit; starting a fresh thread", {
3320
- threadId: binding.threadId,
3321
- maxBytes,
3322
- files: oversizedFiles.map((file) => ({
3323
- path: file.path,
3324
- bytes: file.bytes
3325
- }))
3326
- });
3327
- await params.bindingStore.mutate(params.identity, {
3328
- kind: "clear",
3329
- threadId: binding.threadId
3330
- });
3331
- return;
3332
- }
3740
+ const rolloutFiles = await listCodexAppServerRolloutFilesForThread(params.agentDir, binding.threadId, params.codexHome, binding.rolloutPath);
3741
+ const maxBytes = parseCodexAppServerByteLimit(readCompactionConfig(params.config)?.maxActiveTranscriptBytes);
3742
+ if (maxBytes !== void 0 && params.contextEngineActive === true && hasContextEngineThreadBootstrapProjection(binding)) embeddedAgentLog.debug("codex app-server deferring native transcript byte guard for context-engine thread bootstrap", {
3743
+ threadId: binding.threadId,
3744
+ engineId: binding.contextEngine?.engineId,
3745
+ epoch: binding.contextEngine?.projection?.epoch,
3746
+ fingerprint: binding.contextEngine?.projection?.fingerprint
3747
+ });
3748
+ else if (maxBytes !== void 0) {
3749
+ const oversizedFiles = rolloutFiles.filter((file) => file.bytes >= maxBytes);
3750
+ if (oversizedFiles.length > 0) {
3751
+ await Promise.all(rolloutFiles.map(async (file) => {
3752
+ await file.handle?.close();
3753
+ }));
3754
+ embeddedAgentLog.warn("codex app-server native transcript exceeded active byte limit; starting a fresh thread", {
3755
+ threadId: binding.threadId,
3756
+ maxBytes,
3757
+ files: oversizedFiles.map((file) => ({
3758
+ path: file.path,
3759
+ bytes: file.bytes
3760
+ }))
3761
+ });
3762
+ await params.bindingStore.mutate(params.identity, {
3763
+ kind: "clear",
3764
+ threadId: binding.threadId
3765
+ });
3766
+ return;
3333
3767
  }
3334
3768
  }
3335
- const nativeTokenSnapshots = await Promise.all(rolloutFiles.map(async (file) => readCodexAppServerRolloutTokenSnapshot(file.path)));
3769
+ const nativeTokenSnapshots = await Promise.all(rolloutFiles.map(async (file) => readCodexAppServerRolloutTokenSnapshot(file.path, file.handle)));
3336
3770
  const nativeTokens = maxFiniteNumber(nativeTokenSnapshots.map((snapshot) => snapshot?.totalTokens));
3337
3771
  const nativeModelContextWindow = maxFiniteNumber(nativeTokenSnapshots.map((snapshot) => snapshot?.modelContextWindow));
3338
3772
  const sessionModelContextWindow = typeof sessionRecord?.contextTokens === "number" && Number.isFinite(sessionRecord.contextTokens) && sessionRecord.contextTokens > 0 ? Math.floor(sessionRecord.contextTokens) : void 0;
@@ -3362,16 +3796,6 @@ async function rotateOversizedCodexAppServerStartupBinding(params) {
3362
3796
  });
3363
3797
  return;
3364
3798
  }
3365
- if (compaction?.truncateAfterCompaction !== true) return binding;
3366
- if (shouldDeferByteGuard) {
3367
- embeddedAgentLog.debug("codex app-server deferring native transcript byte guard for context-engine thread bootstrap", {
3368
- threadId: binding.threadId,
3369
- engineId: binding.contextEngine?.engineId,
3370
- epoch: binding.contextEngine?.projection?.epoch,
3371
- fingerprint: binding.contextEngine?.projection?.fingerprint
3372
- });
3373
- return binding;
3374
- }
3375
3799
  return binding;
3376
3800
  }
3377
3801
  //#endregion
@@ -3400,7 +3824,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3400
3824
  const runtimeArtifactRequest = params.captureRuntimeArtifact || params.expectedRuntimeArtifact ? params.expectedRuntimeArtifact ? { expected: params.expectedRuntimeArtifact } : {} : void 0;
3401
3825
  const pluginConfig = readCodexPluginConfig(options.pluginConfig);
3402
3826
  const computerUseConfig = resolveCodexComputerUseConfig({ pluginConfig });
3403
- const { sessionAgentId } = resolveSessionAgentIds$1({
3827
+ const { sessionAgentId } = resolveSessionAgentIds({
3404
3828
  sessionKey: params.sessionKey,
3405
3829
  config: params.config,
3406
3830
  agentId: params.agentId
@@ -3424,23 +3848,46 @@ async function prepareCodexAttemptConnection({ params, options }) {
3424
3848
  config: params.config,
3425
3849
  agentId: sessionAgentId
3426
3850
  });
3427
- const agentDir = params.agentDir ?? resolveAgentDir(params.config ?? {}, sessionAgentId);
3428
- const bindingIdentity = sessionBindingIdentity({
3851
+ const agentDir = params.agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId);
3852
+ let bindingIdentity = sessionBindingIdentity({
3429
3853
  sessionId: params.sessionId,
3430
3854
  sessionKey: params.sessionKey,
3431
3855
  agentId: params.agentId,
3432
3856
  config: params.config
3433
3857
  });
3434
- const bindingStore = options.bindingStore;
3858
+ let bindingStore = options.bindingStore;
3435
3859
  preDynamicStartupStages.mark("session-agent");
3436
3860
  let activeContextEngine = isActiveHarnessContextEngine(params.contextEngine) ? params.contextEngine : void 0;
3437
3861
  const isInactiveThreadBootstrapBinding = (binding) => !activeContextEngine && binding?.contextEngine?.projection?.mode === "thread_bootstrap";
3862
+ if (bindingIdentity.kind === "session" && bindingIdentity.sessionKey && (params.sessionTarget?.storePath || params.config?.session?.store)) {
3863
+ const authority = resolveCodexRunSessionBindingAuthority({
3864
+ identity: bindingIdentity,
3865
+ config: params.config,
3866
+ storePath: params.sessionTarget?.storePath
3867
+ });
3868
+ if (authority === "superseded") throw createCodexSessionGenerationSupersededError(bindingIdentity.sessionId);
3869
+ if (authority === "ephemeral") {
3870
+ const logicalIdentity = bindingIdentity;
3871
+ const physicalIdentity = {
3872
+ kind: "session",
3873
+ agentId: bindingIdentity.agentId,
3874
+ sessionId: bindingIdentity.sessionId
3875
+ };
3876
+ bindingStore = scopeCodexRunBindingStore({
3877
+ bindingStore,
3878
+ logicalIdentity,
3879
+ physicalIdentity
3880
+ });
3881
+ bindingIdentity = physicalIdentity;
3882
+ }
3883
+ }
3438
3884
  let startupBinding = await bindingStore.read(bindingIdentity);
3439
3885
  if (!startupBinding && bindingIdentity.kind === "session" && bindingIdentity.sessionKey) {
3440
3886
  if (!await reclaimCurrentCodexSessionGeneration({
3441
3887
  bindingStore,
3442
3888
  identity: bindingIdentity,
3443
- config: params.config
3889
+ config: params.config,
3890
+ storePath: params.sessionTarget?.storePath
3444
3891
  })) throw createCodexSessionGenerationSupersededError(bindingIdentity.sessionId);
3445
3892
  startupBinding = await bindingStore.read(bindingIdentity);
3446
3893
  }
@@ -3484,6 +3931,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3484
3931
  authProfileId: resolvedStartupAuthProfileId,
3485
3932
  authProfileStore: params.authProfileStore,
3486
3933
  agentDir,
3934
+ homeScope: resolveCodexAppServerHomeScope({ appServer: pluginConfig.appServer }),
3487
3935
  config: params.config,
3488
3936
  subscriptionProfileRequiredError: "Prepared Codex subscription route requires a forwarded OpenAI OAuth or token profile.",
3489
3937
  subscriptionProfileUnusableError: "Prepared Codex subscription auth profile is unusable."
@@ -3509,15 +3957,16 @@ async function prepareCodexAttemptConnection({ params, options }) {
3509
3957
  const requestedCwd = params.cwd ? resolveUserPath(params.cwd) : void 0;
3510
3958
  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");
3511
3959
  const effectiveCwd = sandbox?.enabled ? effectiveWorkspace : requestedCwd ?? effectiveWorkspace;
3512
- await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
3960
+ if (effectiveWorkspace !== resolvedWorkspace) await ensureCodexWorkspaceDirOnce(effectiveWorkspace);
3513
3961
  preDynamicStartupStages.mark("effective-workspace");
3962
+ const shouldPromoteApprovalPolicy = beforeToolCallPolicy.hasBeforeToolCallHook || beforeToolCallPolicy.trustedToolPolicies.length > 0;
3514
3963
  const resolvePolicyAppServer = () => resolveCodexAppServerForOpenClawToolPolicy({
3515
3964
  appServer: configuredAppServer,
3516
3965
  pluginConfig,
3517
3966
  env: process.env,
3518
- shouldPromote: beforeToolCallPolicy.hasBeforeToolCallHook || beforeToolCallPolicy.trustedToolPolicies.length > 0,
3967
+ shouldPromote: shouldPromoteApprovalPolicy,
3519
3968
  execPolicy,
3520
- canUseUntrustedApprovalPolicy: configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted")
3969
+ canUseUntrustedApprovalPolicy: shouldPromoteApprovalPolicy && configuredAppServer.approvalPolicy === "never" && (configuredAppServer.start.transport !== "stdio" || isCodexAppServerApprovalPolicyAllowedByRequirements("untrusted"))
3521
3970
  });
3522
3971
  let policyAppServer = resolvePolicyAppServer();
3523
3972
  let appServer = resolveCodexAppServerForModelProvider({
@@ -3528,7 +3977,8 @@ async function prepareCodexAttemptConnection({ params, options }) {
3528
3977
  env: process.env,
3529
3978
  agentDir
3530
3979
  });
3531
- if (configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted") embeddedAgentLog.info("codex app-server approval policy promoted for OpenClaw tool policy", {
3980
+ let approvalPolicyPromotedForOpenClawToolPolicy = configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted";
3981
+ if (approvalPolicyPromotedForOpenClawToolPolicy) embeddedAgentLog.info("codex app-server approval policy promoted for OpenClaw tool policy", {
3532
3982
  from: "never",
3533
3983
  to: "untrusted",
3534
3984
  beforeToolCallHook: beforeToolCallPolicy.hasBeforeToolCallHook,
@@ -3565,6 +4015,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3565
4015
  };
3566
4016
  if (params.abortSignal?.aborted) abortFromUpstream();
3567
4017
  else params.abortSignal?.addEventListener("abort", abortFromUpstream, { once: true });
4018
+ const startupBindingBeforeRotation = startupBinding;
3568
4019
  startupBinding = await rotateOversizedCodexAppServerStartupBinding({
3569
4020
  binding: startupBinding,
3570
4021
  bindingStore,
@@ -3577,20 +4028,23 @@ async function prepareCodexAttemptConnection({ params, options }) {
3577
4028
  });
3578
4029
  const initialInactiveThreadBootstrapBindingForcedFreshStart = initialStartupBindingHadInactiveThreadBootstrap && !startupBinding?.threadId;
3579
4030
  preDynamicStartupStages.mark("rotate-binding");
3580
- reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
3581
- configuredAppServer = resolveRuntimeOptionsForBinding({
3582
- modelProvider: reviewerPolicyContext.modelProvider,
3583
- model: reviewerPolicyContext.model
3584
- });
3585
- policyAppServer = resolvePolicyAppServer();
3586
- appServer = resolveCodexAppServerForModelProvider({
3587
- appServer: policyAppServer,
3588
- provider: reviewerPolicyContext.modelProvider,
3589
- model: reviewerPolicyContext.model,
3590
- config: params.config,
3591
- env: process.env,
3592
- agentDir
3593
- });
4031
+ if (startupBinding !== startupBindingBeforeRotation) {
4032
+ reviewerPolicyContext = resolveReviewerPolicyContext(startupBinding);
4033
+ configuredAppServer = resolveRuntimeOptionsForBinding({
4034
+ modelProvider: reviewerPolicyContext.modelProvider,
4035
+ model: reviewerPolicyContext.model
4036
+ });
4037
+ policyAppServer = resolvePolicyAppServer();
4038
+ appServer = resolveCodexAppServerForModelProvider({
4039
+ appServer: policyAppServer,
4040
+ provider: reviewerPolicyContext.modelProvider,
4041
+ model: reviewerPolicyContext.model,
4042
+ config: params.config,
4043
+ env: process.env,
4044
+ agentDir
4045
+ });
4046
+ approvalPolicyPromotedForOpenClawToolPolicy = configuredAppServer.approvalPolicy === "never" && appServer.approvalPolicy === "untrusted";
4047
+ }
3594
4048
  const nativeHookRelayEvents = resolveCodexNativeHookRelayEvents({
3595
4049
  configuredEvents: options.nativeHookRelay?.events,
3596
4050
  appServer
@@ -3646,6 +4100,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
3646
4100
  effectiveWorkspace,
3647
4101
  effectiveCwd,
3648
4102
  appServer,
4103
+ approvalPolicyPromotedForOpenClawToolPolicy,
3649
4104
  nativeHookRelayEvents,
3650
4105
  runAbortController,
3651
4106
  terminalState,
@@ -3665,20 +4120,18 @@ async function prepareCodexAttemptConnection({ params, options }) {
3665
4120
  * system-prompt reports, and context-engine projection decisions.
3666
4121
  */
3667
4122
  const CODEX_NATIVE_PROJECT_DOC_BASENAMES = /* @__PURE__ */ new Set(["agents.md"]);
3668
- const CODEX_INHERITED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES = /* @__PURE__ */ new Set(["tools.md"]);
3669
4123
  const CODEX_TURN_SCOPED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES = /* @__PURE__ */ new Set([
3670
4124
  "identity.md",
3671
4125
  "soul.md",
3672
4126
  "user.md"
3673
4127
  ]);
3674
- const CODEX_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES = /* @__PURE__ */ new Set([...CODEX_INHERITED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES, ...CODEX_TURN_SCOPED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES]);
4128
+ const CODEX_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES = new Set(CODEX_TURN_SCOPED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES);
3675
4129
  const CODEX_MEMORY_CONTEXT_BASENAME = "memory.md";
3676
4130
  const CODEX_MEMORY_TOOL_NAMES = /* @__PURE__ */ new Set(["memory_search", "memory_get"]);
3677
4131
  const CODEX_BOOTSTRAP_CONTEXT_ORDER = /* @__PURE__ */ new Map([
3678
4132
  ["soul.md", 10],
3679
4133
  ["identity.md", 20],
3680
4134
  ["user.md", 30],
3681
- ["tools.md", 40],
3682
4135
  ["bootstrap.md", 50],
3683
4136
  ["memory.md", 60]
3684
4137
  ]);
@@ -3779,20 +4232,17 @@ async function buildCodexWorkspaceBootstrapContext(params) {
3779
4232
  excludeMemory: memoryToolsAvailable,
3780
4233
  memoryWorkspaceDir: params.effectiveWorkspace
3781
4234
  });
3782
- const developerInstructionFiles = shouldInjectCodexOpenClawPromptContext(params.params) ? selectCodexWorkspaceInheritedDeveloperInstructionFiles(contextFiles) : [];
3783
4235
  const turnScopedDeveloperInstructionFiles = shouldInjectCodexOpenClawPromptContext(params.params) ? selectCodexWorkspaceTurnScopedDeveloperInstructionFiles(contextFiles) : [];
3784
4236
  return {
3785
4237
  bootstrapFiles,
3786
4238
  contextFiles,
3787
4239
  promptContextFiles,
3788
- developerInstructionFiles,
3789
4240
  turnScopedDeveloperInstructionFiles,
3790
4241
  memoryReferenceFiles,
3791
4242
  memoryToolRoutedBootstrapFiles,
3792
4243
  memoryToolNames: [...params.memoryToolNames],
3793
4244
  memoryToolRouted: memoryToolsAvailable,
3794
4245
  promptContext: renderCodexWorkspaceBootstrapPromptContext(promptContextFiles),
3795
- developerInstructions: renderCodexWorkspaceThreadDeveloperInstructions(developerInstructionFiles),
3796
4246
  turnScopedDeveloperInstructions: renderCodexWorkspaceCollaborationDeveloperInstructions(turnScopedDeveloperInstructionFiles),
3797
4247
  memoryCollaborationInstructions: shouldInjectCodexOpenClawPromptContext(params.params) ? await renderCodexWorkspaceMemoryCollaborationInstructions({
3798
4248
  files: memoryReferenceFiles,
@@ -3841,7 +4291,7 @@ function buildCodexSystemPromptReport(params) {
3841
4291
  injectedWorkspaceFiles: buildCodexBootstrapInjectionStats({
3842
4292
  bootstrapFiles: params.workspaceBootstrapContext.bootstrapFiles,
3843
4293
  injectedFiles: params.workspaceBootstrapContext.promptContextFiles ?? [],
3844
- developerInstructionFiles: [...params.workspaceBootstrapContext.developerInstructionFiles ?? [], ...params.workspaceBootstrapContext.turnScopedDeveloperInstructionFiles ?? []],
4294
+ developerInstructionFiles: params.workspaceBootstrapContext.turnScopedDeveloperInstructionFiles ?? [],
3845
4295
  memoryToolRoutedBootstrapFiles: params.workspaceBootstrapContext.memoryToolRoutedBootstrapFiles ?? [],
3846
4296
  memoryToolRouted: params.workspaceBootstrapContext.memoryToolRouted === true
3847
4297
  }),
@@ -3978,7 +4428,7 @@ function buildCodexOpenClawPromptContext(params) {
3978
4428
  "## OpenClaw Workspace Context",
3979
4429
  "",
3980
4430
  params.workspacePromptContext.trim()
3981
- ].join("\n") : void 0].filter(isNonEmptyString$1);
4431
+ ].join("\n") : void 0, params.watchedSessionsContext?.trim() || void 0].filter(isNonEmptyString$1);
3982
4432
  if (sections.length === 0) return;
3983
4433
  return [
3984
4434
  "OpenClaw runtime context for this turn:",
@@ -3987,6 +4437,21 @@ function buildCodexOpenClawPromptContext(params) {
3987
4437
  ...sections
3988
4438
  ].join("\n");
3989
4439
  }
4440
+ /**
4441
+ * Renders the watched-sessions block for the Codex per-turn runtime context.
4442
+ * Codex builds its own instruction layers, so the embedded prompt's Watched
4443
+ * Sessions section must be re-surfaced here or Codex-backed main sessions
4444
+ * keep refusing cross-session questions (openclaw#114797).
4445
+ */
4446
+ function buildCodexWatchedSessionsContext(params) {
4447
+ if (!shouldInjectCodexOpenClawPromptContext(params.attempt)) return;
4448
+ return buildWatchedSessionsHarnessContext({
4449
+ config: params.attempt.config,
4450
+ sessionKey: params.sessionKey,
4451
+ sandboxed: params.sandboxed,
4452
+ toolNames: flattenCodexDynamicToolFunctions(params.dynamicTools).map((tool) => normalizeCodexDynamicToolName(tool.name))
4453
+ });
4454
+ }
3990
4455
  function shouldInjectCodexOpenClawPromptContext(params) {
3991
4456
  return !(params.bootstrapContextMode === "lightweight" && params.bootstrapContextRunKind === "cron");
3992
4457
  }
@@ -4050,7 +4515,7 @@ function renderCodexWorkspaceBootstrapPromptContext(contextFiles) {
4050
4515
  const files = contextFiles;
4051
4516
  if (files.length === 0) return;
4052
4517
  const lines = [
4053
- "OpenClaw loaded these user-editable workspace files for the current turn. Codex loads AGENTS.md natively. TOOLS.md is provided as inherited Codex developer instructions. 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.",
4518
+ "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.",
4054
4519
  "",
4055
4520
  "# Project Context",
4056
4521
  "",
@@ -4070,9 +4535,6 @@ function selectCodexWorkspacePromptContextFiles(contextFiles, options = {}) {
4070
4535
  })) && !isMissingCodexBootstrapContextFile(file);
4071
4536
  }).toSorted(compareCodexContextFiles);
4072
4537
  }
4073
- function selectCodexWorkspaceInheritedDeveloperInstructionFiles(contextFiles) {
4074
- return selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, CODEX_INHERITED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES);
4075
- }
4076
4538
  function selectCodexWorkspaceTurnScopedDeveloperInstructionFiles(contextFiles) {
4077
4539
  return selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, CODEX_TURN_SCOPED_WORKSPACE_DEVELOPER_CONTEXT_BASENAMES);
4078
4540
  }
@@ -4082,13 +4544,6 @@ function selectCodexWorkspaceDeveloperInstructionFiles(contextFiles, basenames)
4082
4544
  return baseName && basenames.has(baseName) && !isMissingCodexBootstrapContextFile(file) && file.content.trim().length > 0;
4083
4545
  }).toSorted(compareCodexContextFiles);
4084
4546
  }
4085
- function renderCodexWorkspaceThreadDeveloperInstructions(files) {
4086
- return renderCodexWorkspaceDeveloperInstructions({
4087
- files,
4088
- header: "## OpenClaw Workspace Instructions",
4089
- preamble: "OpenClaw loaded these workspace instruction files from the active agent workspace. Internalize and follow them accordingly."
4090
- });
4091
- }
4092
4547
  function renderCodexWorkspaceCollaborationDeveloperInstructions(files) {
4093
4548
  return renderCodexWorkspaceDeveloperInstructions({
4094
4549
  files,
@@ -4246,107 +4701,6 @@ function isNonEmptyString$1(value) {
4246
4701
  return typeof value === "string" && value.length > 0;
4247
4702
  }
4248
4703
  //#endregion
4249
- //#region extensions/codex/src/app-server/run-attempt-state.ts
4250
- async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields) {
4251
- const currentBinding = await bindingStore.read(identity);
4252
- const expectedThreadId = fields.threadId ?? currentBinding?.threadId;
4253
- if (!expectedThreadId) return;
4254
- if (currentBinding && currentBinding.threadId !== expectedThreadId) {
4255
- embeddedAgentLog.warn("codex app-server image payload error detected for unbound thread; preserving thread binding", {
4256
- ...fields,
4257
- boundThreadId: currentBinding.threadId
4258
- });
4259
- return;
4260
- }
4261
- if (currentBinding?.connectionScope === "supervision") {
4262
- embeddedAgentLog.warn("codex app-server image payload error detected for supervised thread; preserving native binding", fields);
4263
- return;
4264
- }
4265
- embeddedAgentLog.warn("codex app-server image payload error detected; clearing thread binding", fields);
4266
- await bindingStore.mutate(identity, {
4267
- kind: "clear",
4268
- threadId: expectedThreadId
4269
- });
4270
- }
4271
- async function markCodexAppServerBindingCoveredThroughTurn(params) {
4272
- await params.bindingStore.mutate(params.identity, {
4273
- kind: "patch",
4274
- threadId: params.threadId,
4275
- patch: { historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString() }
4276
- });
4277
- }
4278
- function isNonEmptyString(value) {
4279
- return typeof value === "string" && value.length > 0;
4280
- }
4281
- function shouldUseFreshCodexThreadAfterContextEngineOverflow(params) {
4282
- if (!params.contextEngineActive || params.thread.lifecycle.action !== "resumed") return false;
4283
- const message = formatErrorMessage(params.error);
4284
- 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);
4285
- }
4286
- function isCodexActiveCompactTurnError(error) {
4287
- if (!(error instanceof CodexAppServerRpcError)) return false;
4288
- const data = isJsonObject(error.data) ? error.data : void 0;
4289
- const codexErrorInfo = isJsonObject(data?.codexErrorInfo) ? data.codexErrorInfo : void 0;
4290
- return (isJsonObject(codexErrorInfo?.activeTurnNotSteerable) ? codexErrorInfo.activeTurnNotSteerable : void 0)?.turnKind === "compact";
4291
- }
4292
- function readCodexFinalizationHookNotification(notification, threadId, turnId) {
4293
- if (notification.method !== "hook/started" && notification.method !== "hook/completed") return;
4294
- const params = isJsonObject(notification.params) ? notification.params : void 0;
4295
- const run = params && isJsonObject(params.run) ? params.run : void 0;
4296
- if (params?.threadId !== threadId || params.turnId !== turnId || run?.eventName !== "stop" && run?.eventName !== "subagentStop" || typeof run.id !== "string" || !run.id) return;
4297
- if (notification.method === "hook/started") return {
4298
- phase: "started",
4299
- runId: run.id
4300
- };
4301
- return {
4302
- phase: "completed",
4303
- runId: run.id,
4304
- status: typeof run.status === "string" ? run.status : void 0
4305
- };
4306
- }
4307
- function joinPresentSections(...sections) {
4308
- return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
4309
- }
4310
- function prependCurrentInboundContext(prompt, context) {
4311
- const text = context?.text.trim();
4312
- return text ? [text, prompt].filter(Boolean).join("\n\n") : prompt;
4313
- }
4314
- function waitForCodexNotificationDispatchTurn() {
4315
- return new Promise((resolve) => {
4316
- setImmediate(resolve);
4317
- });
4318
- }
4319
- function buildCodexAppServerTimeoutDiagnostics(params) {
4320
- const readString = (key) => {
4321
- const value = params.details?.[key];
4322
- return typeof value === "string" && value.trim() ? value : void 0;
4323
- };
4324
- const readNumber = (key) => {
4325
- const value = params.details?.[key];
4326
- return typeof value === "number" && Number.isFinite(value) ? value : void 0;
4327
- };
4328
- const readBoolean = (key) => {
4329
- const value = params.details?.[key];
4330
- return typeof value === "boolean" ? value : void 0;
4331
- };
4332
- return {
4333
- ...params.idleMs !== void 0 ? { idleMs: params.idleMs } : {},
4334
- ...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
4335
- ...params.lastActivityReason ? { lastActivityReason: params.lastActivityReason } : {},
4336
- ...readString("lastNotificationMethod") ? { lastNotificationMethod: readString("lastNotificationMethod") } : {},
4337
- ...readString("lastNotificationItemId") ? { lastNotificationItemId: readString("lastNotificationItemId") } : {},
4338
- ...readString("lastNotificationItemType") ? { lastNotificationItemType: readString("lastNotificationItemType") } : {},
4339
- ...readString("lastNotificationItemRole") ? { lastNotificationItemRole: readString("lastNotificationItemRole") } : {},
4340
- ...readString("lastAssistantTextPreview") ? { lastAssistantTextPreview: readString("lastAssistantTextPreview") } : {},
4341
- ...readNumber("activeAppServerTurnRequests") !== void 0 ? { activeAppServerTurnRequests: readNumber("activeAppServerTurnRequests") } : {},
4342
- ...readNumber("activeTurnItemCount") !== void 0 ? { activeTurnItemCount: readNumber("activeTurnItemCount") } : {},
4343
- ...readBoolean("terminalTurnNotificationQueued") !== void 0 ? { terminalTurnNotificationQueued: readBoolean("terminalTurnNotificationQueued") } : {},
4344
- ...readBoolean("completionIdleWatchArmed") !== void 0 ? { completionIdleWatchArmed: readBoolean("completionIdleWatchArmed") } : {},
4345
- ...readBoolean("assistantCompletionIdleWatchArmed") !== void 0 ? { assistantCompletionIdleWatchArmed: readBoolean("assistantCompletionIdleWatchArmed") } : {},
4346
- ...readBoolean("terminalIdleWatchArmed") !== void 0 ? { terminalIdleWatchArmed: readBoolean("terminalIdleWatchArmed") } : {}
4347
- };
4348
- }
4349
- //#endregion
4350
4704
  //#region extensions/codex/src/app-server/run-attempt-context.ts
4351
4705
  async function prepareCodexAttemptContext(runtime, attemptTools) {
4352
4706
  const { connection, runtimeParams, activeSessionId, activeSessionFile, buildActiveRunAttemptParams, effectiveContextWindowInfo, effectiveContextTokenBudget, effectiveRuntimeProviderId, effectiveRuntimeModelId, hookChannelId } = runtime;
@@ -4417,7 +4771,7 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
4417
4771
  memoryToolNames: getCodexWorkspaceMemoryToolNames(toolBridge.availableSpecs),
4418
4772
  sandboxed: sandbox?.enabled === true
4419
4773
  });
4420
- const baseDeveloperInstructions = joinPresentSections(buildDeveloperInstructions(runtimeParams, { dynamicTools: toolBridge.availableSpecs }), workspaceBootstrapContext.developerInstructions);
4774
+ const baseDeveloperInstructions = buildDeveloperInstructions(runtimeParams, { dynamicTools: toolBridge.availableSpecs });
4421
4775
  return {
4422
4776
  runtime,
4423
4777
  attemptTools,
@@ -4431,7 +4785,13 @@ async function prepareCodexAttemptContext(runtime, attemptTools) {
4431
4785
  baseDeveloperInstructions,
4432
4786
  openClawPromptContext: buildCodexOpenClawPromptContext({
4433
4787
  params: runtimeParams,
4434
- workspacePromptContext: workspaceBootstrapContext.promptContext
4788
+ workspacePromptContext: workspaceBootstrapContext.promptContext,
4789
+ watchedSessionsContext: buildCodexWatchedSessionsContext({
4790
+ attempt: runtimeParams,
4791
+ dynamicTools: toolBridge.availableSpecs,
4792
+ sessionKey: contextSessionKey,
4793
+ sandboxed: sandbox?.enabled === true
4794
+ })
4435
4795
  }),
4436
4796
  skillsCollaborationInstructions: renderCodexSkillsCollaborationInstructions({
4437
4797
  attempt: runtimeParams,
@@ -4625,14 +4985,10 @@ function resolveCodexAppServerReplayBlockedReason(result) {
4625
4985
  /** Builds an attempt result for failures before the app-server turn starts. */
4626
4986
  function buildCodexTurnStartFailureResult(params) {
4627
4987
  return {
4628
- aborted: false,
4629
- externalAbort: false,
4630
- timedOut: false,
4631
- idleTimedOut: false,
4632
- timedOutDuringCompaction: false,
4633
- timedOutDuringToolExecution: false,
4634
- promptError: params.promptError ?? params.message,
4635
- promptErrorSource: "prompt",
4988
+ terminal: attemptTerminal.normalize({
4989
+ promptError: params.promptError ?? params.message,
4990
+ promptErrorSource: "prompt"
4991
+ }),
4636
4992
  sessionIdUsed: params.params.sessionId,
4637
4993
  messagesSnapshot: params.messagesSnapshot,
4638
4994
  assistantTexts: [],
@@ -4664,6 +5020,107 @@ function isInvalidCodexImagePayloadError(message) {
4664
5020
  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);
4665
5021
  }
4666
5022
  //#endregion
5023
+ //#region extensions/codex/src/app-server/run-attempt-state.ts
5024
+ async function clearCodexBindingAfterInvalidImagePayload(bindingStore, identity, fields) {
5025
+ const currentBinding = await bindingStore.read(identity);
5026
+ const expectedThreadId = fields.threadId ?? currentBinding?.threadId;
5027
+ if (!expectedThreadId) return;
5028
+ if (currentBinding && currentBinding.threadId !== expectedThreadId) {
5029
+ embeddedAgentLog.warn("codex app-server image payload error detected for unbound thread; preserving thread binding", {
5030
+ ...fields,
5031
+ boundThreadId: currentBinding.threadId
5032
+ });
5033
+ return;
5034
+ }
5035
+ if (currentBinding?.connectionScope === "supervision") {
5036
+ embeddedAgentLog.warn("codex app-server image payload error detected for supervised thread; preserving native binding", fields);
5037
+ return;
5038
+ }
5039
+ embeddedAgentLog.warn("codex app-server image payload error detected; clearing thread binding", fields);
5040
+ await bindingStore.mutate(identity, {
5041
+ kind: "clear",
5042
+ threadId: expectedThreadId
5043
+ });
5044
+ }
5045
+ async function markCodexAppServerBindingCoveredThroughTurn(params) {
5046
+ await params.bindingStore.mutate(params.identity, {
5047
+ kind: "patch",
5048
+ threadId: params.threadId,
5049
+ patch: { historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString() }
5050
+ });
5051
+ }
5052
+ function isNonEmptyString(value) {
5053
+ return typeof value === "string" && value.length > 0;
5054
+ }
5055
+ function shouldUseFreshCodexThreadAfterContextEngineOverflow(params) {
5056
+ if (!params.contextEngineActive || params.thread.lifecycle.action !== "resumed") return false;
5057
+ const message = formatErrorMessage(params.error);
5058
+ 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);
5059
+ }
5060
+ function isCodexActiveCompactTurnError(error) {
5061
+ if (!(error instanceof CodexAppServerRpcError)) return false;
5062
+ const data = isJsonObject(error.data) ? error.data : void 0;
5063
+ const codexErrorInfo = isJsonObject(data?.codexErrorInfo) ? data.codexErrorInfo : void 0;
5064
+ return (isJsonObject(codexErrorInfo?.activeTurnNotSteerable) ? codexErrorInfo.activeTurnNotSteerable : void 0)?.turnKind === "compact";
5065
+ }
5066
+ function readCodexFinalizationHookNotification(notification, threadId, turnId) {
5067
+ if (notification.method !== "hook/started" && notification.method !== "hook/completed") return;
5068
+ const params = isJsonObject(notification.params) ? notification.params : void 0;
5069
+ const run = params && isJsonObject(params.run) ? params.run : void 0;
5070
+ if (params?.threadId !== threadId || params.turnId !== turnId || run?.eventName !== "stop" && run?.eventName !== "subagentStop" || typeof run.id !== "string" || !run.id) return;
5071
+ if (notification.method === "hook/started") return {
5072
+ phase: "started",
5073
+ runId: run.id
5074
+ };
5075
+ return {
5076
+ phase: "completed",
5077
+ runId: run.id,
5078
+ status: typeof run.status === "string" ? run.status : void 0
5079
+ };
5080
+ }
5081
+ function joinPresentSections(...sections) {
5082
+ return sections.filter((section) => Boolean(section?.trim())).join("\n\n");
5083
+ }
5084
+ function prependCurrentInboundContext(prompt, context) {
5085
+ const text = context?.text.trim();
5086
+ return text ? [text, prompt].filter(Boolean).join("\n\n") : prompt;
5087
+ }
5088
+ function waitForCodexNotificationDispatchTurn() {
5089
+ return new Promise((resolve) => {
5090
+ setImmediate(resolve);
5091
+ });
5092
+ }
5093
+ function buildCodexAppServerTimeoutDiagnostics(params) {
5094
+ const readString = (key) => {
5095
+ const value = params.details?.[key];
5096
+ return typeof value === "string" && value.trim() ? value : void 0;
5097
+ };
5098
+ const readNumber = (key) => {
5099
+ const value = params.details?.[key];
5100
+ return typeof value === "number" && Number.isFinite(value) ? value : void 0;
5101
+ };
5102
+ const readBoolean = (key) => {
5103
+ const value = params.details?.[key];
5104
+ return typeof value === "boolean" ? value : void 0;
5105
+ };
5106
+ return {
5107
+ ...params.idleMs !== void 0 ? { idleMs: params.idleMs } : {},
5108
+ ...params.timeoutMs !== void 0 ? { timeoutMs: params.timeoutMs } : {},
5109
+ ...params.lastActivityReason ? { lastActivityReason: params.lastActivityReason } : {},
5110
+ ...readString("lastNotificationMethod") ? { lastNotificationMethod: readString("lastNotificationMethod") } : {},
5111
+ ...readString("lastNotificationItemId") ? { lastNotificationItemId: readString("lastNotificationItemId") } : {},
5112
+ ...readString("lastNotificationItemType") ? { lastNotificationItemType: readString("lastNotificationItemType") } : {},
5113
+ ...readString("lastNotificationItemRole") ? { lastNotificationItemRole: readString("lastNotificationItemRole") } : {},
5114
+ ...readString("lastAssistantTextPreview") ? { lastAssistantTextPreview: readString("lastAssistantTextPreview") } : {},
5115
+ ...readNumber("activeAppServerTurnRequests") !== void 0 ? { activeAppServerTurnRequests: readNumber("activeAppServerTurnRequests") } : {},
5116
+ ...readNumber("activeTurnItemCount") !== void 0 ? { activeTurnItemCount: readNumber("activeTurnItemCount") } : {},
5117
+ ...readBoolean("terminalTurnNotificationQueued") !== void 0 ? { terminalTurnNotificationQueued: readBoolean("terminalTurnNotificationQueued") } : {},
5118
+ ...readBoolean("completionIdleWatchArmed") !== void 0 ? { completionIdleWatchArmed: readBoolean("completionIdleWatchArmed") } : {},
5119
+ ...readBoolean("assistantCompletionIdleWatchArmed") !== void 0 ? { assistantCompletionIdleWatchArmed: readBoolean("assistantCompletionIdleWatchArmed") } : {},
5120
+ ...readBoolean("terminalIdleWatchArmed") !== void 0 ? { terminalIdleWatchArmed: readBoolean("terminalIdleWatchArmed") } : {}
5121
+ };
5122
+ }
5123
+ //#endregion
4667
5124
  //#region extensions/codex/src/app-server/settled-turn-context.ts
4668
5125
  function collectUniqueMessageIdentities(messages) {
4669
5126
  const identities = /* @__PURE__ */ new Map();
@@ -4787,14 +5244,6 @@ function createCodexHostTrajectorySink(params) {
4787
5244
  /** Creates a trajectory recorder when trajectory capture is enabled for the environment. */
4788
5245
  function createCodexTrajectoryRecorder(params) {
4789
5246
  if (!parseTrajectoryEnabled(params.env ?? process.env)) return null;
4790
- const sqliteMarker = parseSqliteSessionFileMarker(params.trajectorySessionFile ?? params.attempt.sessionFile);
4791
- if (!sqliteMarker || sqliteMarker.sessionId !== params.attempt.sessionId) {
4792
- params.warn?.("codex trajectory capture requires a matching SQLite session target", {
4793
- sessionId: params.attempt.sessionId,
4794
- reason: sqliteMarker ? "session-id-mismatch" : "non-sqlite-session-target"
4795
- });
4796
- return null;
4797
- }
4798
5247
  if (!params.trajectoryRecorder) {
4799
5248
  params.warn?.("codex trajectory capture requires the SQLite host recorder", {
4800
5249
  sessionId: params.attempt.sessionId,
@@ -4843,13 +5292,14 @@ function recordCodexTrajectoryContext(recorder, params) {
4843
5292
  /** Records final Codex model completion metadata and assistant snapshots. */
4844
5293
  function recordCodexTrajectoryCompletion(recorder, params) {
4845
5294
  if (!recorder) return;
5295
+ const terminal = attemptTerminal.project(params.result.terminal);
4846
5296
  recorder.recordEvent("model.completed", {
4847
5297
  threadId: params.threadId,
4848
5298
  turnId: params.turnId,
4849
5299
  timedOut: params.timedOut,
4850
5300
  yieldDetected: params.yieldDetected ?? false,
4851
- aborted: params.result.aborted,
4852
- promptError: normalizeCodexTrajectoryError(params.result.promptError),
5301
+ aborted: terminal.aborted,
5302
+ promptError: normalizeCodexTrajectoryError(terminal.promptError),
4853
5303
  usage: params.result.attemptUsage,
4854
5304
  assistantTexts: params.result.assistantTexts,
4855
5305
  messagesSnapshot: params.result.messagesSnapshot
@@ -4943,11 +5393,12 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4943
5393
  });
4944
5394
  }
4945
5395
  const result = activeProjector.buildResult(toolBridge.telemetry, { yieldDetected: toolState.yieldDetected });
5396
+ const projectedTerminal = attemptTerminal.project(result.terminal);
4946
5397
  const effectiveTimedOut = state.timedOut && !recoveredTurnWatchTimeout;
4947
5398
  const effectiveTurnCompletionIdleTimedOut = state.turnCompletionIdleTimedOut && !recoveredTurnWatchTimeout;
4948
- const isFinalAborted = () => result.aborted || terminalState.explicitCancellationObserved || runAbortController.signal.aborted && !state.clientClosedAbort && !recoveredTurnWatchTimeout;
5399
+ const isFinalAborted = () => projectedTerminal.aborted || terminalState.explicitCancellationObserved || runAbortController.signal.aborted && !state.clientClosedAbort && !recoveredTurnWatchTimeout;
4949
5400
  const clientClosedPromptErrorForFinal = state.clientClosedPromptError && hasRecoverableCompletedAssistant ? void 0 : state.clientClosedPromptError;
4950
- let finalPromptError = clientClosedPromptErrorForFinal ?? (effectiveTurnCompletionIdleTimedOut ? state.turnCompletionIdleTimeoutMessage : effectiveTimedOut ? "codex app-server attempt timed out" : result.promptError);
5401
+ let finalPromptError = clientClosedPromptErrorForFinal ?? (effectiveTurnCompletionIdleTimedOut ? state.turnCompletionIdleTimeoutMessage : effectiveTimedOut ? "codex app-server attempt timed out" : projectedTerminal.promptError);
4951
5402
  const finalPromptErrorMessage = typeof finalPromptError === "string" ? finalPromptError : finalPromptError instanceof Error ? finalPromptError.message : finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
4952
5403
  if (isInvalidCodexImagePayloadError(finalPromptErrorMessage)) await clearCodexBindingAfterInvalidImagePayload(bindingStore, bindingIdentity, {
4953
5404
  phase: "turn_completed",
@@ -4988,7 +5439,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
4988
5439
  authProfileId: startupAuthProfileId,
4989
5440
  rateLimits: readRecentCodexRateLimits(resourceState.client)
4990
5441
  });
4991
- const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : result.promptErrorSource;
5442
+ const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : projectedTerminal.promptErrorSource;
4992
5443
  const codexAppServerFailureKind = clientClosedPromptErrorForFinal ? "client_closed_before_turn_completed" : effectiveTurnCompletionIdleTimedOut ? "turn_completion_idle_timeout" : void 0;
4993
5444
  const replayBlockedReason = codexAppServerFailureKind ? resolveCodexAppServerReplayBlockedReason(result) : void 0;
4994
5445
  const promptTimeoutOutcome = buildCodexAppServerPromptTimeoutOutcome({
@@ -5122,7 +5573,29 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
5122
5573
  ...finalPromptError ? { error: formatErrorMessage(finalPromptError) } : {},
5123
5574
  durationMs: Date.now() - attemptStartedAt
5124
5575
  },
5125
- ctx: hookContext,
5576
+ ctx: {
5577
+ ...hookContext,
5578
+ modelProviderId: resourceState.thread.modelProvider ?? effectiveRuntimeProviderId,
5579
+ modelId: resourceState.thread.model ?? effectiveRuntimeModelId,
5580
+ authProfileId: resourceState.thread.authProfileId ?? startupAuthProfileId,
5581
+ modelIterations: result.modelIterations ?? 0,
5582
+ skillWorkshopAvailable: flattenCodexDynamicToolFunctions(attemptTools.toolBridge.availableSpecs).some((tool) => tool.name === "skill_workshop"),
5583
+ compacted: (result.compactionCount ?? 0) > 0,
5584
+ messageChannel: params.messageChannel,
5585
+ messageProvider: params.messageProvider,
5586
+ chatType: params.chatType,
5587
+ agentAccountId: params.agentAccountId,
5588
+ groupId: params.groupId,
5589
+ groupChannel: params.groupChannel,
5590
+ groupSpace: params.groupSpace,
5591
+ memberRoleIds: params.memberRoleIds,
5592
+ spawnedBy: params.spawnedBy,
5593
+ senderId: params.senderId ?? void 0,
5594
+ senderName: params.senderName,
5595
+ senderUsername: params.senderUsername,
5596
+ senderE164: params.senderE164,
5597
+ senderIsOwner: params.senderIsOwner
5598
+ },
5126
5599
  hookRunner
5127
5600
  });
5128
5601
  state.shouldDelayNativeHookRelayUnregister = completedTurnStatus === "completed" && !effectiveTimedOut && !runAbortController.signal.aborted && !finalAborted && !finalPromptError;
@@ -5183,10 +5656,12 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
5183
5656
  });
5184
5657
  return {
5185
5658
  ...result,
5186
- timedOut: effectiveTimedOut,
5187
- aborted: finalAborted,
5188
- promptError: finalPromptError,
5189
- promptErrorSource: finalPromptErrorSource,
5659
+ terminal: attemptTerminal.normalize({
5660
+ timedOut: effectiveTimedOut,
5661
+ aborted: finalAborted,
5662
+ promptError: finalPromptError,
5663
+ promptErrorSource: finalPromptErrorSource
5664
+ }),
5190
5665
  ...codexAppServerFailure ? { codexAppServerFailure } : {},
5191
5666
  ...promptTimeoutOutcome ? { promptTimeoutOutcome } : {},
5192
5667
  ...assistantTranscriptOwned ? { assistantTranscriptOwned: true } : {},
@@ -6009,6 +6484,9 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
6009
6484
  }
6010
6485
  //#endregion
6011
6486
  //#region extensions/codex/src/app-server/run-attempt-prompt.ts
6487
+ function isRestrictivePromptToolsAllow(toolsAllow) {
6488
+ return toolsAllow !== void 0 && !toolsAllow.some((name) => name.trim() === "*");
6489
+ }
6012
6490
  async function prepareCodexAttemptPrompt(context) {
6013
6491
  const { runtime, attemptTools, historyState, hookContext, workspaceBootstrapContext, baseDeveloperInstructions, openClawPromptContext, skillsCollaborationInstructions, promptState, codexContextProjectionMaxChars } = context;
6014
6492
  const { connection, buildActiveRunAttemptParams, effectiveContextTokenBudget, effectiveRuntimeModelId, effectiveRuntimeProviderId } = runtime;
@@ -6094,13 +6572,17 @@ async function prepareCodexAttemptPrompt(context) {
6094
6572
  embeddedAgentLog.warn("context engine assemble failed; using Codex baseline prompt", { error: formatErrorMessage(assembleErr) });
6095
6573
  }
6096
6574
  const codexModelInputHistoryMessages = [];
6097
- const buildPromptFromCurrentInputs = () => resolveAgentHarnessBeforePromptBuildResult({
6098
- prompt: prependCurrentInboundContext(promptState.promptText, params.currentInboundContext),
6099
- developerInstructions: promptState.developerInstructions,
6100
- messages: structuredClone(historyState.messages),
6101
- ctx: hookContext,
6102
- bootstrapContextRunKind: params.bootstrapContextRunKind
6103
- });
6575
+ const buildPromptFromCurrentInputs = async () => {
6576
+ const result = await resolveAgentHarnessBeforePromptBuildResult({
6577
+ prompt: prependCurrentInboundContext(promptState.promptText, params.currentInboundContext),
6578
+ developerInstructions: promptState.developerInstructions,
6579
+ messages: structuredClone(historyState.messages),
6580
+ ctx: hookContext,
6581
+ bootstrapContextRunKind: params.bootstrapContextRunKind
6582
+ });
6583
+ 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.");
6584
+ return result;
6585
+ };
6104
6586
  const resolveShiftedPromptInputRange = (prompt, promptInputRange, turnPromptText) => {
6105
6587
  if (!promptInputRange || promptInputRange.start < 0 || promptInputRange.end < promptInputRange.start || promptInputRange.end > prompt.length || !turnPromptText.endsWith(prompt)) return;
6106
6588
  const turnPromptOffset = turnPromptText.length - prompt.length;
@@ -7769,8 +8251,10 @@ const sandboxExecServerRegistry = {
7769
8251
  };
7770
8252
  //#endregion
7771
8253
  //#region extensions/codex/src/app-server/sandbox-exec-server/json-rpc.ts
7772
- /** JSON-RPC error code used when a sandbox exec-server method is unknown. */
8254
+ /** JSON-RPC error code used when a sandbox filesystem resource does not exist. */
7773
8255
  const JSON_RPC_NOT_FOUND = -32004;
8256
+ /** JSON-RPC error code used when a sandbox exec-server method is unsupported. */
8257
+ const JSON_RPC_METHOD_NOT_FOUND = -32601;
7774
8258
  /** Protocol-level error carrying the JSON-RPC error code to send to the client. */
7775
8259
  var JsonRpcProtocolError = class extends Error {
7776
8260
  constructor(code, message) {
@@ -8102,6 +8586,101 @@ function requireFsBridge(execServer) {
8102
8586
  * with OpenClaw sandbox policy checks before every bridge operation.
8103
8587
  */
8104
8588
  const CODEX_SANDBOX_EXEC_SERVER_MAX_READ_FILE_BYTES = 512 * 1024 * 1024;
8589
+ const CODEX_SANDBOX_EXEC_SERVER_MAX_OPEN_FILE_READS = 128;
8590
+ const CODEX_SANDBOX_EXEC_SERVER_MAX_BUFFERED_FILE_READ_BYTES = 64 * 1024 * 1024;
8591
+ const CODEX_SANDBOX_EXEC_SERVER_MAX_READ_BLOCK_BYTES = 1024 * 1024;
8592
+ const CODEX_SANDBOX_EXEC_SERVER_MAX_FILE_READ_HANDLE_ID_BYTES = 32;
8593
+ /** Opens a policy-checked sandbox file under a bounded, connection-owned handle. */
8594
+ async function openFile(execServer, handles, params) {
8595
+ const record = requireObject(params, "fs/open params");
8596
+ const handleId = requireFileReadHandleId(record.handleId);
8597
+ if (handles.closed) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, `unknown file read handle \`${handleId}\``);
8598
+ if (handles.has(handleId)) throw new JsonRpcProtocolError(-32600, `file read handle \`${handleId}\` already exists`);
8599
+ if (handles.size >= CODEX_SANDBOX_EXEC_SERVER_MAX_OPEN_FILE_READS) throw new JsonRpcProtocolError(-32600, `at most ${CODEX_SANDBOX_EXEC_SERVER_MAX_OPEN_FILE_READS} file reads may be open per connection`);
8600
+ const filePath = resolveExecServerPath(requireString(record.path, "path"), "read path");
8601
+ assertFsSandboxAccess(execServer, record, [{
8602
+ path: filePath,
8603
+ access: "read"
8604
+ }]);
8605
+ const fsBridge = requireFsBridge(execServer);
8606
+ const handle = {
8607
+ abortController: new AbortController(),
8608
+ closeRequested: false,
8609
+ reservedBytes: 0
8610
+ };
8611
+ handles.set(handleId, handle);
8612
+ try {
8613
+ const stat = await fsBridge.stat({
8614
+ filePath,
8615
+ signal: handle.abortController.signal
8616
+ });
8617
+ if (handles.get(handleId) !== handle || handle.closeRequested || handles.closed) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, `unknown file read handle \`${handleId}\``);
8618
+ if (!stat) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, "file not found");
8619
+ if (stat.type !== "file") throw new JsonRpcProtocolError(-32600, "file read handle requires a regular file");
8620
+ if (!Number.isSafeInteger(stat.size) || stat.size < 0) throw new JsonRpcProtocolError(-32600, "file size must be a non-negative safe integer");
8621
+ if (stat.size > CODEX_SANDBOX_EXEC_SERVER_MAX_BUFFERED_FILE_READ_BYTES - bufferedFileReadBytes(handles)) throw new JsonRpcProtocolError(-32600, "sandbox file read exceeds the per-connection buffered file limit");
8622
+ handle.reservedBytes = stat.size;
8623
+ const data = await fsBridge.readFile({
8624
+ filePath,
8625
+ maxBytes: handle.reservedBytes,
8626
+ signal: handle.abortController.signal
8627
+ });
8628
+ if (handles.get(handleId) !== handle || handle.closeRequested || handles.closed) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, `unknown file read handle \`${handleId}\``);
8629
+ if (data.byteLength > handle.reservedBytes) throw new JsonRpcProtocolError(-32600, "sandbox file read exceeds the per-connection buffered file limit");
8630
+ handle.reservedBytes = data.byteLength;
8631
+ handle.data = data;
8632
+ return { handleId };
8633
+ } catch (error) {
8634
+ if (handles.get(handleId) === handle) handles.delete(handleId);
8635
+ throw error;
8636
+ }
8637
+ }
8638
+ /** Reads a bounded base64 block from a handle belonging to this connection. */
8639
+ function readFileBlock(handles, params) {
8640
+ const record = requireObject(params, "fs/readBlock params");
8641
+ const handleId = requireFileReadHandleId(record.handleId);
8642
+ const handle = handles.get(handleId);
8643
+ if (!handle?.data) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, `unknown file read handle \`${handleId}\``);
8644
+ const offset = requireNumber(record.offset, "offset");
8645
+ const length = requireNumber(record.len, "len");
8646
+ if (!Number.isSafeInteger(offset) || offset < 0) throw new JsonRpcProtocolError(-32600, "file read offset must be a non-negative safe integer");
8647
+ if (!Number.isSafeInteger(length) || length < 1 || length > CODEX_SANDBOX_EXEC_SERVER_MAX_READ_BLOCK_BYTES) throw new JsonRpcProtocolError(-32600, `file read block length must be between 1 and ${CODEX_SANDBOX_EXEC_SERVER_MAX_READ_BLOCK_BYTES}`);
8648
+ const chunk = handle.data.subarray(offset, Math.min(offset + length, handle.data.byteLength));
8649
+ return {
8650
+ chunk: chunk.toString("base64"),
8651
+ eof: offset + chunk.byteLength >= handle.data.byteLength
8652
+ };
8653
+ }
8654
+ /** Closes one connection-owned file handle; repeated closes are harmless. */
8655
+ function closeFile(handles, params) {
8656
+ closeFileReadHandle(handles, requireFileReadHandleId(requireObject(params, "fs/close params").handleId));
8657
+ return {};
8658
+ }
8659
+ /** Cancels a disconnected socket without releasing unsettled read reservations. */
8660
+ function closeAllFileReads(handles) {
8661
+ handles.closed = true;
8662
+ for (const handleId of handles.keys()) closeFileReadHandle(handles, handleId);
8663
+ }
8664
+ function closeFileReadHandle(handles, handleId) {
8665
+ const handle = handles.get(handleId);
8666
+ if (!handle) return;
8667
+ handle.closeRequested = true;
8668
+ if (handle.data !== void 0) {
8669
+ handles.delete(handleId);
8670
+ return;
8671
+ }
8672
+ handle.abortController.abort();
8673
+ }
8674
+ function bufferedFileReadBytes(handles) {
8675
+ let total = 0;
8676
+ for (const handle of handles.values()) total += handle.reservedBytes;
8677
+ return total;
8678
+ }
8679
+ function requireFileReadHandleId(value) {
8680
+ const handleId = requireString(value, "handleId");
8681
+ if (Buffer.byteLength(handleId, "utf8") > CODEX_SANDBOX_EXEC_SERVER_MAX_FILE_READ_HANDLE_ID_BYTES) throw new JsonRpcProtocolError(-32600, `file read handle ID must not exceed ${CODEX_SANDBOX_EXEC_SERVER_MAX_FILE_READ_HANDLE_ID_BYTES} bytes`);
8682
+ return handleId;
8683
+ }
8105
8684
  /** Reads a sandbox file as base64 after read-policy and size checks. */
8106
8685
  async function readFile(execServer, params) {
8107
8686
  const record = requireObject(params, "fs/readFile params");
@@ -8114,7 +8693,10 @@ async function readFile(execServer, params) {
8114
8693
  const stat = await fsBridge.stat({ filePath });
8115
8694
  if (!stat) throw new JsonRpcProtocolError(JSON_RPC_NOT_FOUND, "file not found");
8116
8695
  assertSandboxFileReadWithinLimit(stat);
8117
- return { dataBase64: (await fsBridge.readFile({ filePath })).toString("base64") };
8696
+ return { dataBase64: (await fsBridge.readFile({
8697
+ filePath,
8698
+ maxBytes: CODEX_SANDBOX_EXEC_SERVER_MAX_READ_FILE_BYTES
8699
+ })).toString("base64") };
8118
8700
  }
8119
8701
  /** Writes base64 data to an existing sandbox directory after write-policy checks. */
8120
8702
  async function writeFile(execServer, params) {
@@ -8263,7 +8845,10 @@ async function copySandboxPath(execServer, params) {
8263
8845
  return;
8264
8846
  }
8265
8847
  assertSandboxFileReadWithinLimit(sourceStat);
8266
- const data = await fsBridge.readFile({ filePath: params.sourcePath });
8848
+ const data = await fsBridge.readFile({
8849
+ filePath: params.sourcePath,
8850
+ maxBytes: CODEX_SANDBOX_EXEC_SERVER_MAX_READ_FILE_BYTES
8851
+ });
8267
8852
  await fsBridge.writeFile({
8268
8853
  filePath: params.destinationPath,
8269
8854
  data,
@@ -8278,6 +8863,7 @@ function metadataResponse(stat) {
8278
8863
  isDirectory: stat?.type === "directory",
8279
8864
  isFile: stat?.type === "file",
8280
8865
  isSymlink: false,
8866
+ size: stat?.size ?? 0,
8281
8867
  createdAtMs: 0,
8282
8868
  modifiedAtMs: stat?.mtimeMs ?? 0
8283
8869
  };
@@ -9139,19 +9725,21 @@ function isAuthorizedExecServerRequest(execServer, request) {
9139
9725
  }
9140
9726
  function handleConnection(execServer, socket) {
9141
9727
  const processes = /* @__PURE__ */ new Map();
9728
+ const fileReads = /* @__PURE__ */ new Map();
9142
9729
  socket.on("message", (data) => {
9143
- handleMessage(execServer, processes, socket, data).catch((error) => {
9730
+ handleMessage(execServer, processes, fileReads, socket, data).catch((error) => {
9144
9731
  embeddedAgentLog.warn("codex sandbox exec-server message failed", { error });
9145
9732
  });
9146
9733
  });
9147
9734
  socket.on("close", () => {
9735
+ closeAllFileReads(fileReads);
9148
9736
  for (const process of processes.values()) process.abortController.abort();
9149
9737
  });
9150
9738
  }
9151
9739
  function handleExecServerSocketError(error) {
9152
9740
  embeddedAgentLog.debug("codex sandbox exec-server websocket failed", { error });
9153
9741
  }
9154
- async function handleMessage(execServer, processes, socket, data) {
9742
+ async function handleMessage(execServer, processes, fileReads, socket, data) {
9155
9743
  const request = parseRequest(data);
9156
9744
  if (!request.method) {
9157
9745
  sendError(socket, request.id, -32600, "Invalid Request");
@@ -9163,7 +9751,7 @@ async function handleMessage(execServer, processes, socket, data) {
9163
9751
  return;
9164
9752
  }
9165
9753
  try {
9166
- const result = await dispatchRequest(execServer, processes, socket, {
9754
+ const result = await dispatchRequest(execServer, processes, fileReads, socket, {
9167
9755
  ...request,
9168
9756
  method
9169
9757
  });
@@ -9172,13 +9760,25 @@ async function handleMessage(execServer, processes, socket, data) {
9172
9760
  sendError(socket, request.id, error instanceof JsonRpcProtocolError ? error.code : -32603, error instanceof Error ? error.message : String(error));
9173
9761
  }
9174
9762
  }
9175
- async function dispatchRequest(execServer, processes, socket, request) {
9763
+ async function dispatchRequest(execServer, processes, fileReads, socket, request) {
9176
9764
  switch (request.method) {
9177
9765
  case "initialize": return { sessionId: randomUUID() };
9766
+ case "environment/info": return {
9767
+ shell: {
9768
+ name: "sh",
9769
+ path: "/bin/sh"
9770
+ },
9771
+ cwd: pathToFileURL(execServer.sandbox.containerWorkdir, { windows: false }).href,
9772
+ capabilities: { networkProxyLaunch: false }
9773
+ };
9774
+ case "environment/status": return { status: "ready" };
9178
9775
  case "process/start": return startProcess(execServer, processes, socket, request.params);
9179
9776
  case "process/read": return await readProcess(processes, request.params);
9180
9777
  case "process/write": return writeProcess(processes, request.params);
9181
9778
  case "process/terminate": return terminateProcess(processes, request.params);
9779
+ case "fs/open": return await openFile(execServer, fileReads, request.params);
9780
+ case "fs/readBlock": return readFileBlock(fileReads, request.params);
9781
+ case "fs/close": return closeFile(fileReads, request.params);
9182
9782
  case "fs/readFile": return await readFile(execServer, request.params);
9183
9783
  case "fs/writeFile":
9184
9784
  await writeFile(execServer, request.params);
@@ -9195,7 +9795,7 @@ async function dispatchRequest(execServer, processes, socket, request) {
9195
9795
  await copyPath(execServer, request.params);
9196
9796
  return {};
9197
9797
  case "http/request": return await httpRequest(execServer, socket, request.params);
9198
- default: throw new Error(`Unsupported OpenClaw sandbox exec-server method: ${request.method}`);
9798
+ default: throw new JsonRpcProtocolError(JSON_RPC_METHOD_NOT_FOUND, `Unsupported OpenClaw sandbox exec-server method: ${request.method}`);
9199
9799
  }
9200
9800
  }
9201
9801
  //#endregion
@@ -9213,7 +9813,6 @@ function prepareCodexAttemptResources(prompt) {
9213
9813
  developerInstructions: buildRenderedCodexDeveloperInstructions(),
9214
9814
  prompt: turnState.codexTurnPromptText,
9215
9815
  trajectoryRecorder: hostTrajectoryRecorder,
9216
- trajectorySessionFile: params.trajectorySessionFile,
9217
9816
  tools: toolBridge.availableSpecs,
9218
9817
  warn: (message, fields) => embeddedAgentLog.warn(message, fields)
9219
9818
  });
@@ -9323,14 +9922,7 @@ function prepareCodexAttemptResources(prompt) {
9323
9922
  timeoutFloorMs: options.startupTimeoutFloorMs
9324
9923
  });
9325
9924
  const requesterChannel = params.messageChannel ?? params.messageProvider;
9326
- const requester = {
9327
- ...requesterChannel ? { channel: requesterChannel } : {},
9328
- ...params.agentAccountId ? { accountId: params.agentAccountId } : {},
9329
- ...params.senderId ? { senderId: params.senderId } : {},
9330
- ...params.senderIsOwner !== void 0 ? { senderIsOwner: params.senderIsOwner } : {},
9331
- ...params.memberRoleIds?.length ? { roleIds: [...params.memberRoleIds] } : {}
9332
- };
9333
- const hasRequester = Object.keys(requester).length > 0;
9925
+ const requester = buildCodexHookRequester(params);
9334
9926
  const buildNativeHookRelayFinalConfigPatch = (decision) => {
9335
9927
  state.nativeHookRelay?.unregister();
9336
9928
  state.nativeHookRelay = createCodexNativeHookRelay({
@@ -9344,7 +9936,15 @@ function prepareCodexAttemptResources(prompt) {
9344
9936
  config: params.config,
9345
9937
  runId: params.runId,
9346
9938
  channelId: hookChannelId,
9347
- ...hasRequester ? { requester } : {},
9939
+ ...requester ? { requester } : {},
9940
+ approvalContext: {
9941
+ trigger: params.trigger,
9942
+ approvalReviewerDeviceId: params.approvalReviewerDeviceId,
9943
+ turnSourceChannel: requesterChannel,
9944
+ turnSourceTo: params.currentMessagingTarget ?? params.currentChannelId,
9945
+ turnSourceAccountId: params.agentAccountId,
9946
+ turnSourceThreadId: params.currentThreadTs
9947
+ },
9348
9948
  attemptTimeoutMs: params.timeoutMs,
9349
9949
  startupTimeoutMs,
9350
9950
  turnStartTimeoutMs: params.timeoutMs,
@@ -9454,6 +10054,28 @@ async function prepareCodexAttemptRoute(resources, turnRuntime, notifications, h
9454
10054
  return { ensureCurrentThreadRoute };
9455
10055
  }
9456
10056
  //#endregion
10057
+ //#region extensions/codex/src/app-server/run-attempt-client-prewarm.ts
10058
+ /** Starts the shared process while tools and prompt context are still being prepared. */
10059
+ function prewarmCodexAttemptClient(params) {
10060
+ const { connection, authProfileStore, authBindingFingerprint } = params;
10061
+ const { appServer, attemptClientFactory, options, pluginConfig, runtimeArtifactRequest, startupAuthRequirement, startupClientAuthProfileId, startupPreparedAuth, agentDir, params: runParams, runAbortController } = connection;
10062
+ if (options.clientFactory || attemptClientFactory !== getLeasedSharedCodexAppServerClient || runtimeArtifactRequest) return;
10063
+ getSharedCodexAppServerClient({
10064
+ startOptions: appServer.start,
10065
+ pluginConfig,
10066
+ ...startupPreparedAuth ? { preparedAuth: startupPreparedAuth } : { authProfileId: startupClientAuthProfileId },
10067
+ authRequirement: startupAuthRequirement,
10068
+ authProfileStore,
10069
+ authBindingFingerprint,
10070
+ agentDir,
10071
+ config: runParams.config,
10072
+ timeoutMs: appServer.requestTimeoutMs,
10073
+ abandonSignal: runAbortController.signal
10074
+ }).catch((error) => {
10075
+ embeddedAgentLog.debug("codex app-server client prewarm failed", { error });
10076
+ });
10077
+ }
10078
+ //#endregion
9457
10079
  //#region extensions/codex/src/app-server/run-attempt-runtime.ts
9458
10080
  async function prepareCodexAttemptRuntime(connection) {
9459
10081
  const { params, pluginConfig, usesSupervisionConnection, appServer, startupAuthProfileId, startupPreparedAuth, startupClientAuthProfileId, agentDir, preDynamicStartupStages, effectiveWorkspace, contextSessionKey, sandboxSessionKey, sessionAgentId, sandbox, attemptClientFactory, runAbortController, activeContextEngine, mutable } = connection;
@@ -9464,6 +10086,11 @@ async function prepareCodexAttemptRuntime(connection) {
9464
10086
  config: params.config
9465
10087
  }) : void 0;
9466
10088
  const attemptAuthProfileStore = preparedAuthBinding?.authProfileStore ?? params.authProfileStore;
10089
+ prewarmCodexAttemptClient({
10090
+ connection,
10091
+ authProfileStore: attemptAuthProfileStore,
10092
+ authBindingFingerprint: preparedAuthBinding?.fingerprint
10093
+ });
9467
10094
  const effectiveContextWindowInfo = usesSupervisionConnection ? void 0 : params.contextWindowInfo;
9468
10095
  const effectiveContextTokenBudget = usesSupervisionConnection ? void 0 : params.contextTokenBudget;
9469
10096
  const effectiveRuntimeProviderId = usesSupervisionConnection ? mutable.startupBinding?.modelProvider ?? "codex" : params.provider;
@@ -9491,6 +10118,7 @@ async function prepareCodexAttemptRuntime(connection) {
9491
10118
  modelId: effectiveRuntimeModelId,
9492
10119
  model: supervisedRuntimeModel,
9493
10120
  thinkLevel: _outerThinkLevel,
10121
+ fastMode: _outerFastMode,
9494
10122
  sessionKey: contextSessionKey
9495
10123
  } : {
9496
10124
  ...params,
@@ -9518,7 +10146,8 @@ async function prepareCodexAttemptRuntime(connection) {
9518
10146
  cfg: params.config,
9519
10147
  toolsEnabled: usesSupervisionConnection || supportsModelTools(params.model),
9520
10148
  disableTools: params.disableTools,
9521
- toolsAllow: params.toolsAllow
10149
+ toolsAllow: params.toolsAllow,
10150
+ toolOverrides: params.toolOverrides
9522
10151
  });
9523
10152
  preDynamicStartupStages.mark("bundle-mcp");
9524
10153
  const sandboxExecServerEnabled = isCodexSandboxExecServerEnabled(pluginConfig);
@@ -9592,7 +10221,8 @@ function recordCodexDynamicToolResult(projector, call, response, protocolRespons
9592
10221
  success: protocolResponse.success,
9593
10222
  terminalType: response.diagnosticTerminalType ?? (protocolResponse.success ? "completed" : "error"),
9594
10223
  sideEffectEvidence: response.sideEffectEvidence === true || response.terminalResolution?.sideEffectEvidence === true,
9595
- contentItems: protocolResponse.contentItems
10224
+ contentItems: protocolResponse.contentItems,
10225
+ details: response.transcriptDetails
9596
10226
  });
9597
10227
  }
9598
10228
  //#endregion
@@ -9669,6 +10299,7 @@ function handleApprovalRequest(params) {
9669
10299
  turnId: params.turnId,
9670
10300
  nativeHookRelay: params.nativeHookRelay,
9671
10301
  autoApprove: params.autoApprove,
10302
+ autoApproveOpenClawToolPolicy: params.autoApproveOpenClawToolPolicy,
9672
10303
  signal: params.signal,
9673
10304
  onNativeToolFailureDisposition: params.onNativeToolFailureDisposition
9674
10305
  });
@@ -9686,7 +10317,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
9686
10317
  const { context } = prompt;
9687
10318
  const { runtime, attemptTools } = context;
9688
10319
  const { connection } = runtime;
9689
- const { params, computerUseConfig, runAbortController, appServer, sessionAgentId } = connection;
10320
+ const { params, computerUseConfig, runAbortController, appServer, approvalPolicyPromotedForOpenClawToolPolicy, sessionAgentId } = connection;
9690
10321
  const { toolBridge, toolOutcomeOrdinals, suppressedDynamicToolOutcomeOrdinals, allocateCodexToolOutcomeOrdinal } = attemptTools;
9691
10322
  const { state, turnIdRef, userInputBridgeRef, openClawDynamicToolExecutions, pendingOpenClawDynamicToolCompletionIds, postToolRawAssistantCompletionIdleTimeoutMs, turnWatches } = turnRuntime;
9692
10323
  const { emitExecutionPhaseOnce, scheduleTurnReleaseAfterTerminalDynamicTool, scheduleTerminalDynamicToolReleaseCheck } = lifecycle;
@@ -9744,6 +10375,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
9744
10375
  turnId,
9745
10376
  nativeHookRelay: resourceState.nativeHookRelay,
9746
10377
  autoApprove: shouldAutoApproveCodexAppServerApprovals(appServer),
10378
+ autoApproveOpenClawToolPolicy: approvalPolicyPromotedForOpenClawToolPolicy,
9747
10379
  signal,
9748
10380
  onNativeToolFailureDisposition: (itemId, disposition) => projector?.recordNativeToolApprovalFailure(itemId, disposition)
9749
10381
  });
@@ -10045,8 +10677,8 @@ var CodexPluginMetadataCache = class {
10045
10677
  this.clearGeneration = 0;
10046
10678
  }
10047
10679
  /** Returns a fresh cached snapshot without issuing a request. */
10048
- read(appCacheKey, queryKind) {
10049
- const entryKey = buildMetadataCacheEntryKey(appCacheKey, queryKind);
10680
+ read(appCacheKey, queryKind, requestParams) {
10681
+ const entryKey = buildMetadataCacheEntryKey(appCacheKey, queryKind, requestParams);
10050
10682
  const entry = this.entries.get(entryKey);
10051
10683
  if (!entry) return;
10052
10684
  if (entry.expiresAtMs <= this.nowMs()) {
@@ -10055,10 +10687,10 @@ var CodexPluginMetadataCache = class {
10055
10687
  }
10056
10688
  return entry.snapshot;
10057
10689
  }
10058
- /** Returns a fresh cached snapshot or coalesces one plugin/list request. */
10690
+ /** Returns a fresh snapshot or coalesces one catalog or installed-plugin request. */
10059
10691
  async load(params) {
10060
- const entryKey = buildMetadataCacheEntryKey(params.appCacheKey, params.queryKind);
10061
- const cached = this.read(params.appCacheKey, params.queryKind);
10692
+ const entryKey = buildMetadataCacheEntryKey(params.appCacheKey, params.queryKind, params.requestParams);
10693
+ const cached = this.read(params.appCacheKey, params.queryKind, params.requestParams);
10062
10694
  if (cached) return cached;
10063
10695
  const pending = this.inFlight.get(entryKey);
10064
10696
  if (pending) try {
@@ -10070,7 +10702,8 @@ var CodexPluginMetadataCache = class {
10070
10702
  const generation = this.generations.get(params.appCacheKey) ?? 0;
10071
10703
  const clearGeneration = this.clearGeneration;
10072
10704
  const promise = (async () => {
10073
- const response = await params.request("plugin/list", params.requestParams);
10705
+ const method = params.queryKind === "installed" ? "plugin/installed" : "plugin/list";
10706
+ const response = await params.request(method, params.requestParams);
10074
10707
  const snapshot = {
10075
10708
  appCacheKey: params.appCacheKey,
10076
10709
  queryKind: params.queryKind,
@@ -10109,10 +10742,17 @@ var CodexPluginMetadataCache = class {
10109
10742
  /** Shared plugin metadata cache used by Codex app-server runtime paths. */
10110
10743
  const defaultCodexPluginMetadataCache = new CodexPluginMetadataCache();
10111
10744
  function hasMarketplaceLoadErrors(response) {
10112
- return (response.marketplaceLoadErrors?.length ?? 0) > 0;
10113
- }
10114
- function buildMetadataCacheEntryKey(appCacheKey, queryKind) {
10115
- return JSON.stringify([appCacheKey, queryKind]);
10745
+ return response.marketplaceLoadErrors.length > 0;
10746
+ }
10747
+ function buildMetadataCacheEntryKey(appCacheKey, queryKind, requestParams) {
10748
+ if (queryKind !== "installed") return JSON.stringify([appCacheKey, queryKind]);
10749
+ const installedParams = requestParams;
10750
+ return JSON.stringify([
10751
+ appCacheKey,
10752
+ queryKind,
10753
+ installedParams?.cwds ?? [],
10754
+ Array.from(new Set(installedParams?.installSuggestionPluginNames ?? [])).toSorted()
10755
+ ]);
10116
10756
  }
10117
10757
  //#endregion
10118
10758
  //#region extensions/codex/src/app-server/plugin-thread-config-deadline.ts
@@ -10206,7 +10846,8 @@ function createCodexPluginThreadConfigStartupProvider(params) {
10206
10846
  recoverablePluginConfigKeys: policy ? resolveRecoverableCodexPluginConfigKeys({
10207
10847
  policy,
10208
10848
  metadataCache,
10209
- appCacheKey: params.appCacheKey
10849
+ appCacheKey: params.appCacheKey,
10850
+ configCwd: params.configCwd
10210
10851
  }) : void 0,
10211
10852
  build: () => buildCodexPluginThreadConfigWithinDeadline({
10212
10853
  ...buildParams,
@@ -10284,6 +10925,7 @@ async function startCodexAttemptThread(params) {
10284
10925
  const attemptParams = params.buildAttemptParams();
10285
10926
  startupClient = await params.attemptClientFactory({
10286
10927
  startOptions: params.appServer.start,
10928
+ pluginConfig: params.pluginConfig,
10287
10929
  ...params.startupPreparedAuth ? { preparedAuth: params.startupPreparedAuth } : { authProfileId: params.startupAuthProfileId },
10288
10930
  authRequirement: params.startupAuthRequirement,
10289
10931
  authProfileStore: attemptParams.authProfileStore,
@@ -10315,7 +10957,7 @@ async function startCodexAttemptThread(params) {
10315
10957
  if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
10316
10958
  let runtimeArtifact;
10317
10959
  if (params.runtimeArtifactRequest) {
10318
- const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-C2ITXdhM.js");
10960
+ const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-CmtG_t1L.js");
10319
10961
  runtimeArtifact = readCodexAppServerClientRuntimeArtifact(activeStartupClient);
10320
10962
  const expected = params.runtimeArtifactRequest.expected;
10321
10963
  const matchesExpected = !expected || Boolean(runtimeArtifact && runtimeArtifact.id === expected.id && runtimeArtifact.fingerprint === expected.fingerprint);
@@ -10332,14 +10974,19 @@ async function startCodexAttemptThread(params) {
10332
10974
  config: params.config
10333
10975
  });
10334
10976
  const turnRouter = getCodexAppServerTurnRouter(activeStartupClient);
10335
- await ensureCodexComputerUse({
10336
- client: activeStartupClient,
10337
- pluginConfig: params.pluginConfig,
10338
- config: params.config,
10339
- agentDir: params.agentDir,
10340
- timeoutMs: params.appServer.requestTimeoutMs,
10341
- signal: startupAbandonController.signal
10342
- });
10977
+ try {
10978
+ await ensureCodexComputerUse({
10979
+ client: activeStartupClient,
10980
+ pluginConfig: params.pluginConfig,
10981
+ config: params.config,
10982
+ agentDir: params.agentDir,
10983
+ timeoutMs: params.appServer.requestTimeoutMs,
10984
+ signal: startupAbandonController.signal
10985
+ });
10986
+ } catch (error) {
10987
+ if (startupAbandonController.signal.aborted) throw error;
10988
+ throw new AgentHarnessPreflightError(`Codex Computer Use readiness failed: ${formatErrorMessage(error)}`, { cause: error });
10989
+ }
10343
10990
  const startupRuntimeIdentity = activeStartupClient.getRuntimeIdentity();
10344
10991
  const pluginAppCacheKey = buildCodexPluginAppCacheKey({
10345
10992
  appServer: params.appServer,
@@ -10655,6 +11302,14 @@ async function startCodexAttemptRuntime(resources) {
10655
11302
  spawnedBy: params.spawnedBy
10656
11303
  });
10657
11304
  state.client = startupResult.client;
11305
+ toolBridge.setRemoteWorkspaceFileReader?.(({ path, maxBytes, workspaceRoot, signal, timeoutMs }) => readBoundedCodexRemoteWorkspaceFile({
11306
+ client: startupResult.client,
11307
+ path,
11308
+ maxBytes,
11309
+ workspaceRoot,
11310
+ signal,
11311
+ timeoutMs
11312
+ }));
10658
11313
  state.thread = startupResult.thread;
10659
11314
  state.runtimeArtifact = startupResult.runtimeArtifact;
10660
11315
  state.turnRouter = startupResult.turnRouter;
@@ -10807,7 +11462,7 @@ async function prepareCodexAttemptTools(runtime) {
10807
11462
  sessionId: params.sessionId,
10808
11463
  sessionKey: params.sessionKey,
10809
11464
  workspaceDir: effectiveWorkspace,
10810
- agentDir: agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId),
11465
+ agentDir: agentDir ?? resolveAgentDir(params.config ?? {}, sessionAgentId),
10811
11466
  cfg: params.config,
10812
11467
  requesterSenderId: params.senderId,
10813
11468
  agentAccountId: params.agentAccountId,
@@ -10821,7 +11476,7 @@ async function prepareCodexAttemptTools(runtime) {
10821
11476
  sessionId: params.sessionId,
10822
11477
  runId: params.runId,
10823
11478
  agentId: sessionAgentId,
10824
- agentDir: agentDir ?? resolveAgentDir$1(params.config ?? {}, sessionAgentId),
11479
+ agentDir: agentDir ?? resolveAgentDir(params.config ?? {}, sessionAgentId),
10825
11480
  agentAccountId: params.agentAccountId,
10826
11481
  messageProvider: params.messageProvider ?? params.messageChannel,
10827
11482
  messageChannel: params.messageChannel,
@@ -10873,7 +11528,10 @@ async function prepareCodexAttemptTools(runtime) {
10873
11528
  hookContext: {
10874
11529
  agentId: sessionAgentId,
10875
11530
  config: params.config,
11531
+ contextWindowTokens: params.contextTokenBudget ?? params.model.contextWindow,
10876
11532
  workspaceDir: effectiveWorkspace,
11533
+ remoteWorkspaceRoot: connection.appServer.remoteWorkspaceRoot,
11534
+ remoteWorkspaceRequestTimeoutMs: connection.appServer.requestTimeoutMs,
10877
11535
  sessionId: params.sessionId,
10878
11536
  sessionKey: sandboxSessionKey,
10879
11537
  runId: params.runId,