@openclaw/codex 2026.7.1-beta.6 → 2026.7.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/README.md +27 -3
  2. package/dist/app-server-policy-DVcxdse_.js +49 -0
  3. package/dist/{attempt-notifications-BGsEIIDI.js → attempt-notifications-DEv9h7iC.js} +1 -1
  4. package/dist/auth-binding-C1czuHPA.js +62 -0
  5. package/dist/capabilities-42Dfn2TV.js +33 -0
  6. package/dist/cli-metadata.js +20 -0
  7. package/dist/{app-server-policy-C968Kgin.js → command-formatters-D6ZlGNmb.js} +8 -51
  8. package/dist/{command-handlers-Dv-pzAmg.js → command-handlers-Cpl9fUWv.js} +163 -60
  9. package/dist/{compact-4mVBriKT.js → compact-FnJmiPNA.js} +40 -10
  10. package/dist/computer-use-DVzr8OP1.js +685 -0
  11. package/dist/{config-CYEDnLJ2.js → config-c48K5HP9.js} +200 -29
  12. package/dist/conversation-control-DtQ-E7mr.js +288 -0
  13. package/dist/doctor-contract-api.js +120 -81
  14. package/dist/{provider-capabilities-CDnHbmUZ.js → dynamic-tools-BMLoaTeG.js} +5246 -5140
  15. package/dist/harness.js +55 -15
  16. package/dist/index.js +1435 -265
  17. package/dist/{media-understanding-provider-BHOu9-Gg.js → media-understanding-provider-D580L0P8.js} +28 -10
  18. package/dist/media-understanding-provider.js +1 -1
  19. package/dist/{models-DDmO1zwd.js → models-DuKzZA6G.js} +1 -1
  20. package/dist/notification-correlation-DfaCm0mx.js +67 -0
  21. package/dist/plugin-app-cache-key-BKNjHMEs.js +315 -0
  22. package/dist/{protocol-2POPqAY4.js → protocol-BMifTfdW.js} +3 -1
  23. package/dist/provider-catalog.js +66 -27
  24. package/dist/provider.js +306 -1
  25. package/dist/{provider-zjPfx5Fs.js → rate-limits-Dhp04Rqo.js} +4 -261
  26. package/dist/request-DborTWgw.js +111 -0
  27. package/dist/{run-attempt-FUyOjGCV.js → run-attempt-VPVJoYDP.js} +7897 -7136
  28. package/dist/runtime-artifact-C2ITXdhM.js +488 -0
  29. package/dist/{sandbox-guard-DA2TQfZW.js → sandbox-guard-D1Wky__S.js} +10 -1
  30. package/dist/{session-binding-C1ZXdP-x.js → session-binding-BMfX1OX-.js} +247 -88
  31. package/dist/session-catalog-7H112Tr_.js +2396 -0
  32. package/dist/session-cli-B28RhCyp.js +175 -0
  33. package/dist/{shared-client-4ICy3U6d.js → shared-client-D4mFI9al.js} +1997 -1297
  34. package/dist/{side-question-N4OaDer2.js → side-question-CgJBz52s.js} +135 -67
  35. package/dist/{thread-lifecycle-qWE88Dn2.js → thread-lifecycle-BgLXzjvV.js} +747 -317
  36. package/dist/transcript-mirror-DhLwFIL4.js +485 -0
  37. package/dist/transport-stdio-DXgGZ7Ib.js +88 -0
  38. package/dist/{web-search-provider.runtime-BSlriav6.js → web-search-provider.runtime-Bs-eTn5U.js} +3 -3
  39. package/npm-shrinkwrap.json +56 -30
  40. package/openclaw.plugin.json +168 -10
  41. package/package.json +8 -6
  42. package/dist/command-rpc-eLM_mtC7.js +0 -784
  43. package/dist/computer-use-Bmaz333N.js +0 -377
  44. package/dist/notification-correlation-Bo7KB3ks.js +0 -35
  45. package/dist/plugin-app-cache-key-BrhVdeEf.js +0 -98
  46. package/dist/request-BcJyl8KL.js +0 -36
@@ -0,0 +1,488 @@
1
+ import { n as resolveCodexAppServerSpawnEnv } from "./transport-stdio-DXgGZ7Ib.js";
2
+ import fs from "node:fs/promises";
3
+ import path from "node:path";
4
+ import { createHash } from "node:crypto";
5
+ import { constants } from "node:fs";
6
+ import { resolveWindowsExecutablePath, resolveWindowsSpawnProgram } from "openclaw/plugin-sdk/windows-spawn";
7
+ //#region extensions/codex/src/app-server/runtime-artifact.ts
8
+ /** Exact local runtime artifact identity for verified Codex setup turns. */
9
+ const ARTIFACT_ID_PREFIX = "codex-app-server:v1:";
10
+ const ARTIFACT_HASH_DOMAIN = "openclaw-codex-app-server-runtime-artifact-v1\0";
11
+ const MAX_ARTIFACT_ID_BYTES = 32 * 1024;
12
+ const MAX_ARTIFACT_PATH_BYTES = 4096;
13
+ const MAX_ARTIFACT_INVOCATION_PATHS = 8;
14
+ const MAX_ARTIFACT_DEPTH = 64;
15
+ const MAX_ARTIFACT_ENTRIES = 32768;
16
+ const MAX_ARTIFACT_FILES = 8192;
17
+ const MAX_ARTIFACT_TOTAL_BYTES = 1024n * 1024n * 1024n;
18
+ const READ_CHUNK_BYTES = 64 * 1024;
19
+ const CODE_MODE_HOST_PATH_ENV = "CODEX_CODE_MODE_HOST_PATH";
20
+ const RUNTIME_INJECTION_ENV_KEYS = /* @__PURE__ */ new Set([
21
+ "NODE_PATH",
22
+ "LD_AUDIT",
23
+ "LD_LIBRARY_PATH",
24
+ "LD_PRELOAD",
25
+ "DYLD_FALLBACK_FRAMEWORK_PATH",
26
+ "DYLD_FALLBACK_LIBRARY_PATH",
27
+ "DYLD_FRAMEWORK_PATH",
28
+ "DYLD_INSERT_LIBRARIES",
29
+ "DYLD_LIBRARY_PATH"
30
+ ]);
31
+ const ARTIFACT_BINDINGS_SYMBOL = Symbol.for("openclaw.codexAppServerRuntimeArtifactBindings");
32
+ function getRuntimeArtifactBindings() {
33
+ const globalState = globalThis;
34
+ globalState[ARTIFACT_BINDINGS_SYMBOL] ??= /* @__PURE__ */ new WeakMap();
35
+ return globalState[ARTIFACT_BINDINGS_SYMBOL];
36
+ }
37
+ function throwIfAborted(signal) {
38
+ if (!signal?.aborted) return;
39
+ throw signal.reason instanceof Error ? signal.reason : /* @__PURE__ */ new Error("Codex runtime artifact capture aborted");
40
+ }
41
+ function compareArtifactNames(left, right) {
42
+ return left < right ? -1 : left > right ? 1 : 0;
43
+ }
44
+ function normalizeRelativePath(filePath) {
45
+ return filePath.split(path.sep).join("/");
46
+ }
47
+ function sameOpenedFile(left, right) {
48
+ return left.dev === right.dev && left.ino === right.ino && left.mode === right.mode && left.size === right.size && left.mtimeNs === right.mtimeNs && left.ctimeNs === right.ctimeNs;
49
+ }
50
+ async function readRegularFileFingerprint(params) {
51
+ throwIfAborted(params.signal);
52
+ if (!(await fs.lstat(params.filePath, { bigint: true })).isFile()) throw new Error(`Codex runtime artifact contains a non-regular file: ${params.filePath}`);
53
+ const flags = constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0);
54
+ const handle = await fs.open(params.filePath, flags);
55
+ try {
56
+ const before = await handle.stat({ bigint: true });
57
+ if (!before.isFile()) throw new Error(`Codex runtime artifact contains a non-regular file: ${params.filePath}`);
58
+ if (params.budget.fileCount + 1 > MAX_ARTIFACT_FILES) throw new Error("Codex runtime artifact exceeds the bounded file count");
59
+ if (params.budget.totalBytes + before.size > MAX_ARTIFACT_TOTAL_BYTES) throw new Error("Codex runtime artifact exceeds the bounded content size");
60
+ const hash = createHash("sha256");
61
+ const buffer = Buffer.allocUnsafe(READ_CHUNK_BYTES);
62
+ let offset = 0n;
63
+ while (offset < before.size) {
64
+ throwIfAborted(params.signal);
65
+ const length = Number(before.size - offset < BigInt(buffer.length) ? before.size - offset : BigInt(buffer.length));
66
+ const { bytesRead } = await handle.read(buffer, 0, length, Number(offset));
67
+ if (bytesRead === 0) throw new Error(`Codex runtime artifact changed while reading: ${params.filePath}`);
68
+ hash.update(buffer.subarray(0, bytesRead));
69
+ offset += BigInt(bytesRead);
70
+ }
71
+ const after = await handle.stat({ bigint: true });
72
+ const current = await fs.stat(params.filePath, { bigint: true });
73
+ if (!sameOpenedFile(before, after) || !sameOpenedFile(after, current)) throw new Error(`Codex runtime artifact changed while reading: ${params.filePath}`);
74
+ params.budget.fileCount += 1;
75
+ params.budget.totalBytes += after.size;
76
+ return {
77
+ contentHash: hash.digest("hex"),
78
+ mode: String(after.mode),
79
+ size: String(after.size)
80
+ };
81
+ } finally {
82
+ await handle.close();
83
+ }
84
+ }
85
+ async function listPackageFiles(params) {
86
+ const files = [];
87
+ let entryCount = 0;
88
+ const visit = async (directory, depth) => {
89
+ throwIfAborted(params.signal);
90
+ if (depth > MAX_ARTIFACT_DEPTH) throw new Error("Codex runtime artifact exceeds the bounded directory depth");
91
+ const entries = await fs.readdir(directory, {
92
+ withFileTypes: true,
93
+ encoding: "utf8"
94
+ });
95
+ for (const entry of entries.toSorted((left, right) => compareArtifactNames(left.name, right.name))) {
96
+ throwIfAborted(params.signal);
97
+ entryCount += 1;
98
+ if (entryCount > MAX_ARTIFACT_ENTRIES) throw new Error("Codex runtime artifact exceeds the bounded entry count");
99
+ const entryPath = path.join(directory, entry.name);
100
+ if (entry.isDirectory()) {
101
+ await visit(entryPath, depth + 1);
102
+ continue;
103
+ }
104
+ if (!entry.isFile()) throw new Error(`Codex runtime artifact contains an unsupported entry: ${entryPath}`);
105
+ files.push(normalizeRelativePath(path.relative(params.rootPath, entryPath)));
106
+ }
107
+ };
108
+ await visit(params.rootPath, 0);
109
+ return files;
110
+ }
111
+ function pathIsWithin(rootPath, candidatePath) {
112
+ const relative = path.relative(rootPath, candidatePath);
113
+ return relative === "" || !path.isAbsolute(relative) && !relative.startsWith(`..${path.sep}`) && relative !== "..";
114
+ }
115
+ function assertNoRuntimeInjectionEnvironment(env) {
116
+ for (const [rawKey, value] of Object.entries(env)) {
117
+ const key = rawKey.toUpperCase();
118
+ if (!value?.trim()) continue;
119
+ if (key === "NODE_OPTIONS" && isSafeNodeOptions(value)) continue;
120
+ if (key === "NODE_OPTIONS") throw new Error(`Codex runtime artifact cannot attest injected runtime environment: ${key}`);
121
+ if (RUNTIME_INJECTION_ENV_KEYS.has(key) || key.startsWith("DYLD_")) throw new Error(`Codex runtime artifact cannot attest injected runtime environment: ${key}`);
122
+ }
123
+ }
124
+ function isSafeNodeOptions(value) {
125
+ const tokens = value.trim().split(/\s+/u);
126
+ const valueFlags = /* @__PURE__ */ new Set([
127
+ "--max-old-space-size",
128
+ "--max_old_space_size",
129
+ "--max-semi-space-size",
130
+ "--max_semi_space_size",
131
+ "--stack-trace-limit"
132
+ ]);
133
+ const booleanFlags = /* @__PURE__ */ new Set([
134
+ "--no-deprecation",
135
+ "--no-warnings",
136
+ "--pending-deprecation",
137
+ "--throw-deprecation",
138
+ "--trace-deprecation",
139
+ "--trace-warnings"
140
+ ]);
141
+ for (let index = 0; index < tokens.length; index += 1) {
142
+ const token = tokens[index];
143
+ if (booleanFlags.has(token)) continue;
144
+ const equalsIndex = token.indexOf("=");
145
+ const flag = equalsIndex === -1 ? token : token.slice(0, equalsIndex);
146
+ const inlineValue = equalsIndex === -1 ? void 0 : token.slice(equalsIndex + 1);
147
+ if (flag === "--disable-warning" && inlineValue && /^[A-Za-z][A-Za-z0-9_.:-]{0,63}$/u.test(inlineValue)) continue;
148
+ if (!valueFlags.has(flag)) return false;
149
+ const numericValue = inlineValue ?? tokens[++index];
150
+ if (!numericValue || !/^\d+$/u.test(numericValue)) return false;
151
+ }
152
+ return tokens.length > 0;
153
+ }
154
+ async function hashSelectedArtifactFiles(descriptor, signal) {
155
+ throwIfAborted(signal);
156
+ if (await fs.realpath(descriptor.commandPath) !== descriptor.commandRealPath) throw new Error("Codex runtime launcher selection changed");
157
+ const packageRoot = descriptor.packageRoot;
158
+ if (await resolvePackageRoot(descriptor.nativePath) !== packageRoot) throw new Error("Codex runtime package selection changed");
159
+ if (packageRoot && await fs.realpath(packageRoot) !== packageRoot) throw new Error("Codex runtime package root changed");
160
+ const allFiles = [
161
+ descriptor.commandRealPath,
162
+ ...descriptor.invocationPaths,
163
+ descriptor.nativePath,
164
+ ...descriptor.codeModeHostPath ? [descriptor.codeModeHostPath] : []
165
+ ];
166
+ for (const filePath of allFiles) if (await fs.realpath(filePath) !== filePath) throw new Error(`Codex runtime artifact file selection changed: ${filePath}`);
167
+ if (descriptor.codeModeHostPath) {
168
+ if (await fs.realpath(descriptor.codeModeHostCandidatePath) !== descriptor.codeModeHostPath) throw new Error("Codex code-mode host selection changed");
169
+ } else try {
170
+ await fs.lstat(descriptor.codeModeHostCandidatePath);
171
+ throw new Error("Codex code-mode host selection changed");
172
+ } catch (error) {
173
+ if (!isMissingPathError(error)) throw error;
174
+ }
175
+ const externalFiles = [...new Set(allFiles)].filter((filePath) => !packageRoot || !pathIsWithin(packageRoot, filePath)).toSorted(compareArtifactNames);
176
+ const budget = {
177
+ fileCount: 0,
178
+ totalBytes: 0n
179
+ };
180
+ const hash = createHash("sha256");
181
+ hash.update("codex-runtime-files-v1\0");
182
+ for (const filePath of externalFiles) {
183
+ const file = await readRegularFileFingerprint({
184
+ filePath,
185
+ budget,
186
+ signal
187
+ });
188
+ hash.update(JSON.stringify([
189
+ "file",
190
+ filePath,
191
+ file.mode,
192
+ file.size,
193
+ file.contentHash
194
+ ]));
195
+ hash.update("\n");
196
+ }
197
+ if (packageRoot) {
198
+ const beforeFiles = await listPackageFiles({
199
+ rootPath: packageRoot,
200
+ signal
201
+ });
202
+ for (const relativePath of beforeFiles) {
203
+ const file = await readRegularFileFingerprint({
204
+ filePath: path.join(packageRoot, ...relativePath.split("/")),
205
+ budget,
206
+ signal
207
+ });
208
+ hash.update(JSON.stringify([
209
+ "package",
210
+ relativePath,
211
+ file.mode,
212
+ file.size,
213
+ file.contentHash
214
+ ]));
215
+ hash.update("\n");
216
+ }
217
+ const afterFiles = await listPackageFiles({
218
+ rootPath: packageRoot,
219
+ signal
220
+ });
221
+ if (beforeFiles.length !== afterFiles.length || beforeFiles.some((filePath, index) => filePath !== afterFiles[index])) throw new Error("Codex runtime package changed while reading");
222
+ }
223
+ if (budget.fileCount === 0) throw new Error("Codex runtime artifact contains no regular files");
224
+ return hash.digest("hex");
225
+ }
226
+ async function resolveCommandPath(command, env, cwd) {
227
+ let candidate;
228
+ if (process.platform === "win32") candidate = resolveWindowsExecutablePath(command, env);
229
+ else if (path.isAbsolute(command) || command.includes("/") || command.includes("\\")) candidate = path.resolve(cwd, command);
230
+ else {
231
+ const pathValue = env.PATH;
232
+ if (pathValue === void 0) throw new Error("Codex runtime PATH is unavailable for a bare launcher");
233
+ for (const entry of pathValue.split(path.delimiter)) {
234
+ const entryPath = entry === "" ? cwd : path.isAbsolute(entry) ? entry : path.resolve(cwd, entry);
235
+ const possible = path.join(entryPath, command);
236
+ try {
237
+ await fs.access(possible, constants.X_OK);
238
+ candidate = possible;
239
+ break;
240
+ } catch {}
241
+ }
242
+ }
243
+ if (!candidate) throw new Error(`Codex runtime launcher is unavailable: ${command}`);
244
+ const absolute = path.resolve(candidate);
245
+ if (!(await fs.stat(absolute)).isFile()) throw new Error(`Codex runtime launcher is not a regular file: ${absolute}`);
246
+ return absolute;
247
+ }
248
+ async function readShebang(filePath) {
249
+ const handle = await fs.open(filePath, "r");
250
+ try {
251
+ const buffer = Buffer.alloc(4096);
252
+ const { bytesRead } = await handle.read(buffer, 0, buffer.length, 0);
253
+ const firstLine = buffer.subarray(0, bytesRead).toString("utf8").split(/\r?\n/u, 1)[0] ?? "";
254
+ if (!firstLine.startsWith("#!")) return;
255
+ const tokens = firstLine.slice(2).trim().split(/\s+/u).filter(Boolean);
256
+ if (tokens.length === 0) throw new Error("Codex runtime launcher has an invalid shebang");
257
+ return tokens;
258
+ } finally {
259
+ await handle.close();
260
+ }
261
+ }
262
+ async function resolvePosixInvocationPaths(params) {
263
+ const paths = [params.commandRealPath];
264
+ const shebang = await readShebang(params.commandRealPath);
265
+ if (!shebang) return paths;
266
+ if (!params.nativeCommand) throw new Error("Codex runtime cannot attest a custom script launcher without its native target");
267
+ const interpreter = await resolveCommandPath(shebang[0], params.env, params.cwd);
268
+ paths.push(await fs.realpath(interpreter));
269
+ if (path.basename(interpreter) !== "env") {
270
+ if (shebang.length !== 1) throw new Error("Codex runtime launcher uses unsupported interpreter arguments");
271
+ return paths;
272
+ }
273
+ const envArgs = shebang.slice(1);
274
+ const commandIndex = envArgs[0] === "-S" ? 1 : 0;
275
+ const target = envArgs[commandIndex];
276
+ if (!target || target.startsWith("-") || envArgs.length !== commandIndex + 1) throw new Error("Codex runtime launcher uses unsupported env arguments");
277
+ const targetPath = await resolveCommandPath(target, params.env, params.cwd);
278
+ paths.push(await fs.realpath(targetPath));
279
+ return paths;
280
+ }
281
+ async function resolvePackageRoot(nativePath) {
282
+ const binDir = path.dirname(nativePath);
283
+ if (path.basename(binDir) !== "bin") return;
284
+ const candidate = path.dirname(binDir);
285
+ const metadataPath = path.join(candidate, "codex-package.json");
286
+ try {
287
+ if (!(await fs.lstat(metadataPath)).isFile()) return;
288
+ const root = await fs.realpath(candidate);
289
+ return pathIsWithin(root, nativePath) ? root : void 0;
290
+ } catch {
291
+ return;
292
+ }
293
+ }
294
+ async function resolveOptionalRegularFile(filePath) {
295
+ try {
296
+ const canonical = await fs.realpath(filePath);
297
+ return (await fs.stat(canonical)).isFile() ? canonical : void 0;
298
+ } catch {
299
+ return;
300
+ }
301
+ }
302
+ function isMissingPathError(error) {
303
+ return error instanceof Error && "code" in error && error.code === "ENOENT";
304
+ }
305
+ function readEffectiveSpawnEnvironmentValue(env, name) {
306
+ if (process.platform !== "win32") return env[name];
307
+ const effectiveKey = Object.keys(env).toSorted(compareArtifactNames).find((key) => key.toUpperCase() === name.toUpperCase());
308
+ return effectiveKey ? env[effectiveKey] : void 0;
309
+ }
310
+ async function captureFilesystemDescriptor(params) {
311
+ throwIfAborted(params.signal);
312
+ if (params.startOptions.transport !== "stdio") throw new Error("Verified Codex inference requires a local stdio runtime artifact; WebSocket attestation is unsupported");
313
+ const env = resolveCodexAppServerSpawnEnv(params.startOptions);
314
+ assertNoRuntimeInjectionEnvironment(env);
315
+ const spawnCwd = path.resolve(params.startOptions.cwd ?? process.cwd());
316
+ const commandPath = await resolveCommandPath(params.startOptions.command, env, spawnCwd);
317
+ const commandRealPath = await fs.realpath(commandPath);
318
+ let invocationPaths;
319
+ if (process.platform === "win32") {
320
+ const program = resolveWindowsSpawnProgram({
321
+ command: params.startOptions.command,
322
+ platform: process.platform,
323
+ env,
324
+ execPath: process.execPath,
325
+ packageName: "@openai/codex"
326
+ });
327
+ if (program.resolution === "node-entrypoint" && !params.spawnIdentity.nativeCommand) throw new Error("Codex runtime cannot attest a custom Node launcher without its native target");
328
+ const invocationCandidates = [
329
+ commandRealPath,
330
+ program.command,
331
+ ...program.leadingArgv
332
+ ];
333
+ invocationPaths = [];
334
+ for (const candidate of invocationCandidates) {
335
+ const resolved = await resolveCommandPath(candidate, env, spawnCwd);
336
+ invocationPaths.push(await fs.realpath(resolved));
337
+ }
338
+ } else invocationPaths = await resolvePosixInvocationPaths({
339
+ commandRealPath,
340
+ env,
341
+ cwd: spawnCwd,
342
+ nativeCommand: params.spawnIdentity.nativeCommand
343
+ });
344
+ invocationPaths = [...new Set(invocationPaths)].toSorted(compareArtifactNames);
345
+ if (invocationPaths.length > MAX_ARTIFACT_INVOCATION_PATHS) throw new Error("Codex runtime launcher exceeds the bounded invocation file count");
346
+ const nativeCandidate = params.spawnIdentity.nativeCommand ?? invocationPaths[0];
347
+ if (!nativeCandidate) throw new Error("Codex runtime did not resolve a native executable");
348
+ const nativePath = await fs.realpath(await resolveCommandPath(nativeCandidate, env, spawnCwd));
349
+ const packageRoot = await resolvePackageRoot(nativePath);
350
+ const configuredCodeModeHost = readEffectiveSpawnEnvironmentValue(env, CODE_MODE_HOST_PATH_ENV)?.trim();
351
+ const adjacentCodeModeHost = path.join(path.dirname(nativePath), process.platform === "win32" ? "codex-code-mode-host.exe" : "codex-code-mode-host");
352
+ const codeModeHostCandidatePath = configuredCodeModeHost ? path.isAbsolute(configuredCodeModeHost) ? configuredCodeModeHost : path.resolve(spawnCwd, configuredCodeModeHost) : adjacentCodeModeHost;
353
+ const codeModeHostPath = await resolveOptionalRegularFile(codeModeHostCandidatePath);
354
+ if (configuredCodeModeHost && !codeModeHostPath) throw new Error("Configured Codex code-mode host runtime artifact is unavailable");
355
+ const descriptor = {
356
+ version: 1,
357
+ commandPath,
358
+ commandRealPath,
359
+ invocationPaths,
360
+ nativePath,
361
+ argsFingerprint: params.spawnIdentity.argsFingerprint,
362
+ ...packageRoot ? { packageRoot } : {},
363
+ codeModeHostCandidatePath,
364
+ ...codeModeHostPath ? { codeModeHostPath } : {},
365
+ ...params.spawnIdentity.commandSource ? { commandSource: params.spawnIdentity.commandSource } : {},
366
+ ...params.spawnIdentity.managedCommandOrder ? { managedCommandOrder: params.spawnIdentity.managedCommandOrder } : {}
367
+ };
368
+ validateFilesystemDescriptorShape(descriptor);
369
+ return descriptor;
370
+ }
371
+ function isBoundedPath(value) {
372
+ return typeof value === "string" && value.length > 0 && Buffer.byteLength(value, "utf8") <= MAX_ARTIFACT_PATH_BYTES && path.isAbsolute(value);
373
+ }
374
+ function validateFilesystemDescriptorShape(descriptor) {
375
+ if (descriptor.version !== 1 || !isBoundedPath(descriptor.commandPath) || !isBoundedPath(descriptor.commandRealPath) || !isBoundedPath(descriptor.nativePath) || !isBoundedPath(descriptor.codeModeHostCandidatePath) || !Array.isArray(descriptor.invocationPaths) || descriptor.invocationPaths.length === 0 || descriptor.invocationPaths.length > MAX_ARTIFACT_INVOCATION_PATHS || descriptor.invocationPaths.some((entry) => !isBoundedPath(entry)) || !descriptor.invocationPaths.includes(descriptor.commandRealPath) || !/^[a-f0-9]{64}$/u.test(descriptor.argsFingerprint)) throw new Error("Invalid Codex runtime artifact descriptor");
376
+ if (descriptor.packageRoot) {
377
+ if (!isBoundedPath(descriptor.packageRoot) || path.dirname(path.dirname(descriptor.nativePath)) !== descriptor.packageRoot || path.basename(path.dirname(descriptor.nativePath)) !== "bin") throw new Error("Invalid Codex runtime package descriptor");
378
+ }
379
+ if (descriptor.codeModeHostPath && !isBoundedPath(descriptor.codeModeHostPath)) throw new Error("Invalid Codex code-mode host artifact descriptor");
380
+ if (descriptor.commandSource !== void 0 && ![
381
+ "managed",
382
+ "resolved-managed",
383
+ "config",
384
+ "env"
385
+ ].includes(descriptor.commandSource)) throw new Error("Invalid Codex runtime command source");
386
+ if (descriptor.managedCommandOrder !== void 0 && descriptor.managedCommandOrder !== "package-first" && descriptor.managedCommandOrder !== "desktop-first") throw new Error("Invalid Codex managed command order");
387
+ if (descriptor.managedCommandOrder !== void 0 && descriptor.commandSource !== "resolved-managed") throw new Error("Invalid Codex managed runtime descriptor");
388
+ const canonicalInvocationPaths = [...new Set(descriptor.invocationPaths)].toSorted(compareArtifactNames);
389
+ if (canonicalInvocationPaths.length !== descriptor.invocationPaths.length || canonicalInvocationPaths.some((entry, index) => entry !== descriptor.invocationPaths[index])) throw new Error("Invalid Codex runtime invocation descriptor");
390
+ }
391
+ function validateArtifactDescriptorShape(descriptor) {
392
+ validateFilesystemDescriptorShape(descriptor);
393
+ if (typeof descriptor.serverVersion !== "string" || descriptor.serverVersion.length === 0 || descriptor.serverVersion.length > 128 || descriptor.serverVersion !== descriptor.serverVersion.trim()) throw new Error("Invalid Codex runtime server version");
394
+ if (descriptor.userAgentFingerprint !== void 0 && !/^[a-f0-9]{64}$/u.test(descriptor.userAgentFingerprint)) throw new Error("Invalid Codex runtime user-agent fingerprint");
395
+ }
396
+ function encodeArtifactId(descriptor) {
397
+ return `${ARTIFACT_ID_PREFIX}${Buffer.from(JSON.stringify(descriptor), "utf8").toString("base64url")}`;
398
+ }
399
+ function decodeArtifactId(id) {
400
+ if (!id.startsWith(ARTIFACT_ID_PREFIX) || Buffer.byteLength(id, "utf8") > MAX_ARTIFACT_ID_BYTES) throw new Error("Invalid Codex runtime artifact id");
401
+ const encoded = id.slice(20);
402
+ if (!/^[A-Za-z0-9_-]+$/u.test(encoded)) throw new Error("Invalid Codex runtime artifact encoding");
403
+ const parsed = JSON.parse(Buffer.from(encoded, "base64url").toString("utf8"));
404
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("Invalid Codex runtime artifact descriptor");
405
+ const descriptor = parsed;
406
+ const allowedKeys = /* @__PURE__ */ new Set([
407
+ "version",
408
+ "commandPath",
409
+ "commandRealPath",
410
+ "invocationPaths",
411
+ "nativePath",
412
+ "packageRoot",
413
+ "codeModeHostCandidatePath",
414
+ "codeModeHostPath",
415
+ "argsFingerprint",
416
+ "commandSource",
417
+ "managedCommandOrder",
418
+ "serverVersion",
419
+ "userAgentFingerprint"
420
+ ]);
421
+ if (Object.keys(descriptor).some((key) => !allowedKeys.has(key))) throw new Error("Invalid Codex runtime artifact descriptor fields");
422
+ validateArtifactDescriptorShape(descriptor);
423
+ if (encodeArtifactId(descriptor) !== id) throw new Error("Invalid noncanonical Codex runtime artifact id");
424
+ return descriptor;
425
+ }
426
+ function fingerprintBinding(descriptor, contentFingerprint) {
427
+ return createHash("sha256").update(ARTIFACT_HASH_DOMAIN).update(JSON.stringify(descriptor)).update("\0").update(contentFingerprint).digest("hex");
428
+ }
429
+ /** Captures exact candidate bytes immediately before app-server startup. */
430
+ async function captureCodexAppServerRuntimeArtifactBeforeStart(params) {
431
+ const descriptor = await captureFilesystemDescriptor(params);
432
+ return {
433
+ descriptor,
434
+ contentFingerprint: await hashSelectedArtifactFiles(descriptor, params.signal)
435
+ };
436
+ }
437
+ /** Rechecks startup bytes and adds initialized handshake identity. */
438
+ async function finalizeCodexAppServerRuntimeArtifact(params) {
439
+ const afterDescriptor = await captureFilesystemDescriptor(params);
440
+ const afterContentFingerprint = await hashSelectedArtifactFiles(afterDescriptor, params.signal);
441
+ if (JSON.stringify(afterDescriptor) !== JSON.stringify(params.before.descriptor) || afterContentFingerprint !== params.before.contentFingerprint) throw new Error("Codex app-server runtime artifact changed during startup");
442
+ const serverVersion = params.runtimeIdentity?.serverVersion?.trim();
443
+ if (!serverVersion) throw new Error("Codex app-server did not report an initialized runtime identity");
444
+ const userAgent = params.runtimeIdentity?.userAgent;
445
+ const descriptor = {
446
+ ...afterDescriptor,
447
+ serverVersion,
448
+ ...userAgent ? { userAgentFingerprint: createHash("sha256").update(userAgent).digest("hex") } : {}
449
+ };
450
+ validateArtifactDescriptorShape(descriptor);
451
+ return Object.freeze({
452
+ id: encodeArtifactId(descriptor),
453
+ fingerprint: fingerprintBinding(descriptor, afterContentFingerprint)
454
+ });
455
+ }
456
+ /** Checks current pre-spawn bytes and selection against a previously minted binding. */
457
+ function validateCodexAppServerRuntimeArtifactCapture(binding, capture) {
458
+ try {
459
+ const expectedDescriptor = decodeArtifactId(binding.id);
460
+ const { serverVersion: _serverVersion, userAgentFingerprint: _userAgentFingerprint, ...expectedFilesystemDescriptor } = expectedDescriptor;
461
+ return JSON.stringify(expectedFilesystemDescriptor) === JSON.stringify(capture.descriptor) && binding.fingerprint === fingerprintBinding(expectedDescriptor, capture.contentFingerprint);
462
+ } catch {
463
+ return false;
464
+ }
465
+ }
466
+ /** Commits a verified binding only after the client has completed auth setup. */
467
+ function bindCodexAppServerRuntimeArtifact(client, binding) {
468
+ const bindings = getRuntimeArtifactBindings();
469
+ const existing = bindings.get(client);
470
+ if (existing && (existing.id !== binding.id || existing.fingerprint !== binding.fingerprint)) throw new Error("Codex app-server client already has a different runtime artifact");
471
+ bindings.set(client, Object.freeze({ ...binding }));
472
+ }
473
+ /** Reads the immutable artifact attached to one successfully initialized client. */
474
+ function readCodexAppServerClientRuntimeArtifact(client) {
475
+ return getRuntimeArtifactBindings().get(client);
476
+ }
477
+ /** Re-hashes only the exact Codex files named by a server-minted artifact binding. */
478
+ async function validateCodexAppServerRuntimeArtifact(binding, signal) {
479
+ try {
480
+ const descriptor = decodeArtifactId(binding.id);
481
+ const contentFingerprint = await hashSelectedArtifactFiles(descriptor, signal);
482
+ return binding.fingerprint === fingerprintBinding(descriptor, contentFingerprint);
483
+ } catch {
484
+ return false;
485
+ }
486
+ }
487
+ //#endregion
488
+ export { bindCodexAppServerRuntimeArtifact, captureCodexAppServerRuntimeArtifactBeforeStart, finalizeCodexAppServerRuntimeArtifact, readCodexAppServerClientRuntimeArtifact, validateCodexAppServerRuntimeArtifact, validateCodexAppServerRuntimeArtifactCapture };
@@ -6,6 +6,15 @@ const VALID_AGENT_ID_PATTERN = /^[a-z0-9][a-z0-9_-]{0,63}$/i;
6
6
  const INVALID_AGENT_ID_CHARS_PATTERN = /[^a-z0-9_-]+/g;
7
7
  const LEADING_DASH_PATTERN = /^-+/;
8
8
  const TRAILING_DASH_PATTERN = /-+$/;
9
+ /** Projects node execution ownership into the runtime tool factory options. */
10
+ function resolveCodexNodeExecToolOverrides(policy) {
11
+ if (policy.effectiveExecHost !== "node") return;
12
+ const node = policy.node?.trim();
13
+ return {
14
+ host: "node",
15
+ ...node ? { node } : {}
16
+ };
17
+ }
9
18
  /** Resolves node/gateway/sandbox execution ownership from overrides, session, agent, and config. */
10
19
  function resolveCodexNativeExecutionPolicy(params) {
11
20
  const config = params.config ?? {};
@@ -267,4 +276,4 @@ function resolveCodexNativeNodeExecBlock(params) {
267
276
  });
268
277
  }
269
278
  //#endregion
270
- export { resolveCodexNativeExecutionPolicy as i, resolveCodexNativeExecutionBlock as n, resolveCodexNativeSandboxBlock as r, resolveCodexAppServerDirectSandboxBypassBlock as t };
279
+ export { resolveCodexNodeExecToolOverrides as a, resolveCodexNativeExecutionPolicy as i, resolveCodexNativeExecutionBlock as n, resolveCodexNativeSandboxBlock as r, resolveCodexAppServerDirectSandboxBypassBlock as t };