@openclaw/codex 2026.8.1-beta.3 → 2026.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/api.js +5 -6
  2. package/dist/{attempt-client-cleanup-URjUlCHg.js → attempt-client-cleanup-CpVfwctT.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-CF7BmrDk.js} +2 -2
  5. package/dist/{bounded-turn-4BjrZEwW.js → bounded-turn-DRC3hcjm.js} +16 -20
  6. package/dist/{capabilities-CH3K57v4.js → capabilities-D6m_TdVy.js} +1 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-D0nZ3qtd.js → command-formatters--UToCokS.js} +4 -3
  9. package/dist/{command-handlers-DC86lgT4.js → command-handlers-CLFx2Ypa.js} +114 -79
  10. package/dist/{compact-COqgBRny.js → compact-5xqW1oCh.js} +13 -12
  11. package/dist/{config-CpNeo5AE.js → config-CcYL77O6.js} +350 -288
  12. package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
  13. package/dist/doctor-contract-api.js +121 -16
  14. package/dist/{dynamic-tools-fJZhl4CE.js → dynamic-tools-BmeXjwNZ.js} +243 -1002
  15. package/dist/{effective-mcp-catalog-4YKn51aG.js → effective-mcp-catalog-XXQKgK1U.js} +2 -2
  16. package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
  17. package/dist/{event-projector-usage-CLwNEJqW.js → event-projector-usage-B2r5vhWH.js} +9 -14
  18. package/dist/{harness-DoKQcF8n.js → harness-BgeB7LnD.js} +42 -52
  19. package/dist/harness.js +1 -1
  20. package/dist/index.js +308 -306
  21. package/dist/{isolated-completion-DPMtlH9r.js → isolated-completion-CxTus3vZ.js} +4 -4
  22. package/dist/launch-args-sXOAg0SX.js +84 -0
  23. package/dist/{managed-binary-By4FZC6i.js → managed-binary-ZkGodW19.js} +43 -7
  24. package/dist/media-understanding-provider.js +1 -1
  25. package/dist/model-catalog-DULBcniB.js +101 -0
  26. package/dist/{models-CZw1wClT.js → models-DaWfETQk.js} +27 -29
  27. package/dist/{native-subagent-monitor-GGq3RnOo.js → native-subagent-monitor-vXYUZH37.js} +226 -129
  28. package/dist/{node-exec-server.runtime-Bsu1LdFZ.js → node-exec-server.runtime-DirKVZ5h.js} +9 -6
  29. package/dist/{plugin-approval-roundtrip-C75Yiiwc.js → plugin-approval-roundtrip-CCWQGlAI.js} +2 -1
  30. package/dist/{plugin-marketplace-discovery-CSWDkMrP.js → plugin-marketplace-discovery-BXjIFEiw.js} +38 -46
  31. package/dist/{plugin-metadata-cache-BXH5NF-4.js → plugin-metadata-cache-DQQm4gWT.js} +163 -136
  32. package/dist/{protocol-validators-VAVyEnDp.js → protocol-validators-Bg5rpNxk.js} +148 -5
  33. package/dist/{rate-limits-BI1dMHDG.js → rate-limits-BqHEHXQJ.js} +3 -2
  34. package/dist/{sandbox-guard-C1qEeZ5C.js → request-BWxweEdK.js} +183 -2
  35. package/dist/{run-attempt-BV3HzuCf.js → run-attempt-BVLE4Gbi.js} +706 -517
  36. package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-D9pYp4zL.js} +3 -3
  37. package/dist/{session-binding-BTrLf9Qm.js → session-binding-D0zinCP1.js} +195 -122
  38. package/dist/{session-catalog-ezP_UcRM.js → session-catalog-eMhVm0Ql.js} +448 -313
  39. package/dist/session-catalog-home-id-Dt2GiG5o.js +112 -0
  40. package/dist/{session-cli-B1hKvfkI.js → session-cli-B2lyjJA0.js} +1 -1
  41. package/dist/session-history-C5J1AKzG.js +87 -0
  42. package/dist/session-permission-policy-ScnAyG90.js +160 -0
  43. package/dist/session-retirement-CtUtUTr9.js +90 -0
  44. package/dist/{session-upstream-marker-D_2npHlA.js → session-upstream-marker-gqrYIRHk.js} +2 -3
  45. package/dist/settled-turn-context-Bk3IUwod.js +290 -0
  46. package/dist/settled-turn-finalizer-BXLN9PfJ.js +104 -0
  47. package/dist/{shared-client-Dw-rzii0.js → shared-client-B1tT5U6r.js} +1738 -806
  48. package/dist/{side-question-DbXkJZzg.js → side-question-CZ-mCw-t.js} +76 -43
  49. package/dist/{thread-lifecycle-DKdrnTMX.js → thread-lifecycle-CGGKP720.js} +991 -455
  50. package/dist/{thread-ownership-i2NBwDUL.js → thread-ownership-RkaoZCmQ.js} +18 -8
  51. package/dist/{plugin-app-cache-key-DMNQ8Zi8.js → thread-resume-BFt1-ZDa.js} +55 -8
  52. package/dist/{transcript-mirror-BU0_LKAL.js → transcript-mirror-1ep4XjzF.js} +124 -18
  53. package/dist/transport-stdio-NT_Dpd9V.js +724 -0
  54. package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
  55. package/dist/{upstream-session-fork-BDVJCLAD.js → upstream-session-fork-Dc8BFExw.js} +76 -90
  56. package/dist/{usage-9dKJCgcy.js → usage-DUhd58gI.js} +3 -3
  57. package/dist/{web-search-provider.runtime-DCdx4DGu.js → web-search-provider.runtime-BEmlE7ov.js} +3 -3
  58. package/openclaw.plugin.json +19 -1
  59. package/package.json +8 -8
  60. package/dist/app-server-policy-bg5QPSVP.js +0 -25
  61. package/dist/command-rpc-xUIIonsO.js +0 -90
  62. package/dist/incognito-session-ET_ufDH-.js +0 -2
  63. package/dist/model-catalog-CmGoqVKB.js +0 -48
  64. package/dist/request-DSK0W6YI.js +0 -157
  65. package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
  66. package/dist/session-retirement-CE4iMiLh.js +0 -36
  67. package/dist/settled-turn-finalizer-Dx1onIqg.js +0 -328
  68. package/dist/thread-resume-CdJk2Ehf.js +0 -30
  69. package/dist/transport-stdio-DhoGy33Z.js +0 -99
@@ -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";
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";
1
+ import { i as resolveCodexAppServerRuntimeOptions, j as CODEX_PLUGINS_MARKETPLACE_NAME, k as isCodexFastServiceTier } from "./config-CcYL77O6.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-B1tT5U6r.js";
3
+ import { c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, i as createCodexSessionGenerationSupersededError, n as assertCodexBindingMayBeReplaced, r as bindingStoreKey, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-D0zinCP1.js";
4
+ import { o as assertCodexThreadResumeResponse, r as assertCodexThreadAcceptsDirectInput } from "./protocol-validators-Bg5rpNxk.js";
5
+ import { a as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-CpVfwctT.js";
6
+ import { t as listAllCodexAppServerModels } from "./models-DaWfETQk.js";
7
+ import { i as buildCodexPluginAppCacheKey, s as defaultCodexAppInventoryCache } from "./thread-resume-BFt1-ZDa.js";
8
+ import { dt as isOpenAiCuratedMarketplaceName, lt as refreshCodexPluginRuntimeState } from "./thread-lifecycle-CGGKP720.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-RkaoZCmQ.js";
10
+ import { c as resolveCodexNativeSandboxBlock, s as resolveCodexNativeExecutionBlock } from "./request-BWxweEdK.js";
11
+ import { t as CODEX_CONTROL_METHODS } from "./capabilities-D6m_TdVy.js";
12
+ import { s as summarizeCodexAccountUsage } from "./rate-limits-BqHEHXQJ.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--UToCokS.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-BXjIFEiw.js";
15
+ import { i as readCodexConversationBindingData, n as createCodexCliNodeConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-BiodpIzq.js";
16
+ import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-CF7BmrDk.js";
17
+ import { c as readCodexStatusProbes, l as requestOptions, p as formatCodexCliSessions, s as codexControlRequest, u as safeCodexControlRequest } from "./session-catalog-eMhVm0Ql.js";
18
+ import { i as readCodexComputerUseStatus, r as installCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-DQQm4gWT.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
  }
@@ -584,7 +591,8 @@ function parseCodexCliSessionsArgs(args) {
584
591
  continue;
585
592
  }
586
593
  if (arg === "--limit") {
587
- const parsedLimit = parseStrictPositiveInteger(readRequiredOptionValue(args, index));
594
+ const value = readRequiredOptionValue(args, index);
595
+ const parsedLimit = parseStrictPositiveInteger(value);
588
596
  if (parsedLimit === void 0) {
589
597
  parsed.help = true;
590
598
  continue;
@@ -745,7 +753,7 @@ const CODEX_DIAGNOSTICS_COOLDOWN_MS = 6e4;
745
753
  const CODEX_DIAGNOSTICS_ERROR_MAX_CHARS = 500;
746
754
  const CODEX_DIAGNOSTICS_COOLDOWN_MAX_THREADS = 100;
747
755
  const CODEX_DIAGNOSTICS_COOLDOWN_MAX_SCOPES = 100;
748
- const CODEX_DIAGNOSTICS_CONFIRMATION_TTL_MS = 5 * 6e4;
756
+ const CODEX_DIAGNOSTICS_CONFIRMATION_TTL_MS = 3e5;
749
757
  const CODEX_DIAGNOSTICS_CONFIRMATION_MAX_REQUESTS_PER_SCOPE = 100;
750
758
  const CODEX_DIAGNOSTICS_CONFIRMATION_MAX_SCOPES = 100;
751
759
  const CODEX_DIAGNOSTICS_SCOPE_FIELD_MAX_CHARS = 128;
@@ -1056,7 +1064,8 @@ function resolveCodexCommandDeps(overrides) {
1056
1064
  //#endregion
1057
1065
  //#region extensions/codex/src/command-handler-scope.ts
1058
1066
  async function resolveControlTarget(ctx) {
1059
- const data = readCodexConversationBindingData(await ctx.getCurrentConversationBinding());
1067
+ const binding = await ctx.getCurrentConversationBinding();
1068
+ const data = readCodexConversationBindingData(binding);
1060
1069
  const scope = resolveCodexConversationControlScope(ctx);
1061
1070
  if (data?.kind === "codex-app-server-session") return {
1062
1071
  identity: conversationBindingIdentity(data.bindingId),
@@ -1080,13 +1089,14 @@ async function resolveCommandAppServerScope(deps, ctx, pluginConfig) {
1080
1089
  const fallback = resolveCodexConversationControlScope(ctx);
1081
1090
  const agentDir = target?.agentDir ?? fallback.agentDir;
1082
1091
  const binding = target ? await deps.bindingStore.read(target.identity) : void 0;
1092
+ const authProfileId = binding?.connectionScope === "supervision" ? void 0 : resolveCodexAppServerAuthProfileIdForAgent({
1093
+ authProfileId: binding?.authProfileId ?? target?.requestedAuthProfileId,
1094
+ agentDir,
1095
+ config: ctx.config
1096
+ });
1083
1097
  const connection = resolveCodexBindingAppServerConnection({
1084
1098
  binding,
1085
- authProfileId: binding?.connectionScope === "supervision" ? void 0 : resolveCodexAppServerAuthProfileIdForAgent({
1086
- authProfileId: binding?.authProfileId ?? target?.requestedAuthProfileId,
1087
- agentDir,
1088
- config: ctx.config
1089
- }),
1099
+ authProfileId,
1090
1100
  pluginConfig
1091
1101
  });
1092
1102
  return {
@@ -1105,7 +1115,7 @@ function conversationBindingIdentity(bindingId) {
1105
1115
  };
1106
1116
  }
1107
1117
  function resolveCodexConversationControlScope(ctx) {
1108
- const { sessionAgentId } = resolveSessionAgentIds({
1118
+ const { sessionAgentId } = resolveSessionAgentIdsStrict({
1109
1119
  sessionKey: ctx.sessionKey,
1110
1120
  agentId: ctx.agentId,
1111
1121
  config: ctx.config
@@ -1385,8 +1395,9 @@ function isCurrentSessionModelSelectionLocked(ctx) {
1385
1395
  const sessionKey = ctx.sessionKey?.trim();
1386
1396
  if (!sessionKey) return false;
1387
1397
  const { agentId } = resolveCodexConversationControlScope(ctx);
1398
+ const storePath = resolveStorePath(ctx.config.session?.store, { agentId });
1388
1399
  return isModelSelectionLocked(getSessionEntry({
1389
- storePath: resolveStorePath(ctx.config.session?.store, { agentId }),
1400
+ storePath,
1390
1401
  sessionKey,
1391
1402
  hydrateSkillPromptRefs: false,
1392
1403
  readConsistency: "latest"
@@ -1443,7 +1454,8 @@ async function bindConversation(deps, ctx, pluginConfig, args) {
1443
1454
  }
1444
1455
  async function detachConversation(deps, ctx) {
1445
1456
  if (isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
1446
- const data = readCodexConversationBindingData(await ctx.getCurrentConversationBinding());
1457
+ const current = await ctx.getCurrentConversationBinding();
1458
+ const data = readCodexConversationBindingData(current);
1447
1459
  const identity = data?.kind === "codex-app-server-session" ? conversationBindingIdentity(data.bindingId) : void 0;
1448
1460
  const sourceSessionKey = data?.kind === "codex-app-server-session" ? data.source?.sessionKey : void 0;
1449
1461
  let expectedThreadId;
@@ -1512,13 +1524,14 @@ async function describeConversationBinding(deps, ctx) {
1512
1524
  }
1513
1525
  async function buildThreads(deps, ctx, pluginConfig, filter) {
1514
1526
  const scope = await resolveCommandAppServerScope(deps, ctx, pluginConfig);
1515
- return formatThreads(await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listThreads, {
1527
+ const response = await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listThreads, {
1516
1528
  limit: 10,
1517
1529
  ...filter.trim() ? { searchTerm: filter.trim() } : {}
1518
1530
  }, {
1519
1531
  config: ctx.config,
1520
1532
  ...scope
1521
- }));
1533
+ });
1534
+ return formatThreads(response);
1522
1535
  }
1523
1536
  async function buildCodexCliSessions(deps, args) {
1524
1537
  const parsed = parseCodexCliSessionsArgs(args);
@@ -1556,13 +1569,8 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1556
1569
  })) throw createCodexSessionGenerationSupersededError(identity.sessionId);
1557
1570
  const currentBinding = await deps.bindingStore.read(identity);
1558
1571
  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) => {
1572
+ let pendingResumeConfiguration = false;
1573
+ const commitResumedThread = async (value, client, { authProfileId, assertCurrent }) => {
1566
1574
  const response = assertCodexThreadResumeResponse(value);
1567
1575
  const effectiveThreadId = response.thread.id;
1568
1576
  if (effectiveThreadId !== normalizedThreadId) throw new Error(`Codex thread/resume returned ${effectiveThreadId} for ${normalizedThreadId}`);
@@ -1574,52 +1582,73 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1574
1582
  agentDir: scope.agentDir,
1575
1583
  config: ctx.config
1576
1584
  });
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;
1585
+ const clientId = client.getInstanceId();
1584
1586
  let retained = false;
1587
+ let sameOwner = false;
1588
+ let knownOwnership;
1585
1589
  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
- }
1590
+ const bindingBeforeCommit = await deps.bindingStore.read(identity);
1591
+ assertCodexBindingMayBeReplaced(bindingBeforeCommit, "committing a different resumed thread");
1592
+ sameOwner = isSameCodexAppServerThreadOwner(bindingBeforeCommit, {
1593
+ threadId: effectiveThreadId,
1594
+ clientId
1595
+ });
1596
+ const sameThreadBinding = bindingBeforeCommit?.threadId === effectiveThreadId ? bindingBeforeCommit : void 0;
1597
+ pendingResumeConfiguration = sameThreadBinding?.preserveNativeModel !== true && (!sameThreadBinding?.dynamicToolsFingerprint || !sameThreadBinding.webSearchThreadConfigFingerprint || sameThreadBinding.pendingResumeConfiguration === true);
1598
+ assertCurrent();
1599
+ assertCodexThreadAcceptsDirectInput(response.thread);
1600
+ knownOwnership = sameOwner ? await consumeCodexAppServerLiveThread(client, effectiveThreadId) : void 0;
1601
+ assertCurrent();
1602
+ retained = await retainCodexAppServerBindingSubscription(client, effectiveThreadId, knownOwnership);
1603
+ assertCurrent();
1604
+ if (!retained) throw new Error("Codex resumed thread lost its native subscription owner.");
1590
1605
  if (bindingBeforeCommit && !sameOwner) await releaseCodexAppServerBindingSubscription(bindingBeforeCommit);
1606
+ assertCurrent();
1591
1607
  if (!await deps.bindingStore.mutate(identity, {
1592
1608
  kind: "set",
1593
1609
  binding: {
1594
- ...bindingBeforeCommit?.threadId === effectiveThreadId ? bindingBeforeCommit : {},
1610
+ ...sameThreadBinding,
1595
1611
  threadId: effectiveThreadId,
1596
- ...clientId ? { clientId } : {},
1612
+ clientId,
1597
1613
  cwd: resumedCwd,
1614
+ rolloutPath: response.thread.path ?? sameThreadBinding?.rolloutPath,
1615
+ pendingResumeConfiguration: pendingResumeConfiguration ? true : void 0,
1598
1616
  authProfileId,
1599
1617
  model: response.model,
1600
1618
  modelProvider,
1601
1619
  historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString()
1602
1620
  }
1603
- })) throw new Error("Codex thread binding changed while attaching the resumed thread.");
1621
+ }, assertCurrent)) throw new Error("Codex thread binding changed while attaching the resumed thread.");
1604
1622
  } catch (error) {
1605
- if (client && !sameOwner) await rollbackCodexAppServerBindingSubscription(client, effectiveThreadId, retained);
1623
+ if (sameOwner && knownOwnership && !retained) {
1624
+ if (!await retainCodexAppServerBindingSubscription(client, effectiveThreadId, knownOwnership)) await closeCodexStartupClientBestEffort(client);
1625
+ } else if (retained && !sameOwner || !hasCodexAppServerLiveThread(client, effectiveThreadId)) await rollbackCodexAppServerBindingSubscription(client, effectiveThreadId, retained);
1606
1626
  throw error;
1607
1627
  }
1608
- committedResponse = true;
1609
1628
  };
1610
- const response = await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.resumeThread, {
1629
+ await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.resumeThread, {
1611
1630
  threadId: normalizedThreadId,
1612
1631
  excludeTurns: true
1613
1632
  }, {
1614
1633
  config: ctx.config,
1634
+ agentId: scope.agentId,
1615
1635
  agentDir: scope.agentDir,
1616
- authProfileId,
1636
+ authProfileId: currentBinding?.authProfileId,
1617
1637
  sessionKey: ctx.sessionKey,
1618
1638
  sessionId: ctx.sessionId,
1639
+ beforeRequest: async (request) => {
1640
+ const { thread } = await request({
1641
+ method: "thread/read",
1642
+ requestParams: {
1643
+ threadId: normalizedThreadId,
1644
+ includeTurns: false
1645
+ }
1646
+ });
1647
+ assertCodexThreadAcceptsDirectInput(thread);
1648
+ },
1619
1649
  onResponse: commitResumedThread
1620
1650
  });
1621
- if (!committedResponse) await commitResumedThread(response);
1622
- return `Attached this OpenClaw session to Codex thread ${formatCodexDisplayText(normalizedThreadId)}.`;
1651
+ 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
1652
  })
1624
1653
  });
1625
1654
  }
@@ -1628,12 +1657,13 @@ async function bindCodexCliNodeSession(deps, ctx, parsed) {
1628
1657
  if (isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
1629
1658
  if (ctx.sessionId) {
1630
1659
  const scope = resolveCodexConversationControlScope(ctx);
1631
- assertCodexBindingMayBeReplaced(await deps.bindingStore.read(sessionBindingIdentity({
1660
+ const binding = await deps.bindingStore.read(sessionBindingIdentity({
1632
1661
  sessionId: ctx.sessionId,
1633
1662
  sessionKey: ctx.sessionKey,
1634
1663
  agentId: scope.agentId,
1635
1664
  config: ctx.config
1636
- })), "binding a Codex CLI node session");
1665
+ }));
1666
+ assertCodexBindingMayBeReplaced(binding, "binding a Codex CLI node session");
1637
1667
  }
1638
1668
  const resolved = await deps.resolveCodexCliSessionForBindingOnNode({
1639
1669
  requestedNode: parsed.host,
@@ -1834,7 +1864,7 @@ async function setConversationModel(deps, ctx, pluginConfig, args) {
1834
1864
  }) : void 0;
1835
1865
  const selectedModel = currentSession && currentSession.sessionId === ctx.sessionId ? currentSession.modelOverride ?? currentSession.model : void 0;
1836
1866
  const binding = await deps.bindingStore.read(target.identity);
1837
- const activeModel = selectedModel ?? binding?.model;
1867
+ const activeModel = target.identity.kind === "conversation" ? binding?.model : selectedModel ?? binding?.model;
1838
1868
  return activeModel ? `Codex model: ${formatCodexDisplayText(activeModel)}` : "Usage: /codex model <model>";
1839
1869
  }
1840
1870
  return await deps.setCodexConversationModel({
@@ -1843,12 +1873,7 @@ async function setConversationModel(deps, ctx, pluginConfig, args) {
1843
1873
  pluginConfig,
1844
1874
  model: normalized,
1845
1875
  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
- } } : {}
1876
+ config: ctx.config
1852
1877
  });
1853
1878
  }
1854
1879
  async function setConversationFastMode(deps, ctx, args) {
@@ -1899,12 +1924,13 @@ async function startThreadAction(deps, ctx, pluginConfig, kind, args) {
1899
1924
  });
1900
1925
  if (currentSession?.sessionId !== ctx.sessionId || resolvePersistedSessionRuntimeId(currentSession) !== "codex") return "Codex compaction is unavailable because the current OpenClaw session is not using the Codex runtime.";
1901
1926
  if (target.identity.kind === "conversation") {
1902
- if (!isSameCodexAppServerThreadOwner(binding, ctx.sessionId ? await deps.bindingStore.read(sessionBindingIdentity({
1927
+ const sessionBinding = ctx.sessionId ? await deps.bindingStore.read(sessionBindingIdentity({
1903
1928
  sessionId: ctx.sessionId,
1904
1929
  sessionKey: ctx.sessionKey,
1905
1930
  agentId: sessionTarget.agentId,
1906
1931
  config: ctx.config
1907
- })) : void 0)) return "Codex compaction is unavailable because the conversation-bound thread differs from the current session binding. Resume that thread into the session first.";
1932
+ })) : void 0;
1933
+ if (!isSameCodexAppServerThreadOwner(binding, sessionBinding)) return "Codex compaction is unavailable because the conversation-bound thread differs from the current session binding. Resume that thread into the session first.";
1908
1934
  }
1909
1935
  const compactCurrent = ctx.runtimeContext?.compactCurrent;
1910
1936
  if (!compactCurrent) return "Codex compaction is unavailable because this command is not bound to a session.";
@@ -2293,6 +2319,14 @@ function formatPluginList(plugins, options = {}) {
2293
2319
  }
2294
2320
  //#endregion
2295
2321
  //#region extensions/codex/src/command-handlers.ts
2322
+ const CODEX_HOST_INSPECTION_SUBCOMMANDS = /* @__PURE__ */ new Set([
2323
+ "account",
2324
+ "mcp",
2325
+ "sessions",
2326
+ "skills",
2327
+ "status",
2328
+ "threads"
2329
+ ]);
2296
2330
  async function handleCodexSubcommand(ctx, options) {
2297
2331
  const deps = resolveCodexCommandDeps(options.deps);
2298
2332
  const args = splitArgs(ctx.args);
@@ -2300,6 +2334,7 @@ async function handleCodexSubcommand(ctx, options) {
2300
2334
  const [subcommand = "status", ...rest] = args;
2301
2335
  const normalized = subcommand.toLowerCase();
2302
2336
  if (normalized === "help") return { text: buildHelp() };
2337
+ if (CODEX_HOST_INSPECTION_SUBCOMMANDS.has(normalized) && !canMutateCodexHost(ctx)) return { text: CODEX_HOST_INSPECTION_AUTH_ERROR };
2303
2338
  if (CODEX_NATIVE_CONTROL_SUBCOMMANDS.has(normalized) && !returnsBeforeNativeCodexExecution(normalized, rest) && !isReadOnlyCodexGoalCommand(normalized, rest) && !canMutateCodexHost(ctx)) return { text: CODEX_NATIVE_EXECUTION_AUTH_ERROR };
2304
2339
  const sandboxBlock = resolveCodexNativeCommandSandboxBlock(ctx, normalized, rest);
2305
2340
  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-B1tT5U6r.js";
2
+ import { d as sessionBindingIdentity, t as CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS } from "./session-binding-D0zinCP1.js";
3
+ import { _ as readCodexNotificationThreadId, a as closeCodexStartupClientBestEffort, f as unsubscribeCodexThreadBestEffort, r as CodexAppServerUnsafeSubscriptionError, s as isCodexAlreadyTerminalInterruptError, v as readCodexNotificationTurnId } from "./attempt-client-cleanup-CpVfwctT.js";
4
+ import { i as readCodexThreadContextSnapshot, x as readCodexNotificationItem } from "./event-projector-usage-B2r5vhWH.js";
5
+ import { t as resumeCodexAppServerThread } from "./thread-resume-BFt1-ZDa.js";
6
+ import { l as isIncognitoSessionKey, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-RkaoZCmQ.js";
7
+ import { s as resolveCodexNativeExecutionBlock } from "./request-BWxweEdK.js";
8
+ import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-CF7BmrDk.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";
@@ -282,7 +281,7 @@ async function compactCodexNativeThread(params, options) {
282
281
  config: params.config,
283
282
  sessionKey: params.sandboxSessionKey ?? params.sessionKey,
284
283
  sessionId: params.sessionId,
285
- agentId: params.agentId,
284
+ agentId: params.sandboxAgentId ?? params.agentId,
286
285
  sandbox,
287
286
  surface: "native compaction"
288
287
  });
@@ -534,8 +533,10 @@ async function compactCodexNativeThread(params, options) {
534
533
  try {
535
534
  if ((compactionSucceeded || compactionRequestDefinitelyRejected) && retainedThreadOwnership) {
536
535
  const ownership = retainedThreadOwnership;
537
- if (!(isSameCodexAppServerThreadOwner(await options.bindingStore.read(bindingIdentity), binding) && await options.bindingStore.withLease(bindingIdentity, async () => {
538
- if (!isSameCodexAppServerThreadOwner(await options.bindingStore.read(bindingIdentity), binding)) return false;
536
+ const currentBinding = await options.bindingStore.read(bindingIdentity);
537
+ if (!(isSameCodexAppServerThreadOwner(currentBinding, binding) && await options.bindingStore.withLease(bindingIdentity, async () => {
538
+ const leasedBinding = await options.bindingStore.read(bindingIdentity);
539
+ if (!isSameCodexAppServerThreadOwner(leasedBinding, binding)) return false;
539
540
  return await retainCodexAppServerLiveThread(client, binding.threadId, ownership.release, ownership.configFingerprint, ownership.serviceTier);
540
541
  }))) await releaseThreadSubscription?.();
541
542
  } else await releaseThreadSubscription?.();