@openclaw/codex 2026.7.2-beta.1 → 2026.7.2-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +1 -1
  2. package/dist/{app-server-policy-DVcxdse_.js → app-server-policy-Scc-Wevo.js} +1 -1
  3. package/dist/{attempt-notifications-DEv9h7iC.js → attempt-notifications-BFmNhqFl.js} +3 -6
  4. package/dist/cli-metadata.js +1 -1
  5. package/dist/{command-formatters-D6ZlGNmb.js → command-formatters-Dq9InZUK.js} +34 -3
  6. package/dist/{command-handlers-Cpl9fUWv.js → command-handlers-IgqmL_kv.js} +10 -13
  7. package/dist/{compact-FnJmiPNA.js → compact-DCTmg3id.js} +4 -5
  8. package/dist/{computer-use-DVzr8OP1.js → computer-use-CPcU8TjG.js} +4 -4
  9. package/dist/{conversation-control-DtQ-E7mr.js → conversation-control-CGkBlfc5.js} +5 -7
  10. package/dist/doctor-contract-api.js +1 -1
  11. package/dist/{dynamic-tools-BMLoaTeG.js → dynamic-tools-C_1tEs34.js} +608 -330
  12. package/dist/harness.js +9 -5
  13. package/dist/index.js +52 -31
  14. package/dist/{media-understanding-provider-D580L0P8.js → media-understanding-provider-D31dOJwb.js} +11 -12
  15. package/dist/media-understanding-provider.js +1 -1
  16. package/dist/{models-DuKzZA6G.js → models-uh26C8QU.js} +5 -9
  17. package/dist/{notification-correlation-DfaCm0mx.js → notification-correlation-KmfV4EkP.js} +3 -3
  18. package/dist/{plugin-app-cache-key-BKNjHMEs.js → plugin-app-cache-key-Ceb-lm2c.js} +2 -2
  19. package/dist/{rate-limits-Dhp04Rqo.js → rate-limits-DyXaYAxU.js} +7 -6
  20. package/dist/{request-DborTWgw.js → request-B_oQsCXy.js} +54 -8
  21. package/dist/{run-attempt-VPVJoYDP.js → run-attempt-MLzoMe_m.js} +499 -295
  22. package/dist/{config-c48K5HP9.js → session-binding-h1mmCGnl.js} +786 -3
  23. package/dist/{session-catalog-7H112Tr_.js → session-catalog-CEvoXWHA.js} +45 -29
  24. package/dist/{session-cli-B28RhCyp.js → session-cli-XsEuWb_C.js} +1 -1
  25. package/dist/{shared-client-D4mFI9al.js → shared-client-JiAnW6pc.js} +255 -81
  26. package/dist/{side-question-CgJBz52s.js → side-question-DqDvIwSU.js} +15 -13
  27. package/dist/{thread-lifecycle-BgLXzjvV.js → thread-lifecycle-CN_pPtPh.js} +1787 -1579
  28. package/dist/{protocol-validators-dZQ-UTOa.js → transcript-mirror-D9rTxx2P.js} +485 -2
  29. package/dist/usage-D5Rohxoc.js +25 -0
  30. package/dist/{web-search-provider.runtime-Bs-eTn5U.js → web-search-provider.runtime-CKVBn3fP.js} +3 -3
  31. package/npm-shrinkwrap.json +30 -30
  32. package/openclaw.plugin.json +10 -5
  33. package/package.json +6 -6
  34. package/dist/capabilities-42Dfn2TV.js +0 -33
  35. package/dist/prompt-overlay.js +0 -15
  36. package/dist/protocol-BMifTfdW.js +0 -15
  37. package/dist/provider-catalog.js +0 -118
  38. package/dist/provider-discovery.js +0 -34
  39. package/dist/provider.js +0 -307
  40. package/dist/session-binding-BMfX1OX-.js +0 -786
  41. package/dist/transcript-mirror-DhLwFIL4.js +0 -485
@@ -1,26 +1,21 @@
1
- import { i as isJsonObject, r as flattenCodexDynamicToolFunctions } from "./protocol-BMifTfdW.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-DEv9h7iC.js";
3
- import { _ as resolveCodexPluginsPolicy, b as shouldAutoApproveCodexAppServerApprovals, d as readCodexPluginConfig, g as resolveCodexModelBackedReviewerPolicyContext, h as resolveCodexComputerUseConfig, l as isCodexSandboxExecServerEnabled, s as isCodexAppServerApprovalPolicyAllowedByRequirements, x as withMcpElicitationsApprovalPolicy, y as resolveOpenClawExecPolicyForCodexAppServer } from "./config-c48K5HP9.js";
4
- import { a as readCodexDynamicToolCallParams, i as assertCodexTurnStartResponse } from "./protocol-validators-dZQ-UTOa.js";
5
- import { i as defaultCodexAppInventoryCache, n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-BKNjHMEs.js";
6
- import { A as isCodexAppServerApprovalRequest, C as resolveCodexAppServerFallbackApiKeyCacheKey, D as resolveCodexAppServerHomeDir, O as CodexAppServerRpcError, S as resolveCodexAppServerAuthProfileIdForAgent, T as resolveCodexAppServerPreparedAuthHandoff, _ as readCodexRateLimitsRevision, a as getLeasedSharedCodexAppServerClient, b as resolveCodexAppServerAuthAccountCacheKey, c as releaseLeasedSharedCodexAppServerClient, d as retireSharedCodexAppServerClientIfCurrent, g as ensureCodexAppServerClientRuntime, j as isCodexAppServerConnectionClosedError, 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-D4mFI9al.js";
7
- import { A as fitCodexProjectedContextForTurnStart, B as unsubscribeCodexThreadBestEffort, E as isSystemAgentOnlyCodexDynamicToolAllowlist, F as CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS, G as shouldBuildCodexPluginThreadConfig, H as buildCodexPluginThreadConfig, I as CodexAppServerUnsafeSubscriptionError, L as closeCodexStartupClientBestEffort, M as resolveCodexContextEngineProjectionMaxChars, N as resolveCodexContextEngineProjectionReserveTokens, P as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS, R as interruptCodexTurnBestEffort, U as buildCodexPluginThreadConfigInputFingerprint, W as mergeCodexThreadConfigs, a as buildDeveloperInstructions, b as isCodexAppServerProfilerEnabled, c as codexDynamicToolsFingerprint, g as startOrResumeThread, i as buildContextEngineBinding, j as projectContextEngineAssemblyForCodex, k as resolveCodexDynamicToolsLoadingForRuntime, l as codexLegacyDynamicToolsFingerprint, n as areCodexDynamicToolFingerprintsCompatible, o as buildTurnCollaborationMode, p as resolveCodexAppServerThreadModelSelection, s as buildTurnStartParams, u as isContextEngineBindingCompatible, v as resolveCodexWebSearchPlan, w as filterCodexDynamicTools, z as retireCodexAppServerClientAfterTimedOutTurn } from "./thread-lifecycle-BgLXzjvV.js";
8
- import { c as sessionBindingIdentity, s as reclaimCurrentCodexSessionGeneration } from "./session-binding-BMfX1OX-.js";
9
- import { a as shouldRefreshCodexRateLimitsForUsageLimitMessage, i as resolveCodexUsageLimitResetAtMs, n as formatCodexUsageLimitErrorMessage } from "./rate-limits-Dhp04Rqo.js";
10
- import { i as mirrorPromptAtTurnStartBestEffort, n as createCodexAppServerUserMessagePersistenceNotifier, o as buildCodexUserPromptMessage, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-DhLwFIL4.js";
11
- import { t as CODEX_CONTROL_METHODS } from "./capabilities-42Dfn2TV.js";
12
- import { r as formatCodexDisplayText } from "./command-formatters-D6ZlGNmb.js";
13
- import { n as resolveCodexAppServerForOpenClawToolPolicy, t as resolveCodexAppServerForModelProvider } from "./app-server-policy-DVcxdse_.js";
14
- import { a as resolveCodexBindingAppServerConnection, n as readCodexNotificationThreadId, r as readCodexNotificationTurnId, t as isCodexNotificationForTurn } from "./notification-correlation-DfaCm0mx.js";
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, R as CodexAppServerRpcError, S as resolveCodexAppServerAuthProfileIdForAgent, T as resolveCodexAppServerPreparedAuthHandoff, V as isCodexAppServerBrokenPipeError, X as flattenCodexDynamicToolFunctions, Z as isJsonObject, _ 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 } from "./shared-client-JiAnW6pc.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-BFmNhqFl.js";
3
+ import { C as resolveCodexComputerUseConfig, D as resolveOpenClawExecPolicyForCodexAppServer, O as shouldAutoApproveCodexAppServerApprovals, T as resolveCodexPluginsPolicy, c as sessionBindingIdentity, g as isCodexAppServerApprovalPolicyAllowedByRequirements, k as withMcpElicitationsApprovalPolicy, s as reclaimCurrentCodexSessionGeneration, v as isCodexSandboxExecServerEnabled, w as resolveCodexModelBackedReviewerPolicyContext, y as readCodexPluginConfig } from "./session-binding-h1mmCGnl.js";
4
+ import { _ as readCodexTurnCompletedNotification, f as assertCodexTurnStartResponse, i as mirrorPromptAtTurnStartBestEffort, n as createCodexAppServerUserMessagePersistenceNotifier, o as buildCodexUserPromptMessage, p as readCodexDynamicToolCallParams, t as codexTranscriptMirrorRuntime } from "./transcript-mirror-D9rTxx2P.js";
5
+ import { i as defaultCodexAppInventoryCache, n as buildCodexAppServerRuntimeFingerprint, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-Ceb-lm2c.js";
6
+ import { A as CodexAppServerUnsafeSubscriptionError, B as fitCodexProjectedContextForTurnStart, D as resolveCodexDynamicToolsLoadingForRuntime, F as areCodexDynamicToolFingerprintsCompatible, G as buildCodexPluginThreadConfig, H as resolveCodexContextEngineProjectionMaxChars, I as codexDynamicToolsFingerprint, J as mergeCodexThreadConfigs, K as buildCodexPluginThreadConfigInputFingerprint, L as codexLegacyDynamicToolsFingerprint, M as interruptCodexTurnBestEffort, N as retireCodexAppServerClientAfterTimedOutTurn, O as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS, P as unsubscribeCodexThreadBestEffort, Q as resolveRecoverableCodexPluginConfigKeys, R as buildContextEngineBinding, U as resolveCodexContextEngineProjectionReserveTokens, V as projectContextEngineAssemblyForCodex, Y as shouldBuildCodexPluginThreadConfig, b as isCodexAppServerProfilerEnabled, d as resolveCodexWebSearchPlan, f as buildDeveloperInstructions, g as resolveCodexAppServerThreadModelSelection, j as closeCodexStartupClientBestEffort, k as CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS, n as buildTurnStartParams, q as buildCodexPluginThreadConfigTimeoutFallback, r as buildCodexUserInput, s as startOrResumeThread, t as buildTurnCollaborationMode, w as isSystemAgentOnlyCodexDynamicToolAllowlist, x as filterCodexDynamicTools, z as isContextEngineBindingCompatible } from "./thread-lifecycle-CN_pPtPh.js";
7
+ import { r as formatCodexDisplayText } from "./command-formatters-Dq9InZUK.js";
8
+ import { n as resolveCodexAppServerForOpenClawToolPolicy, t as resolveCodexAppServerForModelProvider } from "./app-server-policy-Scc-Wevo.js";
9
+ import { a as resolveCodexBindingAppServerConnection, n as readCodexNotificationThreadId, r as readCodexNotificationTurnId, t as isCodexNotificationForTurn } from "./notification-correlation-KmfV4EkP.js";
15
10
  import { n as prepareCodexAppServerAuthBinding } from "./auth-binding-C1czuHPA.js";
16
- import { $ as inferCodexDynamicToolMeta, B as handleDynamicToolCallWithTimeout, C as resolveCodexMessageToolProvider, D as shouldWarnCodexDynamicToolBuildStageSummary, E as shouldRequireCodexSandboxExecServerEnvironment, F as createCodexNativeHookRelay, G as resolveTerminalDynamicToolBatchAction, H as isDynamicToolTerminalDiagnosticEvent, I as emitCodexNativePreToolUseFailureDiagnostic, J as toCodexDynamicToolProgressResponse, K as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, L as resolveCodexNativeHookRelayEvents, M as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, N as buildCodexNativeHookRelayConfig, P as buildCodexNativeHookRelayDisabledConfig, Q as shouldEmitTranscriptToolProgress, R as resolveCodexNativeHookRelayTtlMs, S as resolveCodexExternalSandboxPolicyForOpenClawSandbox, T as shouldEnableCodexAppServerNativeToolSurface, U as isMatchingDynamicToolTerminalDiagnostic, V as hasPendingDynamicToolTerminalDiagnostic, W as resolveDynamicToolCallTimeoutMs, X as resolveCodexToolAbortTerminalReason, Y as toCodexDynamicToolProtocolResponse, Z as readCodexMirroredSessionHistoryMessages, _ as createCodexDynamicToolBuildStageTracker, a as emitDynamicToolStartedDiagnostic, b as resolveCodexAppServerExecutionCwd, d as resolveCodexStartupTimeoutMs, et as resolveCodexToolProgressDetailMode, f as resolveCodexTurnAssistantCompletionIdleTimeoutMs, g as buildDynamicTools, h as withCodexStartupTimeout, i as emitDynamicToolErrorDiagnostic, k as CodexAppServerEventProjector, l as CODEX_POST_REASONING_REPLY_IDLE_TIMEOUT_MS, m as resolveCodexTurnTerminalIdleTimeoutMs, n as handleCodexAppServerApprovalRequest, nt as sanitizeCodexToolResponse, o as emitDynamicToolTerminalDiagnostic, p as resolveCodexTurnCompletionIdleTimeoutMs, q as shouldReleaseTurnAfterTerminalDynamicTool, r as handleCodexAppServerElicitationRequest, rt as resolveCodexLocalRuntimeAttribution, s as resolveCodexProviderWebSearchSupport, t as createCodexDynamicToolBridge, tt as sanitizeCodexToolArguments, u as resolveCodexPostToolRawAssistantCompletionIdleTimeoutMs, v as disableCodexPluginThreadConfig, w as resolveCodexSandboxEnvironmentSelection, x as resolveCodexAppServerHookChannelId, y as formatCodexDynamicToolBuildStageSummary, z as scheduleCodexNativeHookRelayUnregister } from "./dynamic-tools-BMLoaTeG.js";
17
- import { a as runCodexComputerUseLiveTest, r as killStaleComputerUseMcpChildren, t as ensureCodexComputerUse } from "./computer-use-DVzr8OP1.js";
11
+ import { $ as resolveCodexToolProgressDetailMode, B as hasPendingDynamicToolTerminalDiagnostic, C as CodexAppServerEventProjector, D as markCodexAuthProfileBlockedFromRateLimits, E as isCodexUsageLimitPromptError, F as emitCodexNativePreToolUseFailureDiagnostic, G as shouldBlockTerminalReleaseForNonTerminalDynamicToolResult, H as isMatchingDynamicToolTerminalDiagnostic, I as resolveCodexNativeHookRelayEvents, J as toCodexDynamicToolProtocolResponse, K as shouldReleaseTurnAfterTerminalDynamicTool, L as resolveCodexNativeHookRelayTtlMs, M as buildCodexNativeHookRelayConfig, N as buildCodexNativeHookRelayDisabledConfig, O as refreshCodexUsageLimitPromptError, P as createCodexNativeHookRelay, Q as inferCodexDynamicToolMeta, R as scheduleCodexNativeHookRelayUnregister, T as formatCodexTurnStartUsageLimitError, U as resolveDynamicToolCallTimeoutMs, V as isDynamicToolTerminalDiagnosticEvent, W as resolveTerminalDynamicToolBatchAction, X as readCodexMirroredSessionHistoryMessages, Y as resolveCodexToolAbortTerminalReason, Z as shouldEmitTranscriptToolProgress, _ as resolveCodexMessageToolProvider, a as emitDynamicToolStartedDiagnostic, b as shouldRequireCodexSandboxExecServerEnvironment, d as createCodexDynamicToolBuildStageTracker, et as sanitizeCodexToolArguments, f as disableCodexPluginThreadConfig, g as resolveCodexExternalSandboxPolicyForOpenClawSandbox, h as resolveCodexAppServerHookChannelId, i as emitDynamicToolErrorDiagnostic, j as CODEX_NATIVE_HOOK_RELAY_TTL_GRACE_MS, l as settleCodexSourceReplyFinality, m as resolveCodexAppServerExecutionCwd, n as handleCodexAppServerApprovalRequest, nt as resolveCodexLocalRuntimeAttribution, o as emitDynamicToolTerminalDiagnostic, p as formatCodexDynamicToolBuildStageSummary, q as toCodexDynamicToolProgressResponse, r as handleCodexAppServerElicitationRequest, s as resolveCodexProviderWebSearchSupport, t as createCodexDynamicToolBridge, tt as sanitizeCodexToolResponse, u as buildDynamicTools, v as resolveCodexSandboxEnvironmentSelection, w as createCodexUsageLimitPromptError, x as shouldWarnCodexDynamicToolBuildStageSummary, y as shouldEnableCodexAppServerNativeToolSurface, z as handleDynamicToolCallWithTimeout } from "./dynamic-tools-C_1tEs34.js";
12
+ import { a as runCodexComputerUseLiveTest, r as killStaleComputerUseMcpChildren, t as ensureCodexComputerUse } from "./computer-use-CPcU8TjG.js";
18
13
  import fs from "node:fs/promises";
19
14
  import path, { posix } from "node:path";
20
15
  import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
21
- import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
16
+ import { sliceUtf16Safe, truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
22
17
  import { createHash, randomUUID } from "node:crypto";
23
- import { markAuthProfileBlockedUntil, resolveAgentDir, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
18
+ import { resolveAgentDir, resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
24
19
  import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
25
20
  import { asFiniteNumber, normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
26
21
  import { CODEX_APP_SERVER_CONTEXT_ENGINE_HOST, FAST_MODE_AUTO_PROGRESS_KIND, assembleHarnessContextEngine, assertContextEngineHostSupport, awaitAgentEndSideEffects, bootstrapHarnessContextEngine, buildAgentHarnessUserInputAnswers, buildBootstrapContextForFiles, buildHarnessContextEngineRuntimeContext, buildHarnessContextEngineRuntimeContextFromUsage, clearActiveEmbeddedRun, deliverAgentHarnessUserInputPrompt, embeddedAgentLog, emitAgentEvent, emptyAgentHarnessUserInputAnswers, finalizeHarnessContextEngineTurn, formatErrorMessage, formatFastModeAutoProgressText, getAgentHarnessHookRunner, getBeforeToolCallPolicyDiagnosticState, isActiveHarnessContextEngine, isHostScopedAgentToolActive, loadCodexBundleMcpThreadConfig, materializeRequesterScopedMcpToolsForHarnessRun, resolveAgentDir as resolveAgentDir$1, resolveAgentHarnessBeforePromptBuildResult, resolveAgentRunAbortLifecycleFields, resolveBootstrapFilesForRun, resolveContextEngineOwnerPluginId, resolveFastModeForElapsed, resolveSandboxContext, resolveSessionAgentIds as resolveSessionAgentIds$1, resolveUserPath, runAgentCleanupStep, runAgentEndSideEffects, runAgentHarnessLlmInputHook, runAgentHarnessLlmOutputHook, runHarnessContextEngineMaintenance, setActiveEmbeddedRun, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
@@ -29,103 +24,171 @@ import { once } from "node:events";
29
24
  import { isIP } from "node:net";
30
25
  import { WebSocketServer } from "ws";
31
26
  import { parseSqliteSessionFileMarker } from "openclaw/plugin-sdk/session-store-runtime";
32
- import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
27
+ import { fileURLToPath } from "node:url";
33
28
  import { createDiagnosticTraceContextFromActiveScope, emitTrustedDiagnosticEvent, emitTrustedDiagnosticEventWithPrivateData, freezeDiagnosticTraceContext, onInternalDiagnosticEvent, resolveDiagnosticModelContentCapturePolicy } from "openclaw/plugin-sdk/diagnostic-runtime";
29
+ import { buildMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
34
30
  import { MESSAGE_TOOL_DELIVERY_HINTS } from "openclaw/plugin-sdk/message-tool-delivery-hints";
35
31
  import { createAgentHarnessTaskRuntime, deliverAgentHarnessTaskCompletion, isDurableAgentHarnessCompletionDelivery } from "openclaw/plugin-sdk/agent-harness-task-runtime";
36
32
  import { SsrFBlockedError, isBlockedHostnameOrIp } from "openclaw/plugin-sdk/ssrf-runtime";
37
33
  //#region extensions/codex/src/app-server/attempt-steering.ts
38
34
  /**
39
- * Debounced steering queue for forwarding user text to an active Codex
35
+ * Debounced steering queue for forwarding user messages to an active Codex
40
36
  * app-server turn.
41
37
  */
42
38
  const CODEX_STEER_ALL_DEBOUNCE_MS = 500;
43
39
  /**
44
- * Creates a queue that batches steer text while still serializing app-server
45
- * `turn/steer` requests.
40
+ * Creates a queue that batches steer messages while still serializing
41
+ * app-server `turn/steer` requests.
46
42
  */
47
43
  function createCodexSteeringQueue(params) {
48
- let batchedTexts = [];
44
+ let batchedMessages = [];
45
+ const dispatchedBatches = /* @__PURE__ */ new Map();
46
+ const pendingMessages = /* @__PURE__ */ new Set();
49
47
  let batchTimer;
48
+ let batchSequence = 0;
50
49
  let sendChain = Promise.resolve();
50
+ let closedError;
51
51
  const clearBatchTimer = () => {
52
52
  if (batchTimer) {
53
53
  clearTimeout(batchTimer);
54
54
  batchTimer = void 0;
55
55
  }
56
56
  };
57
- const sendTexts = async (texts) => {
58
- if (texts.length === 0) return;
59
- if (params.signal.aborted) throw new Error("codex app-server steering queue aborted");
60
- await params.client.request("turn/steer", {
61
- threadId: params.threadId,
62
- expectedTurnId: params.turnId,
63
- input: texts.map(toCodexTextInput)
64
- });
57
+ const resolveItem = (item) => {
58
+ if (item.settled) return;
59
+ item.settled = true;
60
+ pendingMessages.delete(item);
61
+ item.resolve();
62
+ };
63
+ const rejectItem = (item, error) => {
64
+ if (item.settled) return;
65
+ item.settled = true;
66
+ pendingMessages.delete(item);
67
+ item.reject(error);
68
+ };
69
+ const closeQueue = (error) => {
70
+ if (closedError) return;
71
+ closedError = error;
72
+ params.signal.removeEventListener("abort", abortQueue);
73
+ clearBatchTimer();
74
+ batchedMessages = [];
75
+ dispatchedBatches.clear();
76
+ for (const item of pendingMessages) rejectItem(item, error);
77
+ };
78
+ const abortQueue = () => {
79
+ closeQueue(/* @__PURE__ */ new Error("codex app-server steering queue aborted"));
80
+ };
81
+ const cancelQueue = () => {
82
+ closeQueue(/* @__PURE__ */ new Error("codex app-server steering queue cancelled"));
83
+ };
84
+ const sendBatch = async (items) => {
85
+ const liveItems = items.filter((item) => !item.settled);
86
+ if (liveItems.length === 0) return;
87
+ const unavailableError = closedError ?? (params.signal.aborted ? /* @__PURE__ */ new Error("codex app-server steering queue aborted") : void 0);
88
+ if (unavailableError) {
89
+ for (const item of liveItems) rejectItem(item, unavailableError);
90
+ throw unavailableError;
91
+ }
92
+ const clientUserMessageId = `openclaw:${params.turnId}:steer:${++batchSequence}`;
93
+ const batch = { items: liveItems };
94
+ dispatchedBatches.set(clientUserMessageId, batch);
95
+ try {
96
+ await params.client.request("turn/steer", {
97
+ threadId: params.threadId,
98
+ expectedTurnId: params.turnId,
99
+ input: liveItems.flatMap((item) => buildCodexUserInput(item.text, item.images)),
100
+ clientUserMessageId
101
+ });
102
+ } catch (error) {
103
+ dispatchedBatches.delete(clientUserMessageId);
104
+ for (const item of liveItems) rejectItem(item, error);
105
+ throw error;
106
+ }
65
107
  };
66
- const enqueueSend = (texts) => {
67
- const send = sendChain.then(() => sendTexts(texts));
68
- sendChain = send.catch((error) => {
108
+ const enqueueSend = (items) => {
109
+ const send = sendChain.then(() => sendBatch(items));
110
+ sendChain = send;
111
+ send.catch((error) => {
112
+ for (const item of items) rejectItem(item, error);
69
113
  embeddedAgentLog.debug("codex app-server queued steer failed", { error });
70
114
  });
71
115
  return send;
72
116
  };
73
117
  const flushBatch = () => {
74
118
  clearBatchTimer();
75
- const items = batchedTexts;
76
- batchedTexts = [];
77
- const send = enqueueSend(items.map((item) => item.text));
78
- send.then(() => {
79
- for (const item of items) item.resolve();
80
- }, (error) => {
81
- for (const item of items) item.reject(error);
82
- });
119
+ const items = batchedMessages;
120
+ batchedMessages = [];
121
+ if (items.length === 0) return sendChain;
122
+ const send = enqueueSend(items);
123
+ send.catch(() => void 0);
83
124
  return send;
84
125
  };
126
+ const createPendingMessage = (text, images) => {
127
+ let resolveDelivery;
128
+ let rejectDelivery;
129
+ const delivery = new Promise((resolve, reject) => {
130
+ resolveDelivery = resolve;
131
+ rejectDelivery = reject;
132
+ });
133
+ const item = {
134
+ text,
135
+ images,
136
+ resolve: resolveDelivery,
137
+ reject: rejectDelivery,
138
+ settled: false
139
+ };
140
+ pendingMessages.add(item);
141
+ return {
142
+ item,
143
+ delivery
144
+ };
145
+ };
146
+ params.signal.addEventListener("abort", abortQueue, { once: true });
147
+ if (params.signal.aborted) abortQueue();
85
148
  return {
86
149
  async queue(text, options) {
87
- if (params.answerPendingUserInput(text)) return;
88
- return await new Promise((resolve, reject) => {
89
- batchedTexts.push({
90
- text,
91
- resolve,
92
- reject
93
- });
94
- clearBatchTimer();
95
- const debounceMs = normalizeCodexSteerDebounceMs(options?.debounceMs);
96
- if (debounceMs === 0) {
97
- flushBatch().catch(() => void 0);
150
+ const pendingUserInput = params.claimPendingUserInput();
151
+ if (pendingUserInput) {
152
+ if (!options?.images?.length) {
153
+ pendingUserInput.answer(text);
98
154
  return;
99
155
  }
100
- batchTimer = setTimeout(() => {
101
- batchTimer = void 0;
102
- flushBatch().catch(() => void 0);
103
- }, debounceMs);
104
- });
156
+ flushBatch().catch(() => void 0);
157
+ const { item, delivery } = createPendingMessage(text, options.images);
158
+ await Promise.all([enqueueSend([item]).finally(() => pendingUserInput.cancel()), delivery]);
159
+ return;
160
+ }
161
+ if (closedError) throw closedError;
162
+ if (params.signal.aborted) throw new Error("codex app-server steering queue aborted");
163
+ const { item, delivery } = createPendingMessage(text, options?.images);
164
+ batchedMessages.push(item);
165
+ clearBatchTimer();
166
+ const debounceMs = normalizeCodexSteerDebounceMs(options?.debounceMs);
167
+ if (debounceMs === 0) flushBatch();
168
+ else batchTimer = setTimeout(() => {
169
+ batchTimer = void 0;
170
+ flushBatch();
171
+ }, debounceMs);
172
+ return await delivery;
105
173
  },
106
174
  async flushPending() {
175
+ if (closedError) return;
107
176
  await flushBatch().catch(() => void 0);
108
177
  },
109
- cancel() {
110
- clearBatchTimer();
111
- const items = batchedTexts;
112
- batchedTexts = [];
113
- for (const item of items) item.reject(/* @__PURE__ */ new Error("codex app-server steering queue cancelled"));
114
- }
178
+ confirmConsumed(clientUserMessageId) {
179
+ const batch = dispatchedBatches.get(clientUserMessageId);
180
+ if (!batch) return false;
181
+ dispatchedBatches.delete(clientUserMessageId);
182
+ for (const item of batch.items) resolveItem(item);
183
+ return true;
184
+ },
185
+ cancel: cancelQueue
115
186
  };
116
187
  }
117
188
  /** Normalizes steer debounce milliseconds, preserving explicit zero. */
118
189
  function normalizeCodexSteerDebounceMs(value) {
119
190
  return typeof value === "number" && Number.isFinite(value) && value >= 0 ? Math.floor(value) : CODEX_STEER_ALL_DEBOUNCE_MS;
120
191
  }
121
- /** Converts plain text into the Codex app-server user-input shape. */
122
- function toCodexTextInput(text) {
123
- return {
124
- type: "text",
125
- text,
126
- text_elements: []
127
- };
128
- }
129
192
  //#endregion
130
193
  //#region extensions/codex/src/app-server/user-input-bridge.ts
131
194
  /**
@@ -142,6 +205,11 @@ function createCodexUserInputBridge(params) {
142
205
  current.cleanup();
143
206
  current.resolve(value);
144
207
  };
208
+ const resolvePendingIfCurrent = (current, value) => {
209
+ if (pending !== current) return false;
210
+ resolvePending(value);
211
+ return true;
212
+ };
145
213
  return {
146
214
  async handleRequest(request) {
147
215
  const requestParams = readUserInputParams(request.params);
@@ -158,6 +226,7 @@ function createCodexUserInputBridge(params) {
158
226
  turnId: requestParams.turnId,
159
227
  itemId: requestParams.itemId,
160
228
  questions: requestParams.questions,
229
+ claimed: false,
161
230
  resolve,
162
231
  cleanup
163
232
  };
@@ -171,9 +240,18 @@ function createCodexUserInputBridge(params) {
171
240
  });
172
241
  });
173
242
  },
243
+ claimPendingRequest() {
244
+ const current = pending;
245
+ if (!current || current.claimed) return;
246
+ current.claimed = true;
247
+ return {
248
+ answer: (text) => resolvePendingIfCurrent(current, buildUserInputResponse(current.questions, text)),
249
+ cancel: () => resolvePendingIfCurrent(current, emptyUserInputResponse())
250
+ };
251
+ },
174
252
  handleQueuedMessage(text) {
175
253
  const current = pending;
176
- if (!current) return false;
254
+ if (!current || current.claimed) return false;
177
255
  resolvePending(buildUserInputResponse(current.questions, text));
178
256
  return true;
179
257
  },
@@ -181,7 +259,7 @@ function createCodexUserInputBridge(params) {
181
259
  if (notification.method !== "serverRequest/resolved" || !pending) return;
182
260
  const notificationParams = isJsonObject(notification.params) ? notification.params : void 0;
183
261
  const requestId = notificationParams ? readRequestId(notificationParams) : void 0;
184
- if (notificationParams && readString$4(notificationParams, "threadId") === pending.threadId && requestId !== void 0 && String(requestId) === String(pending.requestId)) resolvePending(emptyUserInputResponse());
262
+ if (notificationParams && readString$3(notificationParams, "threadId") === pending.threadId && requestId !== void 0 && String(requestId) === String(pending.requestId)) resolvePending(emptyUserInputResponse());
185
263
  },
186
264
  cancelPending() {
187
265
  resolvePending(emptyUserInputResponse());
@@ -190,9 +268,9 @@ function createCodexUserInputBridge(params) {
190
268
  }
191
269
  function readUserInputParams(value) {
192
270
  if (!isJsonObject(value)) return;
193
- const threadId = readString$4(value, "threadId");
194
- const turnId = readString$4(value, "turnId");
195
- const itemId = readString$4(value, "itemId");
271
+ const threadId = readString$3(value, "threadId");
272
+ const turnId = readString$3(value, "turnId");
273
+ const itemId = readString$3(value, "itemId");
196
274
  const questionsRaw = value.questions;
197
275
  if (!threadId || !turnId || !itemId || !Array.isArray(questionsRaw)) return;
198
276
  return {
@@ -204,9 +282,9 @@ function readUserInputParams(value) {
204
282
  }
205
283
  function readQuestion(value) {
206
284
  if (!isJsonObject(value)) return;
207
- const id = readString$4(value, "id");
208
- const header = readString$4(value, "header");
209
- const question = readString$4(value, "question");
285
+ const id = readString$3(value, "id");
286
+ const header = readString$3(value, "header");
287
+ const question = readString$3(value, "question");
210
288
  if (!id || !header || !question) return;
211
289
  return {
212
290
  id,
@@ -224,8 +302,8 @@ function readOptions(value) {
224
302
  }
225
303
  function readOption(value) {
226
304
  if (!isJsonObject(value)) return;
227
- const label = readString$4(value, "label");
228
- const description = readString$4(value, "description") ?? "";
305
+ const label = readString$3(value, "label");
306
+ const description = readString$3(value, "description") ?? "";
229
307
  return label ? {
230
308
  label,
231
309
  description
@@ -243,7 +321,7 @@ function buildUserInputResponse(questions, inputText) {
243
321
  function emptyUserInputResponse() {
244
322
  return emptyAgentHarnessUserInputAnswers();
245
323
  }
246
- function readString$4(record, key) {
324
+ function readString$3(record, key) {
247
325
  const value = record[key];
248
326
  return typeof value === "string" ? value : void 0;
249
327
  }
@@ -336,7 +414,7 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
336
414
  client: resourceState.client,
337
415
  threadId: resourceState.thread.threadId,
338
416
  turnId: activeTurnId,
339
- answerPendingUserInput: (text) => userInputBridgeRef.current?.handleQueuedMessage(text) ?? false,
417
+ claimPendingUserInput: () => userInputBridgeRef.current?.claimPendingRequest(),
340
418
  signal: runAbortController.signal
341
419
  });
342
420
  steeringQueueRef.current = activeSteeringQueue;
@@ -348,6 +426,7 @@ async function activateCodexAttemptTurn(resources, turnRuntime, lifecycle, notif
348
426
  isStopped: () => state.completed || state.timedOut || runAbortController.signal.aborted,
349
427
  isAbortable: () => !terminalState.terminalOutcomeFrozen || terminalState.sharedAbortAllowedAfterTerminalOutcome,
350
428
  isCompacting: () => projectorRef.current?.isCompacting() ?? false,
429
+ supportsQueueMessageImages: true,
351
430
  sourceReplyDeliveryMode: params.sourceReplyDeliveryMode,
352
431
  cancel: () => abortExplicitly("cancelled"),
353
432
  abort: () => abortExplicitly("aborted")
@@ -1058,6 +1137,7 @@ async function prepareCodexAttemptConnection({ params, options }) {
1058
1137
  isInactiveThreadBootstrapBinding,
1059
1138
  usesSupervisionConnection,
1060
1139
  startupAuthProfileId,
1140
+ startupAuthRequirement: preparedAuthRoute?.authRequirement,
1061
1141
  startupPreparedAuth,
1062
1142
  startupClientAuthProfileId,
1063
1143
  effectiveWorkspace,
@@ -2070,7 +2150,7 @@ function buildCodexTurnStartFailureResult(params) {
2070
2150
  idleTimedOut: false,
2071
2151
  timedOutDuringCompaction: false,
2072
2152
  timedOutDuringToolExecution: false,
2073
- promptError: params.message,
2153
+ promptError: params.promptError ?? params.message,
2074
2154
  promptErrorSource: "prompt",
2075
2155
  sessionIdUsed: params.params.sessionId,
2076
2156
  messagesSnapshot: params.messagesSnapshot,
@@ -2284,139 +2364,6 @@ function normalizeCodexTrajectoryError(value) {
2284
2364
  }
2285
2365
  }
2286
2366
  //#endregion
2287
- //#region extensions/codex/src/app-server/usage-limit-error.ts
2288
- /**
2289
- * Enriches Codex usage-limit failures with current rate-limit information and
2290
- * marks blocked auth profiles when Codex exposes a reset time.
2291
- */
2292
- const CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS = 5e3;
2293
- /** Marks a Codex auth profile blocked until the reset time advertised by rate limits. */
2294
- async function markCodexAuthProfileBlockedFromRateLimits(params) {
2295
- const authProfileId = params.authProfileId?.trim();
2296
- if (!authProfileId || !params.params.authProfileStore) return;
2297
- const blockedUntil = resolveCodexUsageLimitResetAtMs(params.rateLimits);
2298
- if (!blockedUntil) return;
2299
- try {
2300
- await markAuthProfileBlockedUntil({
2301
- store: params.params.authProfileStore,
2302
- profileId: authProfileId,
2303
- blockedUntil,
2304
- source: "codex_rate_limits",
2305
- agentDir: params.params.agentDir,
2306
- runId: params.params.runId,
2307
- modelId: params.params.modelId
2308
- });
2309
- } catch (error) {
2310
- embeddedAgentLog.debug("failed to mark Codex auth profile blocked from app-server limits", {
2311
- authProfileId,
2312
- error: formatErrorMessage(error)
2313
- });
2314
- }
2315
- }
2316
- /** Formats a turn-start usage-limit error, refreshing rate limits when needed. */
2317
- async function formatCodexTurnStartUsageLimitError(params) {
2318
- return refreshCodexUsageLimitError({
2319
- client: params.client,
2320
- source: readCodexTurnStartUsageLimitErrorSource(params.client, params.error, params.errorNotification, params.rateLimitsRevisionBeforeTurnStart),
2321
- timeoutMs: params.timeoutMs,
2322
- signal: params.signal
2323
- });
2324
- }
2325
- /** Refreshes a generic prompt usage-limit message into a reset-aware message. */
2326
- async function refreshCodexUsageLimitPromptError(params) {
2327
- if (!shouldRefreshCodexRateLimitsForUsageLimitMessage(params.message)) return;
2328
- return (await refreshCodexUsageLimitError({
2329
- client: params.client,
2330
- source: {
2331
- message: params.message,
2332
- codexErrorInfo: "usageLimitExceeded",
2333
- rateLimits: readRecentCodexRateLimits(params.client)
2334
- },
2335
- timeoutMs: params.timeoutMs,
2336
- signal: params.signal
2337
- }))?.message;
2338
- }
2339
- async function refreshCodexUsageLimitError(params) {
2340
- const initialMessage = formatCodexUsageLimitErrorMessage(params.source);
2341
- if (!shouldRefreshCodexRateLimitsForUsageLimitMessage(initialMessage)) return initialMessage ? {
2342
- message: initialMessage,
2343
- ...params.source.rateLimitsTrustedForProfile ? { rateLimitsForProfile: params.source.rateLimits } : {}
2344
- } : void 0;
2345
- const rateLimits = await readCodexRateLimitsFromAppServerForUsageLimitError({
2346
- client: params.client,
2347
- timeoutMs: params.timeoutMs,
2348
- signal: params.signal
2349
- });
2350
- if (!rateLimits) return initialMessage ? {
2351
- message: initialMessage,
2352
- ...params.source.rateLimitsTrustedForProfile ? { rateLimitsForProfile: params.source.rateLimits } : {}
2353
- } : void 0;
2354
- const message = formatCodexUsageLimitErrorMessage({
2355
- message: params.source.message,
2356
- codexErrorInfo: params.source.codexErrorInfo,
2357
- rateLimits
2358
- }) ?? initialMessage;
2359
- return message ? {
2360
- message,
2361
- rateLimitsForProfile: rateLimits
2362
- } : void 0;
2363
- }
2364
- async function readCodexRateLimitsFromAppServerForUsageLimitError(params) {
2365
- if (params.signal?.aborted) return;
2366
- try {
2367
- const rateLimits = await params.client.request(CODEX_CONTROL_METHODS.rateLimits, void 0, {
2368
- timeoutMs: resolveCodexUsageLimitRateLimitRefreshTimeoutMs(params.timeoutMs),
2369
- signal: params.signal
2370
- });
2371
- rememberCodexRateLimitsRead(params.client, rateLimits);
2372
- return rateLimits;
2373
- } catch (error) {
2374
- embeddedAgentLog.debug("codex app-server rate-limit refresh failed after usage-limit error", { error: formatErrorMessage(error) });
2375
- return;
2376
- }
2377
- }
2378
- function resolveCodexUsageLimitRateLimitRefreshTimeoutMs(timeoutMs) {
2379
- if (timeoutMs === void 0 || !Number.isFinite(timeoutMs) || timeoutMs <= 0) return CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS;
2380
- return Math.max(100, Math.min(timeoutMs, CODEX_USAGE_LIMIT_RATE_LIMIT_REFRESH_TIMEOUT_MS));
2381
- }
2382
- function readCodexTurnStartUsageLimitErrorSource(client, error, errorNotification, rateLimitsRevisionBeforeTurnStart) {
2383
- const notificationError = readCodexErrorNotification(errorNotification);
2384
- const errorPayload = readCodexErrorPayload(error);
2385
- const rateLimits = errorPayload.rateLimits ?? readRecentCodexRateLimits(client);
2386
- const cacheUpdatedDuringTurnStart = rateLimitsRevisionBeforeTurnStart !== void 0 && readCodexRateLimitsRevision(client) > rateLimitsRevisionBeforeTurnStart;
2387
- return {
2388
- message: notificationError?.message ?? errorPayload.message ?? formatErrorMessage(error),
2389
- codexErrorInfo: notificationError?.codexErrorInfo ?? errorPayload.codexErrorInfo,
2390
- rateLimits,
2391
- rateLimitsTrustedForProfile: errorPayload.rateLimits !== void 0 || cacheUpdatedDuringTurnStart
2392
- };
2393
- }
2394
- function readCodexErrorNotification(notification) {
2395
- if (notification?.method !== "error" || !isJsonObject(notification.params)) return;
2396
- const error = notification.params.error;
2397
- return isJsonObject(error) ? {
2398
- message: readString$3(error, "message"),
2399
- codexErrorInfo: error.codexErrorInfo
2400
- } : void 0;
2401
- }
2402
- function readCodexErrorPayload(error) {
2403
- const message = error instanceof Error ? error.message : void 0;
2404
- if (!error || typeof error !== "object" || !("data" in error)) return { message };
2405
- const data = error.data;
2406
- if (!isJsonObject(data)) return { message };
2407
- const nestedError = isJsonObject(data.error) ? data.error : data;
2408
- const rateLimits = nestedError.rateLimits ?? data.rateLimits;
2409
- return {
2410
- message: readString$3(nestedError, "message") ?? message,
2411
- codexErrorInfo: nestedError.codexErrorInfo,
2412
- rateLimits
2413
- };
2414
- }
2415
- function readString$3(record, key) {
2416
- const value = record[key];
2417
- return typeof value === "string" ? value : void 0;
2418
- }
2419
- //#endregion
2420
2367
  //#region extensions/codex/src/app-server/run-attempt-finalize.ts
2421
2368
  async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notifications, requestRuntime, activeTurn) {
2422
2369
  const { prompt, state: resourceState, trajectoryRecorder, markTrajectoryEndRecorded } = resources;
@@ -2425,7 +2372,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
2425
2372
  const { hookContextWindowFields, hookRunner, promptState } = context;
2426
2373
  const { connection, preparedAuthBinding, activeSessionId, activeSessionFile } = runtime;
2427
2374
  const { buildActiveRunAttemptParams, effectiveContextTokenBudget, effectiveRuntimeProviderId, effectiveRuntimeModelId } = runtime;
2428
- const { params, terminalState, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, usesSupervisionConnection, sessionAgentId, contextSessionKey, effectiveCwd, effectiveWorkspace, agentDir, attemptStartedAt } = connection;
2375
+ const { params, terminalState, runAbortController, activeContextEngine, bindingStore, bindingIdentity, appServer, usesSupervisionConnection, sessionAgentId, contextSessionKey, effectiveCwd, effectiveWorkspace, agentDir, attemptStartedAt, startupAuthProfileId } = connection;
2429
2376
  const { toolBridge, toolState } = attemptTools;
2430
2377
  const { state, completion, pendingOpenClawDynamicToolCompletionIds, activeTurnItemIds, activeCompletionBlockerItemIds, activeFinalizationHookRunIds, turnWatches } = turnRuntime;
2431
2378
  const { emitLifecycleTerminal, buildLifecycleTerminalMeta } = lifecycle;
@@ -2459,7 +2406,7 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
2459
2406
  const isFinalAborted = () => result.aborted || terminalState.explicitCancellationObserved || runAbortController.signal.aborted && !state.clientClosedAbort && !recoveredTurnWatchTimeout;
2460
2407
  const clientClosedPromptErrorForFinal = state.clientClosedPromptError && hasRecoverableCompletedAssistant ? void 0 : state.clientClosedPromptError;
2461
2408
  let finalPromptError = clientClosedPromptErrorForFinal ?? (effectiveTurnCompletionIdleTimedOut ? state.turnCompletionIdleTimeoutMessage : effectiveTimedOut ? "codex app-server attempt timed out" : result.promptError);
2462
- const finalPromptErrorMessage = typeof finalPromptError === "string" ? finalPromptError : finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
2409
+ const finalPromptErrorMessage = typeof finalPromptError === "string" ? finalPromptError : finalPromptError instanceof Error ? finalPromptError.message : finalPromptError ? formatErrorMessage(finalPromptError) : void 0;
2463
2410
  if (isInvalidCodexImagePayloadError(finalPromptErrorMessage)) await clearCodexBindingAfterInvalidImagePayload(bindingStore, bindingIdentity, {
2464
2411
  phase: "turn_completed",
2465
2412
  threadId: resourceState.thread.threadId,
@@ -2487,7 +2434,18 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
2487
2434
  timeoutMs: appServer.requestTimeoutMs,
2488
2435
  signal: runAbortController.signal
2489
2436
  });
2490
- if (refreshedUsageLimitPromptError) finalPromptError = refreshedUsageLimitPromptError;
2437
+ if (refreshedUsageLimitPromptError) {
2438
+ await markCodexAuthProfileBlockedFromRateLimits({
2439
+ params,
2440
+ authProfileId: startupAuthProfileId,
2441
+ rateLimits: refreshedUsageLimitPromptError.rateLimitsForProfile
2442
+ });
2443
+ finalPromptError = createCodexUsageLimitPromptError(refreshedUsageLimitPromptError.message);
2444
+ } else if (isCodexUsageLimitPromptError(finalPromptError) && state.rateLimitsRevisionBeforeLastTurnStart !== void 0 && readCodexRateLimitsRevision(resourceState.client) > state.rateLimitsRevisionBeforeLastTurnStart) await markCodexAuthProfileBlockedFromRateLimits({
2445
+ params,
2446
+ authProfileId: startupAuthProfileId,
2447
+ rateLimits: readRecentCodexRateLimits(resourceState.client)
2448
+ });
2491
2449
  const finalPromptErrorSource = effectiveTimedOut || clientClosedPromptErrorForFinal ? "prompt" : result.promptErrorSource;
2492
2450
  const codexAppServerFailureKind = clientClosedPromptErrorForFinal ? "client_closed_before_turn_completed" : effectiveTurnCompletionIdleTimedOut ? "turn_completion_idle_timeout" : void 0;
2493
2451
  const replayBlockedReason = codexAppServerFailureKind ? resolveCodexAppServerReplayBlockedReason(result) : void 0;
@@ -2515,7 +2473,9 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
2515
2473
  const finalAborted = isFinalAborted();
2516
2474
  const completedTurnStatus = activeProjector.getCompletedTurnStatus();
2517
2475
  const completedWithoutTerminalNotification = state.completed && !state.terminalTurnNotificationQueued && !state.timedOut && clientClosedPromptErrorForFinal === void 0;
2518
- const attemptSucceeded = !finalAborted && !effectiveTimedOut && (finalPromptError === null || finalPromptError === void 0) && result.agentHarnessResultClassification === void 0 && (completedTurnStatus === "completed" || recoveredTurnWatchTimeout || completedWithoutTerminalNotification);
2476
+ const turnSucceeded = !finalAborted && !effectiveTimedOut && (finalPromptError === null || finalPromptError === void 0) && (completedTurnStatus === "completed" || recoveredTurnWatchTimeout || completedWithoutTerminalNotification);
2477
+ if (settleCodexSourceReplyFinality(toolBridge.telemetry, turnSucceeded)) result.agentHarnessResultClassification = void 0;
2478
+ const attemptSucceeded = turnSucceeded && result.agentHarnessResultClassification === void 0;
2519
2479
  terminalState.sharedAbortAllowedAfterTerminalOutcome = shouldKeepCodexSharedAbortOpen({
2520
2480
  trigger: params.trigger,
2521
2481
  result,
@@ -2662,7 +2622,8 @@ async function finalizeCodexAttempt(resources, turnRuntime, lifecycle, notificat
2662
2622
  phase: "end",
2663
2623
  ...buildLifecycleTerminalMeta({
2664
2624
  aborted: finalAborted,
2665
- timedOut: effectiveTimedOut
2625
+ timedOut: effectiveTimedOut,
2626
+ yielded: toolState.yieldDetected
2666
2627
  })
2667
2628
  });
2668
2629
  return {
@@ -2708,7 +2669,7 @@ function reportCodexExecutionNotification(params) {
2708
2669
  /** Returns true when a notification ends the current app-server turn. */
2709
2670
  function isTerminalCodexTurnNotificationForTurn(params) {
2710
2671
  if (!isCodexNotificationForTurn(params.notification.params, params.threadId, params.turnId)) return false;
2711
- return params.notification.method === "turn/completed" || isCodexTurnAbortMarkerNotification(params.notification, { currentPromptTexts: params.currentPromptTexts });
2672
+ return params.notification.method === "turn/completed";
2712
2673
  }
2713
2674
  /**
2714
2675
  * Applies one notification to active item tracking, idle watches, and terminal
@@ -2778,13 +2739,33 @@ function applyCodexTurnNotificationState(params) {
2778
2739
  isTurnTerminal: isTerminalCodexTurnNotificationForTurn({
2779
2740
  notification,
2780
2741
  threadId: params.threadId,
2781
- turnId: params.turnId,
2782
- currentPromptTexts: params.currentPromptTexts
2742
+ turnId: params.turnId
2783
2743
  }),
2784
2744
  turnCrossedToolHandoff
2785
2745
  };
2786
2746
  }
2787
2747
  //#endregion
2748
+ //#region extensions/codex/src/app-server/run-attempt-lifecycle-terminal.ts
2749
+ function buildCodexLifecycleTerminalMeta(input) {
2750
+ if (input.timedOut || input.abortStopReason === "timeout") return {
2751
+ aborted: true,
2752
+ status: "timed_out",
2753
+ stopReason: "timeout",
2754
+ timeoutPhase: "provider",
2755
+ providerStarted: true
2756
+ };
2757
+ if (input.yielded && !input.aborted) return {
2758
+ yielded: true,
2759
+ livenessState: "paused",
2760
+ stopReason: "end_turn"
2761
+ };
2762
+ return input.aborted ? {
2763
+ aborted: true,
2764
+ status: "cancelled",
2765
+ stopReason: "stop"
2766
+ } : void 0;
2767
+ }
2768
+ //#endregion
2788
2769
  //#region extensions/codex/src/app-server/run-attempt-lifecycle-controller.ts
2789
2770
  function createCodexAttemptLifecycleController(resources, turnRuntime) {
2790
2771
  const { prompt, state: resourceState, trajectoryRecorder } = resources;
@@ -2816,6 +2797,7 @@ function createCodexAttemptLifecycleController(resources, turnRuntime) {
2816
2797
  tool: value.call.tool,
2817
2798
  durationMs: value.durationMs
2818
2799
  });
2800
+ turnRuntime.steeringQueueRef.current?.cancel();
2819
2801
  interruptCodexTurnBestEffort(resourceState.client, {
2820
2802
  threadId: value.call.threadId,
2821
2803
  turnId: value.call.turnId,
@@ -2832,6 +2814,7 @@ function createCodexAttemptLifecycleController(resources, turnRuntime) {
2832
2814
  state.terminalDynamicToolReleaseCheckScheduled = true;
2833
2815
  setImmediate(() => {
2834
2816
  state.terminalDynamicToolReleaseCheckScheduled = false;
2817
+ if (state.pendingTerminalDynamicToolRelease?.response.success === true && !state.currentTurnHadNonTerminalDynamicToolResult && state.activeAppServerTurnRequests === 0 && pendingOpenClawDynamicToolCompletionIds.size === 0) turnRuntime.steeringQueueRef.current?.cancel();
2835
2818
  const action = resolveTerminalDynamicToolBatchAction({
2836
2819
  activeAppServerTurnRequests: state.activeAppServerTurnRequests,
2837
2820
  activeTurnItemIdsCount: activeTurnItemIds.size,
@@ -2875,18 +2858,10 @@ function createCodexAttemptLifecycleController(resources, turnRuntime) {
2875
2858
  };
2876
2859
  const buildLifecycleTerminalMeta = (input) => {
2877
2860
  const abortFields = input.aborted ? resolveAgentRunAbortLifecycleFields(runAbortController.signal) : void 0;
2878
- if (input.timedOut || abortFields?.stopReason === "timeout") return {
2879
- aborted: true,
2880
- status: "timed_out",
2881
- stopReason: "timeout",
2882
- timeoutPhase: "provider",
2883
- providerStarted: true
2884
- };
2885
- return input.aborted ? {
2886
- aborted: true,
2887
- status: "cancelled",
2888
- stopReason: "stop"
2889
- } : void 0;
2861
+ return buildCodexLifecycleTerminalMeta({
2862
+ ...input,
2863
+ abortStopReason: abortFields?.stopReason
2864
+ });
2890
2865
  };
2891
2866
  const executionPhaseKeys = /* @__PURE__ */ new Set();
2892
2867
  const emitExecutionPhaseOnce = (key, info) => {
@@ -3307,8 +3282,7 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
3307
3282
  const isTerminalTurnNotificationForTurn = (notification, notificationTurnId) => isTerminalCodexTurnNotificationForTurn({
3308
3283
  notification,
3309
3284
  threadId: resourceState.thread.threadId,
3310
- turnId: notificationTurnId,
3311
- currentPromptTexts: [turnState.codexTurnPromptText]
3285
+ turnId: notificationTurnId
3312
3286
  });
3313
3287
  const handleNotification = async (notification) => {
3314
3288
  const projector = projectorRef.current;
@@ -3335,6 +3309,11 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
3335
3309
  onReportExecutionNotification: reportExecutionNotification
3336
3310
  });
3337
3311
  state.turnCrossedToolHandoff = notificationState.turnCrossedToolHandoff;
3312
+ if (notificationState.isCurrentTurnNotification && notification.method === "item/completed") {
3313
+ const item = readCodexNotificationItem(notification.params);
3314
+ if (item?.type === "userMessage" && typeof item.clientId === "string") steeringQueue?.confirmConsumed(item.clientId);
3315
+ }
3316
+ if (notificationState.isTurnAbortMarker) state.sawCodexInterruptMarker = true;
3338
3317
  const hookNotification = readCodexFinalizationHookNotification(notification, resourceState.thread.threadId, turnId);
3339
3318
  if (hookNotification?.phase === "started") {
3340
3319
  if (activeFinalizationHookRunIds.size === 0) finalizationHookBatchStatuses.clear();
@@ -3378,7 +3357,7 @@ function createCodexAttemptNotificationController(resources, turnRuntime, lifecy
3378
3357
  });
3379
3358
  }
3380
3359
  if (notificationState.isTurnTerminal) {
3381
- if (notificationState.isTurnAbortMarker) projector.markAborted();
3360
+ if ((readCodexTurnCompletedNotification(notification.params)?.turn)?.status === "interrupted" && state.sawCodexInterruptMarker) projector.markAborted();
3382
3361
  if (!state.timedOut && !runAbortController.signal.aborted) await steeringQueue?.flushPending();
3383
3362
  state.completed = true;
3384
3363
  turnWatches.clearCompletionIdleTimer();
@@ -5265,6 +5244,30 @@ function sendError(socket, id, code, message) {
5265
5244
  }));
5266
5245
  }
5267
5246
  //#endregion
5247
+ //#region extensions/codex/src/app-server/sandbox-exec-server/path-uri.ts
5248
+ /** Converts Codex PathUri protocol values into sandbox-backend path strings. */
5249
+ const WINDOWS_DRIVE_PATH_RE = /^\/[A-Za-z]:(?:\/|$)/u;
5250
+ /** Resolves one Codex exec-server PathUri into a POSIX sandbox path. */
5251
+ function resolveExecServerPath(rawPath, label) {
5252
+ let pathUrl;
5253
+ try {
5254
+ pathUrl = new URL(rawPath);
5255
+ } catch (error) {
5256
+ throw new Error(`${label} must be a valid file URI: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
5257
+ }
5258
+ if (pathUrl.protocol !== "file:") throw new Error(`${label} URI must use the file scheme, received ${pathUrl.protocol.slice(0, -1)}.`);
5259
+ if (pathUrl.search || pathUrl.hash) throw new Error(`${label} file URI must not include a query or fragment.`);
5260
+ let resolved;
5261
+ try {
5262
+ resolved = fileURLToPath(pathUrl, { windows: false });
5263
+ } catch (error) {
5264
+ throw new Error(`${label} file URI is not valid for the sandbox: ${error instanceof Error ? error.message : String(error)}`, { cause: error });
5265
+ }
5266
+ if (WINDOWS_DRIVE_PATH_RE.test(resolved)) throw new Error(`${label} Windows file URI is not supported by the sandbox.`);
5267
+ if (resolved.includes("\0")) throw new Error(`${label} file URI must not contain a null byte.`);
5268
+ return resolved;
5269
+ }
5270
+ //#endregion
5268
5271
  //#region extensions/codex/src/app-server/sandbox-exec-server/fs-policy.ts
5269
5272
  /**
5270
5273
  * Resolves Codex filesystem sandbox policy payloads into OpenClaw path/glob
@@ -5304,7 +5307,7 @@ function resolveFsSandboxPolicy(execServer, record) {
5304
5307
  }
5305
5308
  function readFsSandboxCwd(execServer, sandbox) {
5306
5309
  if (sandbox.cwd === void 0 || sandbox.cwd === null) return normalizeSandboxAbsolutePath(execServer.sandbox.containerWorkdir, "sandbox cwd");
5307
- return normalizeSandboxAbsolutePath(requireString(sandbox.cwd, "sandbox cwd"), "sandbox cwd");
5310
+ return normalizeSandboxAbsolutePath(resolveExecServerPath(requireString(sandbox.cwd, "sandbox cwd"), "sandbox cwd"), "sandbox cwd");
5308
5311
  }
5309
5312
  function resolveFsSandboxEntry(entry, cwd) {
5310
5313
  const access = readFsAccessMode(entry.access);
@@ -5312,7 +5315,7 @@ function resolveFsSandboxEntry(entry, cwd) {
5312
5315
  const pathType = requireString(pathSpec.type, "fs sandbox entry path type");
5313
5316
  if (pathType === "path") return {
5314
5317
  kind: "path",
5315
- path: normalizeSandboxAbsolutePath(requireString(pathSpec.path, "fs sandbox path"), "fs sandbox path"),
5318
+ path: normalizeSandboxAbsolutePath(resolveExecServerPath(requireString(pathSpec.path, "fs sandbox path"), "fs sandbox path"), "fs sandbox path"),
5316
5319
  access
5317
5320
  };
5318
5321
  if (pathType === "special") {
@@ -5506,7 +5509,7 @@ const CODEX_SANDBOX_EXEC_SERVER_MAX_READ_FILE_BYTES = 512 * 1024 * 1024;
5506
5509
  /** Reads a sandbox file as base64 after read-policy and size checks. */
5507
5510
  async function readFile(execServer, params) {
5508
5511
  const record = requireObject(params, "fs/readFile params");
5509
- const filePath = requireString(record.path, "path");
5512
+ const filePath = resolveExecServerPath(requireString(record.path, "path"), "read path");
5510
5513
  assertFsSandboxAccess(execServer, record, [{
5511
5514
  path: filePath,
5512
5515
  access: "read"
@@ -5520,7 +5523,7 @@ async function readFile(execServer, params) {
5520
5523
  /** Writes base64 data to an existing sandbox directory after write-policy checks. */
5521
5524
  async function writeFile(execServer, params) {
5522
5525
  const record = requireObject(params, "fs/writeFile params");
5523
- const filePath = requireString(record.path, "path");
5526
+ const filePath = resolveExecServerPath(requireString(record.path, "path"), "write path");
5524
5527
  assertFsSandboxAccess(execServer, record, [{
5525
5528
  path: filePath,
5526
5529
  access: "write"
@@ -5536,7 +5539,7 @@ async function writeFile(execServer, params) {
5536
5539
  /** Creates a sandbox directory, respecting recursive and parent-directory semantics. */
5537
5540
  async function createDirectory(execServer, params) {
5538
5541
  const record = requireObject(params, "fs/createDirectory params");
5539
- const filePath = requireString(record.path, "path");
5542
+ const filePath = resolveExecServerPath(requireString(record.path, "path"), "create-directory path");
5540
5543
  assertFsSandboxAccess(execServer, record, [{
5541
5544
  path: filePath,
5542
5545
  access: "write"
@@ -5551,7 +5554,7 @@ async function createDirectory(execServer, params) {
5551
5554
  /** Returns normalized metadata for a sandbox path. */
5552
5555
  async function getMetadata(execServer, params) {
5553
5556
  const record = requireObject(params, "fs/getMetadata params");
5554
- const filePath = requireString(record.path, "path");
5557
+ const filePath = resolveExecServerPath(requireString(record.path, "path"), "metadata path");
5555
5558
  assertFsSandboxAccess(execServer, record, [{
5556
5559
  path: filePath,
5557
5560
  access: "read"
@@ -5563,7 +5566,7 @@ async function getMetadata(execServer, params) {
5563
5566
  /** Lists sandbox directory entries visible under the resolved filesystem policy. */
5564
5567
  async function readDirectory(execServer, params) {
5565
5568
  const record = requireObject(params, "fs/readDirectory params");
5566
- return { entries: await listDirectoryEntries(execServer, requireString(record.path, "path"), resolveFsSandboxPolicy(execServer, record)) };
5569
+ return { entries: await listDirectoryEntries(execServer, resolveExecServerPath(requireString(record.path, "path"), "read-directory path"), resolveFsSandboxPolicy(execServer, record)) };
5567
5570
  }
5568
5571
  async function listDirectoryEntries(execServer, filePath, fsSandboxPolicy) {
5569
5572
  assertResolvedFsSandboxAccess(fsSandboxPolicy, [{
@@ -5595,7 +5598,7 @@ async function listDirectoryEntries(execServer, filePath, fsSandboxPolicy) {
5595
5598
  /** Removes a sandbox path after rejecting writes outside policy or under read-only descendants. */
5596
5599
  async function removePath(execServer, params) {
5597
5600
  const record = requireObject(params, "fs/remove params");
5598
- const filePath = requireString(record.path, "path");
5601
+ const filePath = resolveExecServerPath(requireString(record.path, "path"), "remove path");
5599
5602
  const fsSandboxPolicy = resolveFsSandboxPolicy(execServer, record);
5600
5603
  assertResolvedFsSandboxAccess(fsSandboxPolicy, [{
5601
5604
  path: filePath,
@@ -5611,8 +5614,8 @@ async function removePath(execServer, params) {
5611
5614
  /** Copies sandbox files or recursive directories while enforcing source and destination policy. */
5612
5615
  async function copyPath(execServer, params) {
5613
5616
  const record = requireObject(params, "fs/copy params");
5614
- const sourcePath = requireString(record.sourcePath ?? record.source, "sourcePath");
5615
- const destinationPath = requireString(record.destinationPath ?? record.destination, "destinationPath");
5617
+ const sourcePath = resolveExecServerPath(requireString(record.sourcePath ?? record.source, "sourcePath"), "copy source path");
5618
+ const destinationPath = resolveExecServerPath(requireString(record.destinationPath ?? record.destination, "destinationPath"), "copy destination path");
5616
5619
  const fsSandboxPolicy = resolveFsSandboxPolicy(execServer, record);
5617
5620
  assertResolvedFsSandboxAccess(fsSandboxPolicy, [{
5618
5621
  path: sourcePath,
@@ -5812,8 +5815,9 @@ function readStreamingSandboxHttpResponse(params) {
5812
5815
  }
5813
5816
  reject(new Error(message));
5814
5817
  };
5818
+ params.child.stdout.setEncoding("utf8");
5815
5819
  params.child.stdout.on("data", (chunk) => {
5816
- stdoutBuffer += chunk.toString("utf8");
5820
+ stdoutBuffer += chunk;
5817
5821
  let newline = stdoutBuffer.indexOf("\n");
5818
5822
  while (newline >= 0) {
5819
5823
  const line = stdoutBuffer.slice(0, newline).trim();
@@ -5849,8 +5853,9 @@ function readStreamingSandboxHttpResponse(params) {
5849
5853
  fail(`sandbox http/request produced an unterminated stdout line longer than ${SANDBOX_HTTP_STREAM_LINE_MAX_CHARS} characters`, null);
5850
5854
  }
5851
5855
  });
5856
+ params.child.stderr.setEncoding("utf8");
5852
5857
  params.child.stderr.on("data", (chunk) => {
5853
- stderr = `${stderr}${chunk.toString("utf8")}`.slice(-4096);
5858
+ stderr = sliceUtf16Safe(`${stderr}${chunk}`, -4096);
5854
5859
  });
5855
5860
  params.child.once("error", (error) => {
5856
5861
  childFailure ??= error.message;
@@ -6101,7 +6106,7 @@ async function startProcess(execServer, processes, socket, params) {
6101
6106
  const processId = requireString(record.processId, "processId");
6102
6107
  if (processes.has(processId)) throw new Error(`process already exists: ${processId}`);
6103
6108
  const argv = requireStringArray(record.argv, "argv");
6104
- const cwd = requireString(record.cwd, "cwd");
6109
+ const cwd = resolveExecServerPath(requireString(record.cwd, "cwd"), "process cwd");
6105
6110
  rejectUnsupportedArg0(record.arg0);
6106
6111
  const env = readProcessEnv(record);
6107
6112
  const managed = {
@@ -6591,7 +6596,7 @@ function prepareCodexAttemptResources(prompt) {
6591
6596
  const { context, turnState, buildRenderedCodexDeveloperInstructions } = prompt;
6592
6597
  const { runtime, attemptTools } = context;
6593
6598
  const { connection, hookChannelId } = runtime;
6594
- const { params, effectiveCwd, sessionAgentId, sandboxSessionKey, runAbortController, sandbox, options, nativeHookRelayEvents } = connection;
6599
+ const { appServer, params, effectiveCwd, sessionAgentId, sandboxSessionKey, runAbortController, sandbox, options, nativeHookRelayEvents } = connection;
6595
6600
  const { toolBridge } = attemptTools;
6596
6601
  const hostTrajectoryRecorder = params.trajectoryRecorder;
6597
6602
  const trajectoryRecorder = createCodexTrajectoryRecorder({
@@ -6724,6 +6729,7 @@ function prepareCodexAttemptResources(prompt) {
6724
6729
  attemptTimeoutMs: params.timeoutMs,
6725
6730
  startupTimeoutMs,
6726
6731
  turnStartTimeoutMs: params.timeoutMs,
6732
+ loopDetectionPreToolUseRelay: appServer.loopDetectionPreToolUseRelay,
6727
6733
  signal: runAbortController.signal,
6728
6734
  onPreToolUseFailure: (failure) => {
6729
6735
  const projector = projectorRef.current;
@@ -6736,7 +6742,8 @@ function prepareCodexAttemptResources(prompt) {
6736
6742
  configPatch: state.nativeHookRelay ? buildCodexNativeHookRelayConfig({
6737
6743
  relay: state.nativeHookRelay,
6738
6744
  events: nativeHookRelayEvents,
6739
- hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec
6745
+ hookTimeoutSec: options.nativeHookRelay?.hookTimeoutSec,
6746
+ loopDetectionPreToolUseRelay: appServer.loopDetectionPreToolUseRelay
6740
6747
  }) : options.nativeHookRelay?.enabled === false ? buildCodexNativeHookRelayDisabledConfig() : void 0,
6741
6748
  nativeHookRelayGeneration: state.nativeHookRelay?.generation
6742
6749
  };
@@ -6955,6 +6962,21 @@ async function prepareCodexAttemptRuntime(connection) {
6955
6962
  };
6956
6963
  }
6957
6964
  //#endregion
6965
+ //#region extensions/codex/src/app-server/dynamic-tool-result-projection.ts
6966
+ /** Project one OpenClaw dynamic-tool response with its executed mutation identity. */
6967
+ function recordCodexDynamicToolResult(projector, call, response, protocolResponse) {
6968
+ projector?.recordDynamicToolResult({
6969
+ callId: call.callId,
6970
+ tool: call.tool,
6971
+ asyncStarted: response.asyncStarted === true,
6972
+ terminalResolution: response.terminalResolution,
6973
+ success: protocolResponse.success,
6974
+ terminalType: response.diagnosticTerminalType ?? (protocolResponse.success ? "completed" : "error"),
6975
+ sideEffectEvidence: response.sideEffectEvidence === true || response.terminalResolution?.sideEffectEvidence === true,
6976
+ contentItems: protocolResponse.contentItems
6977
+ });
6978
+ }
6979
+ //#endregion
6958
6980
  //#region extensions/codex/src/app-server/run-attempt-tools.ts
6959
6981
  function toTranscriptToolResult(response) {
6960
6982
  const sanitized = sanitizeCodexToolResponse(response);
@@ -7180,8 +7202,10 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
7180
7202
  toolBridge,
7181
7203
  signal: runAbortController.signal,
7182
7204
  timeoutMs: dynamicToolTimeoutMs,
7205
+ toolMeta,
7183
7206
  toolCallOrdinal,
7184
7207
  onAgentToolResult: params.onAgentToolResult,
7208
+ observeToolTerminal: params.observeToolTerminal,
7185
7209
  onFallbackSelected: () => {
7186
7210
  if (toolCallOrdinal !== void 0) suppressedDynamicToolOutcomeOrdinals.add(toolCallOrdinal);
7187
7211
  },
@@ -7217,15 +7241,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
7217
7241
  success: protocolResponse.success,
7218
7242
  contentItems: protocolResponse.contentItems
7219
7243
  });
7220
- projector?.recordDynamicToolResult({
7221
- callId: call.callId,
7222
- tool: call.tool,
7223
- asyncStarted: response.asyncStarted === true,
7224
- success: protocolResponse.success,
7225
- terminalType: response.diagnosticTerminalType ?? (protocolResponse.success ? "completed" : "error"),
7226
- sideEffectEvidence: response.sideEffectEvidence === true,
7227
- contentItems: protocolResponse.contentItems
7228
- });
7244
+ recordCodexDynamicToolResult(projector, call, response, protocolResponse);
7229
7245
  if (shouldEmitDynamicToolProgress) {
7230
7246
  const progressResponse = toCodexDynamicToolProgressResponse(response, protocolResponse);
7231
7247
  emitCodexAppServerEvent(params, {
@@ -7255,7 +7271,7 @@ function createCodexAttemptServerRequestController(resources, turnRuntime, lifec
7255
7271
  durationMs: toolDurationMs
7256
7272
  });
7257
7273
  pendingOpenClawDynamicToolCompletionIds.delete(call.callId);
7258
- if (response.terminate === true) scheduleTurnReleaseAfterTerminalDynamicTool({
7274
+ if (response.terminate === true && response.success) scheduleTurnReleaseAfterTerminalDynamicTool({
7259
7275
  call,
7260
7276
  response,
7261
7277
  durationMs: toolDurationMs
@@ -7397,11 +7413,200 @@ function clearComputerUseHealthMonitor(client, monitor) {
7397
7413
  getComputerUseHealthMonitorState().monitors.delete(client);
7398
7414
  }
7399
7415
  //#endregion
7416
+ //#region extensions/codex/src/app-server/plugin-metadata-cache.ts
7417
+ const CODEX_PLUGIN_METADATA_CACHE_TTL_MS = 3600 * 1e3;
7418
+ /** Process-local plugin metadata cache with coalesced loads per query. */
7419
+ var CodexPluginMetadataCache = class {
7420
+ constructor(nowMs = Date.now) {
7421
+ this.nowMs = nowMs;
7422
+ this.entries = /* @__PURE__ */ new Map();
7423
+ this.inFlight = /* @__PURE__ */ new Map();
7424
+ this.generations = /* @__PURE__ */ new Map();
7425
+ this.clearGeneration = 0;
7426
+ }
7427
+ /** Returns a fresh cached snapshot without issuing a request. */
7428
+ read(appCacheKey, queryKind) {
7429
+ const entryKey = buildMetadataCacheEntryKey(appCacheKey, queryKind);
7430
+ const entry = this.entries.get(entryKey);
7431
+ if (!entry) return;
7432
+ if (entry.expiresAtMs <= this.nowMs()) {
7433
+ this.entries.delete(entryKey);
7434
+ return;
7435
+ }
7436
+ return entry.snapshot;
7437
+ }
7438
+ /** Returns a fresh cached snapshot or coalesces one plugin/list request. */
7439
+ async load(params) {
7440
+ const entryKey = buildMetadataCacheEntryKey(params.appCacheKey, params.queryKind);
7441
+ const cached = this.read(params.appCacheKey, params.queryKind);
7442
+ if (cached) return cached;
7443
+ const pending = this.inFlight.get(entryKey);
7444
+ if (pending) try {
7445
+ return await pending.promise;
7446
+ } catch {
7447
+ if (this.inFlight.get(entryKey) === pending) this.inFlight.delete(entryKey);
7448
+ return await this.load(params);
7449
+ }
7450
+ const generation = this.generations.get(params.appCacheKey) ?? 0;
7451
+ const clearGeneration = this.clearGeneration;
7452
+ const promise = (async () => {
7453
+ const response = await params.request("plugin/list", params.requestParams);
7454
+ const snapshot = {
7455
+ appCacheKey: params.appCacheKey,
7456
+ queryKind: params.queryKind,
7457
+ response
7458
+ };
7459
+ if (generation === (this.generations.get(params.appCacheKey) ?? 0) && clearGeneration === this.clearGeneration && !hasMarketplaceLoadErrors(response) && (params.cacheable?.(response) ?? true)) this.entries.set(entryKey, {
7460
+ snapshot,
7461
+ expiresAtMs: this.nowMs() + CODEX_PLUGIN_METADATA_CACHE_TTL_MS
7462
+ });
7463
+ return snapshot;
7464
+ })();
7465
+ this.inFlight.set(entryKey, {
7466
+ appCacheKey: params.appCacheKey,
7467
+ promise
7468
+ });
7469
+ try {
7470
+ return await promise;
7471
+ } finally {
7472
+ if (this.inFlight.get(entryKey)?.promise === promise) this.inFlight.delete(entryKey);
7473
+ }
7474
+ }
7475
+ /** Invalidates all plugin metadata queries for one app-server runtime. */
7476
+ invalidate(appCacheKey) {
7477
+ this.generations.set(appCacheKey, (this.generations.get(appCacheKey) ?? 0) + 1);
7478
+ for (const [entryKey, entry] of this.entries) if (entry.snapshot.appCacheKey === appCacheKey) this.entries.delete(entryKey);
7479
+ for (const [entryKey, pending] of this.inFlight) if (pending.appCacheKey === appCacheKey) this.inFlight.delete(entryKey);
7480
+ }
7481
+ /** Clears snapshots and prevents late in-flight loads from repopulating them. */
7482
+ clear() {
7483
+ this.clearGeneration += 1;
7484
+ this.generations.clear();
7485
+ this.entries.clear();
7486
+ this.inFlight.clear();
7487
+ }
7488
+ };
7489
+ /** Shared plugin metadata cache used by Codex app-server runtime paths. */
7490
+ const defaultCodexPluginMetadataCache = new CodexPluginMetadataCache();
7491
+ function hasMarketplaceLoadErrors(response) {
7492
+ return (response.marketplaceLoadErrors?.length ?? 0) > 0;
7493
+ }
7494
+ function buildMetadataCacheEntryKey(appCacheKey, queryKind) {
7495
+ return JSON.stringify([appCacheKey, queryKind]);
7496
+ }
7497
+ //#endregion
7498
+ //#region extensions/codex/src/app-server/plugin-thread-config-deadline.ts
7499
+ /** Enforces one bounded startup budget across Codex plugin config discovery. */
7500
+ const CODEX_PLUGIN_THREAD_CONFIG_MAX_TIMEOUT_MS = 5e3;
7501
+ const CODEX_PLUGIN_THREAD_CONFIG_TIMEOUT_DIVISOR = 4;
7502
+ const CODEX_PLUGIN_THREAD_CONFIG_MIN_TIMEOUT_MS = 100;
7503
+ var CodexPluginThreadConfigDeadlineError = class extends Error {
7504
+ constructor() {
7505
+ super("Codex plugin thread config deadline elapsed");
7506
+ this.name = "CodexPluginThreadConfigDeadlineError";
7507
+ }
7508
+ };
7509
+ /** Resolves the plugin policy state reused throughout app-server startup. */
7510
+ function resolveCodexPluginThreadConfigStartupPolicy(params) {
7511
+ const pluginThreadConfigRequired = !params.nativeToolSurfaceEnabled || shouldBuildCodexPluginThreadConfig(params.pluginConfig);
7512
+ const pluginThreadConfigPluginConfig = params.nativeToolSurfaceEnabled ? params.pluginConfig : disableCodexPluginThreadConfig(params.pluginConfig);
7513
+ const resolvedPluginPolicy = pluginThreadConfigRequired ? resolveCodexPluginsPolicy(pluginThreadConfigPluginConfig) : void 0;
7514
+ return {
7515
+ pluginThreadConfigRequired,
7516
+ pluginThreadConfigPluginConfig,
7517
+ resolvedPluginPolicy,
7518
+ enabledPluginConfigKeys: resolvedPluginPolicy ? resolvedPluginPolicy.pluginPolicies.filter((plugin) => plugin.enabled).map((plugin) => plugin.configKey).toSorted() : void 0
7519
+ };
7520
+ }
7521
+ /** Builds plugin config without allowing sequential RPC timeouts to consume the turn. */
7522
+ async function buildCodexPluginThreadConfigWithinDeadline(params) {
7523
+ const { requestTimeoutMs, signal, request, ...buildParams } = params;
7524
+ const timeoutMs = resolveCodexPluginThreadConfigTimeoutMs(requestTimeoutMs);
7525
+ const deadlineMs = Date.now() + timeoutMs;
7526
+ try {
7527
+ return await waitForCodexPluginThreadConfigBuild({
7528
+ signal,
7529
+ timeoutMs,
7530
+ build: () => buildCodexPluginThreadConfig({
7531
+ ...buildParams,
7532
+ request: (method, requestParams) => {
7533
+ const remainingTimeoutMs = deadlineMs - Date.now();
7534
+ if (remainingTimeoutMs <= 0) throw new CodexPluginThreadConfigDeadlineError();
7535
+ return request(method, requestParams, {
7536
+ timeoutMs: remainingTimeoutMs,
7537
+ signal
7538
+ });
7539
+ }
7540
+ })
7541
+ });
7542
+ } catch (error) {
7543
+ if (signal.aborted || !isCodexPluginThreadConfigTimeoutError(error)) throw error;
7544
+ return buildCodexPluginThreadConfigTimeoutFallback({
7545
+ pluginConfig: buildParams.pluginConfig,
7546
+ appCacheKey: buildParams.appCacheKey,
7547
+ message: `Codex plugin discovery exceeded its ${timeoutMs} ms startup budget; plugin apps were disabled for this turn.`
7548
+ });
7549
+ }
7550
+ }
7551
+ function waitForCodexPluginThreadConfigBuild(params) {
7552
+ if (params.signal.aborted) return Promise.reject(resolveAbortReason(params.signal));
7553
+ return new Promise((resolve, reject) => {
7554
+ let settled = false;
7555
+ const finish = () => {
7556
+ if (settled) return false;
7557
+ settled = true;
7558
+ clearTimeout(timer);
7559
+ params.signal.removeEventListener("abort", onAbort);
7560
+ return true;
7561
+ };
7562
+ const resolveOnce = (config) => {
7563
+ if (finish()) resolve(config);
7564
+ };
7565
+ const rejectOnce = (error) => {
7566
+ if (finish()) reject(error instanceof Error ? error : new Error(String(error)));
7567
+ };
7568
+ const onAbort = () => rejectOnce(resolveAbortReason(params.signal));
7569
+ const timer = setTimeout(() => rejectOnce(new CodexPluginThreadConfigDeadlineError()), params.timeoutMs);
7570
+ params.signal.addEventListener("abort", onAbort, { once: true });
7571
+ params.build().then(resolveOnce, rejectOnce);
7572
+ });
7573
+ }
7574
+ function resolveAbortReason(signal) {
7575
+ return signal.reason instanceof Error ? signal.reason : /* @__PURE__ */ new Error("Codex plugin thread config aborted");
7576
+ }
7577
+ /** Creates the recovery metadata and bounded builder used by thread startup. */
7578
+ function createCodexPluginThreadConfigStartupProvider(params) {
7579
+ const { client, policy, inputFingerprint, enabledPluginConfigKeys, appCache, metadataCache: configuredMetadataCache, ...buildParams } = params;
7580
+ const metadataCache = configuredMetadataCache ?? defaultCodexPluginMetadataCache;
7581
+ return {
7582
+ enabled: true,
7583
+ inputFingerprint,
7584
+ enabledPluginConfigKeys,
7585
+ accountAppRecoveryEnabled: policy?.allowAllPlugins,
7586
+ recoverablePluginConfigKeys: policy ? resolveRecoverableCodexPluginConfigKeys({
7587
+ policy,
7588
+ metadataCache,
7589
+ appCacheKey: params.appCacheKey
7590
+ }) : void 0,
7591
+ build: () => buildCodexPluginThreadConfigWithinDeadline({
7592
+ ...buildParams,
7593
+ appCache: appCache ?? defaultCodexAppInventoryCache,
7594
+ metadataCache,
7595
+ request: (method, requestParams, options) => client.request(method, requestParams, options)
7596
+ })
7597
+ };
7598
+ }
7599
+ function resolveCodexPluginThreadConfigTimeoutMs(requestTimeoutMs) {
7600
+ return Math.min(CODEX_PLUGIN_THREAD_CONFIG_MAX_TIMEOUT_MS, Math.max(CODEX_PLUGIN_THREAD_CONFIG_MIN_TIMEOUT_MS, Math.floor((Number.isFinite(requestTimeoutMs) && requestTimeoutMs > 0 ? requestTimeoutMs : CODEX_PLUGIN_THREAD_CONFIG_MAX_TIMEOUT_MS * CODEX_PLUGIN_THREAD_CONFIG_TIMEOUT_DIVISOR) / CODEX_PLUGIN_THREAD_CONFIG_TIMEOUT_DIVISOR)));
7601
+ }
7602
+ function isCodexPluginThreadConfigTimeoutError(error) {
7603
+ return error instanceof CodexPluginThreadConfigDeadlineError || error instanceof Error && "code" in error && error.code === "CODEX_APP_SERVER_LOCAL_REQUEST_CANCELLED" && error.message.endsWith(" timed out");
7604
+ }
7605
+ //#endregion
7400
7606
  //#region extensions/codex/src/app-server/attempt-startup.ts
7401
7607
  /**
7402
7608
  * Startup orchestration for Codex app-server attempts, including shared-client
7403
- * leasing, plugin thread config, sandbox execution environment, and thread
7404
- * lifecycle binding.
7609
+ * leasing, plugin thread config, sandbox environment, and thread lifecycle binding.
7405
7610
  */
7406
7611
  const CODEX_APP_SERVER_STARTUP_CONNECTION_CLOSE_MAX_ATTEMPTS = 3;
7407
7612
  const CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED = "CODEX_APP_SERVER_CONTEXT_RESTART_SELECTION_CHANGED";
@@ -7440,13 +7645,12 @@ async function startCodexAttemptThread(params) {
7440
7645
  },
7441
7646
  operation: async () => {
7442
7647
  const threadConfig = mergeCodexThreadConfigs(params.bundleMcpThreadConfig?.configPatch);
7443
- const pluginThreadConfigRequired = !params.nativeToolSurfaceEnabled || shouldBuildCodexPluginThreadConfig(params.pluginConfig);
7444
- const pluginThreadConfigPluginConfig = params.nativeToolSurfaceEnabled ? params.pluginConfig : disableCodexPluginThreadConfig(params.pluginConfig);
7445
- const resolvedPluginPolicy = pluginThreadConfigRequired ? resolveCodexPluginsPolicy(pluginThreadConfigPluginConfig) : void 0;
7648
+ const { pluginThreadConfigRequired, pluginThreadConfigPluginConfig, resolvedPluginPolicy, enabledPluginConfigKeys } = resolveCodexPluginThreadConfigStartupPolicy({
7649
+ pluginConfig: params.pluginConfig,
7650
+ nativeToolSurfaceEnabled: params.nativeToolSurfaceEnabled
7651
+ });
7446
7652
  const computerUseMcpElicitationDelegationRequired = params.computerUseConfig.enabled;
7447
- const mcpElicitationDelegationRequired = resolvedPluginPolicy?.enabled === true || computerUseMcpElicitationDelegationRequired;
7448
- const enabledPluginConfigKeys = resolvedPluginPolicy ? resolvedPluginPolicy.pluginPolicies.filter((plugin) => plugin.enabled).map((plugin) => plugin.configKey).toSorted() : void 0;
7449
- pluginAppServer = mcpElicitationDelegationRequired ? {
7653
+ pluginAppServer = resolvedPluginPolicy?.enabled === true || computerUseMcpElicitationDelegationRequired ? {
7450
7654
  ...params.appServer,
7451
7655
  approvalPolicy: withMcpElicitationsApprovalPolicy(params.appServer.approvalPolicy)
7452
7656
  } : params.appServer;
@@ -7461,6 +7665,7 @@ async function startCodexAttemptThread(params) {
7461
7665
  startupClient = await params.attemptClientFactory({
7462
7666
  startOptions: params.appServer.start,
7463
7667
  ...params.startupPreparedAuth ? { preparedAuth: params.startupPreparedAuth } : { authProfileId: params.startupAuthProfileId },
7668
+ authRequirement: params.startupAuthRequirement,
7464
7669
  authProfileStore: attemptParams.authProfileStore,
7465
7670
  authBindingFingerprint: params.startupAuthBindingFingerprint,
7466
7671
  ...params.runtimeArtifactRequest ? {
@@ -7486,8 +7691,8 @@ async function startCodexAttemptThread(params) {
7486
7691
  releaseSharedClientLease = startupClientLease;
7487
7692
  attemptedClient = activeStartupClient;
7488
7693
  startupClientForAbandonedRequestCleanup = activeStartupClient;
7489
- if (startupAbandoned) throw new Error("codex app-server startup timed out");
7490
- if (startupAbandonController.signal.aborted) throw new Error("codex app-server startup aborted");
7694
+ if (startupAbandoned) throw new CodexAppServerStartupError("timed_out");
7695
+ if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
7491
7696
  let runtimeArtifact;
7492
7697
  if (params.runtimeArtifactRequest) {
7493
7698
  const { readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact } = await import("./runtime-artifact-C2ITXdhM.js");
@@ -7568,7 +7773,7 @@ async function startCodexAttemptThread(params) {
7568
7773
  startupSandboxEnvironmentAcquired = Boolean(startupSandboxEnvironment);
7569
7774
  if (startupAbandonController.signal.aborted) {
7570
7775
  await releaseStartupSandboxEnvironment();
7571
- throw new Error("codex app-server startup aborted");
7776
+ throw new CodexAppServerStartupError("aborted");
7572
7777
  }
7573
7778
  if (params.sandbox?.enabled && params.nativeToolSurfaceEnabled && params.sandboxExecServerEnabled && !startupSandboxEnvironment) throw new Error("Codex app-server did not register an OpenClaw sandbox exec-server environment.");
7574
7779
  } catch (error) {
@@ -7631,21 +7836,17 @@ async function startCodexAttemptThread(params) {
7631
7836
  appServerRuntimeFingerprint,
7632
7837
  contextEngineProjection: params.contextEngineProjection,
7633
7838
  signal,
7634
- pluginThreadConfig: pluginThreadConfigRequired ? {
7635
- enabled: true,
7839
+ pluginThreadConfig: pluginThreadConfigRequired ? createCodexPluginThreadConfigStartupProvider({
7636
7840
  inputFingerprint: pluginThreadConfigInputFingerprint,
7637
7841
  enabledPluginConfigKeys,
7638
- build: () => buildCodexPluginThreadConfig({
7639
- pluginConfig: pluginThreadConfigPluginConfig,
7640
- request: (method, requestParams) => activeStartupClient.request(method, requestParams, {
7641
- timeoutMs: params.appServer.requestTimeoutMs,
7642
- signal
7643
- }),
7644
- configCwd: startupExecutionCwd,
7645
- appCache: defaultCodexAppInventoryCache,
7646
- appCacheKey: pluginAppCacheKey
7647
- })
7648
- } : void 0
7842
+ policy: resolvedPluginPolicy,
7843
+ requestTimeoutMs: params.appServer.requestTimeoutMs,
7844
+ signal,
7845
+ pluginConfig: pluginThreadConfigPluginConfig,
7846
+ client: activeStartupClient,
7847
+ configCwd: startupExecutionCwd,
7848
+ appCacheKey: pluginAppCacheKey
7849
+ }) : void 0
7649
7850
  });
7650
7851
  try {
7651
7852
  const startupThread = await startOrResumeThread(buildThreadLifecycleParams(startupAbandonController.signal, reserveStartupThread));
@@ -7658,7 +7859,7 @@ async function startCodexAttemptThread(params) {
7658
7859
  })) throw new CodexAppServerUnsafeSubscriptionError("Codex startup subscription cleanup failed", { cause: error });
7659
7860
  throw error;
7660
7861
  }
7661
- if (startupAbandonController.signal.aborted) throw new Error("codex app-server startup aborted");
7862
+ if (startupAbandonController.signal.aborted) throw new CodexAppServerStartupError("aborted");
7662
7863
  const startupRoute = startupReservation;
7663
7864
  if (!startupRoute) throw new Error("codex app-server startup did not reserve its thread route");
7664
7865
  startupSandboxEnvironmentAcquired = false;
@@ -7773,14 +7974,14 @@ async function startCodexAttemptThread(params) {
7773
7974
  }
7774
7975
  }
7775
7976
  function shouldClearSharedClientAfterStartupAbandon(error) {
7776
- return error instanceof Error && (error.message === "codex app-server startup timed out" || error.message === "codex app-server startup aborted");
7977
+ return isCodexAppServerStartupError(error);
7777
7978
  }
7778
7979
  function shouldClearSharedClientAfterStartupRace(error) {
7779
- return error instanceof Error && (shouldClearSharedClientAfterStartupAbandon(error) || error.message.endsWith(" timed out"));
7980
+ return shouldClearSharedClientAfterStartupAbandon(error) || isCodexAppServerRequestTimeoutError(error);
7780
7981
  }
7781
7982
  function shouldClearSharedClientAfterStartupFailure(params) {
7782
7983
  if (!(params.error instanceof Error)) return !params.spawnedBy;
7783
- if (params.error.message.includes("write EPIPE")) return true;
7984
+ if (isCodexAppServerBrokenPipeError(params.error)) return true;
7784
7985
  return !params.spawnedBy;
7785
7986
  }
7786
7987
  //#endregion
@@ -7791,7 +7992,7 @@ async function startCodexAttemptRuntime(resources) {
7791
7992
  const { runtime, attemptTools, promptState } = context;
7792
7993
  const { connection, runtimeParams, preparedAuthBinding, buildActiveRunAttemptParams, startupAuthAccountCacheKey, startupEnvApiKeyCacheKey, bundleMcpThreadConfig, nativeToolSurfaceEnabled, nativeProviderWebSearchSupport, sandboxExecServerEnabled } = runtime;
7793
7994
  const { toolBridge, toolState } = attemptTools;
7794
- const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, abortFromUpstream } = connection;
7995
+ const { params, attemptClientFactory, bindingStore, appServer, pluginConfig, computerUseConfig, startupClientAuthProfileId, runtimeArtifactRequest, startupPreparedAuth, agentDir, sessionAgentId, effectiveWorkspace, effectiveCwd, sandbox, runAbortController, usesSupervisionConnection, resolveReviewerPolicyContext, resolveRuntimeOptionsForCurrentBinding, startupAuthProfileId, startupAuthRequirement, abortFromUpstream } = connection;
7795
7996
  let pluginAppServer = withCodexAppServerFastModeServiceTier(appServer, runtimeParams);
7796
7997
  try {
7797
7998
  emitCodexAppServerEvent(params, {
@@ -7805,6 +8006,7 @@ async function startCodexAttemptRuntime(resources) {
7805
8006
  pluginConfig,
7806
8007
  computerUseConfig,
7807
8008
  startupAuthProfileId: startupClientAuthProfileId,
8009
+ startupAuthRequirement,
7808
8010
  startupAuthBindingFingerprint: preparedAuthBinding?.fingerprint,
7809
8011
  ...runtimeArtifactRequest ? { runtimeArtifactRequest } : {},
7810
8012
  startupPreparedAuth,
@@ -8385,6 +8587,7 @@ async function startCodexAttemptTurn(resources, turnRuntime, notifications, requ
8385
8587
  return { result: buildCodexTurnStartFailureResult({
8386
8588
  params,
8387
8589
  message: usageLimitError.message,
8590
+ promptError: createCodexUsageLimitPromptError(usageLimitError.message),
8388
8591
  messagesSnapshot,
8389
8592
  systemPromptReport
8390
8593
  }) };
@@ -8771,6 +8974,7 @@ function createCodexAttemptTurnState(resources) {
8771
8974
  rateLimitsRevisionBeforeLastTurnStart: void 0,
8772
8975
  completed: false,
8773
8976
  terminalTurnNotificationQueued: false,
8977
+ sawCodexInterruptMarker: false,
8774
8978
  timedOut: false,
8775
8979
  turnCompletionIdleTimedOut: false,
8776
8980
  turnWatchTimeoutKind: void 0,