nyte-ai 0.0.9-beta → 0.0.10
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/docs/usage.md +1 -1
- package/package.json +1 -1
- package/src/launcher.js +26 -7
package/docs/usage.md
CHANGED
|
@@ -29,7 +29,7 @@ These requests use your configured provider and may incur charges. Run `nyte log
|
|
|
29
29
|
interactively before using scripts. A script must also run in a trusted workspace.
|
|
30
30
|
|
|
31
31
|
Use `nyte --resume` in a terminal to continue the latest conversation.
|
|
32
|
-
Installed copies can update with `nyte update`.
|
|
32
|
+
Installed copies can update with `nyte update`. Run `nyte update --models` to refresh the model catalog without updating Nyte. The update command installs the new
|
|
33
33
|
release's docs beside the executable when the release archive carries them.
|
|
34
34
|
|
|
35
35
|
## Delegated tasks
|
package/package.json
CHANGED
package/src/launcher.js
CHANGED
|
@@ -5,12 +5,15 @@ import { homedir } from "node:os";
|
|
|
5
5
|
import { dirname, join } from "node:path";
|
|
6
6
|
import process from "node:process";
|
|
7
7
|
|
|
8
|
+
import packageJson from "../package.json" with { type: "json" };
|
|
9
|
+
|
|
8
10
|
export const REPOSITORY = "interfaces-lab/nyte";
|
|
9
11
|
|
|
10
12
|
export function platformTarget(platform = process.platform, arch = process.arch) {
|
|
11
13
|
if ((platform !== "darwin" && platform !== "linux") || (arch !== "arm64" && arch !== "x64")) {
|
|
12
14
|
return undefined;
|
|
13
15
|
}
|
|
16
|
+
|
|
14
17
|
return `${platform}-${arch}`;
|
|
15
18
|
}
|
|
16
19
|
|
|
@@ -18,12 +21,6 @@ export function releaseAssetName(version, target) {
|
|
|
18
21
|
return `nyte-v${version.replace(/^v/u, "")}-${target}`;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
async function packageVersion() {
|
|
22
|
-
const metadata = JSON.parse(await readFile(new URL("../package.json", import.meta.url), "utf8"));
|
|
23
|
-
if (typeof metadata.version !== "string") throw new Error("nyte-ai has no package version.");
|
|
24
|
-
return metadata.version;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
24
|
export function cacheRoot(env = process.env) {
|
|
28
25
|
return env["NYTE_BIN_DIR"] ?? join(homedir(), ".nyte", "bin");
|
|
29
26
|
}
|
|
@@ -31,12 +28,15 @@ export function cacheRoot(env = process.env) {
|
|
|
31
28
|
async function sha256(path) {
|
|
32
29
|
const hash = createHash("sha256");
|
|
33
30
|
hash.update(await readFile(path));
|
|
31
|
+
|
|
34
32
|
return hash.digest("hex");
|
|
35
33
|
}
|
|
36
34
|
|
|
37
35
|
async function fetchOk(fetchFn, url) {
|
|
38
36
|
const response = await fetchFn(url, { signal: AbortSignal.timeout(10 * 60_000) });
|
|
37
|
+
|
|
39
38
|
if (!response.ok) throw new Error(`Failed to download ${url} (HTTP ${response.status}).`);
|
|
39
|
+
|
|
40
40
|
return response;
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -46,13 +46,16 @@ async function download(fetchFn, url, path) {
|
|
|
46
46
|
}
|
|
47
47
|
|
|
48
48
|
export async function ensureBinary(options = {}) {
|
|
49
|
-
const version = options.version ??
|
|
49
|
+
const version = options.version ?? packageJson.version;
|
|
50
50
|
const target = platformTarget(options.platform, options.arch);
|
|
51
|
+
|
|
51
52
|
if (target === undefined) {
|
|
52
53
|
throw new Error(`Nyte has no native release for ${process.platform}/${process.arch}.`);
|
|
53
54
|
}
|
|
55
|
+
|
|
54
56
|
const root = options.root ?? cacheRoot(options.env);
|
|
55
57
|
const binary = join(root, version, "nyte");
|
|
58
|
+
|
|
56
59
|
if ((await stat(binary).catch(() => undefined))?.isFile()) return binary;
|
|
57
60
|
|
|
58
61
|
const fetchFn = options.fetchFn ?? globalThis.fetch;
|
|
@@ -61,20 +64,26 @@ export async function ensureBinary(options = {}) {
|
|
|
61
64
|
const versionDir = dirname(binary);
|
|
62
65
|
const archive = join(versionDir, `${asset}.tar.gz`);
|
|
63
66
|
await mkdir(versionDir, { recursive: true });
|
|
67
|
+
|
|
64
68
|
try {
|
|
65
69
|
const checksum = (await (await fetchOk(fetchFn, `${base}/${asset}.tar.gz.sha256`)).text())
|
|
66
70
|
.trim()
|
|
67
71
|
.split(/\s+/u)[0]
|
|
68
72
|
?.toLowerCase();
|
|
73
|
+
|
|
69
74
|
if (checksum === undefined || !/^[0-9a-f]{64}$/u.test(checksum)) {
|
|
70
75
|
throw new Error(`The checksum file for ${asset} is malformed.`);
|
|
71
76
|
}
|
|
77
|
+
|
|
72
78
|
await download(fetchFn, `${base}/${asset}.tar.gz`, archive);
|
|
73
79
|
const actual = await sha256(archive);
|
|
80
|
+
|
|
74
81
|
if (actual !== checksum) {
|
|
75
82
|
throw new Error(`Checksum mismatch for ${asset}: expected ${checksum}, got ${actual}.`);
|
|
76
83
|
}
|
|
84
|
+
|
|
77
85
|
const result = spawn("tar", ["-xzf", archive, "-C", versionDir], { stdio: "inherit" });
|
|
86
|
+
|
|
78
87
|
const exitCode = await new Promise((resolve, reject) => {
|
|
79
88
|
result.once("error", reject);
|
|
80
89
|
result.once("exit", (code, signal) => {
|
|
@@ -82,10 +91,13 @@ export async function ensureBinary(options = {}) {
|
|
|
82
91
|
else resolve(code);
|
|
83
92
|
});
|
|
84
93
|
});
|
|
94
|
+
|
|
85
95
|
if (exitCode !== 0 || !(await stat(binary).catch(() => undefined))?.isFile()) {
|
|
86
96
|
throw new Error(`${asset}.tar.gz does not contain a nyte binary.`);
|
|
87
97
|
}
|
|
98
|
+
|
|
88
99
|
await chmod(binary, 0o755);
|
|
100
|
+
|
|
89
101
|
return binary;
|
|
90
102
|
} catch (error) {
|
|
91
103
|
await rm(binary, { force: true });
|
|
@@ -98,23 +110,30 @@ export async function ensureBinary(options = {}) {
|
|
|
98
110
|
export async function launch(args = process.argv.slice(2), options = {}) {
|
|
99
111
|
const binary = await ensureBinary(options);
|
|
100
112
|
const child = spawn(binary, args, { stdio: "inherit" });
|
|
113
|
+
|
|
101
114
|
const forwardInt = () => {
|
|
102
115
|
if (!child.killed) child.kill("SIGINT");
|
|
103
116
|
};
|
|
117
|
+
|
|
104
118
|
const forwardTerm = () => {
|
|
105
119
|
if (!child.killed) child.kill("SIGTERM");
|
|
106
120
|
};
|
|
121
|
+
|
|
107
122
|
process.once("SIGINT", forwardInt);
|
|
108
123
|
process.once("SIGTERM", forwardTerm);
|
|
124
|
+
|
|
109
125
|
return new Promise((resolve, reject) => {
|
|
110
126
|
child.once("error", reject);
|
|
111
127
|
child.once("exit", (code, signal) => {
|
|
112
128
|
process.removeListener("SIGINT", forwardInt);
|
|
113
129
|
process.removeListener("SIGTERM", forwardTerm);
|
|
130
|
+
|
|
114
131
|
if (signal !== null) {
|
|
115
132
|
process.kill(process.pid, signal);
|
|
133
|
+
|
|
116
134
|
return;
|
|
117
135
|
}
|
|
136
|
+
|
|
118
137
|
resolve(code ?? 1);
|
|
119
138
|
});
|
|
120
139
|
});
|