@openagentsinc/pylon 0.1.2 → 0.1.3

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.
package/README.md CHANGED
@@ -10,6 +10,9 @@ available.
10
10
 
11
11
  ```bash
12
12
  npx @openagentsinc/pylon
13
+ bunx @openagentsinc/pylon
14
+ npm install -g @openagentsinc/pylon && pylon
15
+ bun install -g @openagentsinc/pylon && pylon
13
16
  npx @openagentsinc/pylon --version 0.0.1-rc4
14
17
  npx @openagentsinc/pylon --no-launch
15
18
  npx @openagentsinc/pylon --download-curated-cache --model gemma-4-e2b --diagnostic-repeats 2
@@ -18,8 +21,10 @@ npx @openagentsinc/pylon --verbose
18
21
 
19
22
  The launcher:
20
23
 
21
- - resolves the latest tagged `pylon-v...` release by default, or a specific
22
- tagged `Pylon` version when `--version` is provided
24
+ - supports direct `npx` / `bunx` execution plus global `npm install -g` /
25
+ `bun install -g` installs with the same `pylon` command
26
+ - checks GitHub for the latest tagged `pylon-v...` release on each default run,
27
+ or resolves a specific tagged `Pylon` version when `--version` is provided
23
28
  - resolves the correct `pylon-v<version>-<os>-<arch>.tar.gz` asset for the
24
29
  current machine
25
30
  - falls back to the exact tagged source checkout and builds `pylon` plus
@@ -29,8 +34,13 @@ The launcher:
29
34
  - downloads the archive and published SHA-256 checksum
30
35
  - verifies the checksum before extracting
31
36
  - caches the unpacked binaries under `~/.openagents/pylon/bootstrap/`
37
+ - never links or copies those cached standalone binaries into a shared global
38
+ bin directory, so the package-managed `pylon` launcher remains the command on
39
+ `PATH`
32
40
  - prints status lines such as release resolution, runtime checks, and local
33
41
  model scanning while it runs
42
+ - ends first run with an explicit verdict such as `fully online`, `runtime
43
+ ready`, or `installed but runtime missing`, plus exact next-step guidance
34
44
  - runs `pylon --help`, `init`, `status --json`, and `inventory --json`
35
45
  - runs `pylon gemma diagnose <model> --json`
36
46
  - only runs `pylon gemma download <model>` when `--download-curated-cache` is
@@ -39,6 +49,9 @@ The launcher:
39
49
  - falls back to `curl` for release metadata and asset downloads when the Node
40
50
  fetch path fails in constrained network contexts
41
51
  - opens `pylon-tui` by default after the smoke path unless `--no-launch` is set
52
+ - does not try to install or register a local runtime automatically; the
53
+ bootstrap stays honest about the separate Ollama-compatible runtime
54
+ prerequisite instead of mutating the host behind the user's back
42
55
 
43
56
  ## Publish
44
57
 
@@ -46,5 +59,6 @@ Publish directly from this package directory:
46
59
 
47
60
  ```bash
48
61
  cd packages/pylon-bootstrap
62
+ npm pack --dry-run
49
63
  npm publish
50
64
  ```
package/bin/pylon ADDED
@@ -0,0 +1,26 @@
1
+ #!/bin/sh
2
+
3
+ set -eu
4
+
5
+ SCRIPT_PATH="$0"
6
+ while [ -L "$SCRIPT_PATH" ]; do
7
+ LINK_TARGET=$(readlink "$SCRIPT_PATH")
8
+ case "$LINK_TARGET" in
9
+ /*) SCRIPT_PATH="$LINK_TARGET" ;;
10
+ *) SCRIPT_PATH="$(dirname -- "$SCRIPT_PATH")/$LINK_TARGET" ;;
11
+ esac
12
+ done
13
+
14
+ SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$SCRIPT_PATH")" && pwd)
15
+ LAUNCHER_JS="${SCRIPT_DIR}/pylon.js"
16
+
17
+ if command -v node >/dev/null 2>&1; then
18
+ exec node "$LAUNCHER_JS" "$@"
19
+ fi
20
+
21
+ if command -v bun >/dev/null 2>&1; then
22
+ exec bun "$LAUNCHER_JS" "$@"
23
+ fi
24
+
25
+ echo "pylon launcher requires Node.js or Bun on PATH." >&2
26
+ exit 1
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@openagentsinc/pylon",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
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.js"
7
+ "pylon": "./bin/pylon"
8
8
  },
9
9
  "files": [
10
10
  "bin",
package/src/cli.js CHANGED
@@ -7,6 +7,7 @@ import {
7
7
  bootstrapInstalledPylon,
8
8
  ensureReleaseInstall,
9
9
  launchInstalledPylonTui,
10
+ resolveBootstrapOutcome,
10
11
  renderBootstrapSummary,
11
12
  } from "./index.js";
12
13
 
@@ -67,6 +68,8 @@ function createReporter({ enableColor = process.stdout.isTTY && !process.env.NO_
67
68
  export function usage() {
68
69
  return `Usage:
69
70
  npx @openagentsinc/pylon [options]
71
+ bunx @openagentsinc/pylon [options]
72
+ pylon [options]
70
73
 
71
74
  Description:
72
75
  Download the latest tagged standalone Pylon release asset for this machine,
@@ -74,7 +77,9 @@ Description:
74
77
  asset exists for the local platform, fetch the exact tagged source checkout
75
78
  and build it locally instead. Cache the binaries, run the first-run smoke
76
79
  path, and then open the Pylon terminal UI by default with live status
77
- updates.
80
+ updates. The launcher checks GitHub for newer tagged pylon-v... releases on
81
+ each default run, but only caches the standalone binaries under the local
82
+ bootstrap root; it does not replace your global npm or bun pylon command.
78
83
 
79
84
  Options:
80
85
  --version <x.y.z> Resolve a specific Pylon release.
@@ -244,7 +249,12 @@ export async function main(argv = process.argv.slice(2), dependencies = {}) {
244
249
  if (options.json) {
245
250
  console.log(JSON.stringify(summary, null, 2));
246
251
  } else {
247
- reporter?.success("Pylon bootstrap complete");
252
+ const outcome = resolveBootstrapOutcome(summary);
253
+ if (outcome.level === "success") {
254
+ reporter?.success(`Pylon ${outcome.verdict}`, outcome.detail);
255
+ } else {
256
+ reporter?.warning(`Pylon ${outcome.verdict}`, outcome.detail);
257
+ }
248
258
  console.log(renderBootstrapSummary(summary));
249
259
  if (!options.noLaunch) {
250
260
  await launchInstalledPylonTuiImpl(
package/src/index.js CHANGED
@@ -17,6 +17,7 @@ export const DEFAULT_FETCH_TIMEOUT_MS = 15_000;
17
17
  const PYLON_RELEASE_TAG_PREFIX = "pylon-v";
18
18
  const RELEASE_ASSET_INSTALL_METHOD = "release_asset";
19
19
  const SOURCE_BUILD_INSTALL_METHOD = "source_build";
20
+ const PREFERRED_RUNTIME_MODEL_NAME = "gemma4:e4b";
20
21
 
21
22
  function emitStatus(onStatus, message, detail = null) {
22
23
  if (typeof onStatus === "function") {
@@ -1133,7 +1134,7 @@ export async function ensureReleaseInstall(
1133
1134
 
1134
1135
  emitStatus(
1135
1136
  onStatus,
1136
- "Resolving latest tagged Pylon release",
1137
+ "Checking for newer tagged Pylon releases",
1137
1138
  options.version ? `requested ${options.version}` : "default release track",
1138
1139
  );
1139
1140
  const target = resolvePlatformTarget(options.platform, options.arch);
@@ -1483,14 +1484,99 @@ export async function launchInstalledPylonTui(
1483
1484
  });
1484
1485
  }
1485
1486
 
1487
+ export function resolveBootstrapOutcome(summary) {
1488
+ const runtimeState =
1489
+ summary.status?.snapshot?.runtime?.authoritative_status ?? "unknown";
1490
+ const localGemma = summary.status?.snapshot?.availability?.local_gemma ?? {};
1491
+ const readyModel = localGemma.ready_model ?? null;
1492
+ const localGemmaError = localGemma.last_error ?? null;
1493
+ const diagnosticStatus = summary.diagnosticResult?.status ?? null;
1494
+
1495
+ if (runtimeState === "online") {
1496
+ return {
1497
+ level: "success",
1498
+ verdict: "fully online",
1499
+ detail: readyModel
1500
+ ? `loaded runtime model ${readyModel}`
1501
+ : "eligible local Gemma supply is online",
1502
+ };
1503
+ }
1504
+
1505
+ if (readyModel) {
1506
+ return {
1507
+ level: "success",
1508
+ verdict: "runtime ready",
1509
+ detail: `loaded runtime model ${readyModel}`,
1510
+ };
1511
+ }
1512
+
1513
+ const loweredError = (localGemmaError ?? "").toLowerCase();
1514
+ if (loweredError.includes("/api/tags") || loweredError.includes("not reachable")) {
1515
+ return {
1516
+ level: "warning",
1517
+ verdict: "installed but runtime missing",
1518
+ detail:
1519
+ "no Ollama-compatible local runtime is answering /api/tags yet",
1520
+ };
1521
+ }
1522
+
1523
+ if (
1524
+ diagnosticStatus &&
1525
+ diagnosticStatus !== "completed" &&
1526
+ diagnosticStatus !== "passed" &&
1527
+ diagnosticStatus !== "healthy"
1528
+ ) {
1529
+ return {
1530
+ level: "warning",
1531
+ verdict: "installed but runtime not yet usable",
1532
+ detail: diagnosticStatus,
1533
+ };
1534
+ }
1535
+
1536
+ return {
1537
+ level: "warning",
1538
+ verdict: "installed",
1539
+ detail: "complete the local runtime setup before bringing the node online",
1540
+ };
1541
+ }
1542
+
1543
+ function renderBootstrapNextSteps(summary, outcome) {
1544
+ const lines = [
1545
+ "Launcher path: use the same npx/bunx command again, or install globally and run `pylon`.",
1546
+ ];
1547
+
1548
+ if (outcome.verdict === "fully online" || outcome.verdict === "runtime ready") {
1549
+ lines.push("Next step: open the TUI with `pylon`, or keep using the package-managed launcher.");
1550
+ return lines;
1551
+ }
1552
+
1553
+ if (summary.target?.os === "darwin") {
1554
+ lines.push(
1555
+ "Runtime setup (macOS default): `brew install ollama`, `brew services start ollama`, `ollama pull gemma4:e4b`.",
1556
+ );
1557
+ } else {
1558
+ lines.push(
1559
+ "Runtime setup: start an Ollama-compatible local runtime at `local_gemma_base_url` and load `gemma4:e4b`.",
1560
+ );
1561
+ }
1562
+ lines.push(
1563
+ "Persistent PATH command: `npm install -g @openagentsinc/pylon` or `bun install -g @openagentsinc/pylon`, then run `pylon`.",
1564
+ );
1565
+ return lines;
1566
+ }
1567
+
1486
1568
  export function renderBootstrapSummary(summary) {
1569
+ const outcome = resolveBootstrapOutcome(summary);
1487
1570
  const lines = [
1571
+ `Onboarding verdict: ${outcome.verdict}`,
1572
+ `Verdict detail: ${outcome.detail}`,
1488
1573
  `Pylon release: ${summary.version} (${summary.target.os}-${summary.target.arch})`,
1489
1574
  `Archive source: ${summary.tagName}`,
1490
1575
  `Installed from cache: ${summary.cached ? "yes" : "no"}`,
1491
1576
  `Pylon binary: ${summary.binaries.pylon}`,
1492
1577
  `Pylon TUI: ${summary.binaries.pylonTui}`,
1493
1578
  `Config path: ${summary.configPath ?? "unknown"}`,
1579
+ `Preferred runtime model name: ${PREFERRED_RUNTIME_MODEL_NAME}`,
1494
1580
  ];
1495
1581
 
1496
1582
  const statusState =
@@ -1549,5 +1635,7 @@ export function renderBootstrapSummary(summary) {
1549
1635
  }
1550
1636
  }
1551
1637
 
1638
+ lines.push(...renderBootstrapNextSteps(summary, outcome));
1639
+
1552
1640
  return lines.join("\n");
1553
1641
  }