@openclaw/codex 2026.8.1-beta.2 → 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 +146 -0
  2. package/dist/{attempt-client-cleanup-DMLXUfa8.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-I5Bo-AsX.js → binding-connection-CCQFs8lf.js} +15 -3
  5. package/dist/{bounded-turn-qgZmzy_4.js → bounded-turn-rq5tiSXk.js} +27 -26
  6. package/dist/{capabilities-CybGI1oz.js → capabilities-CGm_94eL.js} +1 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-B1AEz8ZA.js → command-formatters-C54Yg3eA.js} +2 -2
  9. package/dist/{command-handlers-Db8pu_ds.js → command-handlers-BvOAHTrA.js} +111 -67
  10. package/dist/{compact-LspQaGfl.js → compact-Hd7SAc0N.js} +35 -30
  11. package/dist/{session-binding-DPxIvMgE.js → config-Cxw3Cl3k.js} +361 -1161
  12. package/dist/context-compaction-activity-BOeJf7yo.js +58 -0
  13. package/dist/doctor-contract-api.js +128 -26
  14. package/dist/{dynamic-tools-BVdyWkUD.js → dynamic-tools-BFoUcRdx.js} +1341 -1464
  15. package/dist/{effective-mcp-catalog-DIIhAtOZ.js → effective-mcp-catalog-BTJHnDSx.js} +2 -2
  16. package/dist/elicitation-input-DMkeki8d.js +71 -0
  17. package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
  18. package/dist/{event-projector-usage-e5huIQWu.js → event-projector-usage-D3PHFFXh.js} +18 -18
  19. package/dist/harness-DVfUQBlQ.js +248 -0
  20. package/dist/harness.js +2 -226
  21. package/dist/index.js +405 -299
  22. package/dist/{isolated-completion-C58NbL40.js → isolated-completion-Cbbx_5Ed.js} +4 -4
  23. package/dist/launch-args-sXOAg0SX.js +84 -0
  24. package/dist/managed-binary-ZkGodW19.js +248 -0
  25. package/dist/media-understanding-provider.js +2 -2
  26. package/dist/model-catalog-o6Cgjoss.js +101 -0
  27. package/dist/{models-BFlpn1Ex.js → models-DgFWSuxA.js} +25 -28
  28. package/dist/{native-subagent-monitor-DyTGmTUx.js → native-subagent-monitor-CwFyoylz.js} +385 -94
  29. package/dist/node-exec-server.runtime-DXrqpw1c.js +195 -0
  30. package/dist/plugin-approval-roundtrip-D80UZiJ_.js +95 -0
  31. package/dist/{plugin-marketplace-discovery-CzrGJdCR.js → plugin-marketplace-discovery-mdmScYOj.js} +60 -55
  32. package/dist/{plugin-metadata-cache-CNJPj4_b.js → plugin-metadata-cache-CulOABwu.js} +164 -134
  33. package/dist/{protocol-validators-B4F7L8Rf.js → protocol-validators-Bg5rpNxk.js} +203 -7
  34. package/dist/{rate-limits-DZXmOL8-.js → rate-limits-hFtzt2Up.js} +1 -1
  35. package/dist/{sandbox-guard-Cmwc9eIk.js → request-CCm4LaED.js} +207 -20
  36. package/dist/{run-attempt-P8BdxC1I.js → run-attempt-BwNQDH2u.js} +1506 -836
  37. package/dist/{runtime-artifact-BVSPdd6g.js → runtime-artifact-DeBvleJw.js} +4 -7
  38. package/dist/session-binding-q2WSTVmC.js +947 -0
  39. package/dist/{session-catalog-xwNi_SDM.js → session-catalog-C2Tae4rI.js} +1698 -1346
  40. package/dist/session-catalog-home-id-DAKUrm3C.js +112 -0
  41. package/dist/{session-cli-7hgXZDV7.js → session-cli-BuDjm5Ou.js} +20 -7
  42. package/dist/session-permission-policy-gLm40Vtq.js +160 -0
  43. package/dist/session-retirement-CdkI0bvb.js +90 -0
  44. package/dist/{session-upstream-marker-CrIFX06J.js → session-upstream-marker-Bcy33kam.js} +2 -3
  45. package/dist/{settled-turn-finalizer-BRWBO4MO.js → settled-turn-finalizer-B8JJcxCi.js} +27 -22
  46. package/dist/{shared-client-kIBbGjk4.js → shared-client-kNkljY-R.js} +2023 -607
  47. package/dist/{side-question-9HAL26l9.js → side-question-GwD73tX6.js} +109 -57
  48. package/dist/{thread-lifecycle-Bu1BTDXr.js → thread-lifecycle-Ss-uwnC4.js} +1208 -497
  49. package/dist/{thread-ownership-6kOQHlyC.js → thread-ownership-CeYBqg_4.js} +18 -8
  50. package/dist/{plugin-app-cache-key-C3H2CVp6.js → thread-resume-DF54hagX.js} +64 -6
  51. package/dist/{transcript-mirror-B9gGgnJS.js → transcript-mirror-CkEQIna-.js} +158 -41
  52. package/dist/transport-stdio-C7-s9TLG.js +708 -0
  53. package/dist/{upstream-prompt-provenance-ClRBije0.js → upstream-prompt-provenance-CFmsKwr9.js} +12 -14
  54. package/dist/{upstream-session-fork-CE-_LdnP.js → upstream-session-fork-BACGlOFa.js} +86 -88
  55. package/dist/{usage-CHlV0e-o.js → usage-C2l8Mils.js} +3 -3
  56. package/dist/{web-search-provider.runtime-DRw2Vl42.js → web-search-provider.runtime-B2XgRdFv.js} +3 -3
  57. package/openclaw.plugin.json +50 -2
  58. package/package.json +9 -8
  59. package/dist/app-server-policy-zcBDc1JU.js +0 -49
  60. package/dist/incognito-session-ET_ufDH-.js +0 -2
  61. package/dist/request-BRl5_UfX.js +0 -157
  62. package/dist/session-retirement-DoMMJFKm.js +0 -36
  63. package/dist/thread-resume-CPrJNQVM.js +0 -30
  64. package/dist/transport-stdio-DIImwDVS.js +0 -99
@@ -1,28 +1,30 @@
1
- import { D as CODEX_PLUGINS_MARKETPLACE_NAME, P as isCodexFastServiceTier, c as reclaimCurrentCodexSessionGeneration, d as sessionBindingIdentity, g as resolveCodexAppServerRuntimeOptions, i as createCodexSessionGenerationSupersededError, n as assertCodexBindingMayBeReplaced, r as bindingStoreKey, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-DPxIvMgE.js";
2
- import { Q as resolveCodexAppServerAuthAccountCacheKey, V as consumeCodexAppServerLiveThread, a as getLeasedSharedCodexAppServerClient, ct as isJsonObject, et as resolveCodexAppServerAuthProfileIdForAgent, l as releaseLeasedSharedCodexAppServerClient, tt as resolveCodexAppServerFallbackApiKeyCacheKey } from "./shared-client-kIBbGjk4.js";
3
- import { i as assertCodexThreadResumeResponse } from "./protocol-validators-B4F7L8Rf.js";
4
- import { t as listAllCodexAppServerModels } from "./models-BFlpn1Ex.js";
5
- import { i as defaultCodexAppInventoryCache, r as buildCodexPluginAppCacheKey } from "./plugin-app-cache-key-C3H2CVp6.js";
6
- import { Y as isOpenAiCuratedMarketplaceName, q as refreshCodexPluginRuntimeState } from "./thread-lifecycle-Bu1BTDXr.js";
7
- import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
8
- import { t as CODEX_CONTROL_METHODS } from "./capabilities-CybGI1oz.js";
9
- import { s as summarizeCodexAccountUsage } from "./rate-limits-DZXmOL8-.js";
10
- 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-B1AEz8ZA.js";
11
- import { n as resolveCodexNativeExecutionBlock, r as resolveCodexNativeSandboxBlock } from "./sandbox-guard-Cmwc9eIk.js";
12
- 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-6kOQHlyC.js";
13
- import { a as parseCodexPermissionsModeArg, c as setCodexConversationModel, d as stopCodexConversationTurn, i as parseCodexFastModeArg, l as setCodexConversationPermissions, m as canMutateCodexHost, n as parseCodexPluginMarketplaceId, o as readCodexConversationActiveTurn, p as CODEX_NATIVE_EXECUTION_AUTH_ERROR, r as formatPermissionsMode, s as setCodexConversationFastMode, t as discoverCodexMarketplacePlugins, u as steerCodexConversationTurn } from "./plugin-marketplace-discovery-CzrGJdCR.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";
14
15
  import { i as readCodexConversationBindingData, n as createCodexCliNodeConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-CW2GuupV.js";
15
- import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-I5Bo-AsX.js";
16
- import { c as readCodexStatusProbes, l as requestOptions, p as formatCodexCliSessions, s as codexControlRequest, u as safeCodexControlRequest } from "./session-catalog-xwNi_SDM.js";
17
- import { i as readCodexComputerUseStatus, r as installCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-CNJPj4_b.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";
18
19
  import { normalizeOptionalString, normalizeUniqueStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
19
20
  import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
20
21
  import crypto from "node:crypto";
21
- import { ensureAuthProfileStore, findNormalizedProviderValue, resolveAgentDir, resolveAuthProfileEligibility, resolveAuthProfileOrder, resolveProfileUnusableUntilForDisplay, resolveSessionAgentIds } from "openclaw/plugin-sdk/agent-runtime";
22
- import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
22
+ import { ensureAuthProfileStore, findNormalizedProviderValue, resolveAgentDir, resolveAuthProfileEligibility, resolveAuthProfileOrder, resolveProfileUnusableUntilForDisplay } from "openclaw/plugin-sdk/agent-runtime";
23
+ import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
23
24
  import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
24
25
  import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
25
26
  import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
27
+ import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
26
28
  import { MODEL_SELECTION_LOCKED_MESSAGE, isModelSelectionLocked, resolvePersistedSessionRuntimeId } from "openclaw/plugin-sdk/model-session-runtime";
27
29
  //#region extensions/codex/src/command-account.ts
28
30
  const OPENAI_PROVIDER_ID = "openai";
@@ -49,8 +51,8 @@ async function readCodexAccountAuthOverview(params) {
49
51
  limits: params.limits,
50
52
  now
51
53
  });
52
- const subscriptionProfileId = order.find((profileId) => isChatGptSubscriptionProfile(store.profiles[profileId]));
53
54
  const activeIsSubscription = activeProfileId !== void 0 && isChatGptSubscriptionProfile(store.profiles[activeProfileId]);
55
+ const subscriptionProfileId = activeIsSubscription ? activeProfileId : order.find((profileId) => isChatGptSubscriptionProfile(store.profiles[profileId]));
54
56
  const activeUsage = activeIsSubscription && params.limits.ok ? summarizeCodexAccountUsage(params.limits.value, now) : void 0;
55
57
  const subscriptionUsage = subscriptionProfileId && (!activeIsSubscription || subscriptionProfileId !== activeProfileId) ? await readSubscriptionUsage({
56
58
  ...params,
@@ -155,13 +157,20 @@ function resolveLiveAccountProfileId(params) {
155
157
  const type = normalizeOptionalString(account.type)?.toLowerCase();
156
158
  if (type === "chatgpt") {
157
159
  const email = normalizeOptionalString(account.email)?.toLowerCase();
158
- const firstSubscription = params.order.find((profileId) => isChatGptSubscriptionProfile(params.store.profiles[profileId]));
159
- if (!email) return firstSubscription;
160
- return params.order.find((profileId) => {
161
- const credential = params.store.profiles[profileId];
162
- if (!credential || !isChatGptSubscriptionProfile(credential)) return false;
163
- return (credential.email?.trim().toLowerCase() ?? extractEmailFromProfileId(profileId))?.toLowerCase() === email;
164
- }) ?? 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];
165
174
  }
166
175
  if (type === "apikey" || type === "api_key") return params.order.find((profileId) => params.store.profiles[profileId]?.type === "api_key");
167
176
  }
@@ -1103,7 +1112,7 @@ function conversationBindingIdentity(bindingId) {
1103
1112
  };
1104
1113
  }
1105
1114
  function resolveCodexConversationControlScope(ctx) {
1106
- const { sessionAgentId } = resolveSessionAgentIds({
1115
+ const { sessionAgentId } = resolveSessionAgentIdsStrict({
1107
1116
  sessionKey: ctx.sessionKey,
1108
1117
  agentId: ctx.agentId,
1109
1118
  config: ctx.config
@@ -1487,13 +1496,23 @@ async function describeConversationBinding(deps, ctx) {
1487
1496
  const identity = conversationBindingIdentity(data.bindingId);
1488
1497
  const threadBinding = await deps.bindingStore.read(identity);
1489
1498
  const active = deps.readCodexConversationActiveTurn(identity);
1499
+ const sessionKey = ctx.sessionKey?.trim();
1500
+ const { agentId } = resolveCodexConversationControlScope(ctx);
1501
+ const sessionEntry = sessionKey ? getSessionEntry({
1502
+ agentId,
1503
+ storePath: resolveStorePath(ctx.config.session?.store, { agentId }),
1504
+ sessionKey,
1505
+ hydrateSkillPromptRefs: false,
1506
+ readConsistency: "latest"
1507
+ }) : void 0;
1508
+ const permissionMode = !ctx.sessionId || sessionEntry?.sessionId === ctx.sessionId ? sessionEntry?.permissionMode : void 0;
1490
1509
  return [
1491
1510
  "Codex conversation binding:",
1492
1511
  `- Thread: ${formatCodexDisplayText(threadBinding?.threadId ?? "unknown")}`,
1493
1512
  `- Workspace: ${formatCodexDisplayText(data.workspaceDir)}`,
1494
1513
  `- Model: ${formatCodexDisplayText(threadBinding?.model ?? "default")}`,
1495
1514
  `- Fast: ${isCodexFastServiceTier(threadBinding?.serviceTier) ? "on" : "off"}`,
1496
- `- Permissions: ${threadBinding ? formatPermissionsMode(threadBinding) : "default"}`,
1515
+ `- Permissions: ${formatPermissionsMode(permissionMode)}`,
1497
1516
  `- Active run: ${formatCodexDisplayText(active ? active.turnId : "none")}`,
1498
1517
  `- Binding: ${formatCodexDisplayText(data.bindingId)}`
1499
1518
  ].join("\n");
@@ -1544,13 +1563,8 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1544
1563
  })) throw createCodexSessionGenerationSupersededError(identity.sessionId);
1545
1564
  const currentBinding = await deps.bindingStore.read(identity);
1546
1565
  assertCodexBindingMayBeReplaced(currentBinding, "attaching a different resumed thread");
1547
- const authProfileId = resolveCodexAppServerAuthProfileIdForAgent({
1548
- authProfileId: currentBinding?.authProfileId,
1549
- agentDir: scope.agentDir,
1550
- config: ctx.config
1551
- });
1552
- let committedResponse = false;
1553
- const commitResumedThread = async (value, client) => {
1566
+ let pendingResumeConfiguration = false;
1567
+ const commitResumedThread = async (value, client, { authProfileId, assertCurrent }) => {
1554
1568
  const response = assertCodexThreadResumeResponse(value);
1555
1569
  const effectiveThreadId = response.thread.id;
1556
1570
  if (effectiveThreadId !== normalizedThreadId) throw new Error(`Codex thread/resume returned ${effectiveThreadId} for ${normalizedThreadId}`);
@@ -1562,52 +1576,73 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
1562
1576
  agentDir: scope.agentDir,
1563
1577
  config: ctx.config
1564
1578
  });
1565
- const bindingBeforeCommit = await deps.bindingStore.read(identity);
1566
- assertCodexBindingMayBeReplaced(bindingBeforeCommit, "committing a different resumed thread");
1567
- const clientId = client?.getInstanceId();
1568
- const sameOwner = client ? isSameCodexAppServerThreadOwner(bindingBeforeCommit, {
1569
- threadId: effectiveThreadId,
1570
- clientId
1571
- }) : bindingBeforeCommit?.threadId === effectiveThreadId;
1579
+ const clientId = client.getInstanceId();
1572
1580
  let retained = false;
1581
+ let sameOwner = false;
1582
+ let knownOwnership;
1573
1583
  try {
1574
- if (client) {
1575
- retained = await retainCodexAppServerBindingSubscription(client, effectiveThreadId, sameOwner ? await consumeCodexAppServerLiveThread(client, effectiveThreadId) : void 0);
1576
- if (!retained) throw new Error("Codex resumed thread lost its native subscription owner.");
1577
- }
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.");
1578
1599
  if (bindingBeforeCommit && !sameOwner) await releaseCodexAppServerBindingSubscription(bindingBeforeCommit);
1600
+ assertCurrent();
1579
1601
  if (!await deps.bindingStore.mutate(identity, {
1580
1602
  kind: "set",
1581
1603
  binding: {
1582
- ...bindingBeforeCommit?.threadId === effectiveThreadId ? bindingBeforeCommit : {},
1604
+ ...sameThreadBinding,
1583
1605
  threadId: effectiveThreadId,
1584
- ...clientId ? { clientId } : {},
1606
+ clientId,
1585
1607
  cwd: resumedCwd,
1608
+ rolloutPath: response.thread.path ?? sameThreadBinding?.rolloutPath,
1609
+ pendingResumeConfiguration: pendingResumeConfiguration ? true : void 0,
1586
1610
  authProfileId,
1587
1611
  model: response.model,
1588
1612
  modelProvider,
1589
1613
  historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString()
1590
1614
  }
1591
- })) 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.");
1592
1616
  } catch (error) {
1593
- 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);
1594
1620
  throw error;
1595
1621
  }
1596
- committedResponse = true;
1597
1622
  };
1598
- const response = await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.resumeThread, {
1623
+ await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.resumeThread, {
1599
1624
  threadId: normalizedThreadId,
1600
1625
  excludeTurns: true
1601
1626
  }, {
1602
1627
  config: ctx.config,
1628
+ agentId: scope.agentId,
1603
1629
  agentDir: scope.agentDir,
1604
- authProfileId,
1630
+ authProfileId: currentBinding?.authProfileId,
1605
1631
  sessionKey: ctx.sessionKey,
1606
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
+ },
1607
1643
  onResponse: commitResumedThread
1608
1644
  });
1609
- if (!committedResponse) await commitResumedThread(response);
1610
- 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." : ""}`;
1611
1646
  })
1612
1647
  });
1613
1648
  }
@@ -1820,9 +1855,9 @@ async function setConversationModel(deps, ctx, pluginConfig, args) {
1820
1855
  hydrateSkillPromptRefs: false,
1821
1856
  readConsistency: "latest"
1822
1857
  }) : void 0;
1823
- const selectedModel = currentSession && currentSession.sessionId === ctx.sessionId ? currentSession.modelOverride : void 0;
1858
+ const selectedModel = currentSession && currentSession.sessionId === ctx.sessionId ? currentSession.modelOverride ?? currentSession.model : void 0;
1824
1859
  const binding = await deps.bindingStore.read(target.identity);
1825
- const activeModel = selectedModel ?? binding?.model;
1860
+ const activeModel = target.identity.kind === "conversation" ? binding?.model : selectedModel ?? binding?.model;
1826
1861
  return activeModel ? `Codex model: ${formatCodexDisplayText(activeModel)}` : "Usage: /codex model <model>";
1827
1862
  }
1828
1863
  return await deps.setCodexConversationModel({
@@ -1831,12 +1866,7 @@ async function setConversationModel(deps, ctx, pluginConfig, args) {
1831
1866
  pluginConfig,
1832
1867
  model: normalized,
1833
1868
  agentDir: target.agentDir,
1834
- config: ctx.config,
1835
- ...ctx.sessionId && ctx.sessionKey ? { session: {
1836
- agentId: target.agentId,
1837
- sessionId: ctx.sessionId,
1838
- sessionKey: ctx.sessionKey
1839
- } } : {}
1869
+ config: ctx.config
1840
1870
  });
1841
1871
  }
1842
1872
  async function setConversationFastMode(deps, ctx, args) {
@@ -1855,14 +1885,19 @@ async function setConversationFastMode(deps, ctx, args) {
1855
1885
  async function setConversationPermissions(deps, ctx, args) {
1856
1886
  if (args.length > 1) return "Usage: /codex permissions [default|yolo|status]";
1857
1887
  const target = await resolveControlTarget(ctx);
1858
- if (!target) return "Cannot set Codex permissions because this command did not include a stable binding identity.";
1888
+ if (!target || !ctx.sessionId || !ctx.sessionKey) return "Cannot set Codex permissions because this command did not include a complete session identity.";
1859
1889
  const value = args[0];
1860
1890
  const parsed = parseCodexPermissionsModeArg(value);
1861
1891
  if (value && !parsed && value.trim().toLowerCase() !== "status") return "Usage: /codex permissions [default|yolo|status]";
1892
+ if (parsed === "yolo" && !hasCodexAdminScope(ctx)) return CODEX_FULL_PERMISSIONS_AUTH_ERROR;
1862
1893
  return await deps.setCodexConversationPermissions({
1863
- identity: target.identity,
1864
- bindingStore: deps.bindingStore,
1865
- mode: parsed
1894
+ mode: parsed,
1895
+ config: ctx.config,
1896
+ session: {
1897
+ agentId: target.agentId,
1898
+ sessionId: ctx.sessionId,
1899
+ sessionKey: ctx.sessionKey
1900
+ }
1866
1901
  });
1867
1902
  }
1868
1903
  async function startThreadAction(deps, ctx, pluginConfig, kind, args) {
@@ -2276,6 +2311,14 @@ function formatPluginList(plugins, options = {}) {
2276
2311
  }
2277
2312
  //#endregion
2278
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
+ ]);
2279
2322
  async function handleCodexSubcommand(ctx, options) {
2280
2323
  const deps = resolveCodexCommandDeps(options.deps);
2281
2324
  const args = splitArgs(ctx.args);
@@ -2283,6 +2326,7 @@ async function handleCodexSubcommand(ctx, options) {
2283
2326
  const [subcommand = "status", ...rest] = args;
2284
2327
  const normalized = subcommand.toLowerCase();
2285
2328
  if (normalized === "help") return { text: buildHelp() };
2329
+ if (CODEX_HOST_INSPECTION_SUBCOMMANDS.has(normalized) && !canMutateCodexHost(ctx)) return { text: CODEX_HOST_INSPECTION_AUTH_ERROR };
2286
2330
  if (CODEX_NATIVE_CONTROL_SUBCOMMANDS.has(normalized) && !returnsBeforeNativeCodexExecution(normalized, rest) && !isReadOnlyCodexGoalCommand(normalized, rest) && !canMutateCodexHost(ctx)) return { text: CODEX_NATIVE_EXECUTION_AUTH_ERROR };
2287
2331
  const sandboxBlock = resolveCodexNativeCommandSandboxBlock(ctx, normalized, rest);
2288
2332
  if (sandboxBlock) return { text: sandboxBlock };
@@ -1,16 +1,17 @@
1
- import { d as sessionBindingIdentity, t as CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS } from "./session-binding-DPxIvMgE.js";
2
- import { V as consumeCodexAppServerLiveThread, a as getLeasedSharedCodexAppServerClient, ct as isJsonObject, l as releaseLeasedSharedCodexAppServerClient, q as retainCodexAppServerLiveThread, z as CodexAppServerRpcError } from "./shared-client-kIBbGjk4.js";
3
- import { _ as readCodexNotificationTurnId, a as closeCodexStartupClientBestEffort, d as unsubscribeCodexThreadBestEffort, g as readCodexNotificationThreadId, r as CodexAppServerUnsafeSubscriptionError, s as isCodexAlreadyTerminalInterruptError } from "./attempt-client-cleanup-DMLXUfa8.js";
4
- import { i as readCodexThreadContextSnapshot, x as readCodexNotificationItem } from "./event-projector-usage-e5huIQWu.js";
5
- import { t as isIncognitoSessionKey } from "./incognito-session-ET_ufDH-.js";
6
- import { t as resumeCodexAppServerThread } from "./thread-resume-CPrJNQVM.js";
7
- import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-Cmwc9eIk.js";
8
- import { t as isSameCodexAppServerThreadOwner } from "./thread-ownership-6kOQHlyC.js";
9
- import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-I5Bo-AsX.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";
9
+ import { t as persistCodexContextCompactionActivity } from "./context-compaction-activity-BOeJf7yo.js";
10
10
  import { asOptionalRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
11
11
  import { createDeferred } from "openclaw/plugin-sdk/extension-shared";
12
12
  import { embeddedAgentLog, resolveCompactionTimeoutMs } from "openclaw/plugin-sdk/agent-harness-runtime";
13
- import { resolveAgentDir as resolveAgentDir$1, resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
13
+ import { resolveAgentDir as resolveAgentDir$1 } from "openclaw/plugin-sdk/agent-runtime";
14
+ import { resolveDefaultAgentId as resolveDefaultAgentId$1 } from "openclaw/plugin-sdk/agent-scope-runtime";
14
15
  import { AsyncLocalStorage } from "node:async_hooks";
15
16
  import { coerceErrorMessage } from "openclaw/plugin-sdk/error-runtime";
16
17
  import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
@@ -54,6 +55,8 @@ function watchCodexNativeCompactionCompletion(params) {
54
55
  };
55
56
  const complete = () => finish({
56
57
  completed: true,
58
+ ...compactionTurnId ? { turnId: compactionTurnId } : {},
59
+ ...compactionItemId ? { itemId: compactionItemId } : {},
57
60
  ...tokensAfter !== void 0 ? { tokensAfter } : {}
58
61
  });
59
62
  const fail = (reason) => finish({
@@ -235,11 +238,9 @@ function readIgnoredCompactionOverridePaths(params) {
235
238
  const ignored = /* @__PURE__ */ new Set();
236
239
  for (const entry of readCompactionOverrideEntries(params)) {
237
240
  const localProvider = typeof entry.record.provider === "string" ? entry.record.provider.trim() : "";
238
- const inheritedProvider = !localProvider && typeof entry.inheritedRecord?.provider === "string" ? entry.inheritedRecord.provider.trim() : "";
239
- const providerPath = localProvider ? `${entry.path}.compaction.provider` : inheritedProvider && entry.inheritedPath ? `${entry.inheritedPath}.compaction.provider` : void 0;
240
241
  if (typeof entry.record.model === "string" && entry.record.model.trim()) ignored.add(`${entry.path}.compaction.model`);
241
242
  if (typeof entry.record.thinkingLevel === "string" && entry.record.thinkingLevel.trim()) ignored.add(`${entry.path}.compaction.thinkingLevel`);
242
- if (providerPath) ignored.add(providerPath);
243
+ if (localProvider) ignored.add(`${entry.path}.compaction.provider`);
243
244
  }
244
245
  return [...ignored];
245
246
  }
@@ -250,17 +251,6 @@ function readCompactionOverrideEntries(params) {
250
251
  path: "agents.defaults",
251
252
  record: defaultRecord
252
253
  });
253
- const agentId = readAgentIdFromSessionKey(params.sessionKey ?? params.sandboxSessionKey);
254
- if (!agentId) return entries;
255
- const agentRecord = asOptionalRecord((Array.isArray(params.config?.agents?.list) ? params.config.agents.list : []).find((agent) => {
256
- return (typeof agent?.id === "string" ? agent.id.trim().toLowerCase() : "") === agentId;
257
- })?.compaction);
258
- if (agentRecord) entries.push({
259
- path: `agents.list.${agentId}`,
260
- record: agentRecord,
261
- inheritedRecord: defaultRecord,
262
- inheritedPath: "agents.defaults"
263
- });
264
254
  return entries;
265
255
  }
266
256
  function readAgentIdFromSessionKey(sessionKey) {
@@ -291,6 +281,7 @@ async function compactCodexNativeThread(params, options) {
291
281
  config: params.config,
292
282
  sessionKey: params.sandboxSessionKey ?? params.sessionKey,
293
283
  sessionId: params.sessionId,
284
+ agentId: params.agentId,
294
285
  sandbox,
295
286
  surface: "native compaction"
296
287
  });
@@ -325,7 +316,7 @@ async function compactCodexNativeThread(params, options) {
325
316
  let connection;
326
317
  try {
327
318
  const config = params.config ?? {};
328
- const agentId = params.agentId ?? readAgentIdFromSessionKey(params.sessionKey) ?? resolveDefaultAgentId(config);
319
+ const agentId = params.agentId ?? readAgentIdFromSessionKey(params.sessionKey) ?? resolveDefaultAgentId$1(config);
329
320
  connection = resolveCodexBindingAppServerConnection({
330
321
  binding,
331
322
  authProfileId: requestedAuthProfileId ?? binding.authProfileId,
@@ -431,27 +422,30 @@ async function compactCodexNativeThread(params, options) {
431
422
  result: skippedCodexNativeCompactionResult(params, {
432
423
  reason: "codex app-server compaction aborted before native compaction",
433
424
  code: "aborted_before_native_compaction",
425
+ request: options.nativeCompactionRequest ?? "after_context_engine",
434
426
  expectedThreadId: binding.threadId,
435
427
  currentThreadId: currentBinding?.threadId
436
428
  })
437
429
  };
438
430
  }
439
431
  if (!currentBinding || !isSameNativeCompactionBinding(currentBinding, binding)) {
440
- embeddedAgentLog.warn("skipping codex app-server compaction because the thread binding changed", {
432
+ embeddedAgentLog.warn("codex app-server compaction could not use the thread binding because it changed", {
441
433
  sessionId: params.sessionId,
442
434
  sessionKey: params.sessionKey,
443
435
  expectedThreadId: binding.threadId,
444
436
  currentThreadId: currentBinding?.threadId
445
437
  });
438
+ const isRequiredPreflight = options.nativeCompactionRequest === "required_preflight";
446
439
  return {
447
440
  started: false,
448
- result: options.allowNonManualNativeRequest ? skippedCodexNativeCompactionResult(params, {
441
+ result: options.allowNonManualNativeRequest && !isRequiredPreflight ? skippedCodexNativeCompactionResult(params, {
449
442
  reason: "codex app-server binding changed before native compaction",
450
443
  code: "binding_changed_before_native_compaction",
444
+ request: options.nativeCompactionRequest ?? "after_context_engine",
451
445
  expectedThreadId: binding.threadId,
452
446
  currentThreadId: currentBinding?.threadId
453
447
  }) : failedCodexThreadBindingCompactionResult(params, {
454
- threadId: binding.threadId,
448
+ threadId: currentBinding?.threadId ?? binding.threadId,
455
449
  reason: "codex app-server binding changed before native compaction",
456
450
  recovery: "stale_thread_binding"
457
451
  })
@@ -502,6 +496,16 @@ async function compactCodexNativeThread(params, options) {
502
496
  const completion = await completionWatch.completion;
503
497
  if (!completion.completed) throw new Error(completion.reason);
504
498
  tokensAfter = completion.tokensAfter;
499
+ if (completion.turnId && completion.itemId) await persistCodexContextCompactionActivity({
500
+ sessionTarget: params.sessionTarget,
501
+ config: params.config,
502
+ cwd: params.workspaceDir,
503
+ runId: params.runId,
504
+ threadId: binding.threadId,
505
+ turnId: completion.turnId,
506
+ itemId: completion.itemId,
507
+ timestamp: Date.now()
508
+ });
505
509
  embeddedAgentLog.info("completed codex app-server compaction", {
506
510
  sessionId: params.sessionId,
507
511
  threadId: binding.threadId
@@ -545,7 +549,7 @@ async function compactCodexNativeThread(params, options) {
545
549
  pending: false,
546
550
  completed: true,
547
551
  ...options.allowNonManualNativeRequest ? {
548
- request: "after_context_engine",
552
+ request: options.nativeCompactionRequest ?? "after_context_engine",
549
553
  trigger: params.trigger ?? "unknown"
550
554
  } : {}
551
555
  };
@@ -560,6 +564,7 @@ async function compactCodexNativeThread(params, options) {
560
564
  if (options.allowNonManualNativeRequest) return skippedCodexNativeCompactionResult(params, {
561
565
  reason: "codex app-server compaction aborted before native compaction",
562
566
  code: "aborted_before_native_compaction",
567
+ request: options.nativeCompactionRequest ?? "after_context_engine",
563
568
  expectedThreadId: initialBinding.threadId,
564
569
  currentThreadId: binding.threadId
565
570
  });
@@ -594,7 +599,7 @@ function skippedCodexNativeCompactionResult(params, skipped) {
594
599
  backend: "codex-app-server",
595
600
  skipped: true,
596
601
  reason: skipped.code,
597
- request: "after_context_engine",
602
+ request: skipped.request ?? "after_context_engine",
598
603
  trigger: params.trigger ?? "unknown",
599
604
  ...skipped.expectedThreadId ? { expectedThreadId: skipped.expectedThreadId } : {},
600
605
  ...skipped.currentThreadId ? { currentThreadId: skipped.currentThreadId } : {}