agentworth 0.1.9 → 0.1.11

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 (2) hide show
  1. package/lib/resolver.js +49 -12
  2. package/package.json +1 -1
package/lib/resolver.js CHANGED
@@ -32,7 +32,12 @@ export function getTargetTriple(platform = process.platform, arch = process.arch
32
32
  if (platform === 'darwin' && arch === 'x64') return 'x86_64-apple-darwin';
33
33
  if (platform === 'linux' && arch === 'x64') return 'x86_64-unknown-linux-gnu';
34
34
  if (platform === 'linux' && arch === 'arm64') return 'aarch64-unknown-linux-gnu';
35
- if (platform === 'win32' && arch === 'x64') return 'x86_64-pc-windows-msvc';
35
+ // Windows dropped 2026-09-02: release.yml no longer builds x86_64-pc-windows-msvc, so
36
+ // this would 404 against the downloader even if it matched. The recurring failure was
37
+ // GNU tar on Windows misparsing a "C:\..." archive path as a remote "host:path" tar
38
+ // spec -- fixable (--force-local), but broke across multiple releases regardless, and
39
+ // nobody here can test a real Windows box to catch it before it ships. A user who wants
40
+ // this on Windows can still build it themselves: `cargo build --release -p agentworth-cli`.
36
41
  return null;
37
42
  }
38
43
 
@@ -249,9 +254,12 @@ export async function downloadAndExtractBinary(options = {}) {
249
254
 
250
255
  await downloadFile(url, archivePath);
251
256
 
252
- // Extract archive
257
+ // Extract archive. --force-local matters on Windows: a drive-letter path like
258
+ // "C:\Users\...\agentworth.tar.gz" otherwise gets parsed as a "host:path" remote-tar
259
+ // spec (the "C" before the colon reads as a hostname), and tar tries to rsh/ssh to it
260
+ // instead of opening a local file.
253
261
  try {
254
- execFileSync('tar', ['-xzf', archivePath, '-C', cacheDir]);
262
+ execFileSync('tar', ['--force-local', '-xzf', archivePath, '-C', cacheDir]);
255
263
  } catch (err) {
256
264
  throw new Error(`Failed to extract ${archiveName}: ${err.message}`);
257
265
  } finally {
@@ -411,9 +419,17 @@ export function resolveBinary(options = {}) {
411
419
  }
412
420
  }
413
421
 
422
+ // 4-7 all found a real, executable candidate but said nothing about whether it's the
423
+ // version this launcher is meant to run -- so a debug build from six releases ago,
424
+ // sitting in some worktree's target/ directory upward of wherever the user happened to
425
+ // invoke `agentworth` from, would silently win over the correctly-versioned release cache
426
+ // (8) forever. Same failure mode already fixed for PATH (3) above, same fix here: a
427
+ // candidate only counts if it reports the version this launcher ships.
428
+ const expectedVersion = getPackageVersion(baseDir);
429
+
414
430
  // 4. Local Cargo target from working directory
415
431
  const cwdCargoBin = findCargoTargetBinary(cwd, binName);
416
- if (cwdCargoBin) {
432
+ if (cwdCargoBin && pathBinaryMatchesVersion(cwdCargoBin, expectedVersion)) {
417
433
  return {
418
434
  found: true,
419
435
  path: cwdCargoBin,
@@ -423,7 +439,7 @@ export function resolveBinary(options = {}) {
423
439
 
424
440
  // 5. Local Cargo target from package directory hierarchy
425
441
  const pkgCargoBin = findCargoTargetBinary(baseDir, binName);
426
- if (pkgCargoBin) {
442
+ if (pkgCargoBin && pathBinaryMatchesVersion(pkgCargoBin, expectedVersion)) {
427
443
  return {
428
444
  found: true,
429
445
  path: pkgCargoBin,
@@ -434,7 +450,7 @@ export function resolveBinary(options = {}) {
434
450
  // 6. CARGO_TARGET_DIR environment variable if specified
435
451
  if (env.CARGO_TARGET_DIR) {
436
452
  const targetDirRelease = path.join(env.CARGO_TARGET_DIR, 'release', binName);
437
- if (isExecutable(targetDirRelease)) {
453
+ if (isExecutable(targetDirRelease) && pathBinaryMatchesVersion(targetDirRelease, expectedVersion)) {
438
454
  return {
439
455
  found: true,
440
456
  path: targetDirRelease,
@@ -442,7 +458,7 @@ export function resolveBinary(options = {}) {
442
458
  };
443
459
  }
444
460
  const targetDirDebug = path.join(env.CARGO_TARGET_DIR, 'debug', binName);
445
- if (isExecutable(targetDirDebug)) {
461
+ if (isExecutable(targetDirDebug) && pathBinaryMatchesVersion(targetDirDebug, expectedVersion)) {
446
462
  return {
447
463
  found: true,
448
464
  path: targetDirDebug,
@@ -454,7 +470,7 @@ export function resolveBinary(options = {}) {
454
470
  // 7. User ~/.cargo/bin directory
455
471
  if (homeDir) {
456
472
  const cargoHomeBin = path.join(homeDir, '.cargo', 'bin', binName);
457
- if (isExecutable(cargoHomeBin)) {
473
+ if (isExecutable(cargoHomeBin) && pathBinaryMatchesVersion(cargoHomeBin, expectedVersion)) {
458
474
  return {
459
475
  found: true,
460
476
  path: cargoHomeBin,
@@ -462,8 +478,9 @@ export function resolveBinary(options = {}) {
462
478
  };
463
479
  }
464
480
 
465
- // 8. User local cache (~/.agentworth/bin/v{version}/)
466
- const cacheDir = getCacheDir(getPackageVersion(baseDir), homeDir);
481
+ // 8. User local cache (~/.agentworth/bin/v{version}/) -- versioned by construction,
482
+ // nothing to check.
483
+ const cacheDir = getCacheDir(expectedVersion, homeDir);
467
484
  const cachedBin = path.join(cacheDir, binName);
468
485
  if (isExecutable(cachedBin)) {
469
486
  return {
@@ -507,6 +524,23 @@ export function formatMissingBinaryMessage(platformKey = getPlatformKey()) {
507
524
  ].join('\n');
508
525
  }
509
526
 
527
+ /**
528
+ * Builds the environment passed to the spawned native binary: the caller's base env plus
529
+ * the launcher markers the binary's `agentworth version`/`agentworth update` commands read
530
+ * to detect an npm-managed install (see `apps/cli/src/commands/version_info.rs`).
531
+ *
532
+ * @param {NodeJS.ProcessEnv} baseEnv
533
+ * @param {string} npmVersion
534
+ * @returns {NodeJS.ProcessEnv}
535
+ */
536
+ export function buildChildEnv(baseEnv, npmVersion) {
537
+ return {
538
+ ...baseEnv,
539
+ AGENTWORTH_LAUNCHER_ACTIVE: '1',
540
+ AGENTWORTH_NPM_VERSION: npmVersion,
541
+ };
542
+ }
543
+
510
544
  /**
511
545
  * Launches the native binary with the given arguments.
512
546
  *
@@ -549,8 +583,11 @@ export function run(argv = process.argv.slice(2), options = {}) {
549
583
  return 1;
550
584
  }
551
585
 
552
- // Belt and braces: a child that somehow re-enters this launcher cannot loop.
553
- const childEnv = { ...(options.env || process.env), AGENTWORTH_LAUNCHER_ACTIVE: '1' };
586
+ // Belt and braces: a child that somehow re-enters this launcher cannot loop (the
587
+ // recursion guard in findPathBinary checks AGENTWORTH_LAUNCHER_ACTIVE). The npm version
588
+ // is threaded through too, purely so `agentworth version`/`agentworth update` can report
589
+ // it -- this launcher never reads it back itself.
590
+ const childEnv = buildChildEnv(options.env || process.env, getPackageVersion(options.baseDir || __dirname));
554
591
  const result = spawnSync(binaryResult.path, resolvedArgs, {
555
592
  stdio: 'inherit',
556
593
  env: childEnv,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentworth",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Discover, normalize, and understand AI-agent histories locally.",
5
5
  "type": "module",
6
6
  "main": "./lib/resolver.js",