@openagentsinc/pylon 0.1.17 → 0.2.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 (3) hide show
  1. package/README.md +5 -2
  2. package/package.json +3 -3
  3. package/src/index.js +65 -11
package/README.md CHANGED
@@ -28,8 +28,9 @@ The launcher:
28
28
  - checks GitHub for the latest tagged `pylon-v...` release on each default run,
29
29
  or resolves a specific tagged `Pylon` version when `--version` is provided
30
30
  - only installs releases initiated by `AtlantisPleb` in GitHub Releases
31
- - resolves the correct `pylon-v<version>-<os>-<arch>.tar.gz` asset for the
32
- current machine
31
+ - resolves the correct release asset for the current machine:
32
+ `pylon-v<version>-<os>-<arch>.tar.gz` on darwin/linux and
33
+ `pylon-v<version>-windows-x86_64.zip` on native Windows x86_64
33
34
  - falls back to the exact tagged source checkout and builds `pylon` plus
34
35
  `pylon-tui` locally when no matching release asset exists for the machine
35
36
  - prompts before installing the Rust toolchain via `rustup` if a source build
@@ -63,6 +64,8 @@ The launcher:
63
64
  unless `--no-launch` is set
64
65
  - forwards CLI subcommands such as `pylon status --json` to the installed
65
66
  `pylon` binary after bootstrap instead of opening `pylon-tui`
67
+ - on native Windows x86_64, installs `pylon.exe` and `pylon-tui.exe` from the
68
+ Windows `.zip` release asset and forwards CLI subcommands to `pylon.exe`
66
69
  - while the TUI is running on the default release track, checks GitHub Releases
67
70
  on a six-hour cadence and restarts the TUI from a newer trusted cached release
68
71
  without replacing the global npm/bun command
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@openagentsinc/pylon",
3
- "version": "0.1.17",
3
+ "version": "0.2.2",
4
4
  "description": "Bootstrap the standalone OpenAgents Pylon release asset and run first-run smoke checks.",
5
5
  "type": "module",
6
6
  "bin": {
7
- "pylon": "./bin/pylon"
7
+ "pylon": "bin/pylon"
8
8
  },
9
9
  "files": [
10
10
  "bin",
@@ -16,7 +16,7 @@
16
16
  },
17
17
  "repository": {
18
18
  "type": "git",
19
- "url": "https://github.com/OpenAgentsInc/openagents.git",
19
+ "url": "git+https://github.com/OpenAgentsInc/openagents.git",
20
20
  "directory": "packages/pylon-bootstrap"
21
21
  },
22
22
  "scripts": {
package/src/index.js CHANGED
@@ -30,6 +30,18 @@ const LEGACY_SOURCE_BUILD_SIBLING_REPOSITORIES = {
30
30
  "spark-sdk": "https://github.com/AtlantisPleb/spark-sdk.git",
31
31
  };
32
32
 
33
+ function archiveExtensionForTarget(target) {
34
+ return target?.os === "windows" ? ".zip" : ".tar.gz";
35
+ }
36
+
37
+ function binaryExtensionForTarget(target) {
38
+ return target?.os === "windows" ? ".exe" : "";
39
+ }
40
+
41
+ function binaryNameForTarget(binaryName, target) {
42
+ return `${binaryName}${binaryExtensionForTarget(target)}`;
43
+ }
44
+
33
45
  function emitStatus(onStatus, message, detail = null) {
34
46
  if (typeof onStatus === "function") {
35
47
  onStatus({ message, detail });
@@ -390,10 +402,11 @@ export function resolvePlatformTarget(
390
402
  {
391
403
  darwin: "darwin",
392
404
  linux: "linux",
405
+ win32: "windows",
393
406
  }[platform] ?? null;
394
407
  if (!osLabel) {
395
408
  throw new Error(
396
- `Unsupported platform \`${platform}\`. The npm launcher only supports darwin and linux in v1.`,
409
+ `Unsupported platform \`${platform}\`. The npm launcher only supports darwin, linux, and native Windows in v1.`,
397
410
  );
398
411
  }
399
412
 
@@ -420,10 +433,12 @@ export function buildArchiveBasename(version, target) {
420
433
 
421
434
  export function buildAssetNames(version, target) {
422
435
  const archiveBasename = buildArchiveBasename(version, target);
436
+ const archiveExtension = archiveExtensionForTarget(target);
437
+ const archiveName = `${archiveBasename}${archiveExtension}`;
423
438
  return {
424
439
  archiveBasename,
425
- archiveName: `${archiveBasename}.tar.gz`,
426
- checksumName: `${archiveBasename}.tar.gz.sha256`,
440
+ archiveName,
441
+ checksumName: `${archiveName}.sha256`,
427
442
  };
428
443
  }
429
444
 
@@ -762,8 +777,8 @@ export function buildInstallPaths(installRoot, version, target) {
762
777
  archivePath: path.join(downloadsDir, archiveName),
763
778
  checksumPath: path.join(downloadsDir, checksumName),
764
779
  manifestPath: path.join(installDir, "install.json"),
765
- pylonPath: path.join(installDir, "pylon"),
766
- pylonTuiPath: path.join(installDir, "pylon-tui"),
780
+ pylonPath: path.join(installDir, binaryNameForTarget("pylon", target)),
781
+ pylonTuiPath: path.join(installDir, binaryNameForTarget("pylon-tui", target)),
767
782
  };
768
783
  }
769
784
 
@@ -1219,8 +1234,18 @@ async function installSourceBuild(
1219
1234
  stdio: "inherit",
1220
1235
  });
1221
1236
 
1222
- const builtPylonPath = path.join(repoDir, "target", "release", "pylon");
1223
- const builtPylonTuiPath = path.join(repoDir, "target", "release", "pylon-tui");
1237
+ const builtPylonPath = path.join(
1238
+ repoDir,
1239
+ "target",
1240
+ "release",
1241
+ binaryNameForTarget("pylon", target),
1242
+ );
1243
+ const builtPylonTuiPath = path.join(
1244
+ repoDir,
1245
+ "target",
1246
+ "release",
1247
+ binaryNameForTarget("pylon-tui", target),
1248
+ );
1224
1249
  if (!(await pathExists(builtPylonPath)) || !(await pathExists(builtPylonTuiPath))) {
1225
1250
  throw new Error(
1226
1251
  `Source build completed without the expected binaries at ${path.join(repoDir, "target", "release")}.`,
@@ -1315,8 +1340,11 @@ async function findLatestCachedInstall(installRoot, target) {
1315
1340
 
1316
1341
  const installDir = path.join(versionsDir, entry.name);
1317
1342
  const manifestPath = path.join(installDir, "install.json");
1318
- const pylonPath = path.join(installDir, "pylon");
1319
- const pylonTuiPath = path.join(installDir, "pylon-tui");
1343
+ const pylonPath = path.join(installDir, binaryNameForTarget("pylon", target));
1344
+ const pylonTuiPath = path.join(
1345
+ installDir,
1346
+ binaryNameForTarget("pylon-tui", target),
1347
+ );
1320
1348
  if (
1321
1349
  !(await pathExists(manifestPath)) ||
1322
1350
  !(await pathExists(pylonPath)) ||
@@ -1447,8 +1475,34 @@ function spawnPylonTui(pylonTuiPath, options, spawnProcessImpl) {
1447
1475
  });
1448
1476
  }
1449
1477
 
1450
- async function extractArchive(archivePath, destinationDir, runProcessImpl) {
1478
+ async function extractArchive(archivePath, destinationDir, target, runProcessImpl) {
1451
1479
  await fs.mkdir(destinationDir, { recursive: true });
1480
+ if (target?.os === "windows") {
1481
+ const args = [
1482
+ "-NoProfile",
1483
+ "-NonInteractive",
1484
+ "-ExecutionPolicy",
1485
+ "Bypass",
1486
+ "-Command",
1487
+ "& { param([string]$ArchivePath, [string]$DestinationPath) Expand-Archive -LiteralPath $ArchivePath -DestinationPath $DestinationPath -Force }",
1488
+ archivePath,
1489
+ destinationDir,
1490
+ ];
1491
+ for (const command of ["powershell.exe", "pwsh", "powershell"]) {
1492
+ try {
1493
+ await runProcessImpl(command, args);
1494
+ return;
1495
+ } catch (error) {
1496
+ const message = error instanceof Error ? error.message : String(error);
1497
+ if (!message.startsWith(`Failed to start ${command}`)) {
1498
+ throw error;
1499
+ }
1500
+ }
1501
+ }
1502
+ throw new Error(
1503
+ "Windows archive extraction requires PowerShell (tried powershell.exe, pwsh, and powershell).",
1504
+ );
1505
+ }
1452
1506
  await runProcessImpl("tar", ["-xzf", archivePath, "-C", destinationDir]);
1453
1507
  }
1454
1508
 
@@ -1782,7 +1836,7 @@ export async function ensureReleaseInstall(
1782
1836
  paths.installDir,
1783
1837
  );
1784
1838
  await fs.rm(paths.installDir, { recursive: true, force: true });
1785
- await extractArchive(paths.archivePath, paths.versionsDir, runProcessImpl);
1839
+ await extractArchive(paths.archivePath, paths.versionsDir, target, runProcessImpl);
1786
1840
 
1787
1841
  if (!(await pathExists(paths.pylonPath)) || !(await pathExists(paths.pylonTuiPath))) {
1788
1842
  throw new Error(