@openclaw/codex 2026.7.2-beta.3 → 2026.7.2-beta.5

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 (43) hide show
  1. package/dist/{app-server-policy-DUMF2Xyr.js → app-server-policy-BmDgseo_.js} +1 -1
  2. package/dist/attempt-client-cleanup-Ia52yRWc.js +127 -0
  3. package/dist/{attempt-notifications-Ecjyzufe.js → attempt-notifications-CMR2_fmR.js} +1 -1
  4. package/dist/{media-understanding-provider-IPNNQre6.js → bounded-turn-FEbUXoYT.js} +71 -188
  5. package/dist/capabilities-BHRSI6Cn.js +36 -0
  6. package/dist/cli-metadata.js +1 -1
  7. package/dist/{command-formatters-NCTL7A2q.js → command-formatters-ico4ZFnk.js} +3 -37
  8. package/dist/{command-handlers-DtFbZiba.js → command-handlers-CRmnwI2N.js} +1233 -1221
  9. package/dist/{compact-Kgy26gIM.js → compact-dEN49UH6.js} +8 -7
  10. package/dist/{computer-use-C7x4ZaqR.js → computer-use-BjGylO-E.js} +16 -6
  11. package/dist/{conversation-control-B0s3aIjT.js → conversation-control-DE7d9DOj.js} +6 -5
  12. package/dist/doctor-contract-api.js +24 -86
  13. package/dist/{dynamic-tools-D_vSVmv9.js → dynamic-tools-LIt9ojep.js} +135 -2696
  14. package/dist/event-projector-assistant-message-DTgnPPVF.js +101 -0
  15. package/dist/event-projector-usage-tvgb1NCX.js +69 -0
  16. package/dist/harness.js +31 -11
  17. package/dist/incognito-session-ET_ufDH-.js +2 -0
  18. package/dist/index.js +250 -275
  19. package/dist/media-understanding-provider.js +173 -1
  20. package/dist/{models-DD5zBdX5.js → models-BA01NEez.js} +2 -2
  21. package/dist/{notification-correlation-C8DVQ_Bq.js → notification-correlation-Bj_Ak_jI.js} +3 -3
  22. package/dist/{plugin-app-cache-key-DJbhLYSK.js → plugin-app-cache-key-DSXX-rXO.js} +5 -5
  23. package/dist/{transcript-mirror-D9rTxx2P.js → protocol-validators-Dm4eXZmt.js} +335 -595
  24. package/dist/{rate-limits-CqhWQ2R9.js → rate-limits-S_PXs0ul.js} +1 -1
  25. package/dist/realtime-voice-api-BPcA1uN9.js +494 -0
  26. package/dist/realtime-voice-api.js +2 -0
  27. package/dist/{request-9yf9pZjf.js → request-CXpPennK.js} +1 -1
  28. package/dist/{run-attempt-BIoO8ISr.js → run-attempt-C5GTPJOE.js} +3111 -387
  29. package/dist/{session-binding-Bmt20HfB.js → session-binding-DlVQ-Pxs.js} +957 -890
  30. package/dist/{session-catalog-CA7R-hX2.js → session-catalog-CP2oCcEb.js} +98 -87
  31. package/dist/{session-cli-Bxk3-Wqz.js → session-cli-CqZ0Fp2a.js} +2 -2
  32. package/dist/session-upstream-marker-QE-m5QFG.js +82 -0
  33. package/dist/settled-turn-finalizer-CA_2QXIE.js +303 -0
  34. package/dist/{shared-client-CSXLtCLE.js → shared-client-BVKE40c-.js} +1870 -1694
  35. package/dist/{side-question-DtzquMOb.js → side-question-CO12sHxo.js} +24 -16
  36. package/dist/{thread-lifecycle-CQ_9mAa1.js → thread-lifecycle-DRg_FdzC.js} +127 -153
  37. package/dist/transcript-mirror-uKA-A4tB.js +550 -0
  38. package/dist/upstream-session-fork-_Vrz4WJr.js +320 -0
  39. package/dist/{usage-CuPpFgTc.js → usage-UpVbdX5G.js} +3 -3
  40. package/dist/{web-search-provider.runtime-_x5XTeqh.js → web-search-provider.runtime-CaQMYDbp.js} +3 -3
  41. package/package.json +7 -8
  42. package/npm-shrinkwrap.json +0 -202
  43. package/dist/{auth-binding-C1czuHPA.js → auth-binding-B4FfbcCg.js} +1 -1
@@ -1,10 +1,10 @@
1
- import { R as CodexAppServerRpcError, Z as isJsonObject, a as getLeasedSharedCodexAppServerClient, c as releaseLeasedSharedCodexAppServerClient } from "./shared-client-CSXLtCLE.js";
2
- import { _ as readCodexNotificationItem } from "./attempt-notifications-Ecjyzufe.js";
3
- import { c as sessionBindingIdentity, t as CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS } from "./session-binding-Bmt20HfB.js";
1
+ import { V as isJsonObject, _ as CodexAppServerRpcError, a as getLeasedSharedCodexAppServerClient, l as releaseLeasedSharedCodexAppServerClient } from "./shared-client-BVKE40c-.js";
2
+ import { l as sessionBindingIdentity, t as CODEX_APP_SERVER_BINDING_GUARDED_REQUEST_TIMEOUT_MS } from "./session-binding-DlVQ-Pxs.js";
3
+ import { _ as readCodexNotificationItem } from "./attempt-notifications-CMR2_fmR.js";
4
4
  import { n as resolveCodexNativeExecutionBlock } from "./sandbox-guard-D1Wky__S.js";
5
- import { a as resolveCodexBindingAppServerConnection, n as readCodexNotificationThreadId, r as readCodexNotificationTurnId } from "./notification-correlation-C8DVQ_Bq.js";
6
- import { resolveAgentDir, resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
5
+ import { a as resolveCodexBindingAppServerConnection, n as readCodexNotificationThreadId, r as readCodexNotificationTurnId } from "./notification-correlation-Bj_Ak_jI.js";
7
6
  import { embeddedAgentLog, resolveCompactionTimeoutMs } from "openclaw/plugin-sdk/agent-harness-runtime";
7
+ import { resolveAgentDir as resolveAgentDir$1, resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
8
8
  //#region extensions/codex/src/app-server/compact.ts
9
9
  /**
10
10
  * Native Codex app-server compaction bridge for bound OpenClaw sessions.
@@ -261,6 +261,7 @@ function readIgnoredCompactionOverridePaths(params) {
261
261
  const inheritedProvider = !localProvider && typeof entry.inheritedRecord?.provider === "string" ? entry.inheritedRecord.provider.trim() : "";
262
262
  const providerPath = localProvider ? `${entry.path}.compaction.provider` : inheritedProvider && entry.inheritedPath ? `${entry.inheritedPath}.compaction.provider` : void 0;
263
263
  if (typeof entry.record.model === "string" && entry.record.model.trim()) ignored.add(`${entry.path}.compaction.model`);
264
+ if (typeof entry.record.thinkingLevel === "string" && entry.record.thinkingLevel.trim()) ignored.add(`${entry.path}.compaction.thinkingLevel`);
264
265
  if (providerPath) ignored.add(providerPath);
265
266
  }
266
267
  return [...ignored];
@@ -352,7 +353,7 @@ async function compactCodexNativeThread(params, options) {
352
353
  authProfileId: requestedAuthProfileId ?? binding.authProfileId,
353
354
  pluginConfig: options.pluginConfig,
354
355
  config,
355
- agentDir: resolveAgentDir(config, agentId)
356
+ agentDir: resolveAgentDir$1(config, agentId)
356
357
  });
357
358
  } catch (error) {
358
359
  return {
@@ -370,7 +371,7 @@ async function compactCodexNativeThread(params, options) {
370
371
  const shouldReleaseDefaultLease = !options.clientFactory;
371
372
  const clientFactory = options.clientFactory ?? getLeasedSharedCodexAppServerClient;
372
373
  const runtimeAuthPlan = params.runtimeAuthPlan ?? params.runtimePlan?.auth;
373
- const usesPreparedApiKey = !usesSupervisionConnection && runtimeAuthPlan?.modelRoute?.authRequirement === "api-key";
374
+ const usesPreparedApiKey = !usesSupervisionConnection && appServer.start.homeScope !== "user" && runtimeAuthPlan?.modelRoute?.authRequirement === "api-key";
374
375
  const preparedApiKey = usesPreparedApiKey ? params.resolvedApiKey?.trim() : void 0;
375
376
  if (usesPreparedApiKey && !preparedApiKey) return {
376
377
  ok: false,
@@ -1,7 +1,7 @@
1
- import { E as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, H as isCodexAppServerConnectionClosedError, U as isCodexAppServerIndeterminateRequestCancellationError, W as isCodexAppServerIndeterminateTransportError, a as getLeasedSharedCodexAppServerClient, c as releaseLeasedSharedCodexAppServerClient, h as acquireCodexNativeConfigFence, l as resolveCodexNativeConfigFenceKey } from "./shared-client-CSXLtCLE.js";
2
- import { C as resolveCodexComputerUseConfig, b as resolveCodexAppServerRuntimeOptions } from "./session-binding-Bmt20HfB.js";
3
- import { f as describeControlFailure } from "./command-formatters-NCTL7A2q.js";
4
- import { r as requestCodexAppServerJson } from "./request-9yf9pZjf.js";
1
+ import { C as isCodexAppServerIndeterminateTransportError, H as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, S as isCodexAppServerIndeterminateRequestCancellationError, a as getLeasedSharedCodexAppServerClient, g as acquireCodexNativeConfigFence, l as releaseLeasedSharedCodexAppServerClient, u as resolveCodexNativeConfigFenceKey, x as isCodexAppServerConnectionClosedError } from "./shared-client-BVKE40c-.js";
2
+ import { h as resolveCodexComputerUseConfig, p as resolveCodexAppServerRuntimeOptions } from "./session-binding-DlVQ-Pxs.js";
3
+ import { n as describeControlFailure } from "./capabilities-BHRSI6Cn.js";
4
+ import { r as requestCodexAppServerJson } from "./request-CXpPennK.js";
5
5
  import { existsSync } from "node:fs";
6
6
  import { runExec } from "openclaw/plugin-sdk/process-runtime";
7
7
  //#region extensions/codex/src/app-server/computer-use.ts
@@ -113,6 +113,7 @@ async function inspectCodexComputerUse(params) {
113
113
  if (!runtime) throw new Error("Computer Use install could not resolve its app-server runtime");
114
114
  client = await getLeasedSharedCodexAppServerClient({
115
115
  startOptions: runtime.start,
116
+ pluginConfig: params.pluginConfig,
116
117
  timeoutMs: params.timeoutMs ?? runtime.requestTimeoutMs,
117
118
  config: params.config,
118
119
  agentDir: params.agentDir,
@@ -213,9 +214,11 @@ async function ensureComputerUsePlugin(params) {
213
214
  }
214
215
  async function readComputerUseTools(params) {
215
216
  let server = await readMcpServerStatus(params.request, params.config.mcpServerName);
216
- if (!server && params.installPlugin) {
217
+ let tools = Object.keys(server?.tools ?? {}).toSorted();
218
+ if ((!server || tools.length === 0) && params.installPlugin) {
217
219
  await reloadMcpServers(params.request);
218
220
  server = await readMcpServerStatus(params.request, params.config.mcpServerName);
221
+ tools = Object.keys(server?.tools ?? {}).toSorted();
219
222
  }
220
223
  if (!server) return statusFromPlugin({
221
224
  config: params.config,
@@ -224,10 +227,17 @@ async function readComputerUseTools(params) {
224
227
  reason: "mcp_missing",
225
228
  message: `Computer Use is installed, but the ${params.config.mcpServerName} MCP server is not available.`
226
229
  });
230
+ if (tools.length === 0) return statusFromPlugin({
231
+ config: params.config,
232
+ plugin: params.plugin,
233
+ tools,
234
+ reason: "mcp_missing",
235
+ message: `Computer Use is installed, but the ${params.config.mcpServerName} MCP server exposes no tools.`
236
+ });
227
237
  const status = statusFromPlugin({
228
238
  config: params.config,
229
239
  plugin: params.plugin,
230
- tools: Object.keys(server.tools).toSorted(),
240
+ tools,
231
241
  reason: "ready",
232
242
  message: "Computer Use is ready."
233
243
  });
@@ -1,8 +1,9 @@
1
- import { a as getLeasedSharedCodexAppServerClient, c as releaseLeasedSharedCodexAppServerClient, p as withLeasedCodexAppServerClientStartSelectionRetry, s as releaseCodexAppServerClientLease } from "./shared-client-CSXLtCLE.js";
2
- import { _ as isCodexFastServiceTier, a as isCodexAppServerNativeAuthProfile, b as resolveCodexAppServerRuntimeOptions, o as normalizeCodexAppServerBindingModelProvider, r as bindingStoreKey, w as resolveCodexModelBackedReviewerPolicyContext } from "./session-binding-Bmt20HfB.js";
3
- import { _ as resolveCodexBindingModelProviderFallback, h as resolveCodexAppServerRequestModelSelection } from "./thread-lifecycle-CQ_9mAa1.js";
4
- import { d as CODEX_CONTROL_METHODS, r as formatCodexDisplayText } from "./command-formatters-NCTL7A2q.js";
5
- import { a as resolveCodexBindingAppServerConnection } from "./notification-correlation-C8DVQ_Bq.js";
1
+ import { a as getLeasedSharedCodexAppServerClient, c as releaseCodexAppServerClientLease, l as releaseLeasedSharedCodexAppServerClient, m as withLeasedCodexAppServerClientStartSelectionRetry } from "./shared-client-BVKE40c-.js";
2
+ import { O as isCodexFastServiceTier, S as resolveCodexModelBackedReviewerPolicyContext, o as isCodexAppServerNativeAuthProfile, p as resolveCodexAppServerRuntimeOptions, r as bindingStoreKey, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-DlVQ-Pxs.js";
3
+ import { x as resolveCodexBindingModelProviderFallback, y as resolveCodexAppServerRequestModelSelection } from "./thread-lifecycle-DRg_FdzC.js";
4
+ import { t as CODEX_CONTROL_METHODS } from "./capabilities-BHRSI6Cn.js";
5
+ import { r as formatCodexDisplayText } from "./command-formatters-ico4ZFnk.js";
6
+ import { a as resolveCodexBindingAppServerConnection } from "./notification-correlation-Bj_Ak_jI.js";
6
7
  import { ModelSelectionLockedError } from "openclaw/plugin-sdk/model-session-runtime";
7
8
  //#region extensions/codex/src/command-authorization.ts
8
9
  const CODEX_NATIVE_EXECUTION_AUTH_ERROR = "Only an owner or operator.admin can control Codex native execution.";
@@ -3,37 +3,11 @@ import fs from "node:fs/promises";
3
3
  import path from "node:path";
4
4
  import { listAgentIds, resolveAgentDir, resolveSessionAgentIds } from "openclaw/plugin-sdk/agent-runtime";
5
5
  import { isDeepStrictEqual } from "node:util";
6
+ import { isRecord } from "openclaw/plugin-sdk/string-coerce-runtime";
6
7
  import { patchSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
8
+ import { canonicalPathFromExistingAncestor, isPathInside, pathExists } from "openclaw/plugin-sdk/security-runtime";
7
9
  import { withFileLock } from "openclaw/plugin-sdk/file-lock";
8
- //#region extensions/codex/src/migration/session-binding-sidecar-archive.ts
9
- async function pathExists$1(filePath) {
10
- try {
11
- await fs.access(filePath);
12
- return true;
13
- } catch {
14
- return false;
15
- }
16
- }
17
- async function firstFreeArchivePath(sourcePath) {
18
- for (let index = 2;; index++) {
19
- const candidate = `${sourcePath}.migrated.${index}`;
20
- if (!await pathExists$1(candidate)) return candidate;
21
- }
22
- }
23
- async function archiveBindingSidecar(sourcePath) {
24
- const archivePath = `${sourcePath}.migrated`;
25
- if (!await pathExists$1(archivePath)) {
26
- await fs.rename(sourcePath, archivePath);
27
- return;
28
- }
29
- const [sourceBytes, archiveBytes] = await Promise.all([fs.readFile(sourcePath), fs.readFile(archivePath)]);
30
- if (sourceBytes.equals(archiveBytes)) {
31
- await fs.rm(sourcePath, { force: true });
32
- return;
33
- }
34
- await fs.rename(sourcePath, await firstFreeArchivePath(sourcePath));
35
- }
36
- //#endregion
10
+ import { archiveLegacyStateSource, legacyStateFileExists } from "openclaw/plugin-sdk/runtime-doctor";
37
11
  //#region extensions/codex/src/migration/session-binding-sidecars.ts
38
12
  const LEGACY_BINDING_SUFFIX = ".codex-app-server.json";
39
13
  const CODEX_AGENT_HARNESS_ID = "codex";
@@ -49,9 +23,9 @@ const LEGACY_BINDING_LOCK_OPTIONS = {
49
23
  };
50
24
  async function collectSessionSurfaces(params) {
51
25
  const surfaces = /* @__PURE__ */ new Map();
52
- const stateRoot = await canonicalizePath(params.stateDir);
26
+ const stateRoot = await canonicalPathFromExistingAncestor(params.stateDir);
53
27
  const add = async (root, storePath, agentId, scan) => {
54
- const canonicalRoot = await canonicalizePath(root);
28
+ const canonicalRoot = await canonicalPathFromExistingAncestor(root);
55
29
  const surface = surfaces.get(canonicalRoot) ?? {
56
30
  root: canonicalRoot,
57
31
  scan: false,
@@ -81,7 +55,7 @@ async function collectSessionSurfaces(params) {
81
55
  env: params.env
82
56
  });
83
57
  const root = path.dirname(storePath);
84
- await add(root, storePath, agentId, isPathWithin(stateRoot, await canonicalizePath(root)));
58
+ await add(root, storePath, agentId, isPathInside(stateRoot, await canonicalPathFromExistingAncestor(root)));
85
59
  }
86
60
  const legacyRoot = path.join(params.stateDir, "sessions");
87
61
  const defaultAgentId = resolveSessionAgentIds({ config: params.config }).defaultAgentId;
@@ -92,7 +66,7 @@ async function collectLegacyBindingSources(params, options = {}) {
92
66
  const surfaces = await collectSessionSurfaces(params);
93
67
  const sources = /* @__PURE__ */ new Map();
94
68
  const addSource = async (sidecarPath, surface) => {
95
- const canonicalSidecar = await canonicalizePath(sidecarPath);
69
+ const canonicalSidecar = await canonicalPathFromExistingAncestor(sidecarPath);
96
70
  const source = sources.get(canonicalSidecar) ?? {
97
71
  sidecarPath: canonicalSidecar,
98
72
  transcriptPath: sidecarPath.slice(0, -22),
@@ -167,7 +141,7 @@ async function* iterateIndexedSidecars(surface) {
167
141
  continue;
168
142
  }
169
143
  const sidecarPath = `${transcriptPath}${LEGACY_BINDING_SUFFIX}`;
170
- if (await isRegularFile(sidecarPath)) yield sidecarPath;
144
+ if (await legacyStateFileExists(sidecarPath)) yield sidecarPath;
171
145
  }
172
146
  }
173
147
  }
@@ -190,7 +164,7 @@ async function* walkSidecars(root) {
190
164
  }
191
165
  }
192
166
  async function collectBindingOwners(sources, surfaces, params) {
193
- const sourcePaths = new Set(await Promise.all(sources.map((source) => canonicalizePath(source.transcriptPath))));
167
+ const sourcePaths = new Set(await Promise.all(sources.map((source) => canonicalPathFromExistingAncestor(source.transcriptPath))));
194
168
  const owners = /* @__PURE__ */ new Map();
195
169
  const storePaths = new Set(surfaces.flatMap((surface) => [...surface.storePaths]));
196
170
  const storeAgentIds = /* @__PURE__ */ new Map();
@@ -201,7 +175,7 @@ async function collectBindingOwners(sources, surfaces, params) {
201
175
  }
202
176
  const failures = [];
203
177
  for (const storePath of storePaths) {
204
- const canonicalStorePath = await canonicalizePath(storePath);
178
+ const canonicalStorePath = await canonicalPathFromExistingAncestor(storePath);
205
179
  const index = await readLegacySessionIndex(storePath);
206
180
  if ("failure" in index) {
207
181
  failures.push(index.failure);
@@ -219,7 +193,7 @@ async function collectBindingOwners(sources, surfaces, params) {
219
193
  let canonicalLegacyTranscriptPath;
220
194
  try {
221
195
  legacyTranscriptPath = await resolveLegacySessionFileLocator(sessionsDir, entry, sessionId);
222
- canonicalLegacyTranscriptPath = await canonicalizePath(legacyTranscriptPath);
196
+ canonicalLegacyTranscriptPath = await canonicalPathFromExistingAncestor(legacyTranscriptPath);
223
197
  } catch {
224
198
  failures.push(`session index ${storePath} has an invalid locator for ${sessionKey}`);
225
199
  continue;
@@ -256,8 +230,8 @@ async function resolveLegacySessionFileLocator(sessionsDir, entry, sessionId) {
256
230
  const sessionFile = entry.sessionFile?.trim();
257
231
  if (!sessionFile) return fallback;
258
232
  const candidate = path.resolve(base, sessionFile);
259
- const [canonicalBase, canonicalCandidate] = await Promise.all([canonicalizePathForContainment(base), canonicalizePathForContainment(candidate)]);
260
- if (!isPathWithin(canonicalBase, canonicalCandidate)) throw new Error("legacy session file locator escapes its session directory");
233
+ const [canonicalBase, canonicalCandidate] = await Promise.all([canonicalPathFromExistingAncestor(base), canonicalPathFromExistingAncestor(candidate)]);
234
+ if (!isPathInside(canonicalBase, canonicalCandidate)) throw new Error("legacy session file locator escapes its session directory");
261
235
  return candidate;
262
236
  }
263
237
  function resolveLegacyBindingOwnerAgentId(params) {
@@ -302,7 +276,7 @@ async function migrateSource(source, candidates, params, store) {
302
276
  return await withFileLock(source.sidecarPath, LEGACY_BINDING_LOCK_OPTIONS, async () => {
303
277
  const [contents, stat] = await Promise.all([fs.readFile(source.sidecarPath, "utf8"), fs.stat(source.sidecarPath)]);
304
278
  const raw = JSON.parse(contents);
305
- const [{ bindingStoreKey, createStoredCodexAppServerBinding, normalizeStoredCodexAppServerBindingFingerprints, readStoredCodexAppServerBinding }, { legacyCodexConversationBindingId }] = await Promise.all([import("./session-binding-Bmt20HfB.js").then((n) => n.l), import("./conversation-binding-data-BHRpYbX3.js").then((n) => n.t)]);
279
+ const [{ bindingStoreKey, createStoredCodexAppServerBinding, normalizeStoredCodexAppServerBindingFingerprints, readStoredCodexAppServerBinding }, { legacyCodexConversationBindingId }] = await Promise.all([import("./session-binding-DlVQ-Pxs.js").then((n) => n.u), import("./conversation-binding-data-BHRpYbX3.js").then((n) => n.t)]);
306
280
  const agentId = owner?.agentId ?? (source.agentIds.size === 1 ? [...source.agentIds][0] : void 0);
307
281
  const baseStored = createStoredCodexAppServerBinding(raw, {
308
282
  now: stat.mtime.toISOString(),
@@ -402,7 +376,14 @@ async function migrateSource(source, candidates, params, store) {
402
376
  }
403
377
  for (const entry of entries) if (!hasExpected(await store.lookup(entry.key), entry.value)) return retain(`canonical plugin state changed at ${entry.key}`);
404
378
  }
405
- await archiveBindingSidecar(source.sidecarPath);
379
+ const archiveWarnings = [];
380
+ await archiveLegacyStateSource({
381
+ filePath: source.sidecarPath,
382
+ label: "Codex app-server binding",
383
+ changes: [],
384
+ warnings: archiveWarnings
385
+ });
386
+ if (archiveWarnings.length > 0 && await pathExists(source.sidecarPath)) return retain(archiveWarnings.join("; "));
406
387
  return {
407
388
  archived: true,
408
389
  importedKeys
@@ -427,7 +408,7 @@ async function recordSessionOwner(owner, env) {
427
408
  } catch {
428
409
  return "its session owner changed before Codex ownership could be recorded";
429
410
  }
430
- if (await canonicalizePath(currentTranscriptPath) !== await canonicalizePath(owner.transcriptPath) || currentOwner.entry.lifecycleRevision !== owner.lifecycleRevision) return "its session owner changed before Codex ownership could be recorded";
411
+ if (await canonicalPathFromExistingAncestor(currentTranscriptPath) !== await canonicalPathFromExistingAncestor(owner.transcriptPath) || currentOwner.entry.lifecycleRevision !== owner.lifecycleRevision) return "its session owner changed before Codex ownership could be recorded";
431
412
  const legacyHarnessId = currentOwner.entry.agentHarnessId?.trim();
432
413
  if (currentOwner.entry.agentHarnessId !== void 0 && !legacyHarnessId) return "its session owner changed before Codex ownership could be recorded";
433
414
  if (legacyHarnessId && legacyHarnessId !== CODEX_AGENT_HARNESS_ID) return `its session is owned by agent harness ${legacyHarnessId}`;
@@ -474,54 +455,11 @@ async function readDirectoryEntries(directory) {
474
455
  throw error;
475
456
  }
476
457
  }
477
- async function isRegularFile(filePath) {
478
- try {
479
- return (await fs.stat(filePath)).isFile();
480
- } catch {
481
- return false;
482
- }
483
- }
484
- function isRecord(value) {
485
- return value !== null && typeof value === "object" && !Array.isArray(value);
486
- }
487
458
  function isSafeLegacySessionId(value) {
488
459
  if (typeof value !== "string") return false;
489
460
  const trimmed = value.trim();
490
461
  return trimmed.length > 0 && trimmed.length <= 255 && /^[A-Za-z0-9][A-Za-z0-9._:@-]*$/.test(trimmed);
491
462
  }
492
- function isPathWithin(root, candidate) {
493
- const relative = path.relative(root, candidate);
494
- return relative === "" || relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
495
- }
496
- async function canonicalizePath(filePath) {
497
- try {
498
- return await fs.realpath(filePath);
499
- } catch {
500
- return path.resolve(filePath);
501
- }
502
- }
503
- async function canonicalizePathForContainment(filePath) {
504
- const resolved = path.resolve(filePath);
505
- const suffix = [];
506
- let probe = resolved;
507
- while (true) try {
508
- const realProbe = await fs.realpath(probe);
509
- return suffix.length === 0 ? realProbe : path.join(realProbe, ...suffix.toReversed());
510
- } catch {
511
- const parent = path.dirname(probe);
512
- if (parent === probe) return resolved;
513
- suffix.push(path.basename(probe));
514
- probe = parent;
515
- }
516
- }
517
- async function pathExists(filePath) {
518
- try {
519
- await fs.access(filePath);
520
- return true;
521
- } catch {
522
- return false;
523
- }
524
- }
525
463
  const stateMigrations = [{
526
464
  id: "codex-app-server-sidecars-to-plugin-state",
527
465
  label: "Codex app-server thread bindings",
@@ -554,7 +492,7 @@ const stateMigrations = [{
554
492
  let migrated = 0;
555
493
  let partialImports = 0;
556
494
  for (const source of sources) {
557
- const result = await migrateSource(source, ownerCollection.owners.get(await canonicalizePath(source.transcriptPath)) ?? [], params, store);
495
+ const result = await migrateSource(source, ownerCollection.owners.get(await canonicalPathFromExistingAncestor(source.transcriptPath)) ?? [], params, store);
558
496
  if (result.warning) warnings.push(result.warning);
559
497
  if (result.notice) notices.push(result.notice);
560
498
  if (result.archived) migrated++;