@openclaw/codex 2026.9.1 → 2026.9.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 (67) hide show
  1. package/dist/api.js +6 -6
  2. package/dist/{attempt-client-cleanup-DYHcRQAa.js → attempt-client-cleanup-Bp1ZOnk2.js} +76 -32
  3. package/dist/{attempt-context-DmQUNWwT.js → attempt-context-CSazkWns.js} +6 -6
  4. package/dist/{bounded-turn-wzJrwKKe.js → bounded-turn-DxGJRYbY.js} +46 -45
  5. package/dist/{capabilities-dIjNVCYH.js → capabilities-B1mgvpP8.js} +2 -1
  6. package/dist/cli-metadata.js +1 -1
  7. package/dist/{command-formatters-CLHhEB1Q.js → command-formatters-DSbGMXA0.js} +2 -2
  8. package/dist/{command-handlers-CTGb2csu.js → command-handlers-DOJvGv6-.js} +146 -74
  9. package/dist/{compact-_t0HQrUS.js → compact-Y_xBqrHN.js} +83 -48
  10. package/dist/{config-BhmfC1s6.js → config-CyapYSji.js} +47 -105
  11. package/dist/config-utils-C57JiJrU.js +69 -0
  12. package/dist/doctor-contract-api.js +4 -5
  13. package/dist/{dynamic-tools-BU9tmlYm.js → dynamic-tools-BwpvTxaX.js} +678 -638
  14. package/dist/{effective-mcp-catalog-DzYBW4h1.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
  15. package/dist/{event-projector-assistant-message-DHRFXKbS.js → event-projector-assistant-message-B9kp6iGC.js} +11 -2
  16. package/dist/{event-projector-usage-C5mcrGjp.js → event-projector-usage-ZqEVbAEY.js} +30 -13
  17. package/dist/{harness-DXVZ5II5.js → harness-Czh2Sdoc.js} +36 -13
  18. package/dist/harness.js +1 -1
  19. package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
  20. package/dist/index.js +68 -84
  21. package/dist/{isolated-completion-kg9kv4iH.js → isolated-completion-CRh-51AK.js} +9 -21
  22. package/dist/{managed-binary-4-Vjz5GH.js → managed-binary-DcpnJF9x.js} +105 -73
  23. package/dist/media-understanding-provider.js +1 -1
  24. package/dist/{model-catalog-CUM68Hkl.js → model-catalog-DT5vo6qo.js} +5 -5
  25. package/dist/{models-sYnEc0gd.js → models-CcrgSMQR.js} +4 -4
  26. package/dist/{native-subagent-monitor-CnH147jH.js → native-subagent-monitor-B3bvQGcg.js} +12 -11
  27. package/dist/{node-exec-server.runtime-CstNHCmC.js → node-exec-server.runtime-nfbUOtUB.js} +3 -3
  28. package/dist/{plugin-approval-roundtrip-CNe-Xrjx.js → plugin-approval-roundtrip-aQVdyL5g.js} +1 -1
  29. package/dist/{plugin-marketplace-discovery-CfFlKqDl.js → plugin-marketplace-discovery-B7gHXJ3d.js} +35 -22
  30. package/dist/{plugin-metadata-cache-BFrPhb2c.js → plugin-metadata-cache-BwCLTY_U.js} +5 -5
  31. package/dist/{provider-capabilities-DW5p4k9w.js → provider-capabilities-BpG9Ltc5.js} +2 -2
  32. package/dist/{rate-limits-CawQJfUS.js → rate-limits-Fx_l4eNa.js} +1 -1
  33. package/dist/{request-DYAI5FQE.js → request-C8H22rPi.js} +2 -2
  34. package/dist/{run-attempt-D1hJO4fX.js → run-attempt-BzthFQSM.js} +977 -723
  35. package/dist/{runtime-artifact-C3jVimFn.js → runtime-artifact-Bh_gf6-t.js} +3 -3
  36. package/dist/{session-binding-BHuTCRZQ.js → session-binding-4Ki04sW-.js} +94 -282
  37. package/dist/session-binding-record-CyaXZvTe.js +270 -0
  38. package/dist/{session-catalog-yyvTWFOw.js → session-catalog-B47uwekb.js} +266 -114
  39. package/dist/{session-cli-CmFEXMAM.js → session-cli-BjLhpmS1.js} +1 -1
  40. package/dist/session-history-DWmMqiqW.js +93 -0
  41. package/dist/session-history-read-LHldwvyh.js +36 -0
  42. package/dist/session-history-worker-runtime.js +48 -0
  43. package/dist/{settled-turn-context-D3SNWtUn.js → session-history.worker-zZVcx0ME.js} +30 -31
  44. package/dist/session-history.worker.js +2 -0
  45. package/dist/{session-initialization-BeWzjGiR.js → session-initialization-BCFVnLL4.js} +2 -1
  46. package/dist/{session-permission-policy-DeWVTCMj.js → session-permission-policy-BaueHmSj.js} +1 -1
  47. package/dist/{session-retirement-BujDjXVF.js → session-retirement-DNdmYdFc.js} +7 -7
  48. package/dist/{session-upstream-marker-C351-5Qw.js → session-upstream-marker-DReTpGz6.js} +4 -3
  49. package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
  50. package/dist/{settled-turn-finalizer-BVJx4yoc.js → settled-turn-finalizer-BI-b1sry.js} +53 -42
  51. package/dist/{shared-client-DxcfF9KX.js → shared-client-CKhX2kFt.js} +279 -268
  52. package/dist/{side-question-BTZAII4l.js → side-question-B6DWAw1A.js} +85 -36
  53. package/dist/{thread-lifecycle-DAcEJ_Om.js → thread-lifecycle-DPK30jad.js} +382 -388
  54. package/dist/{thread-ownership-zGokd8i1.js → thread-ownership-CbucAmmp.js} +5 -5
  55. package/dist/thread-policy-CTalhWFy.js +105 -0
  56. package/dist/{thread-resume-C7pyVKeW.js → thread-resume-BLgqkUc1.js} +7 -7
  57. package/dist/{transcript-mirror-DTUxFWa_.js → transcript-mirror-_njEB84z.js} +67 -125
  58. package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
  59. package/dist/{transport-stdio-CyPldczm.js → transport-stdio-CzTngV0j.js} +10 -8
  60. package/dist/{upstream-session-fork-CYlBIGVt.js → upstream-session-fork-1fwbNKzQ.js} +85 -165
  61. package/dist/{usage-Bj-rrzkR.js → usage-i9fv5-4m.js} +3 -3
  62. package/dist/{web-search-provider.runtime-D2FWSK4w.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
  63. package/package.json +6 -6
  64. package/dist/binding-connection-E6uDsPlx.js +0 -45
  65. package/dist/launch-args-RXQwn8zV.js +0 -90
  66. package/dist/session-history-C5J1AKzG.js +0 -87
  67. package/dist/thread-policy-g4KbJPzp.js +0 -54
package/dist/api.js CHANGED
@@ -1,8 +1,8 @@
1
- import { a as resolveCodexAppServerStartOptionsForAgent, i as resolveCodexAppServerRuntimeOptions } from "./config-BhmfC1s6.js";
2
- import { n as resolveManagedCodexAppServerStartOptions, o as CODEX_APP_SERVER_VERSION, r as resolveManagedCodexNativeCommand, t as isManagedCodexDesktopCommand } from "./managed-binary-4-Vjz5GH.js";
1
+ import { a as resolveCodexAppServerStartOptionsForAgent, i as resolveCodexAppServerRuntimeOptions } from "./config-CyapYSji.js";
2
+ import { n as resolveManagedCodexAppServerStartOptions, o as CODEX_APP_SERVER_VERSION, r as resolveManagedCodexNativeCommand, t as isManagedCodexDesktopCommand } from "./managed-binary-DcpnJF9x.js";
3
+ import { listAgentIds, resolveAgentDir } from "openclaw/plugin-sdk/agent-scope-runtime";
3
4
  import path from "node:path";
4
5
  import { resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
5
- import { listAgentIds as listAgentIds$1, resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-scope-runtime";
6
6
  import { execFile } from "node:child_process";
7
7
  import { fileURLToPath } from "node:url";
8
8
  import { resolveEffectiveAgentRuntime } from "openclaw/plugin-sdk/command-auth-native";
@@ -67,7 +67,7 @@ function createCodexManagedAppServerHealthCheck(params) {
67
67
  if (start.transport !== "stdio" || start.commandSource !== "managed") return [];
68
68
  const env = ctx.env ?? process.env;
69
69
  let resolved;
70
- for (const agentId of listAgentIds$1(ctx.cfg)) {
70
+ for (const agentId of listAgentIds(ctx.cfg)) {
71
71
  const model = resolveDefaultModelForAgent({
72
72
  cfg: ctx.cfg,
73
73
  agentId
@@ -80,7 +80,7 @@ function createCodexManagedAppServerHealthCheck(params) {
80
80
  }) !== "codex") continue;
81
81
  const agentStart = resolveAgentStartOptions({
82
82
  startOptions: start,
83
- agentDir: resolveAgentDir$1(ctx.cfg, agentId, env),
83
+ agentDir: resolveAgentDir(ctx.cfg, agentId, env),
84
84
  env
85
85
  });
86
86
  try {
@@ -116,7 +116,7 @@ function createCodexManagedAppServerHealthCheck(params) {
116
116
  })];
117
117
  }
118
118
  const detectedVersion = parseCodexVersion(`${output.stdout}\n${output.stderr}`);
119
- if (detectedVersion !== "0.152.1") return [managedCodexFinding({
119
+ if (detectedVersion !== "0.153.4") return [managedCodexFinding({
120
120
  message: detectedVersion ? `Managed Codex app-server version mismatch: expected ${CODEX_APP_SERVER_VERSION}, detected ${detectedVersion}.` : `Managed Codex app-server did not report a parseable version; expected ${CODEX_APP_SERVER_VERSION}.`,
121
121
  path: nativeCommand,
122
122
  requirement: `the exact OpenClaw-pinned Codex version ${CODEX_APP_SERVER_VERSION}`,
@@ -1,10 +1,24 @@
1
- import { $t as isJsonObject, jt as unsubscribeCodexAppServerLiveThread, q as CodexAppServerRpcError, y as retireSharedCodexAppServerClientIfCurrent } from "./shared-client-DxcfF9KX.js";
1
+ import { B as isJsonObject } from "./config-CyapYSji.js";
2
+ import { Nt as unsubscribeCodexAppServerLiveThread, q as CodexAppServerRpcError, y as retireSharedCodexAppServerClientIfCurrent } from "./shared-client-CKhX2kFt.js";
2
3
  import { asFiniteNumber, normalizeOptionalString, normalizeOptionalString as normalizeOptionalString$1, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
3
4
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
4
5
  import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
5
6
  import { redactSensitiveText } from "openclaw/plugin-sdk/logging-core";
6
7
  import { sanitizeTerminalText } from "openclaw/plugin-sdk/text-chunking";
7
8
  //#region extensions/codex/src/app-server/event-projector-values.ts
9
+ const BIO_POLICY_SAFETY_ACCESS_BLOCK_PREFIX = "This content was flagged for possible biological risk.";
10
+ /** Project only Codex's explicit refusal contracts; other policy errors retain their own paths. */
11
+ function readCodexProviderRefusal(message, codexErrorInfo) {
12
+ if (!message) return;
13
+ if (codexErrorInfo === "cyberPolicy") return {
14
+ category: "cyber",
15
+ message
16
+ };
17
+ return message.startsWith(BIO_POLICY_SAFETY_ACCESS_BLOCK_PREFIX) ? {
18
+ category: "bio",
19
+ message
20
+ } : void 0;
21
+ }
8
22
  function readNonEmptyString(record, key) {
9
23
  return normalizeOptionalString$1(record[key]);
10
24
  }
@@ -334,28 +348,35 @@ var ClientTurnRouter = class {
334
348
  const turnId = requireId(options.turnId, "turn id");
335
349
  if (options.signal?.aborted) return {
336
350
  completion: Promise.resolve(false),
351
+ state: "unconfirmed",
352
+ settledSignal: AbortSignal.abort(),
337
353
  cancel: () => {}
338
354
  };
339
- if (this.routes.get(threadId)?.completedNativeTurnIds.delete(turnId)) return {
355
+ if (this.routes.get(threadId)?.completedNativeTurnIds.has(turnId)) return {
340
356
  completion: Promise.resolve(true),
357
+ state: "confirmed",
358
+ settledSignal: AbortSignal.abort(),
341
359
  cancel: () => {}
342
360
  };
343
361
  const { promise: completion, resolve: settle } = createDeferred();
362
+ const settlement = new AbortController();
344
363
  const watchers = this.nativeTurnCompletionWatchers.get(threadId) ?? /* @__PURE__ */ new Set();
345
364
  this.nativeTurnCompletionWatchers.set(threadId, watchers);
346
- let settled = false;
365
+ let state = "pending";
347
366
  const finish = (completed) => {
348
- if (settled) return;
349
- settled = true;
367
+ if (state !== "pending") return;
368
+ state = completed ? "confirmed" : "unconfirmed";
350
369
  watchers.delete(watcher);
351
370
  if (watchers.size === 0) this.nativeTurnCompletionWatchers.delete(threadId);
352
371
  clearTimeout(timeout);
353
372
  options.signal?.removeEventListener("abort", abort);
373
+ settlement.abort();
354
374
  settle(completed);
355
375
  };
356
376
  const watcher = {
357
377
  turnId,
358
- finish
378
+ finish,
379
+ onStarted: options.onStarted
359
380
  };
360
381
  watchers.add(watcher);
361
382
  const timeout = setTimeout(() => finish(false), Math.max(1, options.timeoutMs));
@@ -364,6 +385,10 @@ var ClientTurnRouter = class {
364
385
  options.signal?.addEventListener("abort", abort, { once: true });
365
386
  return {
366
387
  completion,
388
+ settledSignal: settlement.signal,
389
+ get state() {
390
+ return state;
391
+ },
367
392
  cancel: () => finish(false)
368
393
  };
369
394
  }
@@ -436,6 +461,7 @@ var ClientTurnRouter = class {
436
461
  if (!watchers && !route) return;
437
462
  if (scope.turnId && watchers) {
438
463
  for (const watcher of watchers) if (watcher.turnId === scope.turnId && notification.method === "turn/completed") watcher.finish(true);
464
+ else if (watcher.turnId === scope.turnId && notification.method === "turn/started") watcher.onStarted?.();
439
465
  }
440
466
  if (!route) return;
441
467
  const routeScope = {
@@ -443,12 +469,15 @@ var ClientTurnRouter = class {
443
469
  ...scope.turnId ? { turnId: scope.turnId } : {}
444
470
  };
445
471
  const receivedAtMs = Date.now();
446
- if (route.gate !== "bound" && scope.turnId) {
447
- if (notification.method === "turn/started") route.observedNativeTurn = {
448
- id: scope.turnId,
449
- completed: false
450
- };
451
- else if (notification.method === "turn/completed") {
472
+ if (scope.turnId && (route.gate !== "bound" || scope.turnId === route.turnId)) {
473
+ if (notification.method === "turn/started") {
474
+ route.completedNativeTurnIds.delete(scope.turnId);
475
+ route.observedNativeTurn = {
476
+ id: scope.turnId,
477
+ completed: false
478
+ };
479
+ } else if (notification.method === "turn/completed") {
480
+ if (route.gate === "bound") route.completedNativeTurnIds.clear();
452
481
  route.completedNativeTurnIds.add(scope.turnId);
453
482
  if (!route.observedNativeTurn || route.observedNativeTurn.completed || route.observedNativeTurn.id === scope.turnId) route.observedNativeTurn = {
454
483
  id: scope.turnId,
@@ -626,8 +655,8 @@ const CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS = 5e3;
626
655
  const CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS = 5e3;
627
656
  const CODEX_NO_ACTIVE_TURN_ERROR_CODE = -32600;
628
657
  const CODEX_NO_ACTIVE_TURN_ERROR_MESSAGE = "no active turn to interrupt";
629
- /** Identifies Codex's exact proof that an interrupt target already finished. */
630
- function isCodexAlreadyTerminalInterruptError(error) {
658
+ /** Codex also reports this before an accepted turn publishes its start event. */
659
+ function isCodexNoActiveTurnInterruptError(error) {
631
660
  return error instanceof CodexAppServerRpcError && error.code === CODEX_NO_ACTIVE_TURN_ERROR_CODE && error.message === CODEX_NO_ACTIVE_TURN_ERROR_MESSAGE;
632
661
  }
633
662
  /** Raised when a thread subscription may be live on a client OpenClaw no longer controls. */
@@ -644,18 +673,10 @@ function isCodexAppServerUnsafeSubscriptionError(error) {
644
673
  function assertCodexThreadResumeSubscription(requestedThreadId, returnedThreadId) {
645
674
  if (returnedThreadId !== requestedThreadId) throw new CodexAppServerUnsafeSubscriptionError(`Codex thread/resume returned ${returnedThreadId} for ${requestedThreadId}`);
646
675
  }
647
- async function closeClientAndWaitIfAvailable(client) {
648
- const closeable = client;
649
- if (typeof closeable.closeAndWait === "function") {
650
- await closeable.closeAndWait();
651
- return;
652
- }
653
- closeable.close?.();
654
- }
655
676
  async function closeCodexStartupClientBestEffort(client) {
656
677
  if (!client) return;
657
678
  const retiredSharedClient = retireSharedCodexAppServerClientIfCurrent(client);
658
- if (!retiredSharedClient || retiredSharedClient.closed) await closeClientAndWaitIfAvailable(client);
679
+ if (!retiredSharedClient || retiredSharedClient.closed) await client.closeAndWait();
659
680
  }
660
681
  /** Retires an unsafe turn client without replacing an already-authoritative failure. */
661
682
  async function retireUnsafeCodexTurnClientBestEffort(client, operation) {
@@ -683,21 +704,44 @@ async function interruptCodexTurnAndWaitBestEffort(client, params) {
683
704
  threadId: params.threadId,
684
705
  turnId: params.turnId
685
706
  };
686
- let completion;
707
+ let cancelWatch;
687
708
  try {
688
- completion = params.turnId ? getCodexAppServerTurnRouter(client).watchNativeTurnCompletion({
709
+ if (!params.turnId) {
710
+ await client.request("turn/interrupt", requestParams, { timeoutMs });
711
+ return true;
712
+ }
713
+ const deadline = Date.now() + timeoutMs;
714
+ const started = createDeferred();
715
+ const completion = getCodexAppServerTurnRouter(client).watchNativeTurnCompletion({
689
716
  threadId: params.threadId,
690
717
  turnId: params.turnId,
691
- timeoutMs
692
- }) : void 0;
693
- await client.request("turn/interrupt", requestParams, { timeoutMs });
694
- return completion ? await completion.completion : true;
718
+ timeoutMs,
719
+ onStarted: () => started.resolve(true)
720
+ });
721
+ cancelWatch = completion.cancel;
722
+ if (completion.state !== "pending") return await completion.completion;
723
+ const requestInterrupt = async () => {
724
+ try {
725
+ await client.request("turn/interrupt", requestParams, {
726
+ timeoutMs: Math.max(1, deadline - Date.now()),
727
+ signal: completion.settledSignal
728
+ });
729
+ return true;
730
+ } catch (error) {
731
+ if (completion.state === "confirmed") return true;
732
+ if (isCodexNoActiveTurnInterruptError(error)) return false;
733
+ throw error;
734
+ }
735
+ };
736
+ if (!await requestInterrupt()) {
737
+ if (await Promise.race([completion.completion.then(() => false), started.promise]) && completion.state === "pending" && Date.now() < deadline) await requestInterrupt();
738
+ }
739
+ return await completion.completion;
695
740
  } catch (error) {
696
- if (isCodexAlreadyTerminalInterruptError(error)) return true;
697
741
  embeddedAgentLog.debug("codex app-server turn interrupt failed during abort", { error });
698
742
  return false;
699
743
  } finally {
700
- completion?.cancel();
744
+ cancelWatch?.();
701
745
  }
702
746
  }
703
747
  /** Stops native terminals on the cancelled thread without retiring peer threads. */
@@ -737,4 +781,4 @@ async function unsubscribeCodexThreadBestEffort(client, params) {
737
781
  }
738
782
  }
739
783
  //#endregion
740
- export { shouldRecordNativeToolTranscript as A, readNonNegativeInteger as B, isSideEffectingNativeToolItem as C, itemTitle as D, itemStatus as E, readHookOutputEntries as F, splitPlanText as H, readItem as I, readItemString as L, extractRawAssistantText as M, normalizeOptionalString$1 as N, matchesCodexSnapshotTurn as O, readCodexErrorNotificationMessage as P, readNonEmptyString as R, isNonSuccessItemStatus as S, itemName as T, readNullableString as V, readCodexNotificationTurnId as _, closeCodexStartupClientBestEffort as a, auditNativeToolUnfinishedStatus as b, isCodexAppServerUnsafeSubscriptionError as c, unsubscribeCodexThreadBestEffort as d, CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS as f, readCodexNotificationThreadId as g, isCodexNotificationForTurn as h, assertCodexThreadResumeSubscription as i, shouldSynthesizeToolProgressForItem as j, shouldClearTerminalPresentationForNativeItem as k, retireUnsafeCodexTurnClientBestEffort as l, CodexProjectionDiagnostics as m, CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS as n, interruptCodexTurnAndWaitBestEffort as o, getCodexAppServerTurnRouter as p, CodexAppServerUnsafeSubscriptionError as r, isCodexAlreadyTerminalInterruptError as s, CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS as t, terminateCodexBackgroundTerminals as u, auditNativeToolName as v, itemKind as w, isMutatingNativeToolItem as x, auditNativeToolTerminalStatus as y, readNonEmptyStringArray as z };
784
+ export { shouldRecordNativeToolTranscript as A, readNonEmptyStringArray as B, isSideEffectingNativeToolItem as C, itemTitle as D, itemStatus as E, readCodexProviderRefusal as F, readNullableString as H, readHookOutputEntries as I, readItem as L, extractRawAssistantText as M, normalizeOptionalString$1 as N, matchesCodexSnapshotTurn as O, readCodexErrorNotificationMessage as P, readItemString as R, isNonSuccessItemStatus as S, itemName as T, splitPlanText as U, readNonNegativeInteger as V, readCodexNotificationTurnId as _, closeCodexStartupClientBestEffort as a, auditNativeToolUnfinishedStatus as b, isCodexNoActiveTurnInterruptError as c, unsubscribeCodexThreadBestEffort as d, CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS as f, readCodexNotificationThreadId as g, isCodexNotificationForTurn as h, assertCodexThreadResumeSubscription as i, shouldSynthesizeToolProgressForItem as j, shouldClearTerminalPresentationForNativeItem as k, retireUnsafeCodexTurnClientBestEffort as l, CodexProjectionDiagnostics as m, CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS as n, interruptCodexTurnAndWaitBestEffort as o, getCodexAppServerTurnRouter as p, CodexAppServerUnsafeSubscriptionError as r, isCodexAppServerUnsafeSubscriptionError as s, CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS as t, terminateCodexBackgroundTerminals as u, auditNativeToolName as v, itemKind as w, isMutatingNativeToolItem as x, auditNativeToolTerminalStatus as y, readNonEmptyString as z };
@@ -1,10 +1,10 @@
1
- import { $t as isJsonObject, Qt as flattenCodexDynamicToolFunctions } from "./shared-client-DxcfF9KX.js";
2
- import { ct as isMessageOnlyCodexSourceReply, et as areCodexDynamicToolFingerprintsCompatible, mt as isContextEngineBindingCompatible } from "./thread-lifecycle-DAcEJ_Om.js";
3
- import { n as readCodexMirroredSessionHistoryMessages } from "./session-history-C5J1AKzG.js";
1
+ import { B as isJsonObject, z as flattenCodexDynamicToolFunctions } from "./config-CyapYSji.js";
2
+ import { ct as isMessageOnlyCodexSourceReply, et as areCodexDynamicToolFingerprintsCompatible, mt as isContextEngineBindingCompatible } from "./thread-lifecycle-DPK30jad.js";
3
+ import { t as readCodexMirroredSessionHistoryMessages } from "./session-history-DWmMqiqW.js";
4
4
  import { readNonBlankString } from "openclaw/plugin-sdk/string-coerce-runtime";
5
+ import { createHash } from "node:crypto";
5
6
  import path from "node:path";
6
7
  import { buildBootstrapContextForFiles, buildWatchedSessionsHarnessContext, embeddedAgentLog, resolveBootstrapFilesForRun } from "openclaw/plugin-sdk/agent-harness-runtime";
7
- import { createHash } from "node:crypto";
8
8
  import { resolveAgentWorkspaceDir } from "openclaw/plugin-sdk/agent-runtime";
9
9
  import { resolveBootstrapFilesForPreparation } from "openclaw/plugin-sdk/codex-mcp-projection";
10
10
  import { prepareMemorySystemPromptAddition } from "openclaw/plugin-sdk/core";
@@ -32,8 +32,8 @@ const CODEX_BOOTSTRAP_CONTEXT_ORDER = /* @__PURE__ */ new Map([
32
32
  ]);
33
33
  /** Reads mirrored Codex session history for harness hooks. */
34
34
  async function readMirroredSessionHistoryMessages(params) {
35
- const { admission, ...target } = params;
36
- const messages = await readCodexMirroredSessionHistoryMessages(target, admission, "model-context");
35
+ const { admission, signal, ...target } = params;
36
+ const messages = await readCodexMirroredSessionHistoryMessages(target, admission, "model-context", signal);
37
37
  if (!messages) embeddedAgentLog.warn("failed to read mirrored session history for codex harness hooks", { sessionFile: params.sessionFile });
38
38
  return messages;
39
39
  }
@@ -1,15 +1,15 @@
1
- import { $t as isJsonObject, at as readCodexTurnCompletedNotification, et as assertCodexThreadStartResponse, ot as createCodexElicitationResponse, rt as readCodexErrorNotification, tt as assertCodexTurnStartResponse, u as isCodexAppServerStartSelectionChangedError } from "./shared-client-DxcfF9KX.js";
2
- import { r as readCodexAppServerConfigOptions } from "./launch-args-RXQwn8zV.js";
3
- import { i as resolveCodexAppServerRuntimeOptions } from "./config-BhmfC1s6.js";
4
- import { _ as readCodexNotificationTurnId, a as closeCodexStartupClientBestEffort, o as interruptCodexTurnAndWaitBestEffort, t as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS } from "./attempt-client-cleanup-DYHcRQAa.js";
5
- import { d as isTerminalTurnStatus, f as readCodexNotificationItem, n as normalizeCodexResponseTokenUsage, u as isRetryableErrorNotification } from "./event-projector-usage-C5mcrGjp.js";
6
- import { r as readModelListResult } from "./models-sYnEc0gd.js";
7
- import { Dt as mergeCodexThreadConfigs, G as attestCodexRestrictedToolSurfaceMcpServersDisabled, _ as buildCodexRingZeroThreadConfigPatch, b as readCodexInheritedMcpServerNames, g as assertCodexManagedRequirementsDoNotOverrideToolPolicy, v as buildCodexRuntimeThreadConfig } from "./thread-lifecycle-DAcEJ_Om.js";
1
+ import { B as isJsonObject, i as resolveCodexAppServerRuntimeOptions } from "./config-CyapYSji.js";
2
+ import { at as readCodexErrorNotification, ct as createCodexElicitationResponse, nt as assertCodexThreadStartResponse, rt as assertCodexTurnStartResponse, st as readCodexTurnCompletedNotification, u as isCodexAppServerStartSelectionChangedError } from "./shared-client-CKhX2kFt.js";
3
+ import { m as readCodexAppServerConfigOptions } from "./managed-binary-DcpnJF9x.js";
4
+ import { _ as readCodexNotificationTurnId, a as closeCodexStartupClientBestEffort, o as interruptCodexTurnAndWaitBestEffort, t as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS } from "./attempt-client-cleanup-Bp1ZOnk2.js";
5
+ import { c as isRetryableErrorNotification, l as isTerminalTurnStatus, t as CodexUsageProjection, u as readCodexNotificationItem } from "./event-projector-usage-ZqEVbAEY.js";
6
+ import { r as readModelListResult } from "./models-CcrgSMQR.js";
7
+ import { Et as mergeCodexThreadConfigs, G as attestCodexRestrictedToolSurfaceMcpServersDisabled, _ as buildCodexRingZeroThreadConfigPatch, b as readCodexInheritedMcpServerNames, g as assertCodexManagedRequirementsDoNotOverrideToolPolicy, v as buildCodexRuntimeThreadConfig } from "./thread-lifecycle-DPK30jad.js";
8
8
  import { readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
9
+ import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
9
10
  import fs from "node:fs/promises";
10
11
  import path from "node:path";
11
12
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
12
- import { resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
13
13
  import { resolvePreferredOpenClawTmpDir, withTempWorkspace } from "openclaw/plugin-sdk/temp-path";
14
14
  //#region extensions/codex/src/app-server/bounded-turn.ts
15
15
  const CODEX_APP_SERVER_ARGS_ENV_KEY = "OPENCLAW_CODEX_APP_SERVER_ARGS";
@@ -39,6 +39,7 @@ var CodexBoundedTurnTimeoutError = class extends Error {
39
39
  }
40
40
  };
41
41
  async function runBoundedCodexAppServerTurn(params) {
42
+ params.assertCurrent?.();
42
43
  const appServer = resolveCodexAppServerRuntimeOptions({
43
44
  pluginConfig: params.options.pluginConfig,
44
45
  managedCommandOrder: params.isolation === "private-stdio" ? "package-first" : void 0
@@ -64,27 +65,23 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
64
65
  const deadline = timing?.deadline ?? Date.now() + totalTimeoutMs;
65
66
  const timeoutMs = deadline - Date.now();
66
67
  if (timeoutMs <= 0) throw timeoutError;
68
+ params.assertCurrent?.();
67
69
  const agentDir = params.agentDir?.trim() || void 0;
68
70
  const startOptions = workspace.codexHome ? buildPrivateCodexAppServerStartOptions(appServer.start, workspace.codexHome) : appServer.start;
69
71
  const ownsClient = !params.options.clientFactory;
70
- const authSelection = params.preparedAuth ? { preparedAuth: params.preparedAuth } : { authProfileId: params.profile };
71
- const client = params.options.clientFactory ? await params.options.clientFactory({
72
+ const clientOptions = {
72
73
  startOptions,
73
- ...authSelection,
74
+ ...params.preparedAuth ? { preparedAuth: params.preparedAuth } : { authProfileId: params.profile },
74
75
  authRequirement: params.authRequirement,
75
76
  agentDir,
76
77
  config: params.config,
77
78
  timeoutMs,
79
+ assertCurrent: params.assertCurrent,
78
80
  ...params.signal ? { abandonSignal: params.signal } : {}
79
- }) : await import("./shared-client-DxcfF9KX.js").then((n) => n.x).then(({ createIsolatedCodexAppServerClient }) => createIsolatedCodexAppServerClient({
80
- startOptions,
81
- timeoutMs,
82
- ...authSelection,
83
- authRequirement: params.authRequirement,
84
- agentDir,
85
- authProfileStore: params.authProfileStore,
86
- config: params.config,
87
- ...params.signal ? { abandonSignal: params.signal } : {}
81
+ };
82
+ const client = params.options.clientFactory ? await params.options.clientFactory(clientOptions) : await import("./shared-client-CKhX2kFt.js").then((n) => n.x).then(({ createIsolatedCodexAppServerClient }) => createIsolatedCodexAppServerClient({
83
+ ...clientOptions,
84
+ authProfileStore: params.authProfileStore
88
85
  }));
89
86
  const abortController = new AbortController();
90
87
  let activeThreadId;
@@ -110,17 +107,23 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
110
107
  const timeout = setTimeout(() => abortRun(timeoutError), Math.max(1, remainingRunMs));
111
108
  timeout.unref?.();
112
109
  let retrySelection = false;
110
+ const requestOptions = {
111
+ timeoutMs,
112
+ signal: abortController.signal,
113
+ assertCurrent: params.assertCurrent
114
+ };
113
115
  try {
116
+ params.assertCurrent?.();
114
117
  const modelSelection = await resolveCodexBoundedTurnModel({
115
118
  client,
116
119
  selection: params.model,
117
120
  requiredModalities: params.requiredModalities,
118
- timeoutMs,
119
- signal: abortController.signal
121
+ ...requestOptions
120
122
  });
121
123
  const inheritedMcpServerNames = params.requireNoExternalCapabilities ? await readCodexInheritedMcpServerNames(client, workspace.cwd, abortController.signal) : [];
122
124
  if (params.requireNoExternalCapabilities) await assertCodexManagedRequirementsDoNotOverrideToolPolicy(client, { restrictedToolSurface: true }, abortController.signal);
123
125
  const threadConfig = buildCodexRuntimeThreadConfig(resolveBoundedThreadConfig(params, workspace, inheritedMcpServerNames), { nativeCodeModeEnabled: false });
126
+ params.assertCurrent?.();
124
127
  const thread = assertCodexThreadStartResponse(await client.request("thread/start", {
125
128
  model: modelSelection.runtimeModelId,
126
129
  ...params.modelProvider ? { modelProvider: params.modelProvider } : {},
@@ -135,20 +138,15 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
135
138
  dynamicTools: [],
136
139
  experimentalRawEvents: true,
137
140
  ephemeral: true
138
- }, {
139
- timeoutMs,
140
- signal: abortController.signal
141
- }));
141
+ }, requestOptions));
142
142
  activeThreadId = thread.thread.id;
143
143
  if (abortController.signal.aborted) requestInterrupt();
144
144
  if (params.requireNoExternalCapabilities) await attestCodexRestrictedToolSurfaceMcpServersDisabled(client, thread.thread.id, threadConfig, abortController.signal);
145
145
  if (params.historyItems?.length) await client.request("thread/inject_items", {
146
146
  threadId: thread.thread.id,
147
147
  items: params.historyItems
148
- }, {
149
- timeoutMs,
150
- signal: abortController.signal
151
- });
148
+ }, requestOptions);
149
+ params.assertCurrent?.();
152
150
  const collector = createCodexBoundedTurnCollector(thread.thread.id, params.taskLabel, params.allowEmptyText === true);
153
151
  const cleanup = client.addNotificationHandler(collector.handleNotification);
154
152
  const requestCleanup = client.addRequestHandler(createCodexBoundedApprovalHandler(params.taskLabel));
@@ -157,20 +155,22 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
157
155
  threadId: thread.thread.id,
158
156
  input: params.input,
159
157
  approvalPolicy: "on-request",
160
- model: modelSelection.runtimeModelId,
161
158
  effort: "low"
162
- }, {
163
- timeoutMs,
164
- signal: abortController.signal
165
- }));
159
+ }, requestOptions));
166
160
  activeTurnId = turn.turn.id;
167
161
  if (abortController.signal.aborted) requestInterrupt();
162
+ const result = await collector.collect(turn.turn, {
163
+ signal: abortController.signal,
164
+ timeoutError
165
+ });
166
+ params.assertCurrent?.();
168
167
  return {
169
- ...await collector.collect(turn.turn, {
170
- signal: abortController.signal,
171
- timeoutError
172
- }),
173
- model: modelSelection.catalogId
168
+ ...result,
169
+ model: modelSelection.catalogId,
170
+ nativeSelection: {
171
+ model: thread.model,
172
+ modelProvider: thread.modelProvider
173
+ }
174
174
  };
175
175
  } finally {
176
176
  await interruptPromise;
@@ -246,7 +246,8 @@ async function resolveCodexBoundedTurnModel(params) {
246
246
  includeHidden: params.selection.mode === "required"
247
247
  }, {
248
248
  timeoutMs: Math.min(params.timeoutMs, 5e3),
249
- signal: params.signal
249
+ signal: params.signal,
250
+ assertCurrent: params.assertCurrent
250
251
  });
251
252
  const listed = readModelListResult(result).models;
252
253
  if (params.selection.mode === "live-default") {
@@ -272,7 +273,7 @@ function createCodexBoundedTurnCollector(threadId, taskLabel, allowEmptyText) {
272
273
  let turnId;
273
274
  let completedTurn;
274
275
  let promptError;
275
- let responseUsage;
276
+ const usageProjection = new CodexUsageProjection();
276
277
  const pending = [];
277
278
  const completedItems = /* @__PURE__ */ new Map();
278
279
  const assistantTextByItem = /* @__PURE__ */ new Map();
@@ -306,8 +307,7 @@ function createCodexBoundedTurnCollector(threadId, taskLabel, allowEmptyText) {
306
307
  return;
307
308
  }
308
309
  if (notification.method === "rawResponse/completed") {
309
- const usage = isJsonObject(params.usage) ? params.usage : void 0;
310
- responseUsage = usage ? normalizeCodexResponseTokenUsage(usage) : void 0;
310
+ usageProjection.record(params);
311
311
  return;
312
312
  }
313
313
  if (notification.method === "turn/completed") {
@@ -316,6 +316,7 @@ function createCodexBoundedTurnCollector(threadId, taskLabel, allowEmptyText) {
316
316
  return;
317
317
  }
318
318
  if (notification.method === "error") {
319
+ usageProjection.invalidateContext();
319
320
  if (isRetryableErrorNotification(notification.params)) return;
320
321
  promptError = readCodexErrorNotification(notification.params)?.error.message ?? `codex app-server ${taskLabel} turn failed`;
321
322
  resolveCompletion();
@@ -344,7 +345,7 @@ function createCodexBoundedTurnCollector(threadId, taskLabel, allowEmptyText) {
344
345
  return {
345
346
  text,
346
347
  items,
347
- ...responseUsage ? { usage: responseUsage } : {}
348
+ usage: usageProjection.usage
348
349
  };
349
350
  }
350
351
  };
@@ -1,4 +1,4 @@
1
- import { q as CodexAppServerRpcError } from "./shared-client-DxcfF9KX.js";
1
+ import { q as CodexAppServerRpcError } from "./shared-client-CKhX2kFt.js";
2
2
  //#region extensions/codex/src/app-server/capabilities.ts
3
3
  /**
4
4
  * Capability helpers for optional Codex app-server control-plane methods.
@@ -17,6 +17,7 @@ const CODEX_CONTROL_METHODS = {
17
17
  listSkills: "skills/list",
18
18
  listThreads: "thread/list",
19
19
  listThreadTurns: "thread/turns/list",
20
+ listThreadItems: "thread/items/list",
20
21
  readThread: "thread/read",
21
22
  rateLimits: "account/rateLimits/read",
22
23
  archiveThread: "thread/archive",
@@ -2,7 +2,7 @@ import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
2
2
  //#region extensions/codex/cli-metadata.ts
3
3
  function registerCodexCliMetadata(api) {
4
4
  api.registerCli(async ({ program }) => {
5
- const { registerCodexSessionCli } = await import("./session-cli-CmFEXMAM.js");
5
+ const { registerCodexSessionCli } = await import("./session-cli-BjLhpmS1.js");
6
6
  registerCodexSessionCli(program);
7
7
  }, { descriptors: [{
8
8
  name: "codex",
@@ -1,5 +1,5 @@
1
- import { $t as isJsonObject } from "./shared-client-DxcfF9KX.js";
2
- import { c as summarizeCodexRateLimits, o as summarizeCodexAccountRateLimits, r as hasCodexRateLimitSnapshots } from "./rate-limits-CawQJfUS.js";
1
+ import { B as isJsonObject } from "./config-CyapYSji.js";
2
+ import { c as summarizeCodexRateLimits, o as summarizeCodexAccountRateLimits, r as hasCodexRateLimitSnapshots } from "./rate-limits-Fx_l4eNa.js";
3
3
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  //#region extensions/codex/src/command-formatters.ts
5
5
  /**