agentlab 0.2.2 → 0.2.4
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 +2 -1
- package/dist/cache.js +2 -0
- package/dist/cli.js +22 -3
- package/dist/install-progress.js +82 -0
- package/package.json +1 -1
- package/release-manifest.json +5 -5
package/README.md
CHANGED
|
@@ -15,7 +15,8 @@ agentlab
|
|
|
15
15
|
|
|
16
16
|
Run `agentlab` from any directory. The app opens to the project picker and waits for you to choose a
|
|
17
17
|
folder. On first launch, the npm package downloads the matching AgentLab executable from GitHub and
|
|
18
|
-
caches it.
|
|
18
|
+
caches it. The installer shows the percentage, downloaded size, and download speed while it works.
|
|
19
|
+
Later launches use the cached executable.
|
|
19
20
|
|
|
20
21
|
## Requirements
|
|
21
22
|
|
package/dist/cache.js
CHANGED
|
@@ -32,6 +32,7 @@ export async function ensureCachedBinary(manifest, key, options = {}) {
|
|
|
32
32
|
const fetchImplementation = options.fetch ?? globalThis.fetch;
|
|
33
33
|
const downloadUrl = releaseDownloadUrl(manifest, key);
|
|
34
34
|
try {
|
|
35
|
+
options.onDownloadProgress?.({ downloadedBytes: 0, totalBytes: target.size });
|
|
35
36
|
const response = await fetchImplementation(downloadUrl, {
|
|
36
37
|
redirect: "follow",
|
|
37
38
|
signal: AbortSignal.timeout(DOWNLOAD_TIMEOUT_MILLISECONDS)
|
|
@@ -62,6 +63,7 @@ export async function ensureCachedBinary(manifest, key, options = {}) {
|
|
|
62
63
|
}
|
|
63
64
|
hash.update(chunk);
|
|
64
65
|
await writeAll(file, chunk);
|
|
66
|
+
options.onDownloadProgress?.({ downloadedBytes: size, totalBytes: target.size });
|
|
65
67
|
}
|
|
66
68
|
await file.sync();
|
|
67
69
|
}
|
package/dist/cli.js
CHANGED
|
@@ -4,6 +4,7 @@ import { readFile } from "node:fs/promises";
|
|
|
4
4
|
import { dirname, resolve } from "node:path";
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { ensureCachedBinary, resolveCacheRoot } from "./cache.js";
|
|
7
|
+
import { InstallProgressReporter } from "./install-progress.js";
|
|
7
8
|
import { currentRuntimePlatform, parseReleaseManifest, resolveRuntimeTarget } from "./manifest.js";
|
|
8
9
|
const REGISTRY_LATEST_URL = "https://registry.npmjs.org/agentlab/latest";
|
|
9
10
|
const STABLE_VERSION_PATTERN = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/u;
|
|
@@ -32,10 +33,28 @@ export async function runLauncher(args, options = {}) {
|
|
|
32
33
|
}
|
|
33
34
|
const runtime = options.runtime ?? currentRuntimePlatform();
|
|
34
35
|
const target = resolveRuntimeTarget(runtime);
|
|
35
|
-
const
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
const stderr = options.stderr ?? ((message) => process.stderr.write(message));
|
|
37
|
+
const progress = new InstallProgressReporter({
|
|
38
|
+
isTTY: options.stderrIsTTY ?? (options.stderr === undefined && process.stderr.isTTY),
|
|
39
|
+
target,
|
|
40
|
+
version: packageVersion,
|
|
41
|
+
write: stderr
|
|
38
42
|
});
|
|
43
|
+
let binary;
|
|
44
|
+
try {
|
|
45
|
+
binary = await ensureCachedBinary(manifest, target, {
|
|
46
|
+
cacheRoot: options.cacheRoot ?? resolveCacheRoot(environment),
|
|
47
|
+
fetch: options.fetch,
|
|
48
|
+
onDownloadProgress: (downloadProgress) => {
|
|
49
|
+
progress.report(downloadProgress);
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
progress.clear();
|
|
55
|
+
throw error;
|
|
56
|
+
}
|
|
57
|
+
progress.complete();
|
|
39
58
|
return execute(binary, args, {
|
|
40
59
|
...environment,
|
|
41
60
|
AGENTLAB_INSTALL_METHOD: "npm",
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { performance } from "node:perf_hooks";
|
|
2
|
+
const BAR_WIDTH = 16;
|
|
3
|
+
const BYTES_PER_MEGABYTE = 1_000_000;
|
|
4
|
+
const MINIMUM_RENDER_INTERVAL_MILLISECONDS = 100;
|
|
5
|
+
const CLEAR_LINE = "\r\u001B[2K";
|
|
6
|
+
const targetLabels = {
|
|
7
|
+
"linux-x64": "Linux x64",
|
|
8
|
+
"mac-arm64": "macOS arm64"
|
|
9
|
+
};
|
|
10
|
+
export class InstallProgressReporter {
|
|
11
|
+
isTTY;
|
|
12
|
+
now;
|
|
13
|
+
targetLabel;
|
|
14
|
+
version;
|
|
15
|
+
write;
|
|
16
|
+
active = false;
|
|
17
|
+
finished = false;
|
|
18
|
+
lastRenderAt;
|
|
19
|
+
startedAt;
|
|
20
|
+
constructor(options) {
|
|
21
|
+
this.isTTY = options.isTTY;
|
|
22
|
+
this.now = options.now ?? (() => performance.now());
|
|
23
|
+
this.targetLabel = targetLabels[options.target];
|
|
24
|
+
this.version = options.version;
|
|
25
|
+
this.write = options.write;
|
|
26
|
+
}
|
|
27
|
+
report(progress) {
|
|
28
|
+
if (this.finished)
|
|
29
|
+
return;
|
|
30
|
+
const now = this.now();
|
|
31
|
+
if (!this.active) {
|
|
32
|
+
this.active = true;
|
|
33
|
+
this.startedAt = now;
|
|
34
|
+
if (!this.isTTY) {
|
|
35
|
+
this.write(`Downloading AgentLab ${this.version} for ${this.targetLabel} (${formatMegabytes(progress.totalBytes)} MB)...\n`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!this.isTTY)
|
|
40
|
+
return;
|
|
41
|
+
const complete = progress.downloadedBytes >= progress.totalBytes;
|
|
42
|
+
if (!complete &&
|
|
43
|
+
this.lastRenderAt !== undefined &&
|
|
44
|
+
now - this.lastRenderAt < MINIMUM_RENDER_INTERVAL_MILLISECONDS) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
this.lastRenderAt = now;
|
|
48
|
+
this.write(`${CLEAR_LINE}${renderProgress(progress, now - (this.startedAt ?? now), this.version)}`);
|
|
49
|
+
}
|
|
50
|
+
complete() {
|
|
51
|
+
if (!this.active || this.finished)
|
|
52
|
+
return;
|
|
53
|
+
this.finished = true;
|
|
54
|
+
if (this.isTTY)
|
|
55
|
+
this.write(CLEAR_LINE);
|
|
56
|
+
const marker = this.isTTY ? "✓ " : "";
|
|
57
|
+
this.write(`${marker}AgentLab ${this.version} installed for ${this.targetLabel}.\n`);
|
|
58
|
+
this.write("Starting AgentLab...\n");
|
|
59
|
+
}
|
|
60
|
+
clear() {
|
|
61
|
+
if (!this.active || this.finished)
|
|
62
|
+
return;
|
|
63
|
+
this.finished = true;
|
|
64
|
+
if (this.isTTY)
|
|
65
|
+
this.write(CLEAR_LINE);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function renderProgress(progress, elapsedMilliseconds, version) {
|
|
69
|
+
const ratio = clamp(progress.downloadedBytes / progress.totalBytes, 0, 1);
|
|
70
|
+
const filled = ratio === 1 ? BAR_WIDTH : Math.floor(ratio * BAR_WIDTH);
|
|
71
|
+
const bar = `${"█".repeat(filled)}${"░".repeat(BAR_WIDTH - filled)}`;
|
|
72
|
+
const percent = Math.floor(ratio * 100);
|
|
73
|
+
const elapsedSeconds = Math.max(elapsedMilliseconds / 1_000, 0.001);
|
|
74
|
+
const megabytesPerSecond = progress.downloadedBytes / BYTES_PER_MEGABYTE / elapsedSeconds;
|
|
75
|
+
return `Downloading AgentLab ${version} [${bar}] ${String(percent).padStart(3)}% ${formatMegabytes(progress.downloadedBytes)}/${formatMegabytes(progress.totalBytes)} MB ${megabytesPerSecond.toFixed(1)} MB/s`;
|
|
76
|
+
}
|
|
77
|
+
function formatMegabytes(bytes) {
|
|
78
|
+
return (bytes / BYTES_PER_MEGABYTE).toFixed(1);
|
|
79
|
+
}
|
|
80
|
+
function clamp(value, minimum, maximum) {
|
|
81
|
+
return Math.min(Math.max(value, minimum), maximum);
|
|
82
|
+
}
|
package/package.json
CHANGED
package/release-manifest.json
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
"repository": "RiadMefti/agentlab",
|
|
3
3
|
"targets": {
|
|
4
4
|
"linux-x64": {
|
|
5
|
-
"asset": "agentlab-v0.2.
|
|
6
|
-
"sha256": "
|
|
5
|
+
"asset": "agentlab-v0.2.4-linux-x64",
|
|
6
|
+
"sha256": "bd3a71fb616f3dee3d4209264e4b7318bad0dda89559a51c4f0631d1563a082e",
|
|
7
7
|
"size": 116298952
|
|
8
8
|
},
|
|
9
9
|
"mac-arm64": {
|
|
10
|
-
"asset": "agentlab-v0.2.
|
|
11
|
-
"sha256": "
|
|
10
|
+
"asset": "agentlab-v0.2.4-mac-arm64",
|
|
11
|
+
"sha256": "2ed9413662f1441ebe69c6fb4101e4e179446605186f650e180624e9e369089f",
|
|
12
12
|
"size": 77351282
|
|
13
13
|
}
|
|
14
14
|
},
|
|
15
|
-
"version": "0.2.
|
|
15
|
+
"version": "0.2.4"
|
|
16
16
|
}
|