@openagentsinc/pylon 0.1.0 → 0.1.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.
- package/README.md +20 -4
- package/package.json +1 -1
- package/src/cli.js +108 -8
- package/src/index.js +1050 -82
package/README.md
CHANGED
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
# `@openagentsinc/pylon`
|
|
2
2
|
|
|
3
3
|
Bootstrap the latest tagged standalone `Pylon` release asset from GitHub
|
|
4
|
-
Releases
|
|
4
|
+
Releases, fall back to a deterministic source build when no matching asset
|
|
5
|
+
exists for the local platform, stream first-run status updates in the terminal,
|
|
6
|
+
and open the Pylon terminal UI without Cargo when prebuilt binaries are
|
|
7
|
+
available.
|
|
5
8
|
|
|
6
9
|
## Usage
|
|
7
10
|
|
|
8
11
|
```bash
|
|
9
12
|
npx @openagentsinc/pylon
|
|
10
|
-
npx @openagentsinc/pylon --version 0.1
|
|
11
|
-
npx @openagentsinc/pylon --
|
|
13
|
+
npx @openagentsinc/pylon --version 0.0.1-rc4
|
|
14
|
+
npx @openagentsinc/pylon --no-launch
|
|
15
|
+
npx @openagentsinc/pylon --download-curated-cache --model gemma-4-e2b --diagnostic-repeats 2
|
|
16
|
+
npx @openagentsinc/pylon --verbose
|
|
12
17
|
```
|
|
13
18
|
|
|
14
19
|
The launcher:
|
|
@@ -17,12 +22,23 @@ The launcher:
|
|
|
17
22
|
tagged `Pylon` version when `--version` is provided
|
|
18
23
|
- resolves the correct `pylon-v<version>-<os>-<arch>.tar.gz` asset for the
|
|
19
24
|
current machine
|
|
25
|
+
- falls back to the exact tagged source checkout and builds `pylon` plus
|
|
26
|
+
`pylon-tui` locally when no matching release asset exists for the machine
|
|
27
|
+
- prompts before installing the Rust toolchain via `rustup` if a source build
|
|
28
|
+
is needed and `cargo` / `rustc` are missing
|
|
20
29
|
- downloads the archive and published SHA-256 checksum
|
|
21
30
|
- verifies the checksum before extracting
|
|
22
31
|
- caches the unpacked binaries under `~/.openagents/pylon/bootstrap/`
|
|
32
|
+
- prints status lines such as release resolution, runtime checks, and local
|
|
33
|
+
model scanning while it runs
|
|
23
34
|
- runs `pylon --help`, `init`, `status --json`, and `inventory --json`
|
|
24
|
-
- runs `pylon gemma download <model>`
|
|
25
35
|
- runs `pylon gemma diagnose <model> --json`
|
|
36
|
+
- only runs `pylon gemma download <model>` when `--download-curated-cache` is
|
|
37
|
+
set, because the optional GGUF cache does not satisfy the sellable runtime by
|
|
38
|
+
itself
|
|
39
|
+
- falls back to `curl` for release metadata and asset downloads when the Node
|
|
40
|
+
fetch path fails in constrained network contexts
|
|
41
|
+
- opens `pylon-tui` by default after the smoke path unless `--no-launch` is set
|
|
26
42
|
|
|
27
43
|
## Publish
|
|
28
44
|
|
package/package.json
CHANGED
package/src/cli.js
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
DEFAULT_RELEASE_REPO,
|
|
7
7
|
bootstrapInstalledPylon,
|
|
8
8
|
ensureReleaseInstall,
|
|
9
|
+
launchInstalledPylonTui,
|
|
9
10
|
renderBootstrapSummary,
|
|
10
11
|
} from "./index.js";
|
|
11
12
|
|
|
@@ -17,28 +18,83 @@ function parseIntegerFlag(value, label) {
|
|
|
17
18
|
return parsed;
|
|
18
19
|
}
|
|
19
20
|
|
|
21
|
+
function createTerminalStyles(enableColor) {
|
|
22
|
+
if (!enableColor) {
|
|
23
|
+
return {
|
|
24
|
+
bold: (value) => value,
|
|
25
|
+
cyan: (value) => value,
|
|
26
|
+
dim: (value) => value,
|
|
27
|
+
green: (value) => value,
|
|
28
|
+
red: (value) => value,
|
|
29
|
+
yellow: (value) => value,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const wrap = (open, close) => (value) => `${open}${value}${close}`;
|
|
34
|
+
return {
|
|
35
|
+
bold: wrap("\u001B[1m", "\u001B[22m"),
|
|
36
|
+
cyan: wrap("\u001B[36m", "\u001B[39m"),
|
|
37
|
+
dim: wrap("\u001B[2m", "\u001B[22m"),
|
|
38
|
+
green: wrap("\u001B[32m", "\u001B[39m"),
|
|
39
|
+
red: wrap("\u001B[31m", "\u001B[39m"),
|
|
40
|
+
yellow: wrap("\u001B[33m", "\u001B[39m"),
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function createReporter({ enableColor = process.stdout.isTTY && !process.env.NO_COLOR } = {}) {
|
|
45
|
+
const styles = createTerminalStyles(enableColor);
|
|
46
|
+
return {
|
|
47
|
+
status({ message, detail = null }) {
|
|
48
|
+
const prefix = styles.cyan("›");
|
|
49
|
+
const suffix = detail ? ` ${styles.dim(detail)}` : "";
|
|
50
|
+
console.log(`${prefix} ${styles.bold(message)}${suffix}`);
|
|
51
|
+
},
|
|
52
|
+
success(message, detail = null) {
|
|
53
|
+
const suffix = detail ? ` ${styles.dim(detail)}` : "";
|
|
54
|
+
console.log(`${styles.green("✓")} ${styles.bold(message)}${suffix}`);
|
|
55
|
+
},
|
|
56
|
+
warning(message, detail = null) {
|
|
57
|
+
const suffix = detail ? ` ${styles.dim(detail)}` : "";
|
|
58
|
+
console.log(`${styles.yellow("!")} ${styles.bold(message)}${suffix}`);
|
|
59
|
+
},
|
|
60
|
+
failure(message, detail = null) {
|
|
61
|
+
const suffix = detail ? ` ${styles.dim(detail)}` : "";
|
|
62
|
+
console.error(`${styles.red("x")} ${styles.bold(message)}${suffix}`);
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
20
67
|
export function usage() {
|
|
21
68
|
return `Usage:
|
|
22
69
|
npx @openagentsinc/pylon [options]
|
|
23
70
|
|
|
24
71
|
Description:
|
|
25
72
|
Download the latest tagged standalone Pylon release asset for this machine,
|
|
26
|
-
or a specific tagged Pylon version when --version is set.
|
|
27
|
-
|
|
73
|
+
or a specific tagged Pylon version when --version is set. If no matching
|
|
74
|
+
asset exists for the local platform, fetch the exact tagged source checkout
|
|
75
|
+
and build it locally instead. Cache the binaries, run the first-run smoke
|
|
76
|
+
path, and then open the Pylon terminal UI by default with live status
|
|
77
|
+
updates.
|
|
28
78
|
|
|
29
79
|
Options:
|
|
30
80
|
--version <x.y.z> Resolve a specific Pylon release.
|
|
31
81
|
--install-root <path> Override the launcher cache/install root.
|
|
32
82
|
--config-path <path> Override OPENAGENTS_PYLON_CONFIG_PATH.
|
|
33
83
|
--pylon-home <path> Override OPENAGENTS_PYLON_HOME.
|
|
34
|
-
--model <model-id> Model to
|
|
84
|
+
--model <model-id> Model to diagnose, and optionally
|
|
85
|
+
prefetch into the local GGUF cache.
|
|
35
86
|
Default: ${DEFAULT_MODEL_ID}
|
|
87
|
+
--download-curated-cache Prefetch the optional Hugging Face GGUF
|
|
88
|
+
cache before opening the TUI.
|
|
36
89
|
--diagnostic-repeats <n> Repeat count for pylon gemma diagnose.
|
|
37
90
|
Default: ${DEFAULT_DIAGNOSTIC_REPEATS}
|
|
38
91
|
--diagnostic-max-output-tokens <n> Max output tokens for diagnostics.
|
|
39
92
|
Default: ${DEFAULT_DIAGNOSTIC_MAX_OUTPUT_TOKENS}
|
|
40
|
-
--skip-model-download
|
|
93
|
+
--skip-model-download Keep the curated GGUF cache skipped.
|
|
41
94
|
--skip-diagnostics Skip pylon gemma diagnose.
|
|
95
|
+
--no-launch Do not open pylon-tui after bootstrap.
|
|
96
|
+
--verbose Print extra network and recovery detail.
|
|
97
|
+
--debug-network Alias for --verbose.
|
|
42
98
|
--json Emit a machine-readable JSON summary.
|
|
43
99
|
|
|
44
100
|
Test and maintainer options:
|
|
@@ -59,8 +115,10 @@ export function parseArgs(argv) {
|
|
|
59
115
|
model: DEFAULT_MODEL_ID,
|
|
60
116
|
diagnosticRepeats: DEFAULT_DIAGNOSTIC_REPEATS,
|
|
61
117
|
diagnosticMaxOutputTokens: DEFAULT_DIAGNOSTIC_MAX_OUTPUT_TOKENS,
|
|
62
|
-
skipModelDownload:
|
|
118
|
+
skipModelDownload: true,
|
|
63
119
|
skipDiagnostics: false,
|
|
120
|
+
noLaunch: false,
|
|
121
|
+
verbose: false,
|
|
64
122
|
json: false,
|
|
65
123
|
help: false,
|
|
66
124
|
};
|
|
@@ -98,6 +156,9 @@ export function parseArgs(argv) {
|
|
|
98
156
|
throw new Error("--model requires a value.");
|
|
99
157
|
}
|
|
100
158
|
break;
|
|
159
|
+
case "--download-curated-cache":
|
|
160
|
+
options.skipModelDownload = false;
|
|
161
|
+
break;
|
|
101
162
|
case "--diagnostic-repeats":
|
|
102
163
|
options.diagnosticRepeats = parseIntegerFlag(
|
|
103
164
|
argv[++index],
|
|
@@ -116,6 +177,13 @@ export function parseArgs(argv) {
|
|
|
116
177
|
case "--skip-diagnostics":
|
|
117
178
|
options.skipDiagnostics = true;
|
|
118
179
|
break;
|
|
180
|
+
case "--no-launch":
|
|
181
|
+
options.noLaunch = true;
|
|
182
|
+
break;
|
|
183
|
+
case "--verbose":
|
|
184
|
+
case "--debug-network":
|
|
185
|
+
options.verbose = true;
|
|
186
|
+
break;
|
|
119
187
|
case "--json":
|
|
120
188
|
options.json = true;
|
|
121
189
|
break;
|
|
@@ -144,26 +212,58 @@ export function parseArgs(argv) {
|
|
|
144
212
|
}
|
|
145
213
|
|
|
146
214
|
export async function main(argv = process.argv.slice(2), dependencies = {}) {
|
|
215
|
+
const {
|
|
216
|
+
ensureReleaseInstallImpl = ensureReleaseInstall,
|
|
217
|
+
bootstrapInstalledPylonImpl = bootstrapInstalledPylon,
|
|
218
|
+
launchInstalledPylonTuiImpl = launchInstalledPylonTui,
|
|
219
|
+
} = dependencies;
|
|
147
220
|
const options = parseArgs(argv);
|
|
148
221
|
if (options.help) {
|
|
149
222
|
console.log(usage());
|
|
150
223
|
return null;
|
|
151
224
|
}
|
|
152
225
|
|
|
153
|
-
const
|
|
154
|
-
|
|
226
|
+
const reporter = options.json ? null : createReporter();
|
|
227
|
+
|
|
228
|
+
const install = await ensureReleaseInstallImpl(options, {
|
|
229
|
+
...dependencies,
|
|
230
|
+
onStatus: reporter?.status,
|
|
231
|
+
});
|
|
232
|
+
const summary = await bootstrapInstalledPylonImpl(
|
|
155
233
|
{
|
|
156
234
|
...options,
|
|
157
235
|
...install,
|
|
158
236
|
version: install.version,
|
|
159
237
|
},
|
|
160
|
-
|
|
238
|
+
{
|
|
239
|
+
...dependencies,
|
|
240
|
+
onStatus: reporter?.status,
|
|
241
|
+
},
|
|
161
242
|
);
|
|
162
243
|
|
|
163
244
|
if (options.json) {
|
|
164
245
|
console.log(JSON.stringify(summary, null, 2));
|
|
165
246
|
} else {
|
|
247
|
+
reporter?.success("Pylon bootstrap complete");
|
|
166
248
|
console.log(renderBootstrapSummary(summary));
|
|
249
|
+
if (!options.noLaunch) {
|
|
250
|
+
await launchInstalledPylonTuiImpl(
|
|
251
|
+
{
|
|
252
|
+
...options,
|
|
253
|
+
...install,
|
|
254
|
+
version: install.version,
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
...dependencies,
|
|
258
|
+
onStatus: reporter?.status,
|
|
259
|
+
},
|
|
260
|
+
);
|
|
261
|
+
} else {
|
|
262
|
+
reporter?.warning(
|
|
263
|
+
"Skipped Pylon terminal UI launch",
|
|
264
|
+
"pass no flag to open pylon-tui by default",
|
|
265
|
+
);
|
|
266
|
+
}
|
|
167
267
|
}
|
|
168
268
|
return summary;
|
|
169
269
|
}
|