@openclaw/codex 2026.9.1-beta.1 → 2026.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/api.js +8 -9
  2. package/dist/{attempt-client-cleanup-bfsmcQ6m.js → attempt-client-cleanup-Bp1ZOnk2.js} +105 -75
  3. package/dist/attempt-context-CSazkWns.js +634 -0
  4. package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
  5. package/dist/{bounded-turn-B7iBUcuP.js → bounded-turn-DxGJRYbY.js} +53 -57
  6. package/dist/{capabilities-BRMh0aIq.js → capabilities-B1mgvpP8.js} +2 -1
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-DEsIufkt.js → command-formatters-DSbGMXA0.js} +5 -4
  9. package/dist/{command-handlers-D_-1_qRp.js → command-handlers-DOJvGv6-.js} +243 -148
  10. package/dist/{compact-BglNFZrQ.js → compact-Y_xBqrHN.js} +109 -65
  11. package/dist/{config-giW8X0QA.js → config-CyapYSji.js} +328 -374
  12. package/dist/config-utils-C57JiJrU.js +69 -0
  13. package/dist/{context-compaction-activity-BOeJf7yo.js → context-compaction-activity-CMla5FPJ.js} +4 -1
  14. package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
  15. package/dist/doctor-contract-api.js +144 -14
  16. package/dist/{dynamic-tools-Dnlfa--w.js → dynamic-tools-BwpvTxaX.js} +1119 -1135
  17. package/dist/{effective-mcp-catalog-CTeGrnfO.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
  18. package/dist/{event-projector-assistant-message-C5-Ds8mA.js → event-projector-assistant-message-B9kp6iGC.js} +15 -6
  19. package/dist/event-projector-usage-ZqEVbAEY.js +212 -0
  20. package/dist/{harness-Csz0F-DK.js → harness-Czh2Sdoc.js} +65 -52
  21. package/dist/harness.js +1 -1
  22. package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
  23. package/dist/index.js +495 -457
  24. package/dist/{isolated-completion-Cv6FqygM.js → isolated-completion-CRh-51AK.js} +9 -21
  25. package/dist/{managed-binary-DFYK4DWq.js → managed-binary-DcpnJF9x.js} +117 -80
  26. package/dist/media-understanding-provider.js +1 -1
  27. package/dist/model-catalog-DT5vo6qo.js +101 -0
  28. package/dist/{models-TS3HBU-q.js → models-CcrgSMQR.js} +26 -29
  29. package/dist/{native-subagent-monitor-4Mfq2HDs.js → native-subagent-monitor-B3bvQGcg.js} +63 -122
  30. package/dist/{node-exec-server.runtime-BpWqJO1V.js → node-exec-server.runtime-nfbUOtUB.js} +10 -7
  31. package/dist/{plugin-approval-roundtrip-bUm777tR.js → plugin-approval-roundtrip-aQVdyL5g.js} +30 -3
  32. package/dist/{plugin-marketplace-discovery-B9DvaAG-.js → plugin-marketplace-discovery-B7gHXJ3d.js} +44 -30
  33. package/dist/{plugin-metadata-cache-CTCT3w5L.js → plugin-metadata-cache-BwCLTY_U.js} +6 -6
  34. package/dist/provider-capabilities-BpG9Ltc5.js +101 -0
  35. package/dist/{rate-limits-C5_D8Gmb.js → rate-limits-Fx_l4eNa.js} +3 -2
  36. package/dist/{sandbox-guard-kuWTn9C5.js → request-C8H22rPi.js} +195 -2
  37. package/dist/{run-attempt-DYc0QCBF.js → run-attempt-BzthFQSM.js} +1616 -2634
  38. package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-Bh_gf6-t.js} +22 -15
  39. package/dist/{session-binding-Bcynfd-_.js → session-binding-4Ki04sW-.js} +282 -399
  40. package/dist/session-binding-record-CyaXZvTe.js +270 -0
  41. package/dist/{session-catalog-DaLKVtpH.js → session-catalog-B47uwekb.js} +812 -504
  42. package/dist/{session-cli-DMc4oS2w.js → session-cli-BjLhpmS1.js} +1 -1
  43. package/dist/session-history-DWmMqiqW.js +93 -0
  44. package/dist/session-history-read-LHldwvyh.js +36 -0
  45. package/dist/session-history-worker-runtime.js +48 -0
  46. package/dist/session-history.worker-zZVcx0ME.js +267 -0
  47. package/dist/session-history.worker.js +2 -0
  48. package/dist/session-initialization-BCFVnLL4.js +75 -0
  49. package/dist/{session-permission-policy-BrNH1bjy.js → session-permission-policy-BaueHmSj.js} +2 -2
  50. package/dist/session-retirement-DNdmYdFc.js +97 -0
  51. package/dist/{session-upstream-marker-BIkusb95.js → session-upstream-marker-DReTpGz6.js} +20 -4
  52. package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
  53. package/dist/settled-turn-finalizer-BI-b1sry.js +115 -0
  54. package/dist/{shared-client-DKz23hHY.js → shared-client-CKhX2kFt.js} +3659 -847
  55. package/dist/{side-question-DjA_jsNe.js → side-question-B6DWAw1A.js} +168 -81
  56. package/dist/{thread-lifecycle-L7oEkTlq.js → thread-lifecycle-DPK30jad.js} +2412 -2145
  57. package/dist/{thread-ownership-DZeuKH1j.js → thread-ownership-CbucAmmp.js} +27 -16
  58. package/dist/thread-policy-CTalhWFy.js +105 -0
  59. package/dist/{plugin-app-cache-key-C1CAdfcP.js → thread-resume-BLgqkUc1.js} +61 -9
  60. package/dist/{transcript-mirror-DsCMWBca.js → transcript-mirror-_njEB84z.js} +114 -110
  61. package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
  62. package/dist/transport-stdio-CzTngV0j.js +728 -0
  63. package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
  64. package/dist/upstream-session-fork-1fwbNKzQ.js +886 -0
  65. package/dist/{usage-ROIaW3wo.js → usage-i9fv5-4m.js} +3 -3
  66. package/dist/{web-search-provider.runtime-ClaNPV7N.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
  67. package/openclaw.plugin.json +1 -30
  68. package/package.json +6 -6
  69. package/dist/binding-connection-BMvPX73o.js +0 -45
  70. package/dist/command-rpc-CCeCkf_v.js +0 -90
  71. package/dist/event-projector-usage-Bk1I90Bg.js +0 -328
  72. package/dist/incognito-session-ET_ufDH-.js +0 -2
  73. package/dist/model-catalog-i9rNBthX.js +0 -48
  74. package/dist/protocol-validators-VeJxxJ0U.js +0 -2421
  75. package/dist/request-DXXGHko0.js +0 -157
  76. package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
  77. package/dist/session-retirement-CcNC3YSY.js +0 -36
  78. package/dist/settled-turn-finalizer-Dc3ApjU4.js +0 -328
  79. package/dist/thread-resume-BE9qNEW0.js +0 -30
  80. package/dist/transport-stdio-DhoGy33Z.js +0 -99
  81. package/dist/upstream-session-fork-DlaHxSLC.js +0 -326
@@ -0,0 +1,69 @@
1
+ import { asOptionalRecord as readRecord, normalizeOptionalString as readNonEmptyString, parseBooleanValue } from "openclaw/plugin-sdk/string-coerce-runtime";
2
+ import { createHmac, randomBytes } from "node:crypto";
3
+ import { resolvePositiveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
4
+ import { splitCommandArgs } from "openclaw/plugin-sdk/process-runtime";
5
+ import { normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
6
+ //#region extensions/codex/src/app-server/config-contracts.ts
7
+ const CODEX_PLUGINS_MARKETPLACE_NAME = "openai-curated";
8
+ const CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME = "workspace-directory";
9
+ const CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN = /^[A-Za-z0-9_-]+$/;
10
+ //#endregion
11
+ //#region extensions/codex/src/app-server/config-utils.ts
12
+ const START_OPTIONS_KEY_SECRET_SYMBOL = Symbol.for("openclaw.codexAppServerStartOptionsKeySecret");
13
+ const START_OPTIONS_KEY_SECRET = getStartOptionsKeySecret();
14
+ const PLAIN_DECIMAL_NUMBER_RE = /^[+-]?(?:(?:\d+\.?\d*)|(?:\.\d+))$/;
15
+ function normalizeCodexServiceTier(value) {
16
+ if (typeof value !== "string") return;
17
+ const trimmed = value.trim();
18
+ if (!trimmed) return;
19
+ const normalized = trimmed.toLowerCase();
20
+ if (normalized === "fast" || normalized === "priority") return "priority";
21
+ if (normalized === "flex") return "flex";
22
+ return trimmed;
23
+ }
24
+ function isCodexFastServiceTier(value) {
25
+ return normalizeCodexServiceTier(value) === "priority";
26
+ }
27
+ function normalizePositiveNumber(value, fallback) {
28
+ return resolvePositiveTimerTimeoutMs(value, fallback);
29
+ }
30
+ function normalizeHeaders(value) {
31
+ if (!value || typeof value !== "object" || Array.isArray(value)) return {};
32
+ return Object.fromEntries(Object.entries(value).map(([key, child]) => [key.trim(), normalizeCodexAppServerSecretInput({
33
+ value: child,
34
+ path: `plugins.entries.codex.config.appServer.headers.${key}`
35
+ })]).filter((entry) => Boolean(entry[0] && entry[1])));
36
+ }
37
+ function normalizeCodexAppServerSecretInput(params) {
38
+ return normalizeResolvedSecretInputString(params);
39
+ }
40
+ function readBooleanEnv(value) {
41
+ return parseBooleanValue(value);
42
+ }
43
+ function readExecSecurity(value) {
44
+ return value === "deny" || value === "allowlist" || value === "full" ? value : void 0;
45
+ }
46
+ function readExecAsk(value) {
47
+ return value === "off" || value === "on-miss" || value === "always" ? value : void 0;
48
+ }
49
+ function readNumberEnv(value) {
50
+ const trimmed = value?.trim();
51
+ if (!trimmed || !PLAIN_DECIMAL_NUMBER_RE.test(trimmed)) return;
52
+ const parsed = Number(trimmed);
53
+ return Number.isFinite(parsed) ? parsed : void 0;
54
+ }
55
+ function resolveArgs(configArgs, envArgs) {
56
+ if (Array.isArray(configArgs)) return configArgs.map((entry) => readNonEmptyString(entry)).filter((entry) => entry !== void 0);
57
+ return splitCommandArgs(typeof configArgs === "string" ? configArgs : envArgs ?? "", { allowUnclosedQuotes: true });
58
+ }
59
+ function hashSecretForKey(value, label) {
60
+ if (!value) return null;
61
+ return createHmac("sha256", START_OPTIONS_KEY_SECRET).update(label).update("\0").update(value).digest("hex");
62
+ }
63
+ function getStartOptionsKeySecret() {
64
+ const globalState = globalThis;
65
+ globalState[START_OPTIONS_KEY_SECRET_SYMBOL] ??= randomBytes(32);
66
+ return globalState[START_OPTIONS_KEY_SECRET_SYMBOL];
67
+ }
68
+ //#endregion
69
+ export { normalizeHeaders as a, readExecAsk as c, readNumberEnv as d, readRecord as f, CODEX_PLUGIN_MARKETPLACE_NAME_PATTERN as g, CODEX_PLUGINS_WORKSPACE_MARKETPLACE_NAME as h, normalizeCodexServiceTier as i, readExecSecurity as l, CODEX_PLUGINS_MARKETPLACE_NAME as m, isCodexFastServiceTier as n, normalizePositiveNumber as o, resolveArgs as p, normalizeCodexAppServerSecretInput as r, readBooleanEnv as s, hashSecretForKey as t, readNonEmptyString as u };
@@ -20,7 +20,10 @@ async function persistCodexContextCompactionActivity(params) {
20
20
  itemId: params.itemId,
21
21
  ...params.runId ? { runId: params.runId } : {}
22
22
  },
23
- ...params.runId ? { __openclaw: { runId: params.runId } } : {},
23
+ __openclaw: {
24
+ itemId: params.itemId,
25
+ ...params.runId ? { runId: params.runId } : {}
26
+ },
24
27
  timestamp: params.timestamp,
25
28
  idempotencyKey: activityId
26
29
  };
@@ -94,7 +94,8 @@ function legacyCodexConversationBindingId(sessionFile) {
94
94
  return `legacy-${createHash("sha256").update(sessionFile).digest("base64url")}`;
95
95
  }
96
96
  function resolveCodexDefaultWorkspaceDir(pluginConfig) {
97
- return normalizeOptionalString(asOptionalRecord(asOptionalRecord(pluginConfig)?.appServer)?.defaultWorkspaceDir) ?? process.cwd();
97
+ const appServer = asOptionalRecord(asOptionalRecord(pluginConfig)?.appServer);
98
+ return normalizeOptionalString(appServer?.defaultWorkspaceDir) ?? process.cwd();
98
99
  }
99
100
  function readConversationStart(value) {
100
101
  const read = (key) => {
@@ -1,14 +1,114 @@
1
1
  import { n as CODEX_APP_SERVER_BINDING_NAMESPACE, t as CODEX_APP_SERVER_BINDING_MAX_ENTRIES } from "./session-binding-meta-B7aEMU7g.js";
2
- import { asNullableRecord, isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
2
+ import { asNullableRecord, asOptionalRecord, isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
3
+ import { createHash } from "node:crypto";
4
+ import { listAgentIds, resolveAgentDir, resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
3
5
  import fs from "node:fs/promises";
4
6
  import path from "node:path";
7
+ import { canonicalPathFromExistingAncestor, isPathInside } from "openclaw/plugin-sdk/file-access-runtime";
5
8
  import { isDeepStrictEqual } from "node:util";
6
- import { listAgentIds, resolveAgentDir, resolveSessionAgentIds } from "openclaw/plugin-sdk/agent-scope-runtime";
7
9
  import { pathExists } from "openclaw/plugin-sdk/security-runtime";
10
+ import { setImmediate } from "node:timers/promises";
8
11
  import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
9
- import { canonicalPathFromExistingAncestor, isPathInside } from "openclaw/plugin-sdk/file-access-runtime";
10
12
  import { withFileLock } from "openclaw/plugin-sdk/file-lock";
11
13
  import { archiveLegacyStateSource, legacyStateFileExists } from "openclaw/plugin-sdk/runtime-doctor-migrations";
14
+ import { resolveStorePath } from "openclaw/plugin-sdk/session-store-paths";
15
+ //#region extensions/codex/src/migration/session-binding-orphans.ts
16
+ const PAGE_SIZE = 512;
17
+ const KEY_PREFIXES = ["session-key:", "session:"];
18
+ function readBindingCandidate(row, prefix) {
19
+ const identity = /^([a-z0-9][a-z0-9_-]{0,63}):(.+)$/u.exec(row.key.slice(prefix.length));
20
+ if (!identity) return;
21
+ const agentId = identity[1];
22
+ const keyIdentity = identity[2];
23
+ const stored = asOptionalRecord(row.value);
24
+ const sessionId = typeof stored?.sessionId === "string" ? stored.sessionId.trim() : "";
25
+ const stable = prefix === "session-key:";
26
+ if (!stored || stored.version !== 1 || !sessionId || (stable ? !/^[A-Za-z0-9_-]{43}$/u.test(keyIdentity) : sessionId !== keyIdentity)) return;
27
+ if (stored.state === "cleared") {
28
+ if (stored.binding !== void 0 || stored.retired !== void 0 && stored.retired !== true) return;
29
+ } else if (stored.state === "active") {
30
+ const binding = asOptionalRecord(stored.binding);
31
+ if (!binding || typeof binding.threadId !== "string" || !binding.threadId.trim() || typeof binding.cwd !== "string" || binding.connectionScope !== void 0 || binding.supervisionSourceThreadId !== void 0 || binding.pendingSupervisionBranch !== void 0 || stored.retired !== void 0) return;
32
+ } else return;
33
+ if (stored.lease !== void 0) {
34
+ const lease = asOptionalRecord(stored.lease);
35
+ if (!lease || typeof lease.token !== "string" || !lease.token.trim() || typeof lease.expiresAt !== "number" || !Number.isFinite(lease.expiresAt) || lease.expiresAt > Date.now()) return;
36
+ }
37
+ return {
38
+ row,
39
+ agentId,
40
+ sessionId,
41
+ stable
42
+ };
43
+ }
44
+ async function* iterateOrphanBindingPages({ context }) {
45
+ const readPage = context.readPluginStateEntriesInKeyRange;
46
+ const readEvidence = context.readSessionIdentityEvidenceBatch;
47
+ if (!readPage || !readEvidence) return;
48
+ for (const prefix of KEY_PREFIXES) {
49
+ let after;
50
+ while (true) {
51
+ const rows = readPage(CODEX_APP_SERVER_BINDING_NAMESPACE, {
52
+ prefix,
53
+ ...after ? { after } : {},
54
+ limit: PAGE_SIZE
55
+ });
56
+ if (rows.length === 0) break;
57
+ after = rows.at(-1)?.key;
58
+ const candidates = rows.flatMap((row) => {
59
+ const candidate = readBindingCandidate(row, prefix);
60
+ return candidate ? [candidate] : [];
61
+ });
62
+ if (candidates.length > 0) {
63
+ const identities = new Map(candidates.map(({ agentId, sessionId }) => [`${agentId}\0${sessionId}`, {
64
+ agentId,
65
+ sessionId
66
+ }]));
67
+ const evidence = new Map((await readEvidence([...identities.values()])).map((owner) => [`${owner.agentId}\0${owner.sessionId}`, owner]));
68
+ const stale = candidates.filter(({ row, agentId, sessionId, stable }) => {
69
+ const owner = evidence.get(`${agentId}\0${sessionId}`);
70
+ if (!owner || owner.state === "unknown") return false;
71
+ if (owner.state !== "current") return true;
72
+ if (!stable) return false;
73
+ const digest = createHash("sha256").update(owner.sessionKey).digest("base64url");
74
+ return row.key !== `session-key:${agentId}:${digest}`;
75
+ }).map(({ row }) => row);
76
+ if (stale.length > 0) yield stale;
77
+ }
78
+ if (rows.length < PAGE_SIZE) break;
79
+ await setImmediate();
80
+ }
81
+ }
82
+ }
83
+ const codexOrphanedSessionBindingMigration = {
84
+ id: "codex-app-server-orphaned-session-bindings",
85
+ label: "Codex app-server orphaned session bindings",
86
+ doctorOnly: true,
87
+ phase: "after-session-repair",
88
+ async detectLegacyState(params) {
89
+ for await (const _ of iterateOrphanBindingPages(params)) return { preview: ["- Codex app-server bindings: remove orphaned session ownership"] };
90
+ return null;
91
+ },
92
+ async migrateLegacyState(params) {
93
+ const remove = params.context.deletePluginStateEntriesIfUnchanged;
94
+ if (!remove) return {
95
+ changes: [],
96
+ warnings: ["Codex session binding repair requires locked SQLite maintenance ownership"]
97
+ };
98
+ let deleted = 0;
99
+ let changed = 0;
100
+ for await (const rows of iterateOrphanBindingPages(params)) {
101
+ const result = remove(CODEX_APP_SERVER_BINDING_NAMESPACE, rows);
102
+ deleted += result.deleted;
103
+ changed += result.changed;
104
+ }
105
+ return {
106
+ changes: deleted > 0 ? [`Removed ${deleted} orphaned Codex app-server session binding(s)`] : [],
107
+ warnings: changed > 0 ? [`Preserved ${changed} Codex app-server session binding(s) changed during repair`] : []
108
+ };
109
+ }
110
+ };
111
+ //#endregion
12
112
  //#region extensions/codex/src/migration/session-binding-sidecars.ts
13
113
  const LEGACY_BINDING_SUFFIX = ".codex-app-server.json";
14
114
  const CODEX_AGENT_HARNESS_ID = "codex";
@@ -23,7 +123,6 @@ const LEGACY_BINDING_LOCK_OPTIONS = {
23
123
  stale: 12e4
24
124
  };
25
125
  async function collectSessionSurfaces(params) {
26
- const { resolveStorePath } = await import("openclaw/plugin-sdk/session-store-runtime");
27
126
  const surfaces = /* @__PURE__ */ new Map();
28
127
  const stateRoot = await canonicalPathFromExistingAncestor(params.stateDir);
29
128
  const add = async (root, storePath, agentId, scan) => {
@@ -43,7 +142,7 @@ async function collectSessionSurfaces(params) {
43
142
  const agentsDir = path.join(params.stateDir, "agents");
44
143
  for (const entry of await readDirectoryEntries(agentsDir)) {
45
144
  if (!entry.isDirectory() || entry.isSymbolicLink()) continue;
46
- const agentId = resolveSessionAgentIds({
145
+ const agentId = resolveSessionAgentIdsStrict({
47
146
  agentId: entry.name,
48
147
  config: params.config
49
148
  }).sessionAgentId;
@@ -169,7 +268,6 @@ async function* walkSidecars(root) {
169
268
  }
170
269
  }
171
270
  async function collectBindingOwners(sources, surfaces, params) {
172
- const { resolveStorePath } = await import("openclaw/plugin-sdk/session-store-runtime");
173
271
  const sourcePaths = new Set(await Promise.all(sources.map((source) => canonicalPathFromExistingAncestor(source.transcriptPath))));
174
272
  const owners = /* @__PURE__ */ new Map();
175
273
  const storePaths = new Set(surfaces.flatMap((surface) => [...surface.storePaths]));
@@ -245,7 +343,7 @@ async function resolveLegacySessionFileLocator(sessionsDir, entry, sessionId) {
245
343
  return candidate;
246
344
  }
247
345
  function tryResolveLegacyBindingOwnerAgentId(params) {
248
- if (params.sessionKey.trim().toLowerCase().startsWith("agent:")) return resolveSessionAgentIds({
346
+ if (params.sessionKey.trim().toLowerCase().startsWith("agent:")) return resolveSessionAgentIdsStrict({
249
347
  sessionKey: params.sessionKey,
250
348
  config: params.config
251
349
  }).sessionAgentId;
@@ -254,7 +352,7 @@ function tryResolveLegacyBindingOwnerAgentId(params) {
254
352
  const systemAgentId = !storeAgentId && configuredAgentId ? normalizeAgentId(configuredAgentId) : void 0;
255
353
  const fallbackAgentIds = systemAgentId && listAgentIds(params.config).includes(systemAgentId) ? [void 0, systemAgentId] : [void 0];
256
354
  for (const fallbackAgentId of fallbackAgentIds) try {
257
- return resolveSessionAgentIds({
355
+ return resolveSessionAgentIdsStrict({
258
356
  sessionKey: params.sessionKey,
259
357
  config: params.config,
260
358
  ...storeAgentId ? { agentId: storeAgentId } : fallbackAgentId ? { fallbackAgentId } : {}
@@ -293,7 +391,7 @@ async function migrateSource(source, candidates, params, store) {
293
391
  return await withFileLock(source.sidecarPath, LEGACY_BINDING_LOCK_OPTIONS, async () => {
294
392
  const [contents, stat] = await Promise.all([fs.readFile(source.sidecarPath, "utf8"), fs.stat(source.sidecarPath)]);
295
393
  const raw = JSON.parse(contents);
296
- const [{ bindingStoreKey, createStoredCodexAppServerBinding, normalizeStoredCodexAppServerBindingFingerprints, readStoredCodexAppServerBinding }, { legacyCodexConversationBindingId }] = await Promise.all([import("./session-binding-Bcynfd-_.js").then((n) => n.f), import("./conversation-binding-data-CW2GuupV.js").then((n) => n.t)]);
394
+ const [{ bindingStoreKey, createStoredCodexAppServerBinding, normalizeStoredCodexAppServerBindingFingerprints, readStoredCodexAppServerBinding }, { legacyCodexConversationBindingId }] = await Promise.all([import("./session-binding-4Ki04sW-.js").then((n) => n.d), import("./conversation-binding-data-BiodpIzq.js").then((n) => n.t)]);
297
395
  const agentId = owner?.agentId ?? (source.agentIds.size === 1 ? [...source.agentIds][0] : void 0);
298
396
  const baseStored = createStoredCodexAppServerBinding(raw, {
299
397
  now: stat.mtime.toISOString(),
@@ -478,7 +576,7 @@ function isSafeLegacySessionId(value) {
478
576
  const trimmed = value.trim();
479
577
  return trimmed.length > 0 && trimmed.length <= 255 && /^[A-Za-z0-9][A-Za-z0-9._:@-]*$/.test(trimmed);
480
578
  }
481
- const stateMigrations = [{
579
+ const stateMigrations$1 = [{
482
580
  id: "codex-app-server-sidecars-to-plugin-state",
483
581
  label: "Codex app-server thread bindings",
484
582
  async detectLegacyState(params) {
@@ -541,6 +639,15 @@ function hasRetiredApprovalPolicy(value) {
541
639
  const approvalPolicy = asNullableRecord(value)?.approvalPolicy;
542
640
  return approvalPolicy === "on-failure" || approvalPolicy === "untrusted";
543
641
  }
642
+ const RETIRED_TURN_IDLE_TIMEOUT_KEYS = [
643
+ "turnCompletionIdleTimeoutMs",
644
+ "turnAssistantCompletionIdleTimeoutMs",
645
+ "postToolRawAssistantCompletionIdleTimeoutMs"
646
+ ];
647
+ function hasRetiredTurnIdleTimeout(value) {
648
+ const appServer = asNullableRecord(value);
649
+ return appServer !== null && RETIRED_TURN_IDLE_TIMEOUT_KEYS.some((key) => Object.hasOwn(appServer, key));
650
+ }
544
651
  /** Legacy Codex config keys that doctor should report or repair. */
545
652
  const legacyConfigRules = [
546
653
  {
@@ -574,24 +681,40 @@ const legacyConfigRules = [
574
681
  ],
575
682
  message: "plugins.entries.codex.config.appServer.approvalPolicy values \"on-failure\" and \"untrusted\" are retired; use \"on-request\". Run \"openclaw doctor --fix\".",
576
683
  match: hasRetiredApprovalPolicy
684
+ },
685
+ {
686
+ path: [
687
+ "plugins",
688
+ "entries",
689
+ "codex",
690
+ "config",
691
+ "appServer"
692
+ ],
693
+ message: "Codex app-server turn idle timeouts are retired; native Codex owns provider liveness and turn completion. The existing agents.defaults.timeoutSeconds run limit remains unchanged. Run \"openclaw doctor --fix\" to remove the old settings.",
694
+ match: hasRetiredTurnIdleTimeout
577
695
  }
578
696
  ];
579
697
  /**
580
698
  * Removes retired Codex plugin config keys while preserving unrelated config.
581
699
  */
582
700
  function normalizeCompatibilityConfig({ cfg }) {
583
- const rawPluginConfig = asNullableRecord(asNullableRecord(cfg.plugins?.entries?.codex)?.config);
701
+ const rawEntry = asNullableRecord(cfg.plugins?.entries?.codex);
702
+ const rawPluginConfig = asNullableRecord(rawEntry?.config);
584
703
  const rawCodexPlugins = asNullableRecord(rawPluginConfig?.codexPlugins);
585
704
  const rawAppServer = asNullableRecord(rawPluginConfig?.appServer);
586
705
  const shouldRemoveDynamicToolsProfile = rawPluginConfig !== null && hasRetiredDynamicToolsProfile(rawPluginConfig);
587
706
  const shouldRewriteDestructivePolicy = hasLegacyPluginDestructivePolicy(rawCodexPlugins);
588
707
  const shouldRewriteApprovalPolicy = hasRetiredApprovalPolicy(rawAppServer);
589
- if (!rawPluginConfig || !shouldRemoveDynamicToolsProfile && !shouldRewriteDestructivePolicy && !shouldRewriteApprovalPolicy) return {
708
+ const shouldRemoveTurnIdleTimeouts = hasRetiredTurnIdleTimeout(rawAppServer);
709
+ if (!rawPluginConfig || !shouldRemoveDynamicToolsProfile && !shouldRewriteDestructivePolicy && !shouldRewriteApprovalPolicy && !shouldRemoveTurnIdleTimeouts) return {
590
710
  config: cfg,
591
711
  changes: []
592
712
  };
593
713
  const nextConfig = structuredClone(cfg);
594
- const nextPluginConfig = asNullableRecord(asNullableRecord(asNullableRecord(asNullableRecord(nextConfig.plugins)?.entries)?.codex)?.config);
714
+ const nextPlugins = asNullableRecord(nextConfig.plugins);
715
+ const nextEntries = asNullableRecord(nextPlugins?.entries);
716
+ const nextEntry = asNullableRecord(nextEntries?.codex);
717
+ const nextPluginConfig = asNullableRecord(nextEntry?.config);
595
718
  if (!nextPluginConfig) return {
596
719
  config: cfg,
597
720
  changes: []
@@ -611,8 +734,14 @@ function normalizeCompatibilityConfig({ cfg }) {
611
734
  }
612
735
  changes.push("Renamed plugins.entries.codex.config.codexPlugins allow_destructive_actions=\"on-request\" values to \"auto\".");
613
736
  }
737
+ const nextAppServer = asNullableRecord(nextPluginConfig.appServer);
738
+ if (nextAppServer && shouldRemoveTurnIdleTimeouts) {
739
+ for (const key of RETIRED_TURN_IDLE_TIMEOUT_KEYS) if (Object.hasOwn(nextAppServer, key)) {
740
+ delete nextAppServer[key];
741
+ changes.push(`Removed retired plugins.entries.codex.config.appServer.${key}; native Codex owns provider liveness and turn completion. agents.defaults.timeoutSeconds was not changed.`);
742
+ }
743
+ }
614
744
  if (shouldRewriteApprovalPolicy) {
615
- const nextAppServer = asNullableRecord(nextPluginConfig.appServer);
616
745
  if (nextAppServer?.approvalPolicy === "on-failure" || nextAppServer?.approvalPolicy === "untrusted") nextAppServer.approvalPolicy = "on-request";
617
746
  changes.push("Renamed retired plugins.entries.codex.config.appServer.approvalPolicy to \"on-request\".");
618
747
  }
@@ -621,5 +750,6 @@ function normalizeCompatibilityConfig({ cfg }) {
621
750
  changes
622
751
  };
623
752
  }
753
+ const stateMigrations = [...stateMigrations$1, codexOrphanedSessionBindingMigration];
624
754
  //#endregion
625
755
  export { legacyConfigRules, normalizeCompatibilityConfig, stateMigrations };