@openclaw/codex 2026.8.1-beta.3 → 2026.8.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 (64) hide show
  1. package/dist/api.js +4 -5
  2. package/dist/{attempt-client-cleanup-URjUlCHg.js → attempt-client-cleanup-CVPvp9dL.js} +47 -5
  3. package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
  4. package/dist/{binding-connection-DAvZwp96.js → binding-connection-CCQFs8lf.js} +2 -2
  5. package/dist/{bounded-turn-4BjrZEwW.js → bounded-turn-rq5tiSXk.js} +13 -18
  6. package/dist/{capabilities-CH3K57v4.js → capabilities-CGm_94eL.js} +1 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-D0nZ3qtd.js → command-formatters-C54Yg3eA.js} +2 -2
  9. package/dist/{command-handlers-DC86lgT4.js → command-handlers-BvOAHTrA.js} +89 -62
  10. package/dist/{compact-COqgBRny.js → compact-Hd7SAc0N.js} +8 -9
  11. package/dist/{config-CpNeo5AE.js → config-Cxw3Cl3k.js} +346 -286
  12. package/dist/doctor-contract-api.js +115 -14
  13. package/dist/{dynamic-tools-fJZhl4CE.js → dynamic-tools-BFoUcRdx.js} +147 -903
  14. package/dist/{effective-mcp-catalog-4YKn51aG.js → effective-mcp-catalog-BTJHnDSx.js} +2 -2
  15. package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
  16. package/dist/{event-projector-usage-CLwNEJqW.js → event-projector-usage-D3PHFFXh.js} +3 -3
  17. package/dist/{harness-DoKQcF8n.js → harness-DVfUQBlQ.js} +42 -52
  18. package/dist/harness.js +1 -1
  19. package/dist/index.js +278 -295
  20. package/dist/{isolated-completion-DPMtlH9r.js → isolated-completion-Cbbx_5Ed.js} +4 -4
  21. package/dist/launch-args-sXOAg0SX.js +84 -0
  22. package/dist/{managed-binary-By4FZC6i.js → managed-binary-ZkGodW19.js} +43 -7
  23. package/dist/media-understanding-provider.js +1 -1
  24. package/dist/model-catalog-o6Cgjoss.js +101 -0
  25. package/dist/{models-CZw1wClT.js → models-DgFWSuxA.js} +25 -28
  26. package/dist/{native-subagent-monitor-GGq3RnOo.js → native-subagent-monitor-CwFyoylz.js} +207 -30
  27. package/dist/{node-exec-server.runtime-Bsu1LdFZ.js → node-exec-server.runtime-DXrqpw1c.js} +8 -5
  28. package/dist/{plugin-approval-roundtrip-C75Yiiwc.js → plugin-approval-roundtrip-D80UZiJ_.js} +1 -1
  29. package/dist/{plugin-marketplace-discovery-CSWDkMrP.js → plugin-marketplace-discovery-mdmScYOj.js} +30 -39
  30. package/dist/{plugin-metadata-cache-BXH5NF-4.js → plugin-metadata-cache-CulOABwu.js} +162 -135
  31. package/dist/{protocol-validators-VAVyEnDp.js → protocol-validators-Bg5rpNxk.js} +148 -5
  32. package/dist/{rate-limits-BI1dMHDG.js → rate-limits-hFtzt2Up.js} +1 -1
  33. package/dist/{sandbox-guard-C1qEeZ5C.js → request-CCm4LaED.js} +183 -2
  34. package/dist/{run-attempt-BV3HzuCf.js → run-attempt-BwNQDH2u.js} +599 -361
  35. package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-DeBvleJw.js} +1 -1
  36. package/dist/{session-binding-BTrLf9Qm.js → session-binding-q2WSTVmC.js} +195 -122
  37. package/dist/{session-catalog-ezP_UcRM.js → session-catalog-C2Tae4rI.js} +229 -122
  38. package/dist/session-catalog-home-id-DAKUrm3C.js +112 -0
  39. package/dist/{session-cli-B1hKvfkI.js → session-cli-BuDjm5Ou.js} +1 -1
  40. package/dist/session-permission-policy-gLm40Vtq.js +160 -0
  41. package/dist/session-retirement-CdkI0bvb.js +90 -0
  42. package/dist/{session-upstream-marker-D_2npHlA.js → session-upstream-marker-Bcy33kam.js} +2 -3
  43. package/dist/{settled-turn-finalizer-Dx1onIqg.js → settled-turn-finalizer-B8JJcxCi.js} +7 -6
  44. package/dist/{shared-client-Dw-rzii0.js → shared-client-kNkljY-R.js} +1720 -786
  45. package/dist/{side-question-DbXkJZzg.js → side-question-GwD73tX6.js} +69 -39
  46. package/dist/{thread-lifecycle-DKdrnTMX.js → thread-lifecycle-Ss-uwnC4.js} +852 -359
  47. package/dist/{thread-ownership-i2NBwDUL.js → thread-ownership-CeYBqg_4.js} +18 -8
  48. package/dist/{plugin-app-cache-key-DMNQ8Zi8.js → thread-resume-DF54hagX.js} +52 -6
  49. package/dist/{transcript-mirror-BU0_LKAL.js → transcript-mirror-CkEQIna-.js} +112 -13
  50. package/dist/transport-stdio-C7-s9TLG.js +708 -0
  51. package/dist/{upstream-session-fork-BDVJCLAD.js → upstream-session-fork-BACGlOFa.js} +78 -86
  52. package/dist/{usage-9dKJCgcy.js → usage-C2l8Mils.js} +3 -3
  53. package/dist/{web-search-provider.runtime-DCdx4DGu.js → web-search-provider.runtime-B2XgRdFv.js} +3 -3
  54. package/openclaw.plugin.json +19 -1
  55. package/package.json +8 -8
  56. package/dist/app-server-policy-bg5QPSVP.js +0 -25
  57. package/dist/command-rpc-xUIIonsO.js +0 -90
  58. package/dist/incognito-session-ET_ufDH-.js +0 -2
  59. package/dist/model-catalog-CmGoqVKB.js +0 -48
  60. package/dist/request-DSK0W6YI.js +0 -157
  61. package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
  62. package/dist/session-retirement-CE4iMiLh.js +0 -36
  63. package/dist/thread-resume-CdJk2Ehf.js +0 -30
  64. package/dist/transport-stdio-DhoGy33Z.js +0 -99
package/dist/api.js CHANGED
@@ -1,12 +1,11 @@
1
- import { a as resolveCodexAppServerStartOptionsForAgent, i as resolveCodexAppServerRuntimeOptions } from "./config-CpNeo5AE.js";
2
- import { a as CODEX_APP_SERVER_VERSION, n as resolveManagedCodexAppServerStartOptions, r as resolveManagedCodexNativeCommand, t as isManagedCodexDesktopCommand } from "./managed-binary-By4FZC6i.js";
1
+ import { a as resolveCodexAppServerStartOptionsForAgent, i as resolveCodexAppServerRuntimeOptions } from "./config-Cxw3Cl3k.js";
2
+ import { a as CODEX_APP_SERVER_VERSION, n as resolveManagedCodexAppServerStartOptions, r as resolveManagedCodexNativeCommand, t as isManagedCodexDesktopCommand } from "./managed-binary-ZkGodW19.js";
3
3
  import path from "node:path";
4
4
  import { resolveDefaultModelForAgent } from "openclaw/plugin-sdk/agent-runtime";
5
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";
9
- import { getHealthCheck } from "openclaw/plugin-sdk/health";
10
9
  //#region extensions/codex/src/doctor.ts
11
10
  const CODEX_MANAGED_APP_SERVER_CHECK_ID = "codex/managed-app-server";
12
11
  const CODEX_VERSION_TIMEOUT_MS = 5e3;
@@ -117,7 +116,7 @@ function createCodexManagedAppServerHealthCheck(params) {
117
116
  })];
118
117
  }
119
118
  const detectedVersion = parseCodexVersion(`${output.stdout}\n${output.stderr}`);
120
- if (detectedVersion !== "0.149.1") return [managedCodexFinding({
119
+ if (detectedVersion !== "0.151.0") return [managedCodexFinding({
121
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}.`,
122
121
  path: nativeCommand,
123
122
  requirement: `the exact OpenClaw-pinned Codex version ${CODEX_APP_SERVER_VERSION}`,
@@ -128,7 +127,7 @@ function createCodexManagedAppServerHealthCheck(params) {
128
127
  };
129
128
  }
130
129
  function registerCodexManagedAppServerDoctorChecks$1(host, deps) {
131
- if (getHealthCheck("codex/managed-app-server")) return;
130
+ if (host.getHealthCheck("codex/managed-app-server")) return;
132
131
  host.registerHealthCheck(createCodexManagedAppServerHealthCheck({
133
132
  pluginRoot: host.pluginRoot,
134
133
  deps
@@ -1,4 +1,4 @@
1
- import { B as CodexAppServerRpcError, X as unsubscribeCodexAppServerLiveThread, p as retireSharedCodexAppServerClientIfCurrent, ut as isJsonObject } from "./shared-client-Dw-rzii0.js";
1
+ import { $ as CodexAppServerRpcError, Ht as isJsonObject, wt as unsubscribeCodexAppServerLiveThread, y as retireSharedCodexAppServerClientIfCurrent } from "./shared-client-kNkljY-R.js";
2
2
  import { asFiniteNumber, normalizeOptionalString, normalizeOptionalString as normalizeOptionalString$1, readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
3
3
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
4
4
  import { embeddedAgentLog } from "openclaw/plugin-sdk/agent-harness-runtime";
@@ -259,6 +259,7 @@ var CodexProjectionDiagnostics = class {
259
259
  //#region extensions/codex/src/app-server/turn-router.ts
260
260
  /** Keyed routing for all turn traffic on one shared Codex app-server client. */
261
261
  const DEFAULT_PREBIND_NOTIFICATION_LIMIT = 256;
262
+ const DEFAULT_GLOBAL_WARNING_LIMIT = 32;
262
263
  const CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS = 3e4;
263
264
  const routers = /* @__PURE__ */ new WeakMap();
264
265
  /** Returns the sole router installed on a physical app-server client. */
@@ -272,6 +273,7 @@ function getCodexAppServerTurnRouter(client) {
272
273
  var ClientTurnRouter = class {
273
274
  constructor(client) {
274
275
  this.routes = /* @__PURE__ */ new Map();
276
+ this.globalWarnings = [];
275
277
  this.nativeTurnCompletionWatchers = /* @__PURE__ */ new Map();
276
278
  this.disposed = false;
277
279
  client.addNotificationHandler((notification) => this.routeNotification(notification));
@@ -290,7 +292,11 @@ var ClientTurnRouter = class {
290
292
  ended: createDeferred(),
291
293
  activated: createDeferred(),
292
294
  gate: "open",
293
- pending: [],
295
+ pending: this.globalWarnings.map((notification) => ({
296
+ notification,
297
+ receivedAtMs: Date.now(),
298
+ scope: { threadId }
299
+ })),
294
300
  notificationTail: Promise.resolve(),
295
301
  completedNativeTurnIds: /* @__PURE__ */ new Set(),
296
302
  ignoredTurnNotificationKeys: /* @__PURE__ */ new Set()
@@ -412,6 +418,15 @@ var ClientTurnRouter = class {
412
418
  routeNotification(notification) {
413
419
  if (this.disposed) return;
414
420
  const scope = readScope(notification.params);
421
+ if (!scope.threadId && (notification.method === "configWarning" || notification.method === "warning")) {
422
+ if (this.globalWarnings.length === DEFAULT_GLOBAL_WARNING_LIMIT) this.globalWarnings.shift();
423
+ this.globalWarnings.push(notification);
424
+ for (const route of this.routes.values()) {
425
+ this.bufferNotification(route, notification, { threadId: route.threadId }, Date.now());
426
+ if (route.gate === "bound") this.flushNotifications(route);
427
+ }
428
+ return Promise.all([...this.routes.values()].map((route) => route.notificationTail)).then(() => void 0);
429
+ }
415
430
  const watchers = scope.threadId ? this.nativeTurnCompletionWatchers.get(scope.threadId) : void 0;
416
431
  const route = scope.threadId ? this.routes.get(scope.threadId) : void 0;
417
432
  if (!watchers && !route) return;
@@ -489,6 +504,10 @@ var ClientTurnRouter = class {
489
504
  const handler = route.handlers?.onNotification;
490
505
  if (!handler) return;
491
506
  for (const pending of route.pending.splice(0)) {
507
+ if (route.gate !== "bound" && (pending.notification.method === "configWarning" || pending.notification.method === "warning" && !readScope(pending.notification.params).threadId)) {
508
+ route.pending.push(pending);
509
+ continue;
510
+ }
492
511
  if (route.gate === "bound" && pending.scope.turnId && pending.scope.turnId !== route.turnId) {
493
512
  this.warnDroppedStaleTurnNotification(route, pending.notification, pending.scope);
494
513
  continue;
@@ -541,7 +560,7 @@ var ClientTurnRouter = class {
541
560
  await Promise.race([route.notificationTail, route.ended.promise]);
542
561
  }
543
562
  async drainNotifications(route) {
544
- await route.notificationTail;
563
+ await Promise.race([route.notificationTail, route.ended.promise]);
545
564
  }
546
565
  release(route, error = /* @__PURE__ */ new Error("codex app-server thread route is released")) {
547
566
  if (route.released) return;
@@ -677,12 +696,35 @@ async function interruptCodexTurnAndWaitBestEffort(client, params) {
677
696
  completion?.cancel();
678
697
  }
679
698
  }
699
+ /** Stops native terminals on the cancelled thread without retiring peer threads. */
700
+ async function terminateCodexBackgroundTerminals(client, threadId) {
701
+ const options = {
702
+ timeoutMs: CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS,
703
+ signal: AbortSignal.timeout(CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS)
704
+ };
705
+ try {
706
+ const { data } = await client.request("thread/backgroundTerminals/list", { threadId }, options);
707
+ for (const { processId } of data) await client.request("thread/backgroundTerminals/terminate", {
708
+ threadId,
709
+ processId
710
+ }, options);
711
+ if (data.length > 0) {
712
+ if ((await client.request("thread/backgroundTerminals/list", {
713
+ threadId,
714
+ limit: 1
715
+ }, options)).data.length > 0) throw new Error("native background terminals remain running");
716
+ }
717
+ } catch (cause) {
718
+ throw new Error("Codex background-terminal cleanup failed; inspect the thread's running terminals before starting more work.", { cause });
719
+ }
720
+ }
680
721
  /** Unsubscribes from a thread while swallowing cleanup-only failures. */
681
722
  async function unsubscribeCodexThreadBestEffort(client, params) {
682
723
  try {
683
- await unsubscribeCodexAppServerLiveThread(client, params.threadId, params.timeoutMs);
724
+ await unsubscribeCodexAppServerLiveThread(client, params.threadId, params.timeoutMs, params.assertCurrent);
684
725
  return true;
685
726
  } catch (error) {
727
+ params.assertCurrent?.();
686
728
  embeddedAgentLog.debug("codex app-server thread unsubscribe cleanup failed", {
687
729
  threadId: params.threadId,
688
730
  error
@@ -732,4 +774,4 @@ async function retireCodexAppServerClientAfterTimedOutTurn(client, params) {
732
774
  });
733
775
  }
734
776
  //#endregion
735
- export { shouldSynthesizeToolProgressForItem as A, readNullableString as B, isSideEffectingNativeToolItem as C, itemTitle as D, itemStatus as E, readItem as F, readItemString as I, readNonEmptyString as L, normalizeOptionalString$1 as M, readCodexErrorNotificationMessage as N, shouldClearTerminalPresentationForNativeItem as O, readHookOutputEntries as P, readNonEmptyStringArray as R, isNonSuccessItemStatus as S, itemName as T, splitPlanText 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, extractRawAssistantText as j, shouldRecordNativeToolTranscript as k, retireCodexAppServerClientAfterTimedOutTurn 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, retireUnsafeCodexTurnClientBestEffort as u, auditNativeToolName as v, itemKind as w, isMutatingNativeToolItem as x, auditNativeToolTerminalStatus as y, readNonNegativeInteger as z };
777
+ export { shouldRecordNativeToolTranscript as A, readNonNegativeInteger as B, isNonSuccessItemStatus as C, itemStatus as D, itemName as E, readHookOutputEntries as F, splitPlanText as H, readItem as I, readItemString as L, extractRawAssistantText as M, normalizeOptionalString$1 as N, itemTitle as O, readCodexErrorNotificationMessage as P, readNonEmptyString as R, isMutatingNativeToolItem as S, itemKind as T, readNullableString as V, readCodexNotificationThreadId as _, closeCodexStartupClientBestEffort as a, auditNativeToolTerminalStatus as b, isCodexAppServerUnsafeSubscriptionError as c, terminateCodexBackgroundTerminals as d, unsubscribeCodexThreadBestEffort as f, isCodexNotificationForTurn as g, CodexProjectionDiagnostics as h, assertCodexThreadResumeSubscription as i, shouldSynthesizeToolProgressForItem as j, shouldClearTerminalPresentationForNativeItem as k, retireCodexAppServerClientAfterTimedOutTurn as l, getCodexAppServerTurnRouter as m, CODEX_APP_SERVER_UNSUBSCRIBE_TIMEOUT_MS as n, interruptCodexTurnAndWaitBestEffort as o, CODEX_APP_SERVER_NATIVE_TURN_WAIT_TIMEOUT_MS as p, CodexAppServerUnsafeSubscriptionError as r, isCodexAlreadyTerminalInterruptError as s, CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS as t, retireUnsafeCodexTurnClientBestEffort as u, readCodexNotificationTurnId as v, isSideEffectingNativeToolItem as w, auditNativeToolUnfinishedStatus as x, auditNativeToolName as y, readNonEmptyStringArray as z };
@@ -1,6 +1,7 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-8H4AJuhK.js";
2
2
  import { fingerprintResolvedAuthProfileCredential } from "openclaw/plugin-sdk/agent-harness-runtime";
3
3
  import { resolveApiKeyForProfile } from "openclaw/plugin-sdk/agent-runtime";
4
+ import { resolveOpenAICodexAuthIdentity } from "openclaw/plugin-sdk/provider-auth";
4
5
  //#region extensions/codex/src/app-server/auth-binding.ts
5
6
  var auth_binding_exports = /* @__PURE__ */ __exportAll({
6
7
  fingerprintCodexAppServerAuthBinding: () => fingerprintCodexAppServerAuthBinding,
@@ -26,14 +27,28 @@ function withMaterializedCredential(params) {
26
27
  /** Resolves one forwarded profile once so attestation and execution share exact material. */
27
28
  async function prepareCodexAppServerAuthBinding(params) {
28
29
  const credential = params.authProfileStore.profiles[params.authProfileId];
29
- if (!credential || credential.type === "oauth") return;
30
+ if (!credential) return;
31
+ if (credential.type === "oauth") {
32
+ const fingerprint = fingerprintResolvedAuthProfileCredential({
33
+ profileId: params.authProfileId,
34
+ credential: {
35
+ ...credential,
36
+ accountId: resolveOpenAICodexAuthIdentity(credential).accountId
37
+ },
38
+ resolvedAuth: void 0
39
+ });
40
+ return fingerprint ? {
41
+ fingerprint,
42
+ authProfileStore: structuredClone(params.authProfileStore)
43
+ } : void 0;
44
+ }
30
45
  const resolved = await resolveApiKeyForProfile({
31
46
  cfg: params.config,
32
47
  store: params.authProfileStore,
33
48
  profileId: params.authProfileId,
34
49
  agentDir: params.agentDir
35
50
  });
36
- if (!resolved?.apiKey) throw new Error(`Codex could not resolve auth profile "${params.authProfileId}".`);
51
+ if (!resolved?.apiKey) throw new Error(`Codex could not resolve auth profile "${params.authProfileId}". Repair or replace its credential or SecretRef, then retry.`);
37
52
  const fingerprint = fingerprintResolvedAuthProfileCredential({
38
53
  profileId: params.authProfileId,
39
54
  credential,
@@ -44,7 +59,7 @@ async function prepareCodexAppServerAuthBinding(params) {
44
59
  mode: credential.type === "api_key" ? "api-key" : "token"
45
60
  }
46
61
  });
47
- if (!fingerprint) throw new Error(`Codex could not attest auth profile "${params.authProfileId}".`);
62
+ if (!fingerprint) throw new Error(`Codex could not attest auth profile "${params.authProfileId}". Re-select the OpenAI profile and retry.`);
48
63
  return {
49
64
  fingerprint,
50
65
  authProfileStore: withMaterializedCredential({
@@ -1,5 +1,5 @@
1
- import { h as readCodexPluginConfig, i as resolveCodexAppServerRuntimeOptions, s as resolveCodexSupervisionAppServerRuntimeOptions } from "./config-CpNeo5AE.js";
2
- import { a as resolveCodexCatalogConnectionHome, t as buildCodexAppServerConnectionFingerprint } from "./plugin-app-cache-key-DMNQ8Zi8.js";
1
+ import { T as readCodexPluginConfig, i as resolveCodexAppServerRuntimeOptions, s as resolveCodexSupervisionAppServerRuntimeOptions } from "./config-Cxw3Cl3k.js";
2
+ import { n as buildCodexAppServerConnectionFingerprint, o as resolveCodexCatalogConnectionHome } from "./thread-resume-DF54hagX.js";
3
3
  //#region extensions/codex/src/app-server/binding-connection.ts
4
4
  /** Requires the native model pair after a supervised pending branch has materialized. */
5
5
  function requireCodexSupervisionModelSelection(binding) {
@@ -1,10 +1,11 @@
1
- import { i as resolveCodexAppServerRuntimeOptions } from "./config-CpNeo5AE.js";
2
- import { V as createCodexElicitationResponse, s as isCodexAppServerStartSelectionChangedError, ut as isJsonObject } from "./shared-client-Dw-rzii0.js";
3
- import { _ as readCodexNotificationTurnId, a as closeCodexStartupClientBestEffort, o as interruptCodexTurnAndWaitBestEffort, t as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS } from "./attempt-client-cleanup-URjUlCHg.js";
4
- import { b as isTerminalTurnStatus, n as normalizeCodexResponseTokenUsage, x as readCodexNotificationItem, y as isRetryableErrorNotification } from "./event-projector-usage-CLwNEJqW.js";
5
- import { a as assertCodexThreadStartResponse, c as readCodexErrorNotification, o as assertCodexTurnStartResponse, u as readCodexTurnCompletedNotification } from "./protocol-validators-VAVyEnDp.js";
6
- import { r as readModelListResult } from "./models-CZw1wClT.js";
7
- import { Z as mergeCodexThreadConfigs, c as buildCodexRingZeroThreadConfigPatch, l as buildCodexRuntimeThreadConfig, o as assertCodexManagedRequirementsDoNotOverrideToolPolicy, s as attestCodexRestrictedToolSurfaceMcpServersDisabled, u as readCodexInheritedMcpServerNames } from "./thread-lifecycle-DKdrnTMX.js";
1
+ import { n as readCodexAppServerConfigOptions } from "./launch-args-sXOAg0SX.js";
2
+ import { i as resolveCodexAppServerRuntimeOptions } from "./config-Cxw3Cl3k.js";
3
+ import { Ht as isJsonObject, et as createCodexElicitationResponse, u as isCodexAppServerStartSelectionChangedError } from "./shared-client-kNkljY-R.js";
4
+ import { c as assertCodexTurnStartResponse, f as readCodexTurnCompletedNotification, s as assertCodexThreadStartResponse, u as readCodexErrorNotification } from "./protocol-validators-Bg5rpNxk.js";
5
+ import { a as closeCodexStartupClientBestEffort, o as interruptCodexTurnAndWaitBestEffort, t as CODEX_APP_SERVER_INTERRUPT_TIMEOUT_MS, v as readCodexNotificationTurnId } from "./attempt-client-cleanup-CVPvp9dL.js";
6
+ import { b as isTerminalTurnStatus, n as normalizeCodexResponseTokenUsage, x as readCodexNotificationItem, y as isRetryableErrorNotification } from "./event-projector-usage-D3PHFFXh.js";
7
+ import { r as readModelListResult } from "./models-DgFWSuxA.js";
8
+ import { _ as buildCodexRingZeroThreadConfigPatch, g as attestCodexRestrictedToolSurfaceMcpServersDisabled, h as assertCodexManagedRequirementsDoNotOverrideToolPolicy, ot as mergeCodexThreadConfigs, v as buildCodexRuntimeThreadConfig, y as readCodexInheritedMcpServerNames } from "./thread-lifecycle-Ss-uwnC4.js";
8
9
  import { readStringField } from "openclaw/plugin-sdk/string-coerce-runtime";
9
10
  import fs from "node:fs/promises";
10
11
  import path from "node:path";
@@ -65,11 +66,7 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
65
66
  const timeoutMs = deadline - Date.now();
66
67
  if (timeoutMs <= 0) throw timeoutError;
67
68
  const agentDir = params.agentDir?.trim() || void 0;
68
- const isolatedStartOptions = workspace.codexHome ? buildPrivateCodexAppServerStartOptions(appServer.start, workspace.codexHome) : appServer.start;
69
- const startOptions = workspace.codexHome && params.preparedAuth ? {
70
- ...isolatedStartOptions,
71
- homeScope: "agent"
72
- } : isolatedStartOptions;
69
+ const startOptions = workspace.codexHome ? buildPrivateCodexAppServerStartOptions(appServer.start, workspace.codexHome) : appServer.start;
73
70
  const ownsClient = !params.options.clientFactory;
74
71
  const authSelection = params.preparedAuth ? { preparedAuth: params.preparedAuth } : { authProfileId: params.profile };
75
72
  const client = params.options.clientFactory ? await params.options.clientFactory({
@@ -80,7 +77,7 @@ async function runBoundedCodexAppServerTurnInWorkspace(params, appServer, worksp
80
77
  config: params.config,
81
78
  timeoutMs,
82
79
  ...params.signal ? { abandonSignal: params.signal } : {}
83
- }) : await import("./shared-client-Dw-rzii0.js").then((n) => n.m).then(({ createIsolatedCodexAppServerClient }) => createIsolatedCodexAppServerClient({
80
+ }) : await import("./shared-client-kNkljY-R.js").then((n) => n.x).then(({ createIsolatedCodexAppServerClient }) => createIsolatedCodexAppServerClient({
84
81
  startOptions,
85
82
  timeoutMs,
86
83
  ...authSelection,
@@ -204,10 +201,7 @@ function resolveBoundedThreadConfig(params, workspace, inheritedMcpServerNames)
204
201
  return mergeCodexThreadConfigs(privateConfig, CODEX_SETTLED_FINALIZER_THREAD_CONFIG, buildCodexRingZeroThreadConfigPatch({ toolsAllow: ["openclaw"] }, true, inheritedMcpServerNames)) ?? privateConfig;
205
202
  }
206
203
  function buildPrivateCodexAppServerStartOptions(start, codexHome) {
207
- const providerArgs = start.args.flatMap((arg, index) => {
208
- const override = arg === "-c" || arg === "--config" ? start.args[index + 1] : arg.startsWith("--config=") ? arg.slice(9) : void 0;
209
- return override && /^\s*(?:openai_base_url|model_catalog_json)\s*=/u.test(override) ? ["-c", override] : [];
210
- });
204
+ const providerArgs = readCodexAppServerConfigOptions(start.args).flatMap(({ name, value }) => (name === "-c" || name === "--config") && value && /^\s*(?:openai_base_url|model_catalog_json)\s*=/u.test(value) ? ["-c", value] : []);
211
205
  const privateEnv = Object.fromEntries(Object.entries(start.env ?? {}).filter(([name]) => name.trim().toUpperCase() !== CODEX_APP_SERVER_ARGS_ENV_KEY));
212
206
  const clearEnv = (start.clearEnv ?? []).filter((name) => {
213
207
  const normalized = name.trim().toUpperCase();
@@ -215,6 +209,7 @@ function buildPrivateCodexAppServerStartOptions(start, codexHome) {
215
209
  });
216
210
  return {
217
211
  ...start,
212
+ homeScope: "agent",
218
213
  args: [
219
214
  "app-server",
220
215
  ...providerArgs,
@@ -249,7 +244,7 @@ async function resolveCodexBoundedTurnModel(params) {
249
244
  const listed = readModelListResult(await params.client.request("model/list", {
250
245
  limit: null,
251
246
  cursor: null,
252
- includeHidden: false
247
+ includeHidden: params.selection.mode === "required"
253
248
  }, {
254
249
  timeoutMs: Math.min(params.timeoutMs, 5e3),
255
250
  signal: params.signal
@@ -1,4 +1,4 @@
1
- import { B as CodexAppServerRpcError } from "./shared-client-Dw-rzii0.js";
1
+ import { $ as CodexAppServerRpcError } from "./shared-client-kNkljY-R.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.
@@ -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-B1hKvfkI.js");
5
+ const { registerCodexSessionCli } = await import("./session-cli-BuDjm5Ou.js");
6
6
  registerCodexSessionCli(program);
7
7
  }, { descriptors: [{
8
8
  name: "codex",
@@ -1,5 +1,5 @@
1
- import { ut as isJsonObject } from "./shared-client-Dw-rzii0.js";
2
- import { c as summarizeCodexRateLimits, o as summarizeCodexAccountRateLimits, r as hasCodexRateLimitSnapshots } from "./rate-limits-BI1dMHDG.js";
1
+ import { Ht as isJsonObject } from "./shared-client-kNkljY-R.js";
2
+ import { c as summarizeCodexRateLimits, o as summarizeCodexAccountRateLimits, r as hasCodexRateLimitSnapshots } from "./rate-limits-hFtzt2Up.js";
3
3
  import { normalizeOptionalString } from "openclaw/plugin-sdk/string-coerce-runtime";
4
4
  //#region extensions/codex/src/command-formatters.ts
5
5
  /**
@@ -1,26 +1,26 @@
1
- import { M as isCodexFastServiceTier, _ as CODEX_PLUGINS_MARKETPLACE_NAME, i as resolveCodexAppServerRuntimeOptions } from "./config-CpNeo5AE.js";
2
- import { U as consumeCodexAppServerLiveThread, a as getLeasedSharedCodexAppServerClient, et as resolveCodexAppServerAuthAccountCacheKey, l as releaseLeasedSharedCodexAppServerClient, nt as resolveCodexAppServerAuthProfileIdForAgent, rt as resolveCodexAppServerFallbackApiKeyCacheKey, ut as isJsonObject } from "./shared-client-Dw-rzii0.js";
3
- import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, i as createCodexSessionGenerationSupersededError, n as assertCodexBindingMayBeReplaced, r as bindingStoreKey, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-BTrLf9Qm.js";
4
- import { i as assertCodexThreadResumeResponse } from "./protocol-validators-VAVyEnDp.js";
5
- import { t as listAllCodexAppServerModels } from "./models-CZw1wClT.js";
6
- import { o as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-DMNQ8Zi8.js";
7
- import { et as refreshCodexPluginRuntimeState, nt as isOpenAiCuratedMarketplaceName } from "./thread-lifecycle-DKdrnTMX.js";
8
- import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
9
- import { t as CODEX_CONTROL_METHODS } from "./capabilities-CH3K57v4.js";
10
- import { s as summarizeCodexAccountUsage } from "./rate-limits-BI1dMHDG.js";
11
- import { a as formatComputerUseStatus, c as formatSkills, i as formatCodexStatus, l as formatThreads, n as formatAccount, o as formatList, r as formatCodexDisplayText, s as formatModels, t as buildHelp } from "./command-formatters-D0nZ3qtd.js";
12
- import { n as resolveCodexNativeExecutionBlock, r as resolveCodexNativeSandboxBlock } from "./sandbox-guard-C1qEeZ5C.js";
13
- import { a as rollbackCodexAppServerBindingSubscription, i as retireCodexConversationThreadBinding, n as releaseCodexAppServerBindingSubscription, o as withCodexConversationThreadActivity, r as retainCodexAppServerBindingSubscription, s as withExclusiveCodexAppServerThread, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-i2NBwDUL.js";
14
- import { a as parseCodexPermissionsModeArg, c as setCodexConversationModel, d as stopCodexConversationTurn, g as hasCodexAdminScope, h as canMutateCodexHost, i as parseCodexFastModeArg, l as setCodexConversationPermissions, m as CODEX_NATIVE_EXECUTION_AUTH_ERROR, n as parseCodexPluginMarketplaceId, o as readCodexConversationActiveTurn, p as CODEX_FULL_PERMISSIONS_AUTH_ERROR, r as formatPermissionsMode, s as setCodexConversationFastMode, t as discoverCodexMarketplacePlugins, u as steerCodexConversationTurn } from "./plugin-marketplace-discovery-CSWDkMrP.js";
1
+ import { i as resolveCodexAppServerRuntimeOptions, j as CODEX_PLUGINS_MARKETPLACE_NAME, k as isCodexFastServiceTier } from "./config-Cxw3Cl3k.js";
2
+ import { Ft as resolveCodexAppServerFallbackApiKeyCacheKey, Ht as isJsonObject, Nt as resolveCodexAppServerAuthProfileIdForAgent, c as getLeasedSharedCodexAppServerClient, gt as consumeCodexAppServerLiveThread, h as releaseLeasedSharedCodexAppServerClient, jt as resolveCodexAppServerAuthAccountCacheKey, vt as hasCodexAppServerLiveThread } from "./shared-client-kNkljY-R.js";
3
+ import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, i as createCodexSessionGenerationSupersededError, n as assertCodexBindingMayBeReplaced, r as bindingStoreKey, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-q2WSTVmC.js";
4
+ import { o as assertCodexThreadResumeResponse, r as assertCodexThreadAcceptsDirectInput } from "./protocol-validators-Bg5rpNxk.js";
5
+ import { a as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-CVPvp9dL.js";
6
+ import { t as listAllCodexAppServerModels } from "./models-DgFWSuxA.js";
7
+ import { i as buildCodexPluginAppCacheKey, s as defaultCodexAppInventoryCache } from "./thread-resume-DF54hagX.js";
8
+ import { dt as isOpenAiCuratedMarketplaceName, lt as refreshCodexPluginRuntimeState } from "./thread-lifecycle-Ss-uwnC4.js";
9
+ import { a as rollbackCodexAppServerBindingSubscription, c as withExclusiveCodexAppServerThread, i as retireCodexConversationThreadBinding, l as isIncognitoSessionKey, n as releaseCodexAppServerBindingSubscription, r as retainCodexAppServerBindingSubscription, s as withCodexConversationThreadActivity, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-CeYBqg_4.js";
10
+ import { c as resolveCodexNativeSandboxBlock, s as resolveCodexNativeExecutionBlock } from "./request-CCm4LaED.js";
11
+ import { t as CODEX_CONTROL_METHODS } from "./capabilities-CGm_94eL.js";
12
+ import { s as summarizeCodexAccountUsage } from "./rate-limits-hFtzt2Up.js";
13
+ import { a as formatComputerUseStatus, c as formatSkills, i as formatCodexStatus, l as formatThreads, n as formatAccount, o as formatList, r as formatCodexDisplayText, s as formatModels, t as buildHelp } from "./command-formatters-C54Yg3eA.js";
14
+ import { _ as hasCodexAdminScope, a as parseCodexPermissionsModeArg, c as setCodexConversationModel, d as stopCodexConversationTurn, g as canMutateCodexHost, h as CODEX_NATIVE_EXECUTION_AUTH_ERROR, i as parseCodexFastModeArg, l as setCodexConversationPermissions, m as CODEX_HOST_INSPECTION_AUTH_ERROR, n as parseCodexPluginMarketplaceId, o as readCodexConversationActiveTurn, p as CODEX_FULL_PERMISSIONS_AUTH_ERROR, r as formatPermissionsMode, s as setCodexConversationFastMode, t as discoverCodexMarketplacePlugins, u as steerCodexConversationTurn } from "./plugin-marketplace-discovery-mdmScYOj.js";
15
15
  import { i as readCodexConversationBindingData, n as createCodexCliNodeConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-CW2GuupV.js";
16
- import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-DAvZwp96.js";
17
- import { l as formatCodexCliSessions } from "./session-catalog-ezP_UcRM.js";
18
- import { i as safeCodexControlRequest, n as readCodexStatusProbes, r as requestOptions, t as codexControlRequest } from "./command-rpc-xUIIonsO.js";
19
- import { i as readCodexComputerUseStatus, r as installCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-BXH5NF-4.js";
16
+ import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-CCQFs8lf.js";
17
+ import { c as readCodexStatusProbes, l as requestOptions, p as formatCodexCliSessions, s as codexControlRequest, u as safeCodexControlRequest } from "./session-catalog-C2Tae4rI.js";
18
+ import { i as readCodexComputerUseStatus, r as installCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-CulOABwu.js";
20
19
  import { normalizeOptionalString, normalizeUniqueStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
21
20
  import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
22
21
  import crypto from "node:crypto";
23
- import { ensureAuthProfileStore, findNormalizedProviderValue, resolveAgentDir, resolveAuthProfileEligibility, resolveAuthProfileOrder, resolveProfileUnusableUntilForDisplay, resolveSessionAgentIds } from "openclaw/plugin-sdk/agent-runtime";
22
+ import { ensureAuthProfileStore, findNormalizedProviderValue, resolveAgentDir, resolveAuthProfileEligibility, resolveAuthProfileOrder, resolveProfileUnusableUntilForDisplay } from "openclaw/plugin-sdk/agent-runtime";
23
+ import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
24
24
  import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
25
25
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
26
26
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
@@ -51,8 +51,8 @@ async function readCodexAccountAuthOverview(params) {
51
51
  limits: params.limits,
52
52
  now
53
53
  });
54
- const subscriptionProfileId = order.find((profileId) => isChatGptSubscriptionProfile(store.profiles[profileId]));
55
54
  const activeIsSubscription = activeProfileId !== void 0 && isChatGptSubscriptionProfile(store.profiles[activeProfileId]);
55
+ const subscriptionProfileId = activeIsSubscription ? activeProfileId : order.find((profileId) => isChatGptSubscriptionProfile(store.profiles[profileId]));
56
56
  const activeUsage = activeIsSubscription && params.limits.ok ? summarizeCodexAccountUsage(params.limits.value, now) : void 0;
57
57
  const subscriptionUsage = subscriptionProfileId && (!activeIsSubscription || subscriptionProfileId !== activeProfileId) ? await readSubscriptionUsage({
58
58
  ...params,
@@ -157,13 +157,20 @@ function resolveLiveAccountProfileId(params) {
157
157
  const type = normalizeOptionalString(account.type)?.toLowerCase();
158
158
  if (type === "chatgpt") {
159
159
  const email = normalizeOptionalString(account.email)?.toLowerCase();
160
- const firstSubscription = params.order.find((profileId) => isChatGptSubscriptionProfile(params.store.profiles[profileId]));
161
- if (!email) return firstSubscription;
162
- return params.order.find((profileId) => {
163
- const credential = params.store.profiles[profileId];
164
- if (!credential || !isChatGptSubscriptionProfile(credential)) return false;
165
- return (credential.email?.trim().toLowerCase() ?? extractEmailFromProfileId(profileId))?.toLowerCase() === email;
166
- }) ?? firstSubscription;
160
+ const accountId = normalizeOptionalString(account.accountId ?? account.chatgptAccountId);
161
+ const subscriptionProfiles = params.order.filter((profileId) => isChatGptSubscriptionProfile(params.store.profiles[profileId]));
162
+ if (accountId) {
163
+ const exactWorkspace = subscriptionProfiles.find((profileId) => {
164
+ const credential = params.store.profiles[profileId];
165
+ return credential && "accountId" in credential && credential.accountId === accountId;
166
+ });
167
+ if (exactWorkspace) return exactWorkspace;
168
+ }
169
+ const matchingProfiles = email ? subscriptionProfiles.filter((profileId) => {
170
+ return (params.store.profiles[profileId]?.email?.trim().toLowerCase() ?? extractEmailFromProfileId(profileId))?.toLowerCase() === email;
171
+ }) : subscriptionProfiles;
172
+ const lastGood = params.store.lastGood?.[OPENAI_PROVIDER_ID];
173
+ return (lastGood && matchingProfiles.includes(lastGood) ? lastGood : void 0) ?? matchingProfiles[0] ?? subscriptionProfiles[0];
167
174
  }
168
175
  if (type === "apikey" || type === "api_key") return params.order.find((profileId) => params.store.profiles[profileId]?.type === "api_key");
169
176
  }
@@ -1105,7 +1112,7 @@ function conversationBindingIdentity(bindingId) {
1105
1112
  };
1106
1113
  }
1107
1114
  function resolveCodexConversationControlScope(ctx) {
1108
- const { sessionAgentId } = resolveSessionAgentIds({
1115
+ const { sessionAgentId } = resolveSessionAgentIdsStrict({
1109
1116
  sessionKey: ctx.sessionKey,
1110
1117
  agentId: ctx.agentId,
1111
1118
  config: ctx.config
@@ -1556,13 +1563,8 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1556
1563
  })) throw createCodexSessionGenerationSupersededError(identity.sessionId);
1557
1564
  const currentBinding = await deps.bindingStore.read(identity);
1558
1565
  assertCodexBindingMayBeReplaced(currentBinding, "attaching a different resumed thread");
1559
- const authProfileId = resolveCodexAppServerAuthProfileIdForAgent({
1560
- authProfileId: currentBinding?.authProfileId,
1561
- agentDir: scope.agentDir,
1562
- config: ctx.config
1563
- });
1564
- let committedResponse = false;
1565
- const commitResumedThread = async (value, client) => {
1566
+ let pendingResumeConfiguration = false;
1567
+ const commitResumedThread = async (value, client, { authProfileId, assertCurrent }) => {
1566
1568
  const response = assertCodexThreadResumeResponse(value);
1567
1569
  const effectiveThreadId = response.thread.id;
1568
1570
  if (effectiveThreadId !== normalizedThreadId) throw new Error(`Codex thread/resume returned ${effectiveThreadId} for ${normalizedThreadId}`);
@@ -1574,52 +1576,73 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1574
1576
  agentDir: scope.agentDir,
1575
1577
  config: ctx.config
1576
1578
  });
1577
- const bindingBeforeCommit = await deps.bindingStore.read(identity);
1578
- assertCodexBindingMayBeReplaced(bindingBeforeCommit, "committing a different resumed thread");
1579
- const clientId = client?.getInstanceId();
1580
- const sameOwner = client ? isSameCodexAppServerThreadOwner(bindingBeforeCommit, {
1581
- threadId: effectiveThreadId,
1582
- clientId
1583
- }) : bindingBeforeCommit?.threadId === effectiveThreadId;
1579
+ const clientId = client.getInstanceId();
1584
1580
  let retained = false;
1581
+ let sameOwner = false;
1582
+ let knownOwnership;
1585
1583
  try {
1586
- if (client) {
1587
- retained = await retainCodexAppServerBindingSubscription(client, effectiveThreadId, sameOwner ? await consumeCodexAppServerLiveThread(client, effectiveThreadId) : void 0);
1588
- if (!retained) throw new Error("Codex resumed thread lost its native subscription owner.");
1589
- }
1584
+ const bindingBeforeCommit = await deps.bindingStore.read(identity);
1585
+ assertCodexBindingMayBeReplaced(bindingBeforeCommit, "committing a different resumed thread");
1586
+ sameOwner = isSameCodexAppServerThreadOwner(bindingBeforeCommit, {
1587
+ threadId: effectiveThreadId,
1588
+ clientId
1589
+ });
1590
+ const sameThreadBinding = bindingBeforeCommit?.threadId === effectiveThreadId ? bindingBeforeCommit : void 0;
1591
+ pendingResumeConfiguration = sameThreadBinding?.preserveNativeModel !== true && (!sameThreadBinding?.dynamicToolsFingerprint || !sameThreadBinding.webSearchThreadConfigFingerprint || sameThreadBinding.pendingResumeConfiguration === true);
1592
+ assertCurrent();
1593
+ assertCodexThreadAcceptsDirectInput(response.thread);
1594
+ knownOwnership = sameOwner ? await consumeCodexAppServerLiveThread(client, effectiveThreadId) : void 0;
1595
+ assertCurrent();
1596
+ retained = await retainCodexAppServerBindingSubscription(client, effectiveThreadId, knownOwnership);
1597
+ assertCurrent();
1598
+ if (!retained) throw new Error("Codex resumed thread lost its native subscription owner.");
1590
1599
  if (bindingBeforeCommit && !sameOwner) await releaseCodexAppServerBindingSubscription(bindingBeforeCommit);
1600
+ assertCurrent();
1591
1601
  if (!await deps.bindingStore.mutate(identity, {
1592
1602
  kind: "set",
1593
1603
  binding: {
1594
- ...bindingBeforeCommit?.threadId === effectiveThreadId ? bindingBeforeCommit : {},
1604
+ ...sameThreadBinding,
1595
1605
  threadId: effectiveThreadId,
1596
- ...clientId ? { clientId } : {},
1606
+ clientId,
1597
1607
  cwd: resumedCwd,
1608
+ rolloutPath: response.thread.path ?? sameThreadBinding?.rolloutPath,
1609
+ pendingResumeConfiguration: pendingResumeConfiguration ? true : void 0,
1598
1610
  authProfileId,
1599
1611
  model: response.model,
1600
1612
  modelProvider,
1601
1613
  historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString()
1602
1614
  }
1603
- })) throw new Error("Codex thread binding changed while attaching the resumed thread.");
1615
+ }, assertCurrent)) throw new Error("Codex thread binding changed while attaching the resumed thread.");
1604
1616
  } catch (error) {
1605
- if (client && !sameOwner) await rollbackCodexAppServerBindingSubscription(client, effectiveThreadId, retained);
1617
+ if (sameOwner && knownOwnership && !retained) {
1618
+ if (!await retainCodexAppServerBindingSubscription(client, effectiveThreadId, knownOwnership)) await closeCodexStartupClientBestEffort(client);
1619
+ } else if (retained && !sameOwner || !hasCodexAppServerLiveThread(client, effectiveThreadId)) await rollbackCodexAppServerBindingSubscription(client, effectiveThreadId, retained);
1606
1620
  throw error;
1607
1621
  }
1608
- committedResponse = true;
1609
1622
  };
1610
- const response = await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.resumeThread, {
1623
+ await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.resumeThread, {
1611
1624
  threadId: normalizedThreadId,
1612
1625
  excludeTurns: true
1613
1626
  }, {
1614
1627
  config: ctx.config,
1628
+ agentId: scope.agentId,
1615
1629
  agentDir: scope.agentDir,
1616
- authProfileId,
1630
+ authProfileId: currentBinding?.authProfileId,
1617
1631
  sessionKey: ctx.sessionKey,
1618
1632
  sessionId: ctx.sessionId,
1633
+ beforeRequest: async (request) => {
1634
+ const { thread } = await request({
1635
+ method: "thread/read",
1636
+ requestParams: {
1637
+ threadId: normalizedThreadId,
1638
+ includeTurns: false
1639
+ }
1640
+ });
1641
+ assertCodexThreadAcceptsDirectInput(thread);
1642
+ },
1619
1643
  onResponse: commitResumedThread
1620
1644
  });
1621
- if (!committedResponse) await commitResumedThread(response);
1622
- return `Attached this OpenClaw session to Codex thread ${formatCodexDisplayText(normalizedThreadId)}.`;
1645
+ return `Attached this OpenClaw session to Codex thread ${formatCodexDisplayText(normalizedThreadId)}.${pendingResumeConfiguration ? " The next turn will validate its tools and apply this session's configuration before continuing." : ""}`;
1623
1646
  })
1624
1647
  });
1625
1648
  }
@@ -1834,7 +1857,7 @@ async function setConversationModel(deps, ctx, pluginConfig, args) {
1834
1857
  }) : void 0;
1835
1858
  const selectedModel = currentSession && currentSession.sessionId === ctx.sessionId ? currentSession.modelOverride ?? currentSession.model : void 0;
1836
1859
  const binding = await deps.bindingStore.read(target.identity);
1837
- const activeModel = selectedModel ?? binding?.model;
1860
+ const activeModel = target.identity.kind === "conversation" ? binding?.model : selectedModel ?? binding?.model;
1838
1861
  return activeModel ? `Codex model: ${formatCodexDisplayText(activeModel)}` : "Usage: /codex model <model>";
1839
1862
  }
1840
1863
  return await deps.setCodexConversationModel({
@@ -1843,12 +1866,7 @@ async function setConversationModel(deps, ctx, pluginConfig, args) {
1843
1866
  pluginConfig,
1844
1867
  model: normalized,
1845
1868
  agentDir: target.agentDir,
1846
- config: ctx.config,
1847
- ...ctx.sessionId && ctx.sessionKey ? { session: {
1848
- agentId: target.agentId,
1849
- sessionId: ctx.sessionId,
1850
- sessionKey: ctx.sessionKey
1851
- } } : {}
1869
+ config: ctx.config
1852
1870
  });
1853
1871
  }
1854
1872
  async function setConversationFastMode(deps, ctx, args) {
@@ -2293,6 +2311,14 @@ function formatPluginList(plugins, options = {}) {
2293
2311
  }
2294
2312
  //#endregion
2295
2313
  //#region extensions/codex/src/command-handlers.ts
2314
+ const CODEX_HOST_INSPECTION_SUBCOMMANDS = /* @__PURE__ */ new Set([
2315
+ "account",
2316
+ "mcp",
2317
+ "sessions",
2318
+ "skills",
2319
+ "status",
2320
+ "threads"
2321
+ ]);
2296
2322
  async function handleCodexSubcommand(ctx, options) {
2297
2323
  const deps = resolveCodexCommandDeps(options.deps);
2298
2324
  const args = splitArgs(ctx.args);
@@ -2300,6 +2326,7 @@ async function handleCodexSubcommand(ctx, options) {
2300
2326
  const [subcommand = "status", ...rest] = args;
2301
2327
  const normalized = subcommand.toLowerCase();
2302
2328
  if (normalized === "help") return { text: buildHelp() };
2329
+ if (CODEX_HOST_INSPECTION_SUBCOMMANDS.has(normalized) && !canMutateCodexHost(ctx)) return { text: CODEX_HOST_INSPECTION_AUTH_ERROR };
2303
2330
  if (CODEX_NATIVE_CONTROL_SUBCOMMANDS.has(normalized) && !returnsBeforeNativeCodexExecution(normalized, rest) && !isReadOnlyCodexGoalCommand(normalized, rest) && !canMutateCodexHost(ctx)) return { text: CODEX_NATIVE_EXECUTION_AUTH_ERROR };
2304
2331
  const sandboxBlock = resolveCodexNativeCommandSandboxBlock(ctx, normalized, rest);
2305
2332
  if (sandboxBlock) return { text: sandboxBlock };
@@ -1,12 +1,11 @@
1
- import { B as CodexAppServerRpcError, U as consumeCodexAppServerLiveThread, Y as retainCodexAppServerLiveThread, a as getLeasedSharedCodexAppServerClient, l as releaseLeasedSharedCodexAppServerClient, ut as isJsonObject } from "./shared-client-Dw-rzii0.js";
2
- import { d as sessionBindingIdentity, t as CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS } from "./session-binding-BTrLf9Qm.js";
3
- import { _ as readCodexNotificationTurnId, a as closeCodexStartupClientBestEffort, d as unsubscribeCodexThreadBestEffort, g as readCodexNotificationThreadId, r as CodexAppServerUnsafeSubscriptionError, s as isCodexAlreadyTerminalInterruptError } from "./attempt-client-cleanup-URjUlCHg.js";
4
- import { i as readCodexThreadContextSnapshot, x as readCodexNotificationItem } from "./event-projector-usage-CLwNEJqW.js";
5
- import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
6
- import { t as resumeCodexAppServerThread } from "./thread-resume-CdJk2Ehf.js";
7
- import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-C1qEeZ5C.js";
8
- import { t as isSameCodexAppServerThreadOwner } from "./thread-ownership-i2NBwDUL.js";
9
- import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-DAvZwp96.js";
1
+ import { $ as CodexAppServerRpcError, Ct as retainCodexAppServerLiveThread, Ht as isJsonObject, c as getLeasedSharedCodexAppServerClient, gt as consumeCodexAppServerLiveThread, h as releaseLeasedSharedCodexAppServerClient } from "./shared-client-kNkljY-R.js";
2
+ import { d as sessionBindingIdentity, t as CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS } from "./session-binding-q2WSTVmC.js";
3
+ import { _ as readCodexNotificationThreadId, a as closeCodexStartupClientBestEffort, f as unsubscribeCodexThreadBestEffort, r as CodexAppServerUnsafeSubscriptionError, s as isCodexAlreadyTerminalInterruptError, v as readCodexNotificationTurnId } from "./attempt-client-cleanup-CVPvp9dL.js";
4
+ import { i as readCodexThreadContextSnapshot, x as readCodexNotificationItem } from "./event-projector-usage-D3PHFFXh.js";
5
+ import { t as resumeCodexAppServerThread } from "./thread-resume-DF54hagX.js";
6
+ import { l as isIncognitoSessionKey, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-CeYBqg_4.js";
7
+ import { s as resolveCodexNativeExecutionBlock } from "./request-CCm4LaED.js";
8
+ import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-CCQFs8lf.js";
10
9
  import { t as persistCodexContextCompactionActivity } from "./context-compaction-activity-BOeJf7yo.js";
11
10
  import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
12
11
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";