@openclaw/codex 2026.7.1-beta.6 → 2026.7.2-beta.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 (46) hide show
  1. package/README.md +27 -3
  2. package/dist/app-server-policy-DVcxdse_.js +49 -0
  3. package/dist/{attempt-notifications-BGsEIIDI.js → attempt-notifications-DEv9h7iC.js} +1 -1
  4. package/dist/auth-binding-C1czuHPA.js +62 -0
  5. package/dist/capabilities-42Dfn2TV.js +33 -0
  6. package/dist/cli-metadata.js +20 -0
  7. package/dist/{app-server-policy-C968Kgin.js → command-formatters-D6ZlGNmb.js} +8 -51
  8. package/dist/{command-handlers-Dv-pzAmg.js → command-handlers-Cpl9fUWv.js} +163 -60
  9. package/dist/{compact-4mVBriKT.js → compact-FnJmiPNA.js} +40 -10
  10. package/dist/computer-use-DVzr8OP1.js +685 -0
  11. package/dist/{config-CYEDnLJ2.js → config-c48K5HP9.js} +200 -29
  12. package/dist/conversation-control-DtQ-E7mr.js +288 -0
  13. package/dist/doctor-contract-api.js +120 -81
  14. package/dist/{provider-capabilities-CDnHbmUZ.js → dynamic-tools-BMLoaTeG.js} +5246 -5140
  15. package/dist/harness.js +55 -15
  16. package/dist/index.js +1435 -265
  17. package/dist/{media-understanding-provider-BHOu9-Gg.js → media-understanding-provider-D580L0P8.js} +28 -10
  18. package/dist/media-understanding-provider.js +1 -1
  19. package/dist/{models-DDmO1zwd.js → models-DuKzZA6G.js} +1 -1
  20. package/dist/notification-correlation-DfaCm0mx.js +67 -0
  21. package/dist/plugin-app-cache-key-BKNjHMEs.js +315 -0
  22. package/dist/{protocol-2POPqAY4.js → protocol-BMifTfdW.js} +3 -1
  23. package/dist/provider-catalog.js +66 -27
  24. package/dist/provider.js +306 -1
  25. package/dist/{provider-zjPfx5Fs.js → rate-limits-Dhp04Rqo.js} +4 -261
  26. package/dist/request-DborTWgw.js +111 -0
  27. package/dist/{run-attempt-FUyOjGCV.js → run-attempt-VPVJoYDP.js} +7897 -7136
  28. package/dist/runtime-artifact-C2ITXdhM.js +488 -0
  29. package/dist/{sandbox-guard-DA2TQfZW.js → sandbox-guard-D1Wky__S.js} +10 -1
  30. package/dist/{session-binding-C1ZXdP-x.js → session-binding-BMfX1OX-.js} +247 -88
  31. package/dist/session-catalog-7H112Tr_.js +2396 -0
  32. package/dist/session-cli-B28RhCyp.js +175 -0
  33. package/dist/{shared-client-4ICy3U6d.js → shared-client-D4mFI9al.js} +1997 -1297
  34. package/dist/{side-question-N4OaDer2.js → side-question-CgJBz52s.js} +135 -67
  35. package/dist/{thread-lifecycle-qWE88Dn2.js → thread-lifecycle-BgLXzjvV.js} +747 -317
  36. package/dist/transcript-mirror-DhLwFIL4.js +485 -0
  37. package/dist/transport-stdio-DXgGZ7Ib.js +88 -0
  38. package/dist/{web-search-provider.runtime-BSlriav6.js → web-search-provider.runtime-Bs-eTn5U.js} +3 -3
  39. package/npm-shrinkwrap.json +56 -30
  40. package/openclaw.plugin.json +168 -10
  41. package/package.json +8 -6
  42. package/dist/command-rpc-eLM_mtC7.js +0 -784
  43. package/dist/computer-use-Bmaz333N.js +0 -377
  44. package/dist/notification-correlation-Bo7KB3ks.js +0 -35
  45. package/dist/plugin-app-cache-key-BrhVdeEf.js +0 -98
  46. package/dist/request-BcJyl8KL.js +0 -36
@@ -1,27 +1,34 @@
1
- import { r as isJsonObject } from "./protocol-2POPqAY4.js";
2
- import { o as isCodexFastServiceTier } from "./config-CYEDnLJ2.js";
1
+ import { i as isJsonObject } from "./protocol-BMifTfdW.js";
2
+ import { c as isCodexFastServiceTier } from "./config-c48K5HP9.js";
3
3
  import { n as assertCodexThreadResumeResponse } from "./protocol-validators-dZQ-UTOa.js";
4
- import { t as listAllCodexAppServerModels } from "./models-DDmO1zwd.js";
5
- import { p as summarizeCodexAccountUsage } from "./provider-zjPfx5Fs.js";
6
- import { y as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-4ICy3U6d.js";
7
- import { a as normalizeCodexAppServerBindingModelProvider, n as bindingStoreKey, o as reclaimCurrentCodexSessionGeneration, s as sessionBindingIdentity } from "./session-binding-C1ZXdP-x.js";
8
- import { r as CODEX_CONTROL_METHODS } from "./plugin-app-cache-key-BrhVdeEf.js";
9
- import { a as formatCodexDisplayText, c as formatList, d as formatThreads, f as readString$1, i as formatAccount, l as formatModels, o as formatCodexStatus, r as buildHelp, s as formatComputerUseStatus, u as formatSkills } from "./app-server-policy-C968Kgin.js";
10
- import { n as resolveCodexNativeExecutionBlock, r as resolveCodexNativeSandboxBlock } from "./sandbox-guard-DA2TQfZW.js";
11
- import { S as canMutateCodexHost, _ as setCodexConversationPermissions, d as formatPermissionsMode, f as parseCodexFastModeArg, g as setCodexConversationModel, h as setCodexConversationFastMode, i as safeCodexControlRequest, m as readCodexConversationActiveTurn, n as readCodexStatusProbes, p as parseCodexPermissionsModeArg, r as requestOptions, s as formatCodexCliSessions, t as codexControlRequest, v as steerCodexConversationTurn, x as CODEX_NATIVE_EXECUTION_AUTH_ERROR, y as stopCodexConversationTurn } from "./command-rpc-eLM_mtC7.js";
4
+ import { t as listAllCodexAppServerModels } from "./models-DuKzZA6G.js";
5
+ import { S as resolveCodexAppServerAuthProfileIdForAgent } from "./shared-client-D4mFI9al.js";
6
+ import { c as sessionBindingIdentity, n as assertCodexBindingMayBeReplaced, o as normalizeCodexAppServerBindingModelProvider, r as bindingStoreKey, s as reclaimCurrentCodexSessionGeneration } from "./session-binding-BMfX1OX-.js";
7
+ import { s as summarizeCodexAccountUsage } from "./rate-limits-Dhp04Rqo.js";
8
+ import { t as CODEX_CONTROL_METHODS } from "./capabilities-42Dfn2TV.js";
9
+ 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, u as readString$1 } from "./command-formatters-D6ZlGNmb.js";
10
+ import { n as resolveCodexNativeExecutionBlock, r as resolveCodexNativeSandboxBlock } from "./sandbox-guard-D1Wky__S.js";
11
+ import { a as setCodexConversationFastMode, c as steerCodexConversationTurn, d as CODEX_NATIVE_EXECUTION_AUTH_ERROR, f as canMutateCodexHost, i as readCodexConversationActiveTurn, l as stopCodexConversationTurn, n as parseCodexFastModeArg, o as setCodexConversationModel, r as parseCodexPermissionsModeArg, s as setCodexConversationPermissions, t as formatPermissionsMode } from "./conversation-control-DtQ-E7mr.js";
12
12
  import { i as readCodexConversationBindingData, n as createCodexCliNodeConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-BHRpYbX3.js";
13
- import { n as installCodexComputerUse, r as readCodexComputerUseStatus } from "./computer-use-Bmaz333N.js";
13
+ import { a as resolveCodexBindingAppServerConnection } from "./notification-correlation-DfaCm0mx.js";
14
+ import { c as requestOptions, l as safeCodexControlRequest, o as codexControlRequest, p as formatCodexCliSessions, s as readCodexStatusProbes } from "./session-catalog-7H112Tr_.js";
15
+ import { i as readCodexComputerUseStatus, n as installCodexComputerUse } from "./computer-use-DVzr8OP1.js";
14
16
  import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
17
+ import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
15
18
  import crypto from "node:crypto";
16
- import { ensureAuthProfileStore, findNormalizedProviderValue, resolveAgentDir, resolveAuthProfileEligibility, resolveAuthProfileOrder, resolveDefaultAgentDir, resolveProfileUnusableUntilForDisplay, resolveSessionAgentIds } from "openclaw/plugin-sdk/agent-runtime";
19
+ import { ensureAuthProfileStore, findNormalizedProviderValue, resolveAgentDir, resolveAuthProfileEligibility, resolveAuthProfileOrder, resolveProfileUnusableUntilForDisplay, resolveSessionAgentIds } from "openclaw/plugin-sdk/agent-runtime";
17
20
  import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
18
21
  import { normalizeOptionalString, normalizeUniqueStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
22
+ import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
23
+ import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
24
+ import { MODEL_SELECTION_LOCKED_MESSAGE, isModelSelectionLocked } from "openclaw/plugin-sdk/model-session-runtime";
19
25
  //#region extensions/codex/src/command-account.ts
20
26
  const OPENAI_PROVIDER_ID = "openai";
21
27
  const OPENAI_CODEX_PROVIDER_ID = OPENAI_PROVIDER_ID;
22
28
  async function readCodexAccountAuthOverview(params) {
23
29
  const config = params.ctx.config;
24
- const store = ensureAuthProfileStore(resolveDefaultAgentDir(config), {
30
+ const agentDir = params.agentDir;
31
+ const store = ensureAuthProfileStore(agentDir, {
25
32
  allowKeychainPrompt: false,
26
33
  config
27
34
  });
@@ -45,6 +52,7 @@ async function readCodexAccountAuthOverview(params) {
45
52
  const activeUsage = activeIsSubscription && params.limits.ok ? summarizeCodexAccountUsage(params.limits.value, now) : void 0;
46
53
  const subscriptionUsage = subscriptionProfileId && (!activeIsSubscription || subscriptionProfileId !== activeProfileId) ? await readSubscriptionUsage({
47
54
  ...params,
55
+ agentDir,
48
56
  config,
49
57
  subscriptionProfileId,
50
58
  now
@@ -149,7 +157,7 @@ function resolveLiveAccountProfileId(params) {
149
157
  if (!email) return firstSubscription;
150
158
  return params.order.find((profileId) => {
151
159
  const credential = params.store.profiles[profileId];
152
- if (!isChatGptSubscriptionProfile(credential)) return false;
160
+ if (!credential || !isChatGptSubscriptionProfile(credential)) return false;
153
161
  return (credential.email?.trim().toLowerCase() ?? extractEmailFromProfileId(profileId))?.toLowerCase() === email;
154
162
  }) ?? firstSubscription;
155
163
  }
@@ -161,6 +169,7 @@ function shouldInferApiKeyActiveFromRateLimitProbe(limits) {
161
169
  async function readSubscriptionUsage(params) {
162
170
  const limits = await params.safeCodexControlRequest(params.pluginConfig, CODEX_CONTROL_METHODS.rateLimits, void 0, {
163
171
  config: params.config,
172
+ agentDir: params.agentDir,
164
173
  authProfileId: params.subscriptionProfileId,
165
174
  isolated: true
166
175
  });
@@ -308,6 +317,21 @@ function formatRelativeReset(untilMs, nowMs) {
308
317
  return `in ${days} ${days === 1 ? "day" : "days"}`;
309
318
  }
310
319
  //#endregion
320
+ //#region extensions/codex/src/command-diagnostics-state.ts
321
+ /** Runtime state for diagnostics upload throttling and confirmation handshakes. */
322
+ const codexDiagnosticsFeedbackState = {
323
+ lastUploadByThread: /* @__PURE__ */ new Map(),
324
+ lastUploadByScope: /* @__PURE__ */ new Map(),
325
+ pendingConfirmations: /* @__PURE__ */ new Map(),
326
+ pendingTokensByScope: /* @__PURE__ */ new Map(),
327
+ clear() {
328
+ this.lastUploadByThread.clear();
329
+ this.lastUploadByScope.clear();
330
+ this.pendingConfirmations.clear();
331
+ this.pendingTokensByScope.clear();
332
+ }
333
+ };
334
+ //#endregion
311
335
  //#region extensions/codex/src/command-presentation.ts
312
336
  function buildCodexCommandPickerPresentation(title, prompt, buttons) {
313
337
  return {
@@ -526,10 +550,7 @@ const CODEX_NATIVE_CONTROL_SUBCOMMANDS = /* @__PURE__ */ new Set([
526
550
  "unbind",
527
551
  "stop"
528
552
  ]);
529
- const lastCodexDiagnosticsUploadByThread = /* @__PURE__ */ new Map();
530
- const lastCodexDiagnosticsUploadByScope = /* @__PURE__ */ new Map();
531
- const pendingCodexDiagnosticsConfirmations = /* @__PURE__ */ new Map();
532
- const pendingCodexDiagnosticsConfirmationTokensByScope = /* @__PURE__ */ new Map();
553
+ const { lastUploadByThread: lastCodexDiagnosticsUploadByThread, lastUploadByScope: lastCodexDiagnosticsUploadByScope, pendingConfirmations: pendingCodexDiagnosticsConfirmations, pendingTokensByScope: pendingCodexDiagnosticsConfirmationTokensByScope } = codexDiagnosticsFeedbackState;
533
554
  /**
534
555
  * No-arg `/codex` picker. Codex owns the command tree; channels render the
535
556
  * portable command actions as inline controls when their transport can.
@@ -672,11 +693,13 @@ async function handleCodexSubcommand(ctx, options) {
672
693
  }
673
694
  if (normalized === "status") {
674
695
  if (rest.length > 0) return { text: "Usage: /codex status" };
675
- return { text: formatCodexStatus(await deps.readCodexStatusProbes(options.pluginConfig, ctx.config)) };
696
+ const { agentDir } = resolveCodexConversationControlScope(ctx);
697
+ return { text: formatCodexStatus(await deps.readCodexStatusProbes(options.pluginConfig, ctx.config, agentDir)) };
676
698
  }
677
699
  if (normalized === "models") {
678
700
  if (rest.length > 0) return { text: "Usage: /codex models" };
679
- return { text: formatModels(await deps.listCodexAppServerModels(deps.requestOptions(options.pluginConfig, 100, ctx.config))) };
701
+ const { agentDir } = resolveCodexConversationControlScope(ctx);
702
+ return { text: formatModels(await deps.listCodexAppServerModels(deps.requestOptions(options.pluginConfig, 100, ctx.config, agentDir))) };
680
703
  }
681
704
  if (normalized === "threads") return { text: await buildThreads(deps, ctx, options.pluginConfig, rest.join(" ")) };
682
705
  if (normalized === "sessions") return { text: await buildCodexCliSessions(deps, rest) };
@@ -713,7 +736,7 @@ async function handleCodexSubcommand(ctx, options) {
713
736
  }
714
737
  if (normalized === "mcp") {
715
738
  if (rest.length > 0) return { text: "Usage: /codex mcp" };
716
- const scope = await resolveCommandAppServerScope(deps, ctx);
739
+ const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
717
740
  return { text: formatList(await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.listMcpServers, { limit: 100 }, {
718
741
  config: ctx.config,
719
742
  ...scope
@@ -721,7 +744,7 @@ async function handleCodexSubcommand(ctx, options) {
721
744
  }
722
745
  if (normalized === "skills") {
723
746
  if (rest.length > 0) return { text: "Usage: /codex skills" };
724
- const scope = await resolveCommandAppServerScope(deps, ctx);
747
+ const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
725
748
  return { text: formatSkills(await deps.codexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.listSkills, {}, {
726
749
  config: ctx.config,
727
750
  ...scope
@@ -729,7 +752,7 @@ async function handleCodexSubcommand(ctx, options) {
729
752
  }
730
753
  if (normalized === "account") {
731
754
  if (rest.length > 0) return { text: "Usage: /codex account" };
732
- const scope = await resolveCommandAppServerScope(deps, ctx);
755
+ const scope = await resolveCommandAppServerScope(deps, ctx, options.pluginConfig);
733
756
  const requestScope = {
734
757
  config: ctx.config,
735
758
  ...scope
@@ -737,6 +760,7 @@ async function handleCodexSubcommand(ctx, options) {
737
760
  const [account, limits] = await Promise.all([deps.safeCodexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.account, { refreshToken: false }, requestScope), deps.safeCodexControlRequest(options.pluginConfig, CODEX_CONTROL_METHODS.rateLimits, void 0, requestScope)]);
738
761
  return { text: formatAccount(account, limits, await readCodexAccountAuthOverview({
739
762
  ctx,
763
+ agentDir: scope.agentDir,
740
764
  pluginConfig: options.pluginConfig,
741
765
  safeCodexControlRequest: deps.safeCodexControlRequest,
742
766
  account,
@@ -745,6 +769,16 @@ async function handleCodexSubcommand(ctx, options) {
745
769
  }
746
770
  return { text: `Unknown Codex command: ${formatCodexDisplayText(subcommand)}\n\n${buildHelp()}` };
747
771
  }
772
+ function isCurrentSessionModelSelectionLocked(ctx) {
773
+ const sessionKey = ctx.sessionKey?.trim();
774
+ if (!sessionKey) return false;
775
+ return isModelSelectionLocked(getSessionEntry({
776
+ storePath: resolveStorePath(ctx.config.session?.store, { agentId: ctx.agentId }),
777
+ sessionKey,
778
+ hydrateSkillPromptRefs: false,
779
+ readConsistency: "latest"
780
+ }));
781
+ }
748
782
  function resolveCodexNativeCommandSandboxBlock(ctx, subcommand, args) {
749
783
  if (!CODEX_NATIVE_EXECUTION_SUBCOMMANDS.has(subcommand)) return;
750
784
  if (returnsBeforeNativeCodexExecution(subcommand, args)) return;
@@ -793,9 +827,13 @@ function returnsBeforeNativeCodexResume(args) {
793
827
  async function handleComputerUseCommand(deps, ctx, pluginConfig, args) {
794
828
  const parsed = parseComputerUseArgs(args);
795
829
  if (parsed.help) return ["Usage: /codex computer-use [status|install] [--source <marketplace-source>] [--marketplace-path <path>] [--marketplace <name>]", "Checks or installs the configured Codex Computer Use plugin through app-server."].join("\n");
830
+ if (Object.keys(parsed.persistentIdentity).length > 0) return formatComputerUsePersistentIdentityMigration(parsed);
796
831
  if (parsed.action === "install" && !canMutateCodexHost(ctx)) return "Only an owner or operator.admin gateway client can configure Codex Computer Use.";
832
+ const { agentDir } = resolveCodexConversationControlScope(ctx);
797
833
  const params = {
798
834
  pluginConfig,
835
+ config: ctx.config,
836
+ agentDir,
799
837
  forceEnable: parsed.action === "install" || parsed.hasOverrides,
800
838
  ...Object.keys(parsed.overrides).length > 0 ? { overrides: parsed.overrides } : {}
801
839
  };
@@ -805,6 +843,7 @@ async function handleComputerUseCommand(deps, ctx, pluginConfig, args) {
805
843
  async function bindConversation(deps, ctx, pluginConfig, args) {
806
844
  const parsed = parseBindArgs(args);
807
845
  if (parsed.help) return { text: "Usage: /codex bind [thread-id] [--cwd <path>] [--model <model>] [--provider <provider>]" };
846
+ if (isCurrentSessionModelSelectionLocked(ctx)) return { text: MODEL_SELECTION_LOCKED_MESSAGE };
808
847
  const scope = resolveCodexConversationControlScope(ctx);
809
848
  const workspaceDir = parsed.cwd ?? deps.resolveCodexDefaultWorkspaceDir(pluginConfig);
810
849
  const currentConversation = await ctx.getCurrentConversationBinding();
@@ -818,6 +857,7 @@ async function bindConversation(deps, ctx, pluginConfig, args) {
818
857
  }) : void 0;
819
858
  const currentOwner = currentConversationData?.kind === "codex-app-server-session" ? conversationBindingIdentity(currentConversationData.bindingId) : sessionOwner;
820
859
  const existingBinding = currentOwner ? await deps.bindingStore.read(currentOwner) : void 0;
860
+ assertCodexBindingMayBeReplaced(existingBinding, "binding this conversation to another thread");
821
861
  const sessionSource = sessionOwner && existingBinding ? {
822
862
  agentId: sessionOwner.agentId,
823
863
  sessionId: sessionOwner.sessionId,
@@ -850,7 +890,9 @@ async function bindConversation(deps, ctx, pluginConfig, args) {
850
890
  return { text: `Bound this conversation to ${formatCodexDisplayText(threadLabel)} in ${formatCodexDisplayText(workspaceDir)}. The next message will initialize it.` };
851
891
  }
852
892
  async function detachConversation(deps, ctx) {
893
+ if (isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
853
894
  const data = readCodexConversationBindingData(await ctx.getCurrentConversationBinding());
895
+ if (data?.kind === "codex-app-server-session") assertCodexBindingMayBeReplaced(await deps.bindingStore.read(conversationBindingIdentity(data.bindingId)), "detaching its conversation binding");
854
896
  const detached = await ctx.detachConversationBinding();
855
897
  if (data?.kind === "codex-app-server-session") await deps.bindingStore.mutate(conversationBindingIdentity(data.bindingId), { kind: "clear" });
856
898
  return detached.removed ? "Detached this conversation from Codex." : "No Codex conversation binding was attached.";
@@ -882,7 +924,7 @@ async function describeConversationBinding(deps, ctx) {
882
924
  ].join("\n");
883
925
  }
884
926
  async function buildThreads(deps, ctx, pluginConfig, filter) {
885
- const scope = await resolveCommandAppServerScope(deps, ctx);
927
+ const scope = await resolveCommandAppServerScope(deps, ctx, pluginConfig);
886
928
  return formatThreads(await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listThreads, {
887
929
  limit: 10,
888
930
  ...filter.trim() ? { searchTerm: filter.trim() } : {}
@@ -906,6 +948,7 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
906
948
  if (parsed.help) return args.includes("--help") || args.includes("-h") || parsed.host ? "Usage: /codex resume <thread-id>\nUsage: /codex resume <session-id> --host <node> --bind here" : "Usage: /codex resume <thread-id>";
907
949
  if (parsed.host) return await bindCodexCliNodeSession(deps, ctx, parsed);
908
950
  if (!normalizedThreadId || args.length !== 1) return "Usage: /codex resume <thread-id>";
951
+ if (isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
909
952
  if (!ctx.sessionId) return "Cannot attach a Codex thread because this command did not include an OpenClaw session id.";
910
953
  const scope = resolveCodexConversationControlScope(ctx);
911
954
  const identity = sessionBindingIdentity({
@@ -920,8 +963,10 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
920
963
  identity,
921
964
  config: ctx.config
922
965
  })) throw new Error(`Codex session generation is no longer current: ${identity.sessionId}`);
966
+ const currentBinding = await deps.bindingStore.read(identity);
967
+ assertCodexBindingMayBeReplaced(currentBinding, "attaching a different resumed thread");
923
968
  const authProfileId = resolveCodexAppServerAuthProfileIdForAgent({
924
- authProfileId: (await deps.bindingStore.read(identity))?.authProfileId,
969
+ authProfileId: currentBinding?.authProfileId,
925
970
  agentDir: scope.agentDir,
926
971
  config: ctx.config
927
972
  });
@@ -945,6 +990,7 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
945
990
  agentDir: scope.agentDir,
946
991
  config: ctx.config
947
992
  });
993
+ assertCodexBindingMayBeReplaced(await deps.bindingStore.read(identity), "committing a different resumed thread");
948
994
  if (!await deps.bindingStore.mutate(identity, {
949
995
  kind: "set",
950
996
  binding: {
@@ -961,6 +1007,16 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
961
1007
  }
962
1008
  async function bindCodexCliNodeSession(deps, ctx, parsed) {
963
1009
  if (!parsed.threadId || !parsed.host || parsed.bindHere !== true) return "Usage: /codex resume <session-id> --host <node> --bind here";
1010
+ if (isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
1011
+ if (ctx.sessionId) {
1012
+ const scope = resolveCodexConversationControlScope(ctx);
1013
+ assertCodexBindingMayBeReplaced(await deps.bindingStore.read(sessionBindingIdentity({
1014
+ sessionId: ctx.sessionId,
1015
+ sessionKey: ctx.sessionKey,
1016
+ agentId: scope.agentId,
1017
+ config: ctx.config
1018
+ })), "binding a Codex CLI node session");
1019
+ }
964
1020
  const resolved = await deps.resolveCodexCliSessionForBindingOnNode({
965
1021
  requestedNode: parsed.host,
966
1022
  sessionId: parsed.threadId
@@ -1010,10 +1066,11 @@ async function steerConversationTurn(deps, ctx, pluginConfig, message) {
1010
1066
  }
1011
1067
  async function setConversationModel(deps, ctx, pluginConfig, args) {
1012
1068
  if (args.length > 1) return "Usage: /codex model <model>";
1013
- const target = await resolveControlTarget(ctx);
1014
- if (!target) return "Cannot set Codex model because this command did not include a stable binding identity.";
1015
1069
  const [model = ""] = args;
1016
1070
  const normalized = model.trim();
1071
+ if (normalized && isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
1072
+ const target = await resolveControlTarget(ctx);
1073
+ if (!target) return "Cannot set Codex model because this command did not include a stable binding identity.";
1017
1074
  if (!normalized) {
1018
1075
  const binding = await deps.bindingStore.read(target.identity);
1019
1076
  return binding?.model ? `Codex model: ${formatCodexDisplayText(binding.model)}` : "Usage: /codex model <model>";
@@ -1073,19 +1130,25 @@ async function resolveControlTarget(ctx) {
1073
1130
  agentDir: scope.agentDir
1074
1131
  } : void 0;
1075
1132
  }
1076
- async function resolveCommandAppServerScope(deps, ctx) {
1133
+ async function resolveCommandAppServerScope(deps, ctx, pluginConfig) {
1077
1134
  const target = await resolveControlTarget(ctx);
1078
1135
  const fallback = resolveCodexConversationControlScope(ctx);
1079
1136
  const agentDir = target?.agentDir ?? fallback.agentDir;
1080
- const authProfileId = resolveCodexAppServerAuthProfileIdForAgent({
1081
- authProfileId: (target ? await deps.bindingStore.read(target.identity) : void 0)?.authProfileId ?? target?.requestedAuthProfileId,
1082
- agentDir,
1083
- config: ctx.config
1137
+ const binding = target ? await deps.bindingStore.read(target.identity) : void 0;
1138
+ const connection = resolveCodexBindingAppServerConnection({
1139
+ binding,
1140
+ authProfileId: binding?.connectionScope === "supervision" ? void 0 : resolveCodexAppServerAuthProfileIdForAgent({
1141
+ authProfileId: binding?.authProfileId ?? target?.requestedAuthProfileId,
1142
+ agentDir,
1143
+ config: ctx.config
1144
+ }),
1145
+ pluginConfig
1084
1146
  });
1085
1147
  return {
1086
1148
  agentId: target?.agentId ?? fallback.agentId,
1087
1149
  agentDir,
1088
- ...authProfileId ? { authProfileId } : {},
1150
+ ...connection.clientAuthProfileId !== void 0 ? { authProfileId: connection.clientAuthProfileId } : {},
1151
+ ...connection.usesSupervisionConnection ? { startOptions: connection.appServer.start } : {},
1089
1152
  ...ctx.sessionKey ? { sessionKey: ctx.sessionKey } : {},
1090
1153
  ...ctx.sessionId ? { sessionId: ctx.sessionId } : {}
1091
1154
  };
@@ -1233,6 +1296,20 @@ async function sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, n
1233
1296
  const sent = [];
1234
1297
  const failed = [];
1235
1298
  for (const target of targets) {
1299
+ let connection;
1300
+ try {
1301
+ connection = resolveCodexBindingAppServerConnection({
1302
+ binding: target,
1303
+ authProfileId: target.authProfileId,
1304
+ pluginConfig
1305
+ });
1306
+ } catch (error) {
1307
+ failed.push({
1308
+ target,
1309
+ error: error instanceof Error ? error.message : String(error)
1310
+ });
1311
+ continue;
1312
+ }
1236
1313
  const response = await deps.safeCodexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.feedback, {
1237
1314
  classification: "bug",
1238
1315
  threadId: target.threadId,
@@ -1242,7 +1319,8 @@ async function sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, n
1242
1319
  }, {
1243
1320
  config: ctx.config,
1244
1321
  agentDir: target.agentDir,
1245
- ...target.authProfileId ? { authProfileId: target.authProfileId } : {},
1322
+ ...connection.clientAuthProfileId !== void 0 ? { authProfileId: connection.clientAuthProfileId } : {},
1323
+ ...connection.usesSupervisionConnection ? { startOptions: connection.appServer.start } : {},
1246
1324
  ...target.sessionId ? { sessionId: target.sessionId } : {},
1247
1325
  ...target.sessionKey ? { sessionKey: target.sessionKey } : {}
1248
1326
  });
@@ -1325,13 +1403,31 @@ async function resolvePendingCodexDiagnosticsTargets(deps, targets, config) {
1325
1403
  return resolved;
1326
1404
  }
1327
1405
  function resolveCodexDiagnosticsTarget(target, binding, config) {
1406
+ const candidate = {
1407
+ identity: target.identity,
1408
+ agentDir: target.agentDir,
1409
+ sessionKey: target.sessionKey,
1410
+ sessionId: target.sessionId,
1411
+ channel: target.channel,
1412
+ channelId: target.channelId,
1413
+ accountId: target.accountId,
1414
+ messageThreadId: target.messageThreadId,
1415
+ threadParentId: target.threadParentId
1416
+ };
1417
+ if (binding.connectionScope === "supervision") return {
1418
+ ...candidate,
1419
+ threadId: binding.threadId,
1420
+ connectionScope: binding.connectionScope,
1421
+ appServerRuntimeFingerprint: binding.appServerRuntimeFingerprint,
1422
+ pendingSupervisionBranch: binding.pendingSupervisionBranch
1423
+ };
1328
1424
  const authProfileId = resolveCodexAppServerAuthProfileIdForAgent({
1329
1425
  authProfileId: binding.authProfileId,
1330
1426
  agentDir: target.agentDir,
1331
1427
  config
1332
1428
  });
1333
1429
  return {
1334
- ...target,
1430
+ ...candidate,
1335
1431
  threadId: binding.threadId,
1336
1432
  authProfileId
1337
1433
  };
@@ -1340,6 +1436,8 @@ function codexDiagnosticsTargetsMatch(expected, actual) {
1340
1436
  const fingerprint = (target) => JSON.stringify([
1341
1437
  bindingStoreKey(target.identity),
1342
1438
  target.threadId,
1439
+ target.connectionScope ?? null,
1440
+ target.pendingSupervisionBranch?.connectionFingerprint ?? target.appServerRuntimeFingerprint ?? null,
1343
1441
  target.authProfileId ?? null
1344
1442
  ]);
1345
1443
  const expectedTargets = expected.map(fingerprint).toSorted();
@@ -1387,7 +1485,7 @@ function formatCodexDiagnosticsTargetLine(target) {
1387
1485
  }
1388
1486
  function normalizeDiagnosticsReason(note) {
1389
1487
  const normalized = normalizeOptionalString(note);
1390
- return normalized ? normalized.slice(0, CODEX_DIAGNOSTICS_REASON_MAX_CHARS) : void 0;
1488
+ return normalized ? truncateUtf16Safe(normalized, CODEX_DIAGNOSTICS_REASON_MAX_CHARS) : void 0;
1391
1489
  }
1392
1490
  function parseDiagnosticsArgs(args) {
1393
1491
  const [action, token, ...extra] = splitArgs(args);
@@ -1590,7 +1688,7 @@ function pruneCodexDiagnosticsCooldownMap(map, now) {
1590
1688
  for (const [key, lastSentAt] of map) if (now - lastSentAt >= CODEX_DIAGNOSTICS_COOLDOWN_MS) map.delete(key);
1591
1689
  }
1592
1690
  function formatCodexErrorForDisplay(error) {
1593
- return escapeCodexChatText(formatCodexTextForDisplay(error).slice(0, CODEX_DIAGNOSTICS_ERROR_MAX_CHARS)) || "unknown error";
1691
+ return escapeCodexChatText(truncateUtf16Safe(formatCodexTextForDisplay(error), CODEX_DIAGNOSTICS_ERROR_MAX_CHARS)) || "unknown error";
1594
1692
  }
1595
1693
  function formatCodexResumeCommandForDisplay(threadId) {
1596
1694
  const safeThreadId = formatCodexTextForDisplay(threadId);
@@ -1613,13 +1711,19 @@ async function startThreadAction(deps, ctx, pluginConfig, kind, args) {
1613
1711
  if (!target) return `Cannot start Codex ${label} because this command did not include a stable binding identity.`;
1614
1712
  const binding = await deps.bindingStore.read(target.identity);
1615
1713
  if (!binding?.threadId) return `No Codex thread is attached to this OpenClaw session yet.`;
1714
+ const connection = resolveCodexBindingAppServerConnection({
1715
+ binding,
1716
+ authProfileId: binding.authProfileId,
1717
+ pluginConfig
1718
+ });
1616
1719
  await deps.codexControlRequest(pluginConfig, kind === "compact" ? CODEX_CONTROL_METHODS.compact : CODEX_CONTROL_METHODS.review, kind === "review" ? {
1617
1720
  threadId: binding.threadId,
1618
1721
  target: { type: "uncommittedChanges" }
1619
1722
  } : { threadId: binding.threadId }, {
1620
1723
  agentDir: target.agentDir,
1621
- authProfileId: binding.authProfileId,
1622
- config: ctx.config
1724
+ authProfileId: connection.clientAuthProfileId,
1725
+ config: ctx.config,
1726
+ ...connection.usesSupervisionConnection ? { startOptions: connection.appServer.start } : {}
1623
1727
  });
1624
1728
  return `Started Codex ${label} for thread ${formatCodexDisplayText(binding.threadId)}.`;
1625
1729
  }
@@ -1671,7 +1775,7 @@ function splitArgs(value) {
1671
1775
  function parseBindArgs(args) {
1672
1776
  const parsed = {};
1673
1777
  for (let index = 0; index < args.length; index += 1) {
1674
- const arg = args[index];
1778
+ const arg = expectDefined(args[index], "current Codex bind argument");
1675
1779
  if (arg === "--help" || arg === "-h") {
1676
1780
  parsed.help = true;
1677
1781
  continue;
@@ -1722,7 +1826,7 @@ function parseCodexCliSessionsArgs(args) {
1722
1826
  const parsed = { filter: "" };
1723
1827
  const filter = [];
1724
1828
  for (let index = 0; index < args.length; index += 1) {
1725
- const arg = args[index];
1829
+ const arg = expectDefined(args[index], "current Codex sessions argument");
1726
1830
  if (arg === "--help" || arg === "-h") {
1727
1831
  parsed.help = true;
1728
1832
  continue;
@@ -1760,7 +1864,7 @@ function parseCodexCliSessionsArgs(args) {
1760
1864
  function parseResumeArgs(args) {
1761
1865
  const parsed = {};
1762
1866
  for (let index = 0; index < args.length; index += 1) {
1763
- const arg = args[index];
1867
+ const arg = expectDefined(args[index], "current Codex resume argument");
1764
1868
  if (arg === "--help" || arg === "-h") {
1765
1869
  parsed.help = true;
1766
1870
  continue;
@@ -1798,7 +1902,8 @@ function parseComputerUseArgs(args) {
1798
1902
  const parsed = {
1799
1903
  action: "status",
1800
1904
  overrides: {},
1801
- hasOverrides: false
1905
+ hasOverrides: false,
1906
+ persistentIdentity: {}
1802
1907
  };
1803
1908
  let sawAction = false;
1804
1909
  for (let index = 0; index < args.length; index += 1) {
@@ -1846,23 +1951,14 @@ function parseComputerUseArgs(args) {
1846
1951
  index += 1;
1847
1952
  continue;
1848
1953
  }
1849
- if (arg === "--plugin") {
1850
- const value = readRequiredOptionValue(args, index);
1851
- if (!value || parsed.overrides.pluginName !== void 0) {
1852
- parsed.help = true;
1853
- continue;
1854
- }
1855
- parsed.overrides.pluginName = value;
1856
- index += 1;
1857
- continue;
1858
- }
1859
- if (arg === "--server" || arg === "--mcp-server") {
1954
+ if (arg === "--plugin" || arg === "--server" || arg === "--mcp-server") {
1860
1955
  const value = readRequiredOptionValue(args, index);
1861
- if (!value || parsed.overrides.mcpServerName !== void 0) {
1956
+ const configKey = arg === "--plugin" ? "pluginName" : "mcpServerName";
1957
+ if (!value || parsed.persistentIdentity[configKey] !== void 0) {
1862
1958
  parsed.help = true;
1863
1959
  continue;
1864
1960
  }
1865
- parsed.overrides.mcpServerName = value;
1961
+ parsed.persistentIdentity[configKey] = value.trim();
1866
1962
  index += 1;
1867
1963
  continue;
1868
1964
  }
@@ -1872,6 +1968,17 @@ function parseComputerUseArgs(args) {
1872
1968
  parsed.hasOverrides = Object.values(parsed.overrides).some(Boolean);
1873
1969
  return parsed;
1874
1970
  }
1971
+ function formatComputerUsePersistentIdentityMigration(parsed) {
1972
+ const configPrefix = "plugins.entries.codex.config.computerUse";
1973
+ const settings = [parsed.persistentIdentity.pluginName ? `${configPrefix}.pluginName = ${JSON.stringify(parsed.persistentIdentity.pluginName)}` : void 0, parsed.persistentIdentity.mcpServerName ? `${configPrefix}.mcpServerName = ${JSON.stringify(parsed.persistentIdentity.mcpServerName)}` : void 0].filter((setting) => Boolean(setting));
1974
+ const retryArgs = [
1975
+ `/codex computer-use ${parsed.action}`,
1976
+ parsed.overrides.marketplaceSource ? `--source ${JSON.stringify(parsed.overrides.marketplaceSource)}` : void 0,
1977
+ parsed.overrides.marketplacePath ? `--marketplace-path ${JSON.stringify(parsed.overrides.marketplacePath)}` : void 0,
1978
+ parsed.overrides.marketplaceName ? `--marketplace ${JSON.stringify(parsed.overrides.marketplaceName)}` : void 0
1979
+ ].filter((arg) => Boolean(arg));
1980
+ return ["One-off Computer Use plugin/server overrides are no longer supported.", `Set ${settings.join(" and ")} persistently, then rerun ${retryArgs.join(" ")}.`].join(" ");
1981
+ }
1875
1982
  function readRequiredOptionValue(args, index) {
1876
1983
  const value = args[index + 1];
1877
1984
  const normalized = value?.trim();
@@ -1886,10 +1993,6 @@ function normalizeComputerUseStringOverrides(overrides) {
1886
1993
  if (marketplacePath) normalized.marketplacePath = marketplacePath;
1887
1994
  const marketplaceName = normalizeOptionalString(overrides.marketplaceName);
1888
1995
  if (marketplaceName) normalized.marketplaceName = marketplaceName;
1889
- const pluginName = normalizeOptionalString(overrides.pluginName);
1890
- if (pluginName) normalized.pluginName = pluginName;
1891
- const mcpServerName = normalizeOptionalString(overrides.mcpServerName);
1892
- if (mcpServerName) normalized.mcpServerName = mcpServerName;
1893
1996
  return normalized;
1894
1997
  }
1895
1998
  //#endregion
@@ -1,10 +1,10 @@
1
- import { r as isJsonObject } from "./protocol-2POPqAY4.js";
2
- import { _ as readCodexNotificationItem } from "./attempt-notifications-BGsEIIDI.js";
3
- import { d as resolveCodexAppServerRuntimeOptions } from "./config-CYEDnLJ2.js";
4
- import { a as getLeasedSharedCodexAppServerClient, o as releaseLeasedSharedCodexAppServerClient, u as CodexAppServerRpcError } from "./shared-client-4ICy3U6d.js";
5
- import { s as sessionBindingIdentity, t as CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS } from "./session-binding-C1ZXdP-x.js";
6
- import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-DA2TQfZW.js";
7
- import { n as readCodexNotificationThreadId, r as readCodexNotificationTurnId } from "./notification-correlation-Bo7KB3ks.js";
1
+ import { i as isJsonObject } from "./protocol-BMifTfdW.js";
2
+ import { _ as readCodexNotificationItem } from "./attempt-notifications-DEv9h7iC.js";
3
+ import { O as CodexAppServerRpcError, a as getLeasedSharedCodexAppServerClient, c as releaseLeasedSharedCodexAppServerClient } from "./shared-client-D4mFI9al.js";
4
+ import { c as sessionBindingIdentity, t as CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS } from "./session-binding-BMfX1OX-.js";
5
+ import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-D1Wky__S.js";
6
+ import { a as resolveCodexBindingAppServerConnection, n as readCodexNotificationThreadId, r as readCodexNotificationTurnId } from "./notification-correlation-DfaCm0mx.js";
7
+ import { resolveAgentDir, resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
8
8
  import { embeddedAgentLog, resolveCompactionTimeoutMs } from "openclaw/plugin-sdk/agent-harness-runtime";
9
9
  //#region extensions/codex/src/app-server/compact.ts
10
10
  /**
@@ -331,7 +331,6 @@ async function compactCodexNativeThread(params, options) {
331
331
  compacted: false,
332
332
  reason: nativeExecutionBlock
333
333
  };
334
- const appServer = resolveCodexAppServerRuntimeOptions({ pluginConfig: options.pluginConfig });
335
334
  const bindingIdentity = sessionBindingIdentity({
336
335
  sessionId: params.sessionId,
337
336
  sessionKey: params.sessionKey,
@@ -345,18 +344,48 @@ async function compactCodexNativeThread(params, options) {
345
344
  });
346
345
  let binding = initialBinding;
347
346
  const requestedAuthProfileId = params.authProfileId?.trim() || void 0;
348
- if (requestedAuthProfileId && binding.authProfileId && binding.authProfileId !== requestedAuthProfileId) return {
347
+ let connection;
348
+ try {
349
+ const config = params.config ?? {};
350
+ const agentId = params.agentId ?? readAgentIdFromSessionKey(params.sessionKey) ?? resolveDefaultAgentId(config);
351
+ connection = resolveCodexBindingAppServerConnection({
352
+ binding,
353
+ authProfileId: requestedAuthProfileId ?? binding.authProfileId,
354
+ pluginConfig: options.pluginConfig,
355
+ config,
356
+ agentDir: resolveAgentDir(config, agentId)
357
+ });
358
+ } catch (error) {
359
+ return {
360
+ ok: false,
361
+ compacted: false,
362
+ reason: formatCompactionError(error)
363
+ };
364
+ }
365
+ const { appServer, usesSupervisionConnection } = connection;
366
+ if (!usesSupervisionConnection && requestedAuthProfileId && binding.authProfileId && binding.authProfileId !== requestedAuthProfileId) return {
349
367
  ok: false,
350
368
  compacted: false,
351
369
  reason: "auth profile mismatch for session binding"
352
370
  };
353
371
  const shouldReleaseDefaultLease = !options.clientFactory;
354
372
  const clientFactory = options.clientFactory ?? getLeasedSharedCodexAppServerClient;
373
+ const runtimeAuthPlan = params.runtimeAuthPlan ?? params.runtimePlan?.auth;
374
+ const usesPreparedApiKey = !usesSupervisionConnection && runtimeAuthPlan?.modelRoute?.authRequirement === "api-key";
375
+ const preparedApiKey = usesPreparedApiKey ? params.resolvedApiKey?.trim() : void 0;
376
+ if (usesPreparedApiKey && !preparedApiKey) return {
377
+ ok: false,
378
+ compacted: false,
379
+ reason: "Prepared Codex Platform compaction route is missing its resolved API key."
380
+ };
355
381
  try {
356
382
  return await runExclusiveCodexNativeCompaction(binding.threadId, params.abortSignal, async () => {
357
383
  const client = await clientFactory({
358
384
  startOptions: appServer.start,
359
- authProfileId: requestedAuthProfileId ?? binding.authProfileId,
385
+ ...preparedApiKey ? { preparedAuth: {
386
+ kind: "api-key",
387
+ apiKey: preparedApiKey
388
+ } } : { authProfileId: connection.clientAuthProfileId },
360
389
  agentDir: params.agentDir,
361
390
  config: params.config
362
391
  });
@@ -375,6 +404,7 @@ async function compactCodexNativeThread(params, options) {
375
404
  if (transportStopped) return;
376
405
  throw new Error("failed to stop unconfirmed codex app-server process");
377
406
  }
407
+ if (usesSupervisionConnection) throw new Error("cannot detach an unconfirmed supervised codex thread");
378
408
  if (await options.bindingStore.mutate(bindingIdentity, {
379
409
  kind: "clear",
380
410
  threadId: binding.threadId