agentroam 0.2.0-preview.47 → 0.2.0-preview.48

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.
@@ -1,13 +1,13 @@
1
1
  import { execFile } from "node:child_process";
2
2
  import { constants } from "node:fs";
3
- import { access, chmod, mkdir, mkdtemp, open, rename, rm, stat, } from "node:fs/promises";
3
+ import { access, chmod, mkdir, mkdtemp, open, readdir, rename, rm, stat, } from "node:fs/promises";
4
4
  import { delimiter, dirname, isAbsolute, relative, resolve, win32 } from "node:path";
5
5
  import { promisify } from "node:util";
6
6
  const execFileAsync = promisify(execFile);
7
- export const CODEX_RUNTIME_VERSION = "0.153.0";
8
- // Managed install pin tracks releases; the compatibility floor for user installs is independent.
7
+ // Fresh installs follow npm's latest stable release; existing installs have an independent floor.
8
+ export const CODEX_RUNTIME_TAG = "latest";
9
9
  export const CODEX_MINIMUM_VERSION = "0.153.0";
10
- const CODEX_PACKAGE = `@openai/codex@${CODEX_RUNTIME_VERSION}`;
10
+ const CODEX_PACKAGE = `@openai/codex@${CODEX_RUNTIME_TAG}`;
11
11
  const NPM_REGISTRY = "https://registry.npmjs.org";
12
12
  export const CODEX_INSTALL_TIMEOUT_MS = 60 * 60_000;
13
13
  const DEFAULT_LOCK_WAIT_MS = 190_000;
@@ -50,17 +50,16 @@ export async function resolveCodexRuntime(options) {
50
50
  const global = await findCompatibleGlobalCodex(environment.PATH, platform, dependencies);
51
51
  if (global)
52
52
  return global;
53
- const managedRoot = resolve(options.dataDir, "runtimes", "codex", CODEX_RUNTIME_VERSION);
54
- const managed = await validateManagedRuntime(managedRoot, options.target, platform, dependencies);
53
+ const managedParent = resolve(options.dataDir, "runtimes", "codex");
54
+ const managed = await findManagedRuntime(managedParent, options.target, platform, dependencies);
55
55
  if (managed)
56
56
  return managed;
57
- options.onProgress?.(`Installing managed Codex ${CODEX_RUNTIME_VERSION}...`);
57
+ options.onProgress?.(`Installing managed Codex from ${CODEX_PACKAGE}...`);
58
58
  return installManagedCodex({
59
59
  ...options,
60
60
  environment,
61
61
  platform,
62
62
  dependencies,
63
- managedRoot,
64
63
  });
65
64
  }
66
65
  export async function resolveNpmExecutor(options = {}) {
@@ -165,19 +164,19 @@ async function findCompatibleGlobalCodex(pathValue, platform, dependencies) {
165
164
  }
166
165
  async function installManagedCodex(options) {
167
166
  const parent = resolve(options.dataDir, "runtimes", "codex");
168
- const lockPath = `${options.managedRoot}.lock`;
167
+ const lockPath = resolve(parent, "install.lock");
169
168
  const lockWaitMs = options.lockWaitMs ?? DEFAULT_LOCK_WAIT_MS;
170
169
  const staleLockMs = options.staleLockMs ?? DEFAULT_STALE_LOCK_MS;
171
170
  await mkdir(parent, { recursive: true });
172
- const lock = await acquireInstallLock(lockPath, options.managedRoot, options.target, options.platform, options.dependencies, lockWaitMs, staleLockMs);
171
+ const lock = await acquireInstallLock(lockPath, parent, options.target, options.platform, options.dependencies, lockWaitMs, staleLockMs);
173
172
  if (lock.completed)
174
173
  return lock.completed;
175
174
  let temporaryRoot = null;
176
175
  try {
177
- const existing = await validateManagedRuntime(options.managedRoot, options.target, options.platform, options.dependencies);
176
+ const existing = await findManagedRuntime(parent, options.target, options.platform, options.dependencies);
178
177
  if (existing)
179
178
  return existing;
180
- temporaryRoot = await mkdtemp(resolve(parent, `.${CODEX_RUNTIME_VERSION}-${process.pid}-`));
179
+ temporaryRoot = await mkdtemp(resolve(parent, `.${CODEX_RUNTIME_TAG}-${process.pid}-`));
181
180
  const npm = await resolveNpmExecutor({
182
181
  environment: options.environment,
183
182
  platform: options.platform,
@@ -189,6 +188,7 @@ async function installManagedCodex(options) {
189
188
  "--ignore-scripts",
190
189
  "--no-audit",
191
190
  "--no-fund",
191
+ "--prefer-online",
192
192
  `--registry=${NPM_REGISTRY}`,
193
193
  "--prefix",
194
194
  temporaryRoot,
@@ -198,18 +198,21 @@ async function installManagedCodex(options) {
198
198
  if (!temporary) {
199
199
  throw new Error(`Codex runtime validation failed after installing ${CODEX_PACKAGE}`);
200
200
  }
201
- await rename(temporaryRoot, options.managedRoot);
201
+ const managedRoot = resolve(parent, temporary.version);
202
+ // An invalid cache for this version must not block a validated replacement.
203
+ await rm(managedRoot, { recursive: true, force: true });
204
+ await rename(temporaryRoot, managedRoot);
202
205
  temporaryRoot = null;
203
- const installed = await validateManagedRuntime(options.managedRoot, options.target, options.platform, options.dependencies);
206
+ const installed = await validateManagedRuntime(managedRoot, options.target, options.platform, options.dependencies);
204
207
  if (!installed)
205
208
  throw new Error("Codex runtime validation failed after activation");
206
209
  return installed;
207
210
  }
208
211
  catch (error) {
209
- const concurrent = await validateManagedRuntime(options.managedRoot, options.target, options.platform, options.dependencies);
212
+ const concurrent = await findManagedRuntime(parent, options.target, options.platform, options.dependencies);
210
213
  if (concurrent)
211
214
  return concurrent;
212
- throw new Error(`Unable to install managed Codex ${CODEX_RUNTIME_VERSION}: ${describeError(error)}`, {
215
+ throw new Error(`Unable to install managed Codex from ${CODEX_PACKAGE}: ${describeError(error)}`, {
213
216
  cause: error,
214
217
  });
215
218
  }
@@ -220,7 +223,7 @@ async function installManagedCodex(options) {
220
223
  await rm(lockPath, { force: true });
221
224
  }
222
225
  }
223
- async function acquireInstallLock(lockPath, managedRoot, target, platform, dependencies, waitMs, staleMs) {
226
+ async function acquireInstallLock(lockPath, managedParent, target, platform, dependencies, waitMs, staleMs) {
224
227
  const deadline = dependencies.now() + waitMs;
225
228
  while (true) {
226
229
  try {
@@ -231,7 +234,7 @@ async function acquireInstallLock(lockPath, managedRoot, target, platform, depen
231
234
  catch (error) {
232
235
  if (error.code !== "EEXIST")
233
236
  throw error;
234
- const completed = await validateManagedRuntime(managedRoot, target, platform, dependencies);
237
+ const completed = await findManagedRuntime(managedParent, target, platform, dependencies);
235
238
  if (completed)
236
239
  return { completed };
237
240
  try {
@@ -251,6 +254,24 @@ async function acquireInstallLock(lockPath, managedRoot, target, platform, depen
251
254
  }
252
255
  }
253
256
  }
257
+ async function findManagedRuntime(parent, target, platform, dependencies) {
258
+ const entries = await readdir(parent, { withFileTypes: true }).catch((error) => {
259
+ if (error.code === "ENOENT")
260
+ return [];
261
+ throw error;
262
+ });
263
+ const versions = entries
264
+ .filter((entry) => entry.isDirectory() && parseCodexVersion(entry.name) === entry.name)
265
+ .map((entry) => entry.name)
266
+ .filter(meetsCodexMinimum)
267
+ .sort((left, right) => left === right ? 0 : isCodexVersionAtLeast(left, right) ? -1 : 1);
268
+ for (const version of versions) {
269
+ const runtime = await validateManagedRuntime(resolve(parent, version), target, platform, dependencies);
270
+ if (runtime?.version === version)
271
+ return runtime;
272
+ }
273
+ return null;
274
+ }
254
275
  async function validateManagedRuntime(runtimeRoot, target, platform, dependencies) {
255
276
  for (const candidate of managedCodexBinaryCandidates(runtimeRoot, target)) {
256
277
  if (!isWithin(runtimeRoot, candidate) || !(await pathAccessible(candidate)))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentroam",
3
- "version": "0.2.0-preview.47",
3
+ "version": "0.2.0-preview.48",
4
4
  "description": "Zero-install mobile remote terminal and file console",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,8 +27,8 @@
27
27
  "ws": "^8.21.3"
28
28
  },
29
29
  "optionalDependencies": {
30
- "agentroam-runtime-darwin-arm64": "0.2.0-preview.47",
31
- "agentroam-runtime-win32-x64": "0.2.0-preview.47",
30
+ "agentroam-runtime-darwin-arm64": "0.2.0-preview.48",
31
+ "agentroam-runtime-win32-x64": "0.2.0-preview.48",
32
32
  "agentroam-cloudflared-darwin-arm64": "0.2.0-preview.39",
33
33
  "agentroam-cloudflared-win32-x64": "0.2.0-preview.39",
34
34
  "agentroam-tui-darwin-arm64": "0.2.0-preview.47",