@rebon/cli-win32-x64 1.2.0 → 1.4.0
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/LICENSE +202 -0
- package/NOTICE +10 -0
- package/README.md +203 -144
- package/THIRD_PARTY_NOTICES.txt +1232 -128
- package/bin/rebon.js +22 -22
- package/lib/windows-managed.js +390 -390
- package/package.json +9 -2
- package/payload/compose-runtime/package.json +17 -17
- package/payload/compose-runtime/payload/compose/shims/dsh-anonymous-user-id.js +10 -10
- package/payload/compose-runtime/payload/compose/shims/dsh-credentials.js +13 -13
- package/payload/compose-runtime/payload/compose/shims/dsh-launch-environment.js +21 -21
- package/payload/compose-runtime/payload/compose/shims/dsh-llm.js +313 -313
- package/payload/compose-runtime/payload/compose/shims/dsh-settings.js +43 -43
- package/payload/compose-runtime/payload/compose/shims/dsh-tools.js +20 -20
- package/payload/compose-runtime/payload/compose/shims/dsh-web.js +10 -10
- package/payload/compose-runtime/payload/compose/shims/llm-adapter.js +32 -32
- package/payload/compose-runtime/payload/compose/shims/zod-lite.js +49 -49
- package/payload/compose-runtime/payload/vendor/cordis/LICENSE +21 -0
- package/payload/compose-runtime/payload/vendor/cordis/index.js +1530 -1530
- package/payload/compose-runtime/payload/vendor/cosmokit/LICENSE +21 -21
- package/payload/compose-runtime/payload/vendor/cosmokit/index.mjs +357 -357
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-agent +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-agent-loop +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-llm-core +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-llm-deepseek +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-logger-console +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-scope +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-session +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-system-prompt +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-timeout +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-timer +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-tool-todo +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-tool-web +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-tools-schema +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-turndown +21 -0
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-turndown-plugin-gfm +21 -0
- package/payload/compose-runtime/payload/vendor/dsh/LICENSE-web-search-exa +21 -21
- package/payload/compose-runtime/payload/vendor/dsh/agent-loop.js +1193 -1193
- package/payload/compose-runtime/payload/vendor/dsh/agent.js +714 -714
- package/payload/compose-runtime/payload/vendor/dsh/llm-core.js +269 -269
- package/payload/compose-runtime/payload/vendor/dsh/llm-deepseek.js +672 -672
- package/payload/compose-runtime/payload/vendor/dsh/logger-console.js +83 -83
- package/payload/compose-runtime/payload/vendor/dsh/scope.js +287 -287
- package/payload/compose-runtime/payload/vendor/dsh/session.js +1668 -1668
- package/payload/compose-runtime/payload/vendor/dsh/system-prompt.js +309 -309
- package/payload/compose-runtime/payload/vendor/dsh/timeout.js +100 -100
- package/payload/compose-runtime/payload/vendor/dsh/timer.js +128 -128
- package/payload/compose-runtime/payload/vendor/dsh/tool-todo.js +143 -143
- package/payload/compose-runtime/payload/vendor/dsh/tool-web.js +1527 -1527
- package/payload/compose-runtime/payload/vendor/dsh/tools-schema.js +849 -849
- package/payload/compose-runtime/payload/vendor/dsh/web-search-exa.js +122 -122
- package/payload/compose-runtime/payload/vendor/eventsource-parser/LICENSE +21 -21
- package/payload/compose-runtime/payload/vendor/eventsource-parser/index.js +177 -177
- package/payload/compose-runtime/payload/vendor/eventsource-parser/stream.js +48 -48
- package/payload/compose-runtime/payload/vendor/schemastery/LICENSE +21 -0
- package/payload/compose-runtime/payload/vendor/schemastery/index.mjs +656 -656
- package/payload/compose-runtime/payload-manifests.json +48 -48
- package/payload/compose-runtime/src/bridge.mjs +193 -195
- package/payload/compose-runtime/src/credentials-runtime.mjs +50 -50
- package/payload/compose-runtime/src/eventsource-stream.mjs +48 -48
- package/payload/compose-runtime/src/index.mjs +7 -7
- package/payload/compose-runtime/src/llm-runtime.mjs +326 -326
- package/payload/compose-runtime/src/loader.mjs +78 -78
- package/payload/compose-runtime/src/loop-assembly.mjs +237 -237
- package/payload/compose-runtime/src/payload.mjs +49 -49
- package/payload/compose-runtime/src/plugin.mjs +59 -59
- package/payload/compose-runtime/src/realm.mjs +223 -223
- package/payload/compose-runtime/src/registry.mjs +191 -191
- package/payload/compose-runtime/src/resolve.mjs +115 -115
- package/payload/compose-runtime/src/systemprompt-runtime.mjs +67 -67
- package/payload/compose-runtime/src/tools-runtime.mjs +239 -239
- package/payload/compose-runtime/src/web-runtime.mjs +209 -209
- package/payload/plugin-host/package.json +11 -11
- package/payload/plugin-host/src/bridge.mjs +64 -64
- package/payload/plugin-host/src/cli.mjs +147 -147
- package/payload/plugin-host/src/framing.mjs +113 -113
- package/payload/plugin-host/src/host.mjs +691 -691
- package/payload/plugin-host/src/json.mjs +208 -208
- package/payload/plugin-host/src/lifecycle.mjs +114 -114
- package/payload/plugin-host/src/loader.mjs +183 -183
- package/payload/plugin-host/src/methods.mjs +377 -377
- package/payload/plugin-host/src/ownership.mjs +57 -57
- package/payload/plugin-host/src/protocol.mjs +129 -129
- package/payload/plugin-host/src/sdk.mjs +7 -7
- package/payload/rebon-boa-helper.exe +0 -0
- package/payload/rebon-browser-mcp.exe +0 -0
- package/payload/rebon-computer-use.exe +0 -0
- package/payload/rebon-lsp-mcp.exe +0 -0
- package/payload/rebon.exe +2 -2
- package/payload/sandbox-win.exe +0 -0
- package/scripts/postinstall.js +112 -112
- package/payload/compose-runtime/payload/compose/credentials-runtime.js +0 -38
- package/payload/compose-runtime/payload/compose/llm-runtime.js +0 -330
- package/payload/compose-runtime/payload/compose/loop-assembly.js +0 -149
- package/payload/compose-runtime/payload/compose/serve-dispatch.js +0 -82
- package/payload/compose-runtime/payload/compose/systemprompt-runtime.js +0 -74
- package/payload/compose-runtime/payload/compose/tools-runtime.js +0 -228
- package/payload/compose-runtime/payload/compose/web-runtime.js +0 -204
package/lib/windows-managed.js
CHANGED
|
@@ -1,390 +1,390 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
const fs = require("fs");
|
|
4
|
-
const path = require("path");
|
|
5
|
-
|
|
6
|
-
const CURRENT_MANIFEST = "current.json";
|
|
7
|
-
const EXECUTABLE_NAME = "rebon.exe";
|
|
8
|
-
const PAYLOAD_DIR = "payload";
|
|
9
|
-
const VERSIONS_DIR = "versions";
|
|
10
|
-
const STAGING_DIR = "staging";
|
|
11
|
-
|
|
12
|
-
function defaultPackageRoot() {
|
|
13
|
-
return path.resolve(__dirname, "..");
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function managedBinDir() {
|
|
17
|
-
const base = process.env.LOCALAPPDATA || (process.env.USERPROFILE && path.join(process.env.USERPROFILE, ".rebon"));
|
|
18
|
-
if (!base) {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
return path.join(base, "rebon", "bin");
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
function requireManagedBinDir() {
|
|
25
|
-
const binDir = managedBinDir();
|
|
26
|
-
if (!binDir) {
|
|
27
|
-
throw new Error("LOCALAPPDATA and USERPROFILE are both unset; cannot choose a per-user install directory");
|
|
28
|
-
}
|
|
29
|
-
return binDir;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function sanitizeVersionPart(value) {
|
|
33
|
-
return String(value || "unknown").replace(/[^0-9A-Za-z._-]/g, "_");
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
function firstString(candidates) {
|
|
37
|
-
for (const candidate of candidates) {
|
|
38
|
-
if (typeof candidate === "string" && candidate.length > 0) {
|
|
39
|
-
return candidate;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
return null;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function packageBuildId(packageJson) {
|
|
46
|
-
const rebon = packageJson && packageJson.rebon;
|
|
47
|
-
return firstString([
|
|
48
|
-
rebon && rebon.build,
|
|
49
|
-
rebon && rebon.buildId,
|
|
50
|
-
rebon && rebon.commit,
|
|
51
|
-
rebon && rebon.hash,
|
|
52
|
-
packageJson && packageJson.rebonBuild,
|
|
53
|
-
packageJson && packageJson.rebonBuildId,
|
|
54
|
-
]);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function versionKeyFromPackageJson(packageJson) {
|
|
58
|
-
const version = sanitizeVersionPart(packageJson && packageJson.version);
|
|
59
|
-
const buildId = packageBuildId(packageJson);
|
|
60
|
-
return buildId ? `${version}-${sanitizeVersionPart(buildId)}` : version;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function payloadSignature(payloadPath) {
|
|
64
|
-
const stat = fs.statSync(payloadPath);
|
|
65
|
-
return { size: stat.size, mtimeMs: Math.trunc(stat.mtimeMs) };
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function readPackageInfo(packageRoot) {
|
|
69
|
-
const root = path.resolve(packageRoot || defaultPackageRoot());
|
|
70
|
-
const packageJson = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
|
|
71
|
-
const payloadDir = path.join(root, PAYLOAD_DIR);
|
|
72
|
-
const payloadPath = path.join(payloadDir, EXECUTABLE_NAME);
|
|
73
|
-
return {
|
|
74
|
-
packageRoot: root,
|
|
75
|
-
name: String(packageJson.name || "rebon"),
|
|
76
|
-
version: String(packageJson.version || "unknown"),
|
|
77
|
-
versionKey: versionKeyFromPackageJson(packageJson),
|
|
78
|
-
payloadDir,
|
|
79
|
-
payloadPath,
|
|
80
|
-
payload: fs.existsSync(payloadPath) ? payloadSignature(payloadPath) : null,
|
|
81
|
-
};
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
function managedRelativeExecutable(versionKey) {
|
|
85
|
-
return `${VERSIONS_DIR}/${versionKey}/${EXECUTABLE_NAME}`;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
function payloadSpecificVersionKey(packageInfo) {
|
|
89
|
-
if (!packageInfo.payload) {
|
|
90
|
-
return packageInfo.versionKey;
|
|
91
|
-
}
|
|
92
|
-
return `${packageInfo.versionKey}-${packageInfo.payload.size}-${packageInfo.payload.mtimeMs}`;
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
function acceptedVersionKeys(packageInfo) {
|
|
96
|
-
const keys = [packageInfo.versionKey];
|
|
97
|
-
const payloadKey = payloadSpecificVersionKey(packageInfo);
|
|
98
|
-
if (payloadKey !== packageInfo.versionKey) {
|
|
99
|
-
keys.push(payloadKey);
|
|
100
|
-
}
|
|
101
|
-
return keys;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
function layoutForVersion(binDir, versionKey) {
|
|
105
|
-
const versionDir = path.join(binDir, VERSIONS_DIR, versionKey);
|
|
106
|
-
const stagingDir = path.join(binDir, STAGING_DIR, versionKey);
|
|
107
|
-
return {
|
|
108
|
-
versionDir,
|
|
109
|
-
stagingDir,
|
|
110
|
-
exePath: path.join(versionDir, EXECUTABLE_NAME),
|
|
111
|
-
manifestPath: path.join(binDir, CURRENT_MANIFEST),
|
|
112
|
-
manifestRelativePath: managedRelativeExecutable(versionKey),
|
|
113
|
-
};
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
function normalizeManifestPath(value) {
|
|
117
|
-
return String(value || "").replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
function resolveManifestPath(binDir, manifestPath) {
|
|
121
|
-
if (typeof manifestPath !== "string" || path.isAbsolute(manifestPath)) {
|
|
122
|
-
return null;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const resolved = path.resolve(binDir, manifestPath.replace(/[\\/]+/g, path.sep));
|
|
126
|
-
const relative = path.relative(path.resolve(binDir), resolved);
|
|
127
|
-
if (!relative || relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
128
|
-
return null;
|
|
129
|
-
}
|
|
130
|
-
return resolved;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function readCurrentManifest(binDir) {
|
|
134
|
-
try {
|
|
135
|
-
return JSON.parse(fs.readFileSync(path.join(binDir, CURRENT_MANIFEST), "utf8"));
|
|
136
|
-
} catch (_) {
|
|
137
|
-
return null;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
function payloadMatchesManifest(manifest, packageInfo) {
|
|
142
|
-
if (!packageInfo.payload) {
|
|
143
|
-
return true;
|
|
144
|
-
}
|
|
145
|
-
if (!manifest.payload) {
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
return (
|
|
149
|
-
Number(manifest.payload.size) === packageInfo.payload.size &&
|
|
150
|
-
Math.trunc(Number(manifest.payload.mtimeMs)) === packageInfo.payload.mtimeMs
|
|
151
|
-
);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function manifestMatchesPackage(manifest, binDir, packageInfo) {
|
|
155
|
-
if (!manifest) {
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
if (manifest.package !== packageInfo.name || manifest.version !== packageInfo.version) {
|
|
159
|
-
return false;
|
|
160
|
-
}
|
|
161
|
-
if (!acceptedVersionKeys(packageInfo).includes(manifest.versionKey)) {
|
|
162
|
-
return false;
|
|
163
|
-
}
|
|
164
|
-
if (normalizeManifestPath(manifest.path) !== managedRelativeExecutable(manifest.versionKey)) {
|
|
165
|
-
return false;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
const resolved = resolveManifestPath(binDir, manifest.path);
|
|
169
|
-
return Boolean(resolved && fs.existsSync(resolved) && payloadMatchesManifest(manifest, packageInfo));
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function readInstalledManifest(packageInfo) {
|
|
173
|
-
const binDir = managedBinDir();
|
|
174
|
-
if (!binDir) {
|
|
175
|
-
return null;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const manifest = readCurrentManifest(binDir);
|
|
179
|
-
if (!manifestMatchesPackage(manifest, binDir, packageInfo)) {
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
return manifest;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
function readInstalledExecutable(packageInfo) {
|
|
186
|
-
const binDir = managedBinDir();
|
|
187
|
-
const manifest = readInstalledManifest(packageInfo);
|
|
188
|
-
if (!binDir || !manifest) {
|
|
189
|
-
return null;
|
|
190
|
-
}
|
|
191
|
-
return resolveManifestPath(binDir, manifest.path);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
function writeManifest(manifestPath, manifest) {
|
|
195
|
-
const nonce = Math.random().toString(36).slice(2, 10);
|
|
196
|
-
const tmpPath = `${manifestPath}.${process.pid}.${nonce}.tmp`;
|
|
197
|
-
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
198
|
-
fs.writeFileSync(tmpPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
|
|
199
|
-
fs.renameSync(tmpPath, manifestPath);
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
function copyPayloadDirectory(srcDir, destDir) {
|
|
203
|
-
fs.mkdirSync(destDir, { recursive: true });
|
|
204
|
-
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
205
|
-
for (const entry of entries) {
|
|
206
|
-
const src = path.join(srcDir, entry.name);
|
|
207
|
-
const dest = path.join(destDir, entry.name);
|
|
208
|
-
if (entry.isDirectory()) {
|
|
209
|
-
copyPayloadDirectory(src, dest);
|
|
210
|
-
} else if (entry.isFile()) {
|
|
211
|
-
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
212
|
-
fs.copyFileSync(src, dest);
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
function resetDirectory(dir) {
|
|
218
|
-
try {
|
|
219
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
220
|
-
} catch (_) {
|
|
221
|
-
}
|
|
222
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
function removeDirectoryIfExists(dir) {
|
|
226
|
-
try {
|
|
227
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
228
|
-
} catch (_) {
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
function cleanupDirectoryEntries(rootDir, keepName) {
|
|
233
|
-
let entries;
|
|
234
|
-
try {
|
|
235
|
-
entries = fs.readdirSync(rootDir, { withFileTypes: true });
|
|
236
|
-
} catch (_) {
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
for (const entry of entries) {
|
|
241
|
-
if (!entry.isDirectory() || entry.name === keepName) {
|
|
242
|
-
continue;
|
|
243
|
-
}
|
|
244
|
-
removeDirectoryIfExists(path.join(rootDir, entry.name));
|
|
245
|
-
}
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
function cleanupLegacyRootFiles(binDir) {
|
|
249
|
-
let entries;
|
|
250
|
-
try {
|
|
251
|
-
entries = fs.readdirSync(binDir, { withFileTypes: true });
|
|
252
|
-
} catch (_) {
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
for (const entry of entries) {
|
|
257
|
-
if (!entry.isFile()) {
|
|
258
|
-
continue;
|
|
259
|
-
}
|
|
260
|
-
if (!/^rebon-.+\.exe$/i.test(entry.name)) {
|
|
261
|
-
continue;
|
|
262
|
-
}
|
|
263
|
-
try {
|
|
264
|
-
fs.unlinkSync(path.join(binDir, entry.name));
|
|
265
|
-
} catch (_) {
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
function cleanupOldVersions(binDir, keepVersionKey) {
|
|
271
|
-
cleanupDirectoryEntries(path.join(binDir, VERSIONS_DIR), keepVersionKey);
|
|
272
|
-
cleanupDirectoryEntries(path.join(binDir, STAGING_DIR), keepVersionKey);
|
|
273
|
-
cleanupLegacyRootFiles(binDir);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
function promoteStagingDirectory(stagingDir, versionDir) {
|
|
277
|
-
fs.mkdirSync(path.dirname(versionDir), { recursive: true });
|
|
278
|
-
if (fs.existsSync(versionDir)) {
|
|
279
|
-
fs.rmSync(versionDir, { recursive: true, force: true });
|
|
280
|
-
}
|
|
281
|
-
fs.renameSync(stagingDir, versionDir);
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
function installToVersionKey(packageInfo, binDir, versionKey) {
|
|
285
|
-
const layout = layoutForVersion(binDir, versionKey);
|
|
286
|
-
resetDirectory(layout.stagingDir);
|
|
287
|
-
copyPayloadDirectory(packageInfo.payloadDir, layout.stagingDir);
|
|
288
|
-
promoteStagingDirectory(layout.stagingDir, layout.versionDir);
|
|
289
|
-
|
|
290
|
-
writeManifest(layout.manifestPath, {
|
|
291
|
-
version: packageInfo.version,
|
|
292
|
-
versionKey,
|
|
293
|
-
path: layout.manifestRelativePath,
|
|
294
|
-
package: packageInfo.name,
|
|
295
|
-
payload: packageInfo.payload || payloadSignature(packageInfo.payloadPath),
|
|
296
|
-
installedAt: new Date().toISOString(),
|
|
297
|
-
});
|
|
298
|
-
cleanupOldVersions(binDir, versionKey);
|
|
299
|
-
return layout.exePath;
|
|
300
|
-
}
|
|
301
|
-
|
|
302
|
-
function installManagedPackage(packageInfo) {
|
|
303
|
-
const binDir = managedBinDir();
|
|
304
|
-
if (!binDir || !fs.existsSync(packageInfo.payloadPath)) {
|
|
305
|
-
return null;
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
const installedManifest = readInstalledManifest(packageInfo);
|
|
309
|
-
if (installedManifest) {
|
|
310
|
-
cleanupOldVersions(binDir, installedManifest.versionKey);
|
|
311
|
-
return resolveManifestPath(binDir, installedManifest.path);
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
try {
|
|
315
|
-
return installToVersionKey(packageInfo, binDir, packageInfo.versionKey);
|
|
316
|
-
} catch (error) {
|
|
317
|
-
const fallbackVersionKey = payloadSpecificVersionKey(packageInfo);
|
|
318
|
-
if (fallbackVersionKey === packageInfo.versionKey) {
|
|
319
|
-
throw error;
|
|
320
|
-
}
|
|
321
|
-
return installToVersionKey(packageInfo, binDir, fallbackVersionKey);
|
|
322
|
-
}
|
|
323
|
-
}
|
|
324
|
-
|
|
325
|
-
function resolveExecutable(packageInfo) {
|
|
326
|
-
const info = packageInfo || readPackageInfo();
|
|
327
|
-
const installed = readInstalledExecutable(info);
|
|
328
|
-
if (installed) {
|
|
329
|
-
return { exe: installed, usedFallback: false, installError: null };
|
|
330
|
-
}
|
|
331
|
-
|
|
332
|
-
let installError = null;
|
|
333
|
-
try {
|
|
334
|
-
const managed = installManagedPackage(info);
|
|
335
|
-
if (managed) {
|
|
336
|
-
return { exe: managed, usedFallback: false, installError: null };
|
|
337
|
-
}
|
|
338
|
-
} catch (error) {
|
|
339
|
-
installError = error;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
if (fs.existsSync(info.payloadPath)) {
|
|
343
|
-
return { exe: info.payloadPath, usedFallback: true, installError };
|
|
344
|
-
}
|
|
345
|
-
|
|
346
|
-
return { exe: null, usedFallback: false, installError };
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
function spawnResolvedExecutable(resolved, argv, spawnImpl) {
|
|
350
|
-
const child = spawnImpl(resolved.exe, argv, {
|
|
351
|
-
stdio: "inherit",
|
|
352
|
-
windowsHide: false,
|
|
353
|
-
env: { ...process.env, REBON_CODE_MODE_NODE: process.execPath },
|
|
354
|
-
});
|
|
355
|
-
|
|
356
|
-
child.on("error", (error) => {
|
|
357
|
-
console.error(`rebon: failed to start ${resolved.exe}: ${error.message}`);
|
|
358
|
-
process.exit(1);
|
|
359
|
-
});
|
|
360
|
-
|
|
361
|
-
child.on("exit", (code, signal) => {
|
|
362
|
-
if (signal) {
|
|
363
|
-
try {
|
|
364
|
-
process.kill(process.pid, signal);
|
|
365
|
-
} catch (_) {
|
|
366
|
-
process.exit(1);
|
|
367
|
-
}
|
|
368
|
-
return;
|
|
369
|
-
}
|
|
370
|
-
process.exit(code === null ? 1 : code);
|
|
371
|
-
});
|
|
372
|
-
|
|
373
|
-
return child;
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
module.exports = {
|
|
377
|
-
cleanupOldVersions,
|
|
378
|
-
installManagedPackage,
|
|
379
|
-
layoutForVersion,
|
|
380
|
-
managedBinDir,
|
|
381
|
-
managedRelativeExecutable,
|
|
382
|
-
payloadSignature,
|
|
383
|
-
readCurrentManifest,
|
|
384
|
-
readInstalledExecutable,
|
|
385
|
-
readPackageInfo,
|
|
386
|
-
requireManagedBinDir,
|
|
387
|
-
resolveExecutable,
|
|
388
|
-
spawnResolvedExecutable,
|
|
389
|
-
versionKeyFromPackageJson,
|
|
390
|
-
};
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const fs = require("fs");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
|
|
6
|
+
const CURRENT_MANIFEST = "current.json";
|
|
7
|
+
const EXECUTABLE_NAME = "rebon.exe";
|
|
8
|
+
const PAYLOAD_DIR = "payload";
|
|
9
|
+
const VERSIONS_DIR = "versions";
|
|
10
|
+
const STAGING_DIR = "staging";
|
|
11
|
+
|
|
12
|
+
function defaultPackageRoot() {
|
|
13
|
+
return path.resolve(__dirname, "..");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function managedBinDir() {
|
|
17
|
+
const base = process.env.LOCALAPPDATA || (process.env.USERPROFILE && path.join(process.env.USERPROFILE, ".rebon"));
|
|
18
|
+
if (!base) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
return path.join(base, "rebon", "bin");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function requireManagedBinDir() {
|
|
25
|
+
const binDir = managedBinDir();
|
|
26
|
+
if (!binDir) {
|
|
27
|
+
throw new Error("LOCALAPPDATA and USERPROFILE are both unset; cannot choose a per-user install directory");
|
|
28
|
+
}
|
|
29
|
+
return binDir;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function sanitizeVersionPart(value) {
|
|
33
|
+
return String(value || "unknown").replace(/[^0-9A-Za-z._-]/g, "_");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function firstString(candidates) {
|
|
37
|
+
for (const candidate of candidates) {
|
|
38
|
+
if (typeof candidate === "string" && candidate.length > 0) {
|
|
39
|
+
return candidate;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function packageBuildId(packageJson) {
|
|
46
|
+
const rebon = packageJson && packageJson.rebon;
|
|
47
|
+
return firstString([
|
|
48
|
+
rebon && rebon.build,
|
|
49
|
+
rebon && rebon.buildId,
|
|
50
|
+
rebon && rebon.commit,
|
|
51
|
+
rebon && rebon.hash,
|
|
52
|
+
packageJson && packageJson.rebonBuild,
|
|
53
|
+
packageJson && packageJson.rebonBuildId,
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function versionKeyFromPackageJson(packageJson) {
|
|
58
|
+
const version = sanitizeVersionPart(packageJson && packageJson.version);
|
|
59
|
+
const buildId = packageBuildId(packageJson);
|
|
60
|
+
return buildId ? `${version}-${sanitizeVersionPart(buildId)}` : version;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function payloadSignature(payloadPath) {
|
|
64
|
+
const stat = fs.statSync(payloadPath);
|
|
65
|
+
return { size: stat.size, mtimeMs: Math.trunc(stat.mtimeMs) };
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function readPackageInfo(packageRoot) {
|
|
69
|
+
const root = path.resolve(packageRoot || defaultPackageRoot());
|
|
70
|
+
const packageJson = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf8"));
|
|
71
|
+
const payloadDir = path.join(root, PAYLOAD_DIR);
|
|
72
|
+
const payloadPath = path.join(payloadDir, EXECUTABLE_NAME);
|
|
73
|
+
return {
|
|
74
|
+
packageRoot: root,
|
|
75
|
+
name: String(packageJson.name || "rebon"),
|
|
76
|
+
version: String(packageJson.version || "unknown"),
|
|
77
|
+
versionKey: versionKeyFromPackageJson(packageJson),
|
|
78
|
+
payloadDir,
|
|
79
|
+
payloadPath,
|
|
80
|
+
payload: fs.existsSync(payloadPath) ? payloadSignature(payloadPath) : null,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function managedRelativeExecutable(versionKey) {
|
|
85
|
+
return `${VERSIONS_DIR}/${versionKey}/${EXECUTABLE_NAME}`;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function payloadSpecificVersionKey(packageInfo) {
|
|
89
|
+
if (!packageInfo.payload) {
|
|
90
|
+
return packageInfo.versionKey;
|
|
91
|
+
}
|
|
92
|
+
return `${packageInfo.versionKey}-${packageInfo.payload.size}-${packageInfo.payload.mtimeMs}`;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function acceptedVersionKeys(packageInfo) {
|
|
96
|
+
const keys = [packageInfo.versionKey];
|
|
97
|
+
const payloadKey = payloadSpecificVersionKey(packageInfo);
|
|
98
|
+
if (payloadKey !== packageInfo.versionKey) {
|
|
99
|
+
keys.push(payloadKey);
|
|
100
|
+
}
|
|
101
|
+
return keys;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function layoutForVersion(binDir, versionKey) {
|
|
105
|
+
const versionDir = path.join(binDir, VERSIONS_DIR, versionKey);
|
|
106
|
+
const stagingDir = path.join(binDir, STAGING_DIR, versionKey);
|
|
107
|
+
return {
|
|
108
|
+
versionDir,
|
|
109
|
+
stagingDir,
|
|
110
|
+
exePath: path.join(versionDir, EXECUTABLE_NAME),
|
|
111
|
+
manifestPath: path.join(binDir, CURRENT_MANIFEST),
|
|
112
|
+
manifestRelativePath: managedRelativeExecutable(versionKey),
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function normalizeManifestPath(value) {
|
|
117
|
+
return String(value || "").replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function resolveManifestPath(binDir, manifestPath) {
|
|
121
|
+
if (typeof manifestPath !== "string" || path.isAbsolute(manifestPath)) {
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const resolved = path.resolve(binDir, manifestPath.replace(/[\\/]+/g, path.sep));
|
|
126
|
+
const relative = path.relative(path.resolve(binDir), resolved);
|
|
127
|
+
if (!relative || relative === ".." || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return resolved;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function readCurrentManifest(binDir) {
|
|
134
|
+
try {
|
|
135
|
+
return JSON.parse(fs.readFileSync(path.join(binDir, CURRENT_MANIFEST), "utf8"));
|
|
136
|
+
} catch (_) {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function payloadMatchesManifest(manifest, packageInfo) {
|
|
142
|
+
if (!packageInfo.payload) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
if (!manifest.payload) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
return (
|
|
149
|
+
Number(manifest.payload.size) === packageInfo.payload.size &&
|
|
150
|
+
Math.trunc(Number(manifest.payload.mtimeMs)) === packageInfo.payload.mtimeMs
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function manifestMatchesPackage(manifest, binDir, packageInfo) {
|
|
155
|
+
if (!manifest) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
if (manifest.package !== packageInfo.name || manifest.version !== packageInfo.version) {
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
if (!acceptedVersionKeys(packageInfo).includes(manifest.versionKey)) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
if (normalizeManifestPath(manifest.path) !== managedRelativeExecutable(manifest.versionKey)) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
const resolved = resolveManifestPath(binDir, manifest.path);
|
|
169
|
+
return Boolean(resolved && fs.existsSync(resolved) && payloadMatchesManifest(manifest, packageInfo));
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function readInstalledManifest(packageInfo) {
|
|
173
|
+
const binDir = managedBinDir();
|
|
174
|
+
if (!binDir) {
|
|
175
|
+
return null;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const manifest = readCurrentManifest(binDir);
|
|
179
|
+
if (!manifestMatchesPackage(manifest, binDir, packageInfo)) {
|
|
180
|
+
return null;
|
|
181
|
+
}
|
|
182
|
+
return manifest;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function readInstalledExecutable(packageInfo) {
|
|
186
|
+
const binDir = managedBinDir();
|
|
187
|
+
const manifest = readInstalledManifest(packageInfo);
|
|
188
|
+
if (!binDir || !manifest) {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
return resolveManifestPath(binDir, manifest.path);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function writeManifest(manifestPath, manifest) {
|
|
195
|
+
const nonce = Math.random().toString(36).slice(2, 10);
|
|
196
|
+
const tmpPath = `${manifestPath}.${process.pid}.${nonce}.tmp`;
|
|
197
|
+
fs.mkdirSync(path.dirname(manifestPath), { recursive: true });
|
|
198
|
+
fs.writeFileSync(tmpPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
|
|
199
|
+
fs.renameSync(tmpPath, manifestPath);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
function copyPayloadDirectory(srcDir, destDir) {
|
|
203
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
204
|
+
const entries = fs.readdirSync(srcDir, { withFileTypes: true });
|
|
205
|
+
for (const entry of entries) {
|
|
206
|
+
const src = path.join(srcDir, entry.name);
|
|
207
|
+
const dest = path.join(destDir, entry.name);
|
|
208
|
+
if (entry.isDirectory()) {
|
|
209
|
+
copyPayloadDirectory(src, dest);
|
|
210
|
+
} else if (entry.isFile()) {
|
|
211
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
212
|
+
fs.copyFileSync(src, dest);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function resetDirectory(dir) {
|
|
218
|
+
try {
|
|
219
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
220
|
+
} catch (_) {
|
|
221
|
+
}
|
|
222
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function removeDirectoryIfExists(dir) {
|
|
226
|
+
try {
|
|
227
|
+
fs.rmSync(dir, { recursive: true, force: true });
|
|
228
|
+
} catch (_) {
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function cleanupDirectoryEntries(rootDir, keepName) {
|
|
233
|
+
let entries;
|
|
234
|
+
try {
|
|
235
|
+
entries = fs.readdirSync(rootDir, { withFileTypes: true });
|
|
236
|
+
} catch (_) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
for (const entry of entries) {
|
|
241
|
+
if (!entry.isDirectory() || entry.name === keepName) {
|
|
242
|
+
continue;
|
|
243
|
+
}
|
|
244
|
+
removeDirectoryIfExists(path.join(rootDir, entry.name));
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function cleanupLegacyRootFiles(binDir) {
|
|
249
|
+
let entries;
|
|
250
|
+
try {
|
|
251
|
+
entries = fs.readdirSync(binDir, { withFileTypes: true });
|
|
252
|
+
} catch (_) {
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
for (const entry of entries) {
|
|
257
|
+
if (!entry.isFile()) {
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (!/^rebon-.+\.exe$/i.test(entry.name)) {
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
try {
|
|
264
|
+
fs.unlinkSync(path.join(binDir, entry.name));
|
|
265
|
+
} catch (_) {
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function cleanupOldVersions(binDir, keepVersionKey) {
|
|
271
|
+
cleanupDirectoryEntries(path.join(binDir, VERSIONS_DIR), keepVersionKey);
|
|
272
|
+
cleanupDirectoryEntries(path.join(binDir, STAGING_DIR), keepVersionKey);
|
|
273
|
+
cleanupLegacyRootFiles(binDir);
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function promoteStagingDirectory(stagingDir, versionDir) {
|
|
277
|
+
fs.mkdirSync(path.dirname(versionDir), { recursive: true });
|
|
278
|
+
if (fs.existsSync(versionDir)) {
|
|
279
|
+
fs.rmSync(versionDir, { recursive: true, force: true });
|
|
280
|
+
}
|
|
281
|
+
fs.renameSync(stagingDir, versionDir);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function installToVersionKey(packageInfo, binDir, versionKey) {
|
|
285
|
+
const layout = layoutForVersion(binDir, versionKey);
|
|
286
|
+
resetDirectory(layout.stagingDir);
|
|
287
|
+
copyPayloadDirectory(packageInfo.payloadDir, layout.stagingDir);
|
|
288
|
+
promoteStagingDirectory(layout.stagingDir, layout.versionDir);
|
|
289
|
+
|
|
290
|
+
writeManifest(layout.manifestPath, {
|
|
291
|
+
version: packageInfo.version,
|
|
292
|
+
versionKey,
|
|
293
|
+
path: layout.manifestRelativePath,
|
|
294
|
+
package: packageInfo.name,
|
|
295
|
+
payload: packageInfo.payload || payloadSignature(packageInfo.payloadPath),
|
|
296
|
+
installedAt: new Date().toISOString(),
|
|
297
|
+
});
|
|
298
|
+
cleanupOldVersions(binDir, versionKey);
|
|
299
|
+
return layout.exePath;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
function installManagedPackage(packageInfo) {
|
|
303
|
+
const binDir = managedBinDir();
|
|
304
|
+
if (!binDir || !fs.existsSync(packageInfo.payloadPath)) {
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
const installedManifest = readInstalledManifest(packageInfo);
|
|
309
|
+
if (installedManifest) {
|
|
310
|
+
cleanupOldVersions(binDir, installedManifest.versionKey);
|
|
311
|
+
return resolveManifestPath(binDir, installedManifest.path);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
try {
|
|
315
|
+
return installToVersionKey(packageInfo, binDir, packageInfo.versionKey);
|
|
316
|
+
} catch (error) {
|
|
317
|
+
const fallbackVersionKey = payloadSpecificVersionKey(packageInfo);
|
|
318
|
+
if (fallbackVersionKey === packageInfo.versionKey) {
|
|
319
|
+
throw error;
|
|
320
|
+
}
|
|
321
|
+
return installToVersionKey(packageInfo, binDir, fallbackVersionKey);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
function resolveExecutable(packageInfo) {
|
|
326
|
+
const info = packageInfo || readPackageInfo();
|
|
327
|
+
const installed = readInstalledExecutable(info);
|
|
328
|
+
if (installed) {
|
|
329
|
+
return { exe: installed, usedFallback: false, installError: null };
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
let installError = null;
|
|
333
|
+
try {
|
|
334
|
+
const managed = installManagedPackage(info);
|
|
335
|
+
if (managed) {
|
|
336
|
+
return { exe: managed, usedFallback: false, installError: null };
|
|
337
|
+
}
|
|
338
|
+
} catch (error) {
|
|
339
|
+
installError = error;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (fs.existsSync(info.payloadPath)) {
|
|
343
|
+
return { exe: info.payloadPath, usedFallback: true, installError };
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
return { exe: null, usedFallback: false, installError };
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
function spawnResolvedExecutable(resolved, argv, spawnImpl) {
|
|
350
|
+
const child = spawnImpl(resolved.exe, argv, {
|
|
351
|
+
stdio: "inherit",
|
|
352
|
+
windowsHide: false,
|
|
353
|
+
env: { ...process.env, REBON_CODE_MODE_NODE: process.execPath },
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
child.on("error", (error) => {
|
|
357
|
+
console.error(`rebon: failed to start ${resolved.exe}: ${error.message}`);
|
|
358
|
+
process.exit(1);
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
child.on("exit", (code, signal) => {
|
|
362
|
+
if (signal) {
|
|
363
|
+
try {
|
|
364
|
+
process.kill(process.pid, signal);
|
|
365
|
+
} catch (_) {
|
|
366
|
+
process.exit(1);
|
|
367
|
+
}
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
process.exit(code === null ? 1 : code);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
return child;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
module.exports = {
|
|
377
|
+
cleanupOldVersions,
|
|
378
|
+
installManagedPackage,
|
|
379
|
+
layoutForVersion,
|
|
380
|
+
managedBinDir,
|
|
381
|
+
managedRelativeExecutable,
|
|
382
|
+
payloadSignature,
|
|
383
|
+
readCurrentManifest,
|
|
384
|
+
readInstalledExecutable,
|
|
385
|
+
readPackageInfo,
|
|
386
|
+
requireManagedBinDir,
|
|
387
|
+
resolveExecutable,
|
|
388
|
+
spawnResolvedExecutable,
|
|
389
|
+
versionKeyFromPackageJson,
|
|
390
|
+
};
|