@openclaw/codex 2026.8.2 → 2026.9.1

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 (61) hide show
  1. package/dist/api.js +3 -3
  2. package/dist/{attempt-client-cleanup-CpVfwctT.js → attempt-client-cleanup-DYHcRQAa.js} +6 -43
  3. package/dist/attempt-context-DmQUNWwT.js +634 -0
  4. package/dist/{binding-connection-CF7BmrDk.js → binding-connection-E6uDsPlx.js} +2 -2
  5. package/dist/{bounded-turn-DRC3hcjm.js → bounded-turn-wzJrwKKe.js} +8 -9
  6. package/dist/{capabilities-D6m_TdVy.js → capabilities-dIjNVCYH.js} +1 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters--UToCokS.js → command-formatters-CLHhEB1Q.js} +3 -3
  9. package/dist/{command-handlers-CLFx2Ypa.js → command-handlers-CTGb2csu.js} +54 -55
  10. package/dist/{compact-5xqW1oCh.js → compact-_t0HQrUS.js} +33 -25
  11. package/dist/{config-CcYL77O6.js → config-BhmfC1s6.js} +12 -8
  12. package/dist/{context-compaction-activity-BOeJf7yo.js → context-compaction-activity-CMla5FPJ.js} +4 -1
  13. package/dist/doctor-contract-api.js +31 -4
  14. package/dist/{dynamic-tools-BmeXjwNZ.js → dynamic-tools-BU9tmlYm.js} +448 -457
  15. package/dist/{effective-mcp-catalog-XXQKgK1U.js → effective-mcp-catalog-DzYBW4h1.js} +2 -2
  16. package/dist/{event-projector-assistant-message-C5-Ds8mA.js → event-projector-assistant-message-DHRFXKbS.js} +4 -4
  17. package/dist/{event-projector-usage-B2r5vhWH.js → event-projector-usage-C5mcrGjp.js} +9 -137
  18. package/dist/{harness-BgeB7LnD.js → harness-DXVZ5II5.js} +13 -13
  19. package/dist/harness.js +1 -1
  20. package/dist/index.js +323 -313
  21. package/dist/{isolated-completion-CxTus3vZ.js → isolated-completion-kg9kv4iH.js} +4 -4
  22. package/dist/{launch-args-sXOAg0SX.js → launch-args-RXQwn8zV.js} +7 -1
  23. package/dist/{managed-binary-ZkGodW19.js → managed-binary-4-Vjz5GH.js} +14 -9
  24. package/dist/media-understanding-provider.js +1 -1
  25. package/dist/{model-catalog-DULBcniB.js → model-catalog-CUM68Hkl.js} +11 -11
  26. package/dist/{models-DaWfETQk.js → models-sYnEc0gd.js} +3 -3
  27. package/dist/{native-subagent-monitor-vXYUZH37.js → native-subagent-monitor-CnH147jH.js} +3 -3
  28. package/dist/{node-exec-server.runtime-DirKVZ5h.js → node-exec-server.runtime-CstNHCmC.js} +2 -2
  29. package/dist/{plugin-approval-roundtrip-CCWQGlAI.js → plugin-approval-roundtrip-CNe-Xrjx.js} +29 -3
  30. package/dist/{plugin-marketplace-discovery-BXjIFEiw.js → plugin-marketplace-discovery-CfFlKqDl.js} +6 -6
  31. package/dist/{plugin-metadata-cache-DQQm4gWT.js → plugin-metadata-cache-BFrPhb2c.js} +5 -5
  32. package/dist/provider-capabilities-DW5p4k9w.js +101 -0
  33. package/dist/{rate-limits-BqHEHXQJ.js → rate-limits-CawQJfUS.js} +1 -1
  34. package/dist/{request-BWxweEdK.js → request-DYAI5FQE.js} +18 -6
  35. package/dist/{run-attempt-BVLE4Gbi.js → run-attempt-D1hJO4fX.js} +483 -1865
  36. package/dist/{runtime-artifact-D9pYp4zL.js → runtime-artifact-C3jVimFn.js} +19 -12
  37. package/dist/{session-binding-D0zinCP1.js → session-binding-BHuTCRZQ.js} +8 -10
  38. package/dist/{session-catalog-eMhVm0Ql.js → session-catalog-yyvTWFOw.js} +138 -116
  39. package/dist/{session-cli-B2lyjJA0.js → session-cli-CmFEXMAM.js} +1 -1
  40. package/dist/session-initialization-BeWzjGiR.js +74 -0
  41. package/dist/{session-permission-policy-ScnAyG90.js → session-permission-policy-DeWVTCMj.js} +2 -2
  42. package/dist/{session-retirement-CtUtUTr9.js → session-retirement-BujDjXVF.js} +16 -9
  43. package/dist/{session-upstream-marker-gqrYIRHk.js → session-upstream-marker-C351-5Qw.js} +18 -2
  44. package/dist/{settled-turn-context-Bk3IUwod.js → settled-turn-context-D3SNWtUn.js} +6 -28
  45. package/dist/{settled-turn-finalizer-BXLN9PfJ.js → settled-turn-finalizer-BVJx4yoc.js} +5 -5
  46. package/dist/{shared-client-B1tT5U6r.js → shared-client-DxcfF9KX.js} +2748 -101
  47. package/dist/{side-question-CZ-mCw-t.js → side-question-BTZAII4l.js} +97 -63
  48. package/dist/{thread-lifecycle-CGGKP720.js → thread-lifecycle-DAcEJ_Om.js} +2039 -1487
  49. package/dist/{thread-ownership-RkaoZCmQ.js → thread-ownership-zGokd8i1.js} +10 -9
  50. package/dist/thread-policy-g4KbJPzp.js +54 -0
  51. package/dist/{thread-resume-BFt1-ZDa.js → thread-resume-C7pyVKeW.js} +15 -7
  52. package/dist/{transcript-mirror-1ep4XjzF.js → transcript-mirror-DTUxFWa_.js} +47 -10
  53. package/dist/{transport-stdio-NT_Dpd9V.js → transport-stdio-CyPldczm.js} +3 -1
  54. package/dist/upstream-session-fork-CYlBIGVt.js +966 -0
  55. package/dist/{usage-DUhd58gI.js → usage-Bj-rrzkR.js} +3 -3
  56. package/dist/{web-search-provider.runtime-BEmlE7ov.js → web-search-provider.runtime-D2FWSK4w.js} +3 -3
  57. package/openclaw.plugin.json +0 -30
  58. package/package.json +5 -5
  59. package/dist/protocol-validators-Bg5rpNxk.js +0 -2542
  60. package/dist/session-catalog-home-id-Dt2GiG5o.js +0 -112
  61. package/dist/upstream-session-fork-Dc8BFExw.js +0 -312
@@ -1,20 +1,23 @@
1
- import { C as isCodexRemoteExecPlacementSandbox, D as resolveOpenClawExecPolicyForCodexAppServer, S as isCodexPairedNodeRemoteExecPlacementSandbox, T as readCodexPluginConfig, m as resolveCodexModelBackedReviewerPolicyContext, p as canUseCodexModelBackedApprovalsReviewerForModel, r as resolveCodexAppServerHomeScope, u as shouldAutoApproveCodexAppServerApprovals, v as readCodexRequirementsToml, w as isCodexSandboxExecServerEnabled } from "./config-CcYL77O6.js";
2
- import { C as withLeasedCodexAppServerClientStartSelectionRetry, Ht as isJsonObject, K as isCodexAppServerIndeterminateRequestCancellationError, Lt as resolveCodexAppServerPreparedAuthHandoff, Ot as readRecentCodexRateLimits, U as isCodexAppServerApprovalRequest, _t as ensureCodexAppServerClientRuntime, at as resolveDynamicToolCallTimeoutMs, c as getLeasedSharedCodexAppServerClient, dt as resolveCodexToolAbortTerminalReason, et as createCodexElicitationResponse, m as releaseCodexAppServerClientLease, tt as handleDynamicToolCallWithTimeout } from "./shared-client-B1tT5U6r.js";
3
- import { d as sessionBindingIdentity } from "./session-binding-D0zinCP1.js";
4
- import { a as assertCodexThreadForkResponse, c as assertCodexTurnStartResponse, d as readCodexTurn, l as readCodexDynamicToolCallParams } from "./protocol-validators-Bg5rpNxk.js";
5
- import { f as unsubscribeCodexThreadBestEffort, g as isCodexNotificationForTurn, s as isCodexAlreadyTerminalInterruptError, u as retireUnsafeCodexTurnClientBestEffort } from "./attempt-client-cleanup-CpVfwctT.js";
6
- import { A as readCodexSupportedReasoningEfforts, E as resolveCodexAppServerRequestModelSelection, L as filterCodexDynamicTools, O as resolveCodexBindingModelProviderFallback, T as resolveCodexAppServerModelProvider, U as resolveCodexDynamicToolsLoading, c as buildCodexNativeHookRelayConfig, d as emitCodexNativePreToolUseFailureDiagnostic, et as buildCodexPluginAppsConfigPatchFromPolicyContext, k as resolveReasoningEffort, l as buildCodexNativeHookRelayDisabledConfig, o as CODEX_NATIVE_HOOK_RELAY_EVENTS, ot as mergeCodexThreadConfigs, v as buildCodexRuntimeThreadConfig, w as CODEX_NATIVE_PERSONALITY_NONE, x as resolveCodexWebSearchPlan } from "./thread-lifecycle-CGGKP720.js";
7
- import { s as resolveCodexNativeExecutionBlock } from "./request-BWxweEdK.js";
8
- import { n as formatCodexUsageLimitErrorMessage } from "./rate-limits-BqHEHXQJ.js";
9
- import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy, t as CODEX_SESSION_PERMISSION_EXEC_MODES } from "./session-permission-policy-ScnAyG90.js";
10
- import { n as resolveCodexBindingAppServerConnection, t as requireCodexSupervisionModelSelection } from "./binding-connection-CF7BmrDk.js";
11
- import { C as shouldRequireCodexSandboxExecServerEnvironment, D as CodexNativeToolLifecycleProjector, S as shouldEnableCodexAppServerNativeToolSurface, T as filterCodexVisionTools, a as emitDynamicToolStartedDiagnostic, b as resolveCodexNodePlacementToolConstructionPlan, d as releaseCodexSandboxExecServerEnvironment, i as emitDynamicToolErrorDiagnostic, l as resolveCodexProviderWebSearchSupportForClient, o as emitDynamicToolTerminalDiagnostic, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, u as ensureCodexSandboxExecServerEnvironment, v as resolveCodexExternalSandboxPolicyForOpenClawSandbox, x as resolveCodexSandboxEnvironmentSelection, y as resolveCodexMessageToolProvider } from "./dynamic-tools-BmeXjwNZ.js";
1
+ import { $t as isJsonObject, B as isCodexAppServerIndeterminateRequestCancellationError, C as withLeasedCodexAppServerClientStartSelectionRetry, Ct as ensureCodexAppServerClientRuntime, Ft as readRecentCodexRateLimits, L as isCodexAppServerApprovalRequest, Q as assertCodexThreadForkResponse, Wt as resolveCodexAppServerPreparedAuthHandoff, _t as resolveCodexToolAbortTerminalReason, c as getLeasedSharedCodexAppServerClient, dt as resolveDynamicToolCallTimeoutMs, it as readCodexTurn, m as releaseCodexAppServerClientLease, nt as readCodexDynamicToolCallParams, ot as createCodexElicitationResponse, st as handleDynamicToolCallWithTimeout, tt as assertCodexTurnStartResponse } from "./shared-client-DxcfF9KX.js";
2
+ import { C as isCodexPairedNodeRemoteExecPlacementSandbox, E as readCodexPluginConfig, O as resolveOpenClawExecPolicyForCodexAppServer, T as isCodexSandboxExecServerEnabled, d as shouldAutoApproveCodexAppServerApprovals, f as withMcpElicitationsApprovalPolicy, h as resolveCodexModelBackedReviewerPolicyContext, l as hasCodexMcpToolApprovalOverrides, m as canUseCodexModelBackedApprovalsReviewerForModel, r as resolveCodexAppServerHomeScope, w as isCodexRemoteExecPlacementSandbox, y as readCodexRequirementsToml } from "./config-BhmfC1s6.js";
3
+ import { d as sessionBindingIdentity } from "./session-binding-BHuTCRZQ.js";
4
+ import { d as unsubscribeCodexThreadBestEffort, h as isCodexNotificationForTurn, l as retireUnsafeCodexTurnClientBestEffort, s as isCodexAlreadyTerminalInterruptError } from "./attempt-client-cleanup-DYHcRQAa.js";
5
+ import { B as emitCodexNativePreToolUseFailureDiagnostic, Dt as mergeCodexThreadConfigs, E as resolveCodexAppServerRequestModelSelection, I as buildCodexNativeHookRelayConfig, L as buildCodexNativeHookRelayDisabledConfig, N as CODEX_NATIVE_HOOK_RELAY_EVENTS, O as resolveCodexBindingModelProviderFallback, S as resolveCodexWebSearchPlan, St as buildCodexPluginAppsConfigPatchFromPolicyContext, T as resolveCodexAppServerModelProvider, a as readCodexSupportedReasoningEfforts, at as filterCodexDynamicTools, dt as resolveCodexDynamicToolsLoading, o as resolveCodexAppServerReasoningEffort, t as buildCodexTemporalAdditionalContext, v as buildCodexRuntimeThreadConfig, w as CODEX_NATIVE_PERSONALITY_NONE } from "./thread-lifecycle-DAcEJ_Om.js";
6
+ import { s as resolveCodexNativeExecutionBlock } from "./request-DYAI5FQE.js";
7
+ import { i as refreshCodexThreadPolicy, n as CodexThreadPolicyHandoffError, r as assertCodexSupervisionThreadLineage } from "./thread-policy-g4KbJPzp.js";
8
+ import { n as formatCodexUsageLimitErrorMessage } from "./rate-limits-CawQJfUS.js";
9
+ import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, r as resolveCodexEffectiveSessionPermissionPolicy, t as CODEX_SESSION_PERMISSION_EXEC_MODES } from "./session-permission-policy-DeWVTCMj.js";
10
+ import { n as resolveCodexBindingAppServerConnection, t as requireCodexSupervisionModelSelection } from "./binding-connection-E6uDsPlx.js";
11
+ import { C as filterCodexVisionTools, T as CodexNativeToolLifecycleProjector, _ as resolveCodexMessageToolProvider, a as emitDynamicToolStartedDiagnostic, b as shouldEnableCodexAppServerNativeToolSurface, c as ensureCodexSandboxExecServerEnvironment, g as resolveCodexExternalSandboxPolicyForOpenClawSandbox, i as emitDynamicToolErrorDiagnostic, l as releaseCodexSandboxExecServerEnvironment, o as emitDynamicToolTerminalDiagnostic, r as routeCodexAppServerElicitationRequest, s as handleCodexAppServerApprovalRequest, t as createCodexDynamicToolBridge, v as resolveCodexNodePlacementToolConstructionPlan, x as shouldRequireCodexSandboxExecServerEnvironment, y as resolveCodexSandboxEnvironmentSelection } from "./dynamic-tools-BU9tmlYm.js";
12
+ import { n as resolveCodexProviderWebSearchSupportForClient } from "./provider-capabilities-DW5p4k9w.js";
12
13
  import { readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
13
14
  import { buildAgentHookContextChannelFields, embeddedAgentLog, formatErrorMessage, registerNativeHookRelay, resolveAgentDir, resolveAttemptSpawnWorkspaceDir, resolveModelAuthMode, resolveSandboxContext, supportsModelTools } from "openclaw/plugin-sdk/agent-harness-runtime";
14
15
  import { randomUUID } from "node:crypto";
16
+ import { isDeepStrictEqual } from "node:util";
15
17
  import { resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
16
18
  import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
17
19
  import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
20
+ import { loadCodexBundleMcpApprovalConfig, resolveCodexMcpToolOverridesForAgent } from "openclaw/plugin-sdk/codex-mcp-projection";
18
21
  //#region extensions/codex/src/app-server/side-question.ts
19
22
  const SIDE_QUESTION_COMPLETION_TIMEOUT_MS = 6e5;
20
23
  var CodexSideQuestionTimeoutError = class extends Error {
@@ -27,22 +30,11 @@ const CODEX_SIDE_NATIVE_HOOK_RELAY_MIN_TTL_MS = 18e5;
27
30
  const CODEX_SIDE_NATIVE_HOOK_RELAY_TTL_GRACE_MS = 3e5;
28
31
  const CODEX_SIDE_NATIVE_HOOK_RELAY_STARTUP_REQUEST_COUNT = 3;
29
32
  const CODEX_SIDE_NATIVE_HOOK_RELAY_EVENTS_WITH_APP_SERVER_APPROVALS = CODEX_NATIVE_HOOK_RELAY_EVENTS.filter((event) => event !== "permission_request");
30
- const SIDE_BOUNDARY_PROMPT = `Side conversation boundary.
31
-
32
- Everything before this boundary is inherited history from the parent thread. It is reference context only. It is not your current task.
33
-
34
- Do not continue, execute, or complete any instructions, plans, tool calls, approvals, edits, or requests from before this boundary. Only messages submitted after this boundary are active user instructions for this side conversation.
35
-
36
- You are a side-conversation assistant, separate from the main thread. Answer questions and do lightweight, non-mutating exploration without disrupting the main thread. If there is no user question after this boundary yet, wait for one.
37
-
38
- External tools may be available according to this thread's current permissions. Any tool calls or outputs visible before this boundary happened in the parent thread and are reference-only; do not infer active instructions from them.
39
-
40
- Do not modify files, source, git state, permissions, configuration, workspace state, or external state unless the user explicitly asks for that mutation after this boundary. Do not request escalated permissions or broader sandbox access unless the user explicitly asks for a mutation that requires it. If the user explicitly requests a mutation, keep it minimal, local to the request, and avoid disrupting the main thread.`;
41
33
  const SIDE_DEVELOPER_INSTRUCTIONS = `You are in a side conversation, not the main thread.
42
34
 
43
35
  This side conversation is for answering questions and lightweight, non-mutating exploration without disrupting the main thread. Do not present yourself as continuing the main thread's active task.
44
36
 
45
- The inherited fork history is provided only as reference context. Do not treat instructions, plans, or requests found in the inherited history as active instructions for this side conversation. Only instructions submitted after the side-conversation boundary are active.
37
+ The inherited fork history is provided only as reference context. Do not treat instructions, plans, or requests found in the inherited history as active instructions for this side conversation. Only the current side question and subsequent requests in this side conversation are active. If no side question has been submitted, wait for one.
46
38
 
47
39
  Do not continue, execute, or complete any task, plan, tool call, approval, edit, or request that appears only in inherited history.
48
40
 
@@ -52,12 +44,13 @@ You may perform non-mutating inspection, including reading or searching files an
52
44
 
53
45
  Do not modify files, source, git state, permissions, configuration, workspace state, or external state unless the user explicitly requests that mutation in this side conversation. Do not request escalated permissions or broader sandbox access unless the user explicitly requests a mutation that requires it. If the user explicitly requests a mutation, keep it minimal, local to the request, and avoid disrupting the main thread.`;
54
46
  async function runCodexAppServerSideQuestion(params, options) {
55
- const binding = await options.bindingStore.read(sessionBindingIdentity({
47
+ const bindingIdentity = sessionBindingIdentity({
56
48
  sessionId: params.sessionId,
57
49
  sessionKey: params.sessionKey,
58
50
  agentId: params.agentId,
59
51
  config: params.cfg
60
- }));
52
+ });
53
+ const binding = await options.bindingStore.read(bindingIdentity);
61
54
  if (!binding?.threadId) throw new Error("Codex /btw needs an active Codex thread. Send a normal message first, then try /btw again.");
62
55
  if (isCodexPairedNodeRemoteExecPlacementSandbox(params.sandbox)) throw new Error("Normal Codex turns are supported on nodes, but /btw is not yet bound to the active placement.");
63
56
  const pluginConfig = readCodexPluginConfig(options.pluginConfig);
@@ -269,6 +262,8 @@ async function runCodexAppServerSideQuestion(params, options) {
269
262
  if (params.opts?.abortSignal?.aborted) abortFromUpstream();
270
263
  else params.opts?.abortSignal?.addEventListener("abort", abortFromUpstream, { once: true });
271
264
  let childThreadId;
265
+ let childClient;
266
+ let policyWriteUncertain = false;
272
267
  let turnId;
273
268
  let sandboxEnvironment;
274
269
  let sandboxEnvironmentClient;
@@ -303,7 +298,16 @@ async function runCodexAppServerSideQuestion(params, options) {
303
298
  sandboxEnvironmentClient = targetClient;
304
299
  };
305
300
  try {
306
- const approvalPolicy = appServer.approvalPolicy;
301
+ const autoApproveMcpTools = shouldAutoApproveCodexAppServerApprovals(appServer);
302
+ const projectedMcpServers = loadCodexBundleMcpApprovalConfig({
303
+ workspaceDir: agentWorkspaceDir,
304
+ cfg: params.cfg,
305
+ toolOverrides: resolveCodexMcpToolOverridesForAgent(params.cfg, {
306
+ agentId: sessionAgentId,
307
+ toolOverrides: params.sessionEntry.toolOverrides
308
+ })
309
+ });
310
+ const approvalPolicy = hasCodexMcpToolApprovalOverrides(params.cfg?.mcp?.servers, Object.keys(projectedMcpServers), projectedMcpServers) ? withMcpElicitationsApprovalPolicy(appServer.approvalPolicy) : appServer.approvalPolicy;
307
311
  const sandbox = appServer.sandbox;
308
312
  const { toolBridge, webSearchPlan } = await createCodexSideToolBridge({
309
313
  params: effectiveParams,
@@ -341,6 +345,9 @@ async function runCodexAppServerSideQuestion(params, options) {
341
345
  paramsForRun: sideRunParams,
342
346
  threadId: childThreadId,
343
347
  turnId,
348
+ autoApproveMcpTools,
349
+ projectedMcpServers,
350
+ getActiveMcpToolCall: (serverName) => nativeToolLifecycleProjector?.getActiveMcpToolCall(serverName),
344
351
  pluginAppPolicyContext: binding.pluginAppPolicyContext,
345
352
  signal: runAbortController.signal
346
353
  });
@@ -354,11 +361,7 @@ async function runCodexAppServerSideQuestion(params, options) {
354
361
  threadId: childThreadId,
355
362
  turnId,
356
363
  nativeHookRelay,
357
- autoApprove: shouldAutoApproveCodexAppServerApprovals({
358
- approvalPolicy,
359
- networkProxy: appServer.networkProxy,
360
- sandbox
361
- }),
364
+ autoApprove: autoApproveMcpTools,
362
365
  signal: runAbortController.signal,
363
366
  onNativeToolFailureDisposition: (itemId, disposition) => nativeToolLifecycleProjector?.recordApprovalFailureDisposition(itemId, disposition)
364
367
  });
@@ -424,7 +427,7 @@ async function runCodexAppServerSideQuestion(params, options) {
424
427
  const serviceTier = binding.serviceTier ?? appServer.serviceTier;
425
428
  const nativeHookRelayEvents = resolveCodexSideNativeHookRelayEvents({
426
429
  configuredEvents: options.nativeHookRelay?.events,
427
- approvalPolicy
430
+ approvalPolicy: appServer.approvalPolicy
428
431
  });
429
432
  nativeHookRelay = options.nativeHookRelay ? registerCodexSideNativeHookRelay({
430
433
  options: options.nativeHookRelay,
@@ -433,6 +436,8 @@ async function runCodexAppServerSideQuestion(params, options) {
433
436
  sessionId: params.sessionId,
434
437
  sessionKey: params.sessionKey,
435
438
  config: params.cfg,
439
+ autoApproveMcpTools,
440
+ projectedMcpServers,
436
441
  runId: sideRunParams.runId,
437
442
  channelId: buildAgentHookContextChannelFields({
438
443
  sessionKey: params.sessionKey,
@@ -441,7 +446,7 @@ async function runCodexAppServerSideQuestion(params, options) {
441
446
  currentChannelId: params.currentChannelId
442
447
  }).channelId,
443
448
  requestTimeoutMs: appServer.requestTimeoutMs,
444
- completionTimeoutMs: Math.max(appServer.turnCompletionIdleTimeoutMs, SIDE_QUESTION_COMPLETION_TIMEOUT_MS),
449
+ completionTimeoutMs: SIDE_QUESTION_COMPLETION_TIMEOUT_MS,
445
450
  loopDetectionPreToolUseRelay: appServer.loopDetectionPreToolUseRelay,
446
451
  signal: runAbortController.signal,
447
452
  hostCapabilities: sideRunParams.hostCapabilities,
@@ -463,14 +468,26 @@ async function runCodexAppServerSideQuestion(params, options) {
463
468
  });
464
469
  const pluginAppsConfigPatch = binding.pluginAppPolicyContext ? buildCodexPluginAppsConfigPatchFromPolicyContext(binding.pluginAppPolicyContext) : void 0;
465
470
  const threadConfig = mergeCodexThreadConfigs(nativeHookRelayConfig, runtimeThreadConfig, pluginAppsConfigPatch, appServer.networkProxy?.configPatch) ?? runtimeThreadConfig;
466
- const forkResponse = assertCodexThreadForkResponse(await withLeasedCodexAppServerClientStartSelectionRetry({
471
+ const sideThreadId = await withLeasedCodexAppServerClientStartSelectionRetry({
467
472
  lease: clientLease,
468
473
  options: clientOptions,
469
474
  signal: runAbortController.signal,
470
- run: async (forkClient, requestOptions) => {
475
+ run: async (forkClient, requestOptions) => options.bindingStore.withLease(bindingIdentity, async () => {
476
+ if (binding.connectionScope === "supervision") {
477
+ params.hostCapabilities.assertActive();
478
+ const { thread } = await forkClient.request("thread/read", {
479
+ threadId: binding.threadId,
480
+ includeTurns: false
481
+ }, requestOptions());
482
+ params.hostCapabilities.assertActive();
483
+ if (!isDeepStrictEqual(await options.bindingStore.read(bindingIdentity), binding)) throw new Error("Codex side-question binding changed before fork");
484
+ params.hostCapabilities.assertActive();
485
+ assertCodexSupervisionThreadLineage(binding, thread);
486
+ }
471
487
  await ensureSandboxEnvironment(forkClient);
488
+ params.hostCapabilities.assertActive();
472
489
  const executionCwd = sandboxEnvironment?.cwd ?? cwd;
473
- return await forkCodexSideThread(forkClient, {
490
+ const response = assertCodexThreadForkResponse(await forkCodexSideThread(forkClient, {
474
491
  threadId: binding.threadId,
475
492
  model: modelSelection.model,
476
493
  ...modelSelection.modelProvider ? { modelProvider: modelSelection.modelProvider } : {},
@@ -483,28 +500,51 @@ async function runCodexAppServerSideQuestion(params, options) {
483
500
  config: threadConfig,
484
501
  developerInstructions: SIDE_DEVELOPER_INSTRUCTIONS,
485
502
  ephemeral: true,
503
+ excludeTurns: true,
486
504
  threadSource: "user"
487
- }, requestOptions());
488
- },
505
+ }, requestOptions()));
506
+ if (!response.thread.id.trim() || response.thread.id === binding.threadId) {
507
+ await retireUnsafeCodexTurnClientBestEffort(forkClient, "unsafe side child identity");
508
+ throw new Error("Codex side fork returned an unsafe child identity");
509
+ }
510
+ childThreadId = response.thread.id;
511
+ childClient = forkClient;
512
+ try {
513
+ if (supervisionModelSelection && (response.model !== supervisionModelSelection.model || response.modelProvider !== supervisionModelSelection.modelProvider)) throw new Error("Codex supervised side thread did not preserve its native model and provider");
514
+ const scoped = requestOptions();
515
+ await refreshCodexThreadPolicy({
516
+ client: forkClient,
517
+ threadId: childThreadId,
518
+ developerInstructions: SIDE_DEVELOPER_INSTRUCTIONS,
519
+ ...scoped,
520
+ signal: runAbortController.signal,
521
+ assertCurrent: () => {
522
+ params.hostCapabilities.assertActive();
523
+ runAbortController.signal.throwIfAborted();
524
+ scoped.assertCurrent();
525
+ }
526
+ });
527
+ } catch (error) {
528
+ policyWriteUncertain = error instanceof CodexThreadPolicyHandoffError && error.outcome === "unknown";
529
+ throw error instanceof CodexThreadPolicyHandoffError ? error : new CodexThreadPolicyHandoffError("not-written", error);
530
+ }
531
+ return response.thread.id;
532
+ }),
489
533
  onClientChange: rebindClientHandlers
490
- }));
491
- childThreadId = forkResponse.thread.id;
492
- if (supervisionModelSelection && (forkResponse.model !== supervisionModelSelection.model || forkResponse.modelProvider !== supervisionModelSelection.modelProvider)) throw new Error("Codex supervised side thread did not preserve its native model and provider");
493
- await client.request("thread/inject_items", {
494
- threadId: childThreadId,
495
- items: [sideBoundaryPromptItem()]
496
- }, {
497
- timeoutMs: appServer.requestTimeoutMs,
498
- signal: runAbortController.signal
499
534
  });
500
- const effort = usesSupervisionConnection ? void 0 : resolveReasoningEffort(params.resolvedThinkLevel ?? "off", modelSelection.model, readCodexSupportedReasoningEfforts(params.runtimeModel?.compat));
535
+ const effort = usesSupervisionConnection ? void 0 : resolveCodexAppServerReasoningEffort({
536
+ thinkLevel: params.resolvedThinkLevel ?? "off",
537
+ modelId: modelSelection.model,
538
+ supportedReasoningEfforts: readCodexSupportedReasoningEfforts(params.runtimeModel?.compat)
539
+ });
501
540
  turnId = assertCodexTurnStartResponse(await client.request("turn/start", {
502
- threadId: childThreadId,
541
+ threadId: sideThreadId,
503
542
  input: [{
504
543
  type: "text",
505
544
  text: params.question.trim(),
506
545
  text_elements: []
507
546
  }],
547
+ additionalContext: buildCodexTemporalAdditionalContext(sideRunParams, { sessionStatusAvailable: toolBridge.availableTools.some((tool) => tool.name === "session_status") }),
508
548
  ...sandboxEnvironment ? {
509
549
  cwd: sandboxEnvironment.cwd,
510
550
  sandboxPolicy: resolveCodexExternalSandboxPolicyForOpenClawSandbox(params.sandbox ?? void 0),
@@ -531,11 +571,11 @@ async function runCodexAppServerSideQuestion(params, options) {
531
571
  if (isCodexAppServerIndeterminateRequestCancellationError(error)) turnId = "";
532
572
  throw error;
533
573
  })).turn.id;
534
- collector.setTurn(childThreadId, turnId);
574
+ collector.setTurn(sideThreadId, turnId);
535
575
  nativeToolLifecycleProjector = new CodexNativeToolLifecycleProjector({
536
576
  ...sideRunParams,
537
577
  agentId: sessionAgentId
538
- }, childThreadId, turnId, { runAbortSignal: runAbortController.signal });
578
+ }, sideThreadId, turnId, { runAbortSignal: runAbortController.signal });
539
579
  for (const failure of pendingNativePreToolUseFailures) nativeToolLifecycleProjector.recordPreToolUseFailure(failure);
540
580
  pendingNativePreToolUseFailures.length = 0;
541
581
  for (const notification of pendingNativeToolNotifications) nativeToolLifecycleProjector.handleNotification(notification);
@@ -544,7 +584,7 @@ async function runCodexAppServerSideQuestion(params, options) {
544
584
  try {
545
585
  text = await collector.wait({
546
586
  signal: runAbortController.signal,
547
- timeoutMs: Math.max(appServer.turnCompletionIdleTimeoutMs, SIDE_QUESTION_COMPLETION_TIMEOUT_MS)
587
+ timeoutMs: SIDE_QUESTION_COMPLETION_TIMEOUT_MS
548
588
  });
549
589
  } catch (error) {
550
590
  if (error instanceof CodexSideQuestionTimeoutError && !runAbortController.signal.aborted) runAbortController.abort(error);
@@ -562,13 +602,14 @@ async function runCodexAppServerSideQuestion(params, options) {
562
602
  if (!runAbortController.signal.aborted) runAbortController.abort("codex_side_question_finished");
563
603
  await Promise.allSettled(activeDynamicToolCalls);
564
604
  try {
565
- await cleanupCodexSideThread(client, {
605
+ await cleanupCodexSideThread(childClient ?? client, {
566
606
  threadId: childThreadId,
567
607
  turnId,
568
608
  interrupt: !collector.completed,
569
609
  timeoutMs: appServer.requestTimeoutMs
570
610
  });
571
611
  } finally {
612
+ if (policyWriteUncertain && childClient) await retireUnsafeCodexTurnClientBestEffort(childClient, "side policy handoff");
572
613
  removeNotificationHandler();
573
614
  try {
574
615
  nativeToolLifecycleProjector?.finalizeActive(runWasAbortedBeforeCleanup);
@@ -599,6 +640,8 @@ function registerCodexSideNativeHookRelay(params) {
599
640
  sessionId: params.sessionId,
600
641
  ...params.sessionKey ? { sessionKey: params.sessionKey } : {},
601
642
  ...params.config ? { config: params.config } : {},
643
+ autoApproveMcpTools: params.autoApproveMcpTools,
644
+ projectedMcpServers: params.projectedMcpServers,
602
645
  runId: params.runId,
603
646
  ...params.channelId ? { channelId: params.channelId } : {},
604
647
  allowedEvents: params.events,
@@ -698,6 +741,7 @@ async function createCodexSideToolBridge(input) {
698
741
  const toolConstructionPlan = resolveCodexNodePlacementToolConstructionPlan(sandbox, input.nativeToolSurfaceEnabled);
699
742
  const allTools = createOpenClawCodingTools({
700
743
  agentId: input.sessionAgentId,
744
+ requesterThinkingLevel: input.params.resolvedThinkLevel ?? "off",
701
745
  sessionKey: sandboxSessionKey,
702
746
  runSessionKey: input.params.sessionKey && input.params.sessionKey !== sandboxSessionKey ? input.params.sessionKey : void 0,
703
747
  sessionId: input.params.sessionId,
@@ -815,16 +859,6 @@ function isMissingCodexParentThreadError(error) {
815
859
  const message = formatErrorMessage(error);
816
860
  return message.includes("no rollout found for thread id") || message.includes("includeTurns is unavailable before first user message");
817
861
  }
818
- function sideBoundaryPromptItem() {
819
- return {
820
- type: "message",
821
- role: "user",
822
- content: [{
823
- type: "input_text",
824
- text: SIDE_BOUNDARY_PROMPT
825
- }]
826
- };
827
- }
828
862
  async function cleanupCodexSideThread(client, params) {
829
863
  if (!params.threadId) return;
830
864
  if (params.interrupt && params.turnId !== void 0) try {