@volter/live 0.5.211 → 0.5.213

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.
Files changed (73) hide show
  1. package/BUNDLED_NOTICES +13 -13
  2. package/README.md +10 -11
  3. package/dist/asset-library.d.ts +98 -0
  4. package/dist/asset-library.js +7 -0
  5. package/dist/asset-library.js.map +7 -0
  6. package/dist/chunk-7WKVJGHZ.js +15 -0
  7. package/dist/chunk-7WKVJGHZ.js.map +7 -0
  8. package/dist/chunk-B2HUWFTT.js +25 -0
  9. package/dist/chunk-B2HUWFTT.js.map +7 -0
  10. package/dist/chunk-IZJOOON2.js +805 -0
  11. package/dist/chunk-IZJOOON2.js.map +7 -0
  12. package/dist/chunk-JDOIPALX.js +158 -0
  13. package/dist/chunk-JDOIPALX.js.map +7 -0
  14. package/dist/chunk-JFAHP5CC.js +218 -0
  15. package/dist/chunk-JFAHP5CC.js.map +7 -0
  16. package/dist/chunk-PC56TDHV.js +189 -0
  17. package/dist/chunk-PC56TDHV.js.map +7 -0
  18. package/dist/chunk-WIAH4XZE.js +82 -0
  19. package/dist/chunk-WIAH4XZE.js.map +7 -0
  20. package/dist/client.d.ts +376 -0
  21. package/dist/client.js +10 -0
  22. package/dist/client.js.map +7 -0
  23. package/dist/discovery.d.ts +32 -0
  24. package/dist/discovery.js +19 -0
  25. package/dist/discovery.js.map +7 -0
  26. package/dist/editor-document.d.ts +12 -47
  27. package/dist/editor.d.ts +45 -183
  28. package/dist/http-transport.d.ts +6 -0
  29. package/dist/index.d.ts +3 -6
  30. package/dist/index.js +83 -1762
  31. package/dist/index.js.map +4 -4
  32. package/dist/installed-package.d.ts +6 -0
  33. package/dist/installed-package.js +7 -0
  34. package/dist/installed-package.js.map +7 -0
  35. package/dist/lazy-proxy.d.ts +11 -11
  36. package/dist/member-hints.d.ts +6 -9
  37. package/dist/product-create.d.ts +29 -0
  38. package/dist/product-create.js +13 -0
  39. package/dist/product-create.js.map +7 -0
  40. package/dist/product-locator.d.ts +100 -0
  41. package/dist/product-locator.js +25 -0
  42. package/dist/product-locator.js.map +7 -0
  43. package/dist/registry-format.d.ts +72 -0
  44. package/dist/registry-format.js +31 -0
  45. package/dist/registry-format.js.map +7 -0
  46. package/dist/session.d.ts +11 -15
  47. package/dist/singleton.d.ts +1 -13
  48. package/dist/volter-manifest.d.ts +55 -0
  49. package/dist/volter-manifest.js +9 -0
  50. package/dist/volter-manifest.js.map +7 -0
  51. package/dist/workbench-locator.d.ts +84 -0
  52. package/dist/workbench-locator.js +416 -0
  53. package/dist/workbench-locator.js.map +7 -0
  54. package/package.json +39 -3
  55. package/src/asset-library.ts +104 -0
  56. package/src/client.ts +1093 -0
  57. package/src/discovery.ts +105 -0
  58. package/src/editor-document.ts +12 -49
  59. package/src/editor.ts +56 -215
  60. package/src/http-transport.ts +19 -0
  61. package/src/index.ts +5 -8
  62. package/src/installed-package.ts +15 -0
  63. package/src/lazy-proxy.ts +11 -11
  64. package/src/member-hints.ts +8 -12
  65. package/src/product-create.ts +38 -0
  66. package/src/product-locator.ts +327 -0
  67. package/src/registry-format.ts +248 -0
  68. package/src/session.ts +36 -144
  69. package/src/singleton.ts +1 -16
  70. package/src/volter-manifest.ts +97 -0
  71. package/src/workbench-locator.ts +625 -0
  72. package/dist/tools.d.ts +0 -23
  73. package/src/tools.ts +0 -45
@@ -0,0 +1,416 @@
1
+ import {
2
+ PRODUCT_DECLARATION_KEY,
3
+ workbenchProductId
4
+ } from "./chunk-PC56TDHV.js";
5
+ import "./chunk-JFAHP5CC.js";
6
+ import "./chunk-7WKVJGHZ.js";
7
+
8
+ // src/workbench-locator.ts
9
+ import { execFileSync } from "node:child_process";
10
+ import { createHash } from "node:crypto";
11
+ import {
12
+ createWriteStream,
13
+ existsSync,
14
+ mkdirSync,
15
+ readFileSync,
16
+ renameSync,
17
+ rmSync,
18
+ writeFileSync
19
+ } from "node:fs";
20
+ import { homedir } from "node:os";
21
+ import { basename, isAbsolute, join, resolve, sep } from "node:path";
22
+ import { Readable } from "node:stream";
23
+ import { pipeline } from "node:stream/promises";
24
+ var WORKBENCH_LOCATOR_PATH = ".volter/workbench.json";
25
+ var RELEASE_RECORD = "BUILD.json";
26
+ var SOURCES_LAUNCHER = join("scripts", "code-server.sh");
27
+ var OVERLAY_RECORD = ".volter-overlay.json";
28
+ function workbenchDeclarationExample(projectRoot) {
29
+ return `${join(projectRoot, WORKBENCH_LOCATOR_PATH)}:
30
+ { "workbench": "<path to an extracted Code-OSS release, or to a fork checkout>" }`;
31
+ }
32
+ function readWorkbenchDeclaration(projectRoot) {
33
+ const file = join(projectRoot, WORKBENCH_LOCATOR_PATH);
34
+ if (!existsSync(file)) return null;
35
+ let parsed;
36
+ try {
37
+ parsed = JSON.parse(readFileSync(file, "utf8"));
38
+ } catch (error) {
39
+ throw new Error(
40
+ `${file} is not valid JSON (${error instanceof Error ? error.message : String(error)}). It says which Code-OSS workbench this project opens in, and nothing else:
41
+ ${workbenchDeclarationExample(projectRoot)}`
42
+ );
43
+ }
44
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
45
+ throw new Error(
46
+ `${file} must be a JSON object naming one workbench:
47
+ ${workbenchDeclarationExample(projectRoot)}`
48
+ );
49
+ }
50
+ const record = parsed;
51
+ const extra = Object.keys(record).filter((key) => key !== "workbench");
52
+ if (extra.length > 0) {
53
+ throw new Error(
54
+ `${file} carries ${extra.map((key) => `"${key}"`).join(", ")}, which this document has no meaning for. It names ONE key:
55
+ ${workbenchDeclarationExample(projectRoot)}`
56
+ );
57
+ }
58
+ const declared = record["workbench"];
59
+ if (typeof declared !== "string" || declared.trim() === "") {
60
+ throw new Error(
61
+ `${file} names no workbench directory:
62
+ ${workbenchDeclarationExample(projectRoot)}`
63
+ );
64
+ }
65
+ return isAbsolute(declared) ? resolve(declared) : resolve(projectRoot, declared);
66
+ }
67
+ function writeWorkbenchDeclaration(projectRoot, workbenchDir) {
68
+ mkdirSync(join(projectRoot, ".volter"), { recursive: true });
69
+ writeFileSync(
70
+ join(projectRoot, WORKBENCH_LOCATOR_PATH),
71
+ `${JSON.stringify({ workbench: resolve(workbenchDir) }, null, 2)}
72
+ `
73
+ );
74
+ }
75
+ function workbenchUrl(proxyPort, projectRoot) {
76
+ const id = basename(resolve(projectRoot));
77
+ return `http://editor-${projectKey(projectRoot)}.localhost:${proxyPort}/?project=${encodeURIComponent(id)}`;
78
+ }
79
+ function projectKey(projectRoot) {
80
+ return createHash("sha256").update(resolve(projectRoot)).digest("hex").slice(0, 16);
81
+ }
82
+ function machinePlatform() {
83
+ return `${process.platform}-${process.arch}`;
84
+ }
85
+ function resolveWorkbench(dir, expectedProduct) {
86
+ const root = resolve(dir);
87
+ const resolved = existsSync(join(root, RELEASE_RECORD)) ? resolveRelease(root) : existsSync(join(root, SOURCES_LAUNCHER)) ? resolveSources(root) : null;
88
+ if (resolved === null) {
89
+ throw new Error(
90
+ `${root} is neither a Code-OSS release nor a fork checkout: it carries no ${RELEASE_RECORD} (the record scripts/workbench/build-release.mjs writes beside its tarball) and no ${SOURCES_LAUNCHER}. Name the directory the release was extracted into, or the fork checkout itself.`
91
+ );
92
+ }
93
+ if (expectedProduct !== void 0 && resolved.product !== expectedProduct) {
94
+ throw new Error(
95
+ `${root} is a ${resolved.product} workbench and this project opens in ${expectedProduct}. A workbench is built for ONE product \u2014 the editor kit and that product's workbench half are overlaid on the fork together \u2014 so its title, its look and its commands are the other product's, whatever this session serves into it. ${resolved.kind === "sources" ? `Re-overlay the checkout:
96
+ node scripts/workbench/dev.mjs --checkout ${root} --product ${expectedProduct}` : `Name a ${expectedProduct} release in .volter/workbench.json, or cut one:
97
+ node scripts/workbench/build-release.mjs --product ${expectedProduct} --platform ${machinePlatform()} --checkout <fork dir>`}`
98
+ );
99
+ }
100
+ return resolved;
101
+ }
102
+ function resolveRelease(dir) {
103
+ const record = join(dir, RELEASE_RECORD);
104
+ const cut = `node scripts/workbench/build-release.mjs --product <id> --platform ${machinePlatform()} --checkout <fork dir> --out ${dir}`;
105
+ let parsed;
106
+ try {
107
+ parsed = JSON.parse(readFileSync(record, "utf8"));
108
+ } catch (error) {
109
+ throw new Error(`${record} could not be read: ${String(error)}`);
110
+ }
111
+ const needed = ["target", "platform", "commit", "serverBin", "product"];
112
+ const missing = needed.filter((key) => typeof parsed[key] !== "string");
113
+ if (missing.length > 0) {
114
+ throw new Error(
115
+ `${record} is not a release record this understands: ${missing.join(", ")} ${missing.length === 1 ? "is" : "are"} missing or not a string. A release names ${needed.join(", ")} \u2014 the five fields scripts/workbench/build-release.mjs writes and this one spawns from. The record must name the product compiled into the workbench. Re-cut it:
116
+ ` + cut
117
+ );
118
+ }
119
+ const target = parsed["target"];
120
+ const platform = parsed["platform"];
121
+ const commit = parsed["commit"];
122
+ const serverBin = parsed["serverBin"];
123
+ const product = parsed["product"];
124
+ const machine = machinePlatform();
125
+ if (platform !== machine) {
126
+ throw new Error(
127
+ `${dir} was built for ${platform} and this machine is ${machine}. A Code-OSS server package carries its own platform's node binary and native modules, so it cannot run here \u2014 and this never falls back to a source checkout, because a boot that silently was not the release measures nothing. Cut the ${machine} release:
128
+ node scripts/workbench/build-release.mjs --product ${product} --platform ${machine} --checkout <fork dir>`
129
+ );
130
+ }
131
+ const packageRoot = join(dir, target);
132
+ const serverBinPath = join(packageRoot, serverBin);
133
+ if (!existsSync(serverBinPath)) {
134
+ const tarball = typeof parsed["tarball"] === "string" ? parsed["tarball"] : `${target}-<commit>.tar.gz`;
135
+ throw new Error(
136
+ `${dir} records ${target}, but ${serverBinPath} is not there \u2014 the tarball has not been extracted beside ${RELEASE_RECORD}. Run:
137
+ tar -xzf ${join(dir, tarball)} -C ${dir}`
138
+ );
139
+ }
140
+ return { kind: "release", dir, commit, product, serverBin: serverBinPath, cwd: packageRoot };
141
+ }
142
+ function resolveSources(dir) {
143
+ let commit;
144
+ try {
145
+ commit = execFileSync("git", ["rev-parse", "HEAD"], { windowsHide: true, cwd: dir, encoding: "utf8" }).trim();
146
+ } catch (error) {
147
+ throw new Error(
148
+ `${dir} carries ${SOURCES_LAUNCHER}, so it reads as a Code-OSS fork checkout, but \`git rev-parse HEAD\` there failed (${error instanceof Error ? error.message : String(error)}). A checkout's commit is the only record of which fork this workbench is.`
149
+ );
150
+ }
151
+ const marker = join(dir, OVERLAY_RECORD);
152
+ if (!existsSync(marker)) {
153
+ throw new Error(
154
+ `${dir} is a Code-OSS checkout with no volter overlay: ${OVERLAY_RECORD} is not there, so nothing of the editor is compiled into it and the workbench would come up as plain Code-OSS. Overlay and compile it:
155
+ node scripts/workbench/dev.mjs --checkout ${dir} --product <product>`
156
+ );
157
+ }
158
+ let product;
159
+ try {
160
+ product = JSON.parse(readFileSync(marker, "utf8"))["product"];
161
+ } catch (error) {
162
+ throw new Error(`${marker} could not be read: ${String(error)}`);
163
+ }
164
+ if (typeof product !== "string" || product === "") {
165
+ throw new Error(
166
+ `${marker} names no product. It is written by scripts/workbench/overlay.mjs and says which product's workbench half is in this checkout; re-run the overlay rather than editing it.`
167
+ );
168
+ }
169
+ return {
170
+ kind: "sources",
171
+ dir,
172
+ commit,
173
+ product,
174
+ serverBin: join(dir, SOURCES_LAUNCHER),
175
+ cwd: dir
176
+ };
177
+ }
178
+ var RELEASE_REPO = "volter-ai/code-oss";
179
+ var WORKBENCH_CACHE_ROOT = join(homedir(), ".volter", "workbenches");
180
+ async function resolveWorkbenchForProject(options) {
181
+ const { projectRoot, product, override, io } = options;
182
+ const productId = workbenchProductId(product.name);
183
+ if (override !== void 0) return resolveWorkbench(resolve(override), productId);
184
+ const declared = readWorkbenchDeclaration(projectRoot);
185
+ const fetchRecord = declared !== null && product.workbench !== null && declared.startsWith(`${WORKBENCH_CACHE_ROOT}${sep}`);
186
+ if (declared !== null && !fetchRecord) return resolveWorkbench(declared, productId);
187
+ if (product.workbench === null) throw new Error(
188
+ `${product.name} is a private source product with no released workbench. Pass --workbench <compiled checkout> or declare it in ${WORKBENCH_LOCATOR_PATH}. Public distribution requires a pinned workbench release and checksum.`
189
+ );
190
+ const tag = product.workbench.release;
191
+ const dir = join(WORKBENCH_CACHE_ROOT, tag);
192
+ const fetched = !existsSync(join(dir, RELEASE_RECORD));
193
+ if (fetched) await fetchDeclaredRelease(product, tag, dir, io);
194
+ else io.log(`Workbench ${tag} is already installed (${dir}).`);
195
+ const workbench = resolveWorkbench(dir, productId);
196
+ writeWorkbenchDeclaration(projectRoot, dir);
197
+ io.log(`Declared in ${WORKBENCH_LOCATOR_PATH}: ${dir}`);
198
+ return workbench;
199
+ }
200
+ function githubToken() {
201
+ const fromEnv = process.env["GITHUB_TOKEN"];
202
+ if (typeof fromEnv === "string" && fromEnv.trim() !== "") return fromEnv.trim();
203
+ try {
204
+ const out = execFileSync("gh", ["auth", "token"], {
205
+ windowsHide: true,
206
+ encoding: "utf8",
207
+ stdio: ["ignore", "pipe", "ignore"]
208
+ }).trim();
209
+ return out === "" ? null : out;
210
+ } catch {
211
+ return null;
212
+ }
213
+ }
214
+ function apiHeaders(token) {
215
+ return {
216
+ Accept: "application/vnd.github+json",
217
+ "X-GitHub-Api-Version": "2022-11-28",
218
+ "User-Agent": "volter-workbench-locator",
219
+ ...token === null ? {} : { Authorization: `Bearer ${token}` }
220
+ };
221
+ }
222
+ function megabytes(bytes) {
223
+ return (bytes / 1024 ** 2).toFixed(0);
224
+ }
225
+ function tokenDoors() {
226
+ return " GITHUB_TOKEN=<a token with repo scope> \u2014 in this shell, or\n gh auth login \u2014 so `gh auth token` answers";
227
+ }
228
+ async function downloadOperation(stage, url, token, operation) {
229
+ try {
230
+ return await operation();
231
+ } catch (cause) {
232
+ const seen = /* @__PURE__ */ new Set();
233
+ const redact = (text) => {
234
+ const withoutToken = token === null ? text : text.replaceAll(token, "[redacted]");
235
+ return withoutToken.replace(/https?:\/\/[^\s"<>]+/gi, (raw) => {
236
+ try {
237
+ const parsed = new URL(raw);
238
+ parsed.username = "";
239
+ parsed.password = "";
240
+ parsed.search = "";
241
+ parsed.hash = "";
242
+ return parsed.href;
243
+ } catch {
244
+ return "[redacted URL]";
245
+ }
246
+ }).slice(0, 1e3);
247
+ };
248
+ const describe = (error, depth) => {
249
+ if (seen.has(error) || depth > 4) return "[cause omitted]";
250
+ seen.add(error);
251
+ if (typeof error !== "object" || error === null) return redact(String(error));
252
+ const fields = error;
253
+ const name = typeof fields.name === "string" ? fields.name : "Error";
254
+ const message = typeof fields.message === "string" ? fields.message : "Unknown transport error";
255
+ const code = typeof fields.code === "string" ? ` [${fields.code}]` : "";
256
+ let detail = redact(`${name}${code}: ${message}`);
257
+ if (fields.cause !== void 0) detail += `; caused by ${describe(fields.cause, depth + 1)}`;
258
+ if (Array.isArray(fields.errors))
259
+ detail += `; ${fields.errors.slice(0, 4).map((error2) => describe(error2, depth + 1)).join("; ")}`;
260
+ return detail;
261
+ };
262
+ throw new Error(`Workbench download failed during ${stage} at ${url}: ${describe(cause, 0)}`, { cause });
263
+ }
264
+ }
265
+ function assetUrl(asset) {
266
+ return `https://api.github.com/repos/${RELEASE_REPO}/releases/assets/${asset.id}`;
267
+ }
268
+ async function fetchDeclaredRelease(product, tag, dir, io) {
269
+ if (product.workbench === null) throw new Error("Cannot download an unpinned workbench.");
270
+ const productId = workbenchProductId(product.name);
271
+ const machine = machinePlatform();
272
+ const token = githubToken();
273
+ const partial = join(WORKBENCH_CACHE_ROOT, `.${tag}.${process.pid}.partial`);
274
+ const cutLine = ` node scripts/workbench/build-release.mjs --product ${productId} --platform ${machine} --checkout <fork dir> --publish`;
275
+ const releaseUrl = `https://api.github.com/repos/${RELEASE_REPO}/releases/tags/${encodeURIComponent(tag)}`;
276
+ const response = await downloadOperation(
277
+ "release metadata request",
278
+ releaseUrl,
279
+ token,
280
+ () => fetch(releaseUrl, { headers: apiHeaders(token) })
281
+ );
282
+ if (response.status === 404 && token === null)
283
+ throw new Error(
284
+ `${product.name} opens in the Code-OSS workbench published as ${tag} on ${RELEASE_REPO}, and that repository answers 404 to this machine \u2014 it is private, and nothing here has a GitHub token to read it with. Two doors, either one:
285
+ ${tokenDoors()}
286
+ Or name a workbench you already have, which needs no network at all:
287
+ ${product.command} edit --workbench <dir>`
288
+ );
289
+ if (response.status === 404)
290
+ throw new Error(
291
+ `${RELEASE_REPO} has no release tagged ${tag}, and that is the workbench ${product.name} declares (package.json#${PRODUCT_DECLARATION_KEY}.workbench). Either the declaration names a tag that was never published, or this token cannot see the repository. Cut and publish it:
292
+ ${cutLine}`
293
+ );
294
+ if (!response.ok)
295
+ throw new Error(
296
+ `${RELEASE_REPO}'s release ${tag} answered ${response.status} ${response.statusText}. That is the workbench ${product.name} declares; ${token === null ? "no token was found" : "the token this machine has was used"}.` + (token === null ? `
297
+ ${tokenDoors()}` : "")
298
+ );
299
+ const metadata = await downloadOperation("release metadata response", releaseUrl, token, () => response.json());
300
+ const assets = metadata.assets ?? [];
301
+ const record = assets.find((asset) => asset.name === RELEASE_RECORD);
302
+ const tarball = assets.find((asset) => asset.name.endsWith(".tar.gz"));
303
+ if (record === void 0 || tarball === void 0)
304
+ throw new Error(
305
+ `Release ${tag} on ${RELEASE_REPO} carries ${assets.length === 0 ? "no assets" : assets.map((asset) => asset.name).join(", ")}. A workbench release is a tarball and its ${RELEASE_RECORD}, both uploaded by \`build-release.mjs --publish\`; re-publish it:
306
+ ${cutLine}`
307
+ );
308
+ rmSync(partial, { recursive: true, force: true });
309
+ mkdirSync(partial, { recursive: true });
310
+ try {
311
+ const recordText = await downloadAssetText(record, token);
312
+ const built = await downloadOperation(
313
+ "BUILD.json parse",
314
+ assetUrl(record),
315
+ token,
316
+ async () => JSON.parse(recordText)
317
+ );
318
+ if (built["platform"] !== machine)
319
+ throw new Error(
320
+ `Release ${tag} was built for ${String(built["platform"])} and this machine is ${machine}. A Code-OSS server package carries its own platform's node binary and native modules, so it cannot run here, and nothing falls back. Cut and publish the ${machine} release:
321
+ ${cutLine}`
322
+ );
323
+ if (built["tarballSha256"] !== product.workbench.tarballSha256)
324
+ throw new Error(
325
+ `Release ${tag}'s own ${RELEASE_RECORD} records tarballSha256 ${String(built["tarballSha256"])} and ${product.name} pins ${product.workbench.tarballSha256}. A release is immutable, so these two cannot disagree about one tag: either the product declares the wrong release, or the release was replaced. Nothing was downloaded.`
326
+ );
327
+ writeFileSync(join(partial, RELEASE_RECORD), recordText);
328
+ io.log(
329
+ `Fetching the ${productId} workbench ${tag} from ${RELEASE_REPO} \u2014 ${megabytes(tarball.size)} MB, once for this user on this computer.`
330
+ );
331
+ const tarballPath = join(partial, tarball.name);
332
+ let announced = 0;
333
+ const sha = await downloadAsset(tarball, token, tarballPath, (received) => {
334
+ if (received - announced < 4 * 1024 ** 2 && received !== tarball.size) return;
335
+ announced = received;
336
+ io.progress?.(
337
+ ` ${megabytes(received)} / ${megabytes(tarball.size)} MB (${Math.floor(received / tarball.size * 100)}%)`
338
+ );
339
+ });
340
+ if (sha !== product.workbench.tarballSha256)
341
+ throw new Error(
342
+ `The download of ${tag} hashes to ${sha} and ${product.name} pins ${product.workbench.tarballSha256}. These are not the bytes this product runs in; the partial download was deleted and nothing was extracted.`
343
+ );
344
+ io.log(` sha256 ${sha.slice(0, 12)}\u2026 matches the pin. Extracting\u2026`);
345
+ const tar = process.platform === "win32" ? join(process.env["SystemRoot"] ?? "C:\\Windows", "System32", "tar.exe") : "tar";
346
+ execFileSync(tar, ["-xzf", tarballPath, "-C", partial], {
347
+ windowsHide: true,
348
+ stdio: ["ignore", "ignore", "pipe"]
349
+ });
350
+ rmSync(tarballPath, { force: true });
351
+ if (existsSync(join(dir, RELEASE_RECORD))) {
352
+ rmSync(partial, { recursive: true, force: true });
353
+ } else {
354
+ rmSync(dir, { recursive: true, force: true });
355
+ renameSync(partial, dir);
356
+ }
357
+ io.log(`Workbench installed at ${dir}.`);
358
+ } catch (error) {
359
+ rmSync(partial, { recursive: true, force: true });
360
+ throw error;
361
+ }
362
+ }
363
+ async function downloadAssetText(asset, token) {
364
+ const url = assetUrl(asset);
365
+ const response = await downloadOperation(
366
+ "BUILD.json request",
367
+ url,
368
+ token,
369
+ () => fetch(url, { headers: { ...apiHeaders(token), Accept: "application/octet-stream" } })
370
+ );
371
+ if (!response.ok)
372
+ throw new Error(
373
+ `${asset.name} of ${RELEASE_REPO} answered ${response.status} ${response.statusText}.`
374
+ );
375
+ return await downloadOperation("BUILD.json response", url, token, () => response.text());
376
+ }
377
+ async function downloadAsset(asset, token, destination, onProgress) {
378
+ const url = assetUrl(asset);
379
+ const response = await downloadOperation(
380
+ "archive request",
381
+ url,
382
+ token,
383
+ () => fetch(url, { headers: { ...apiHeaders(token), Accept: "application/octet-stream" } })
384
+ );
385
+ if (!response.ok || response.body === null)
386
+ throw new Error(
387
+ `${asset.name} of ${RELEASE_REPO} answered ${response.status} ${response.statusText}.`
388
+ );
389
+ const hash = createHash("sha256");
390
+ let received = 0;
391
+ await downloadOperation("archive transfer", url, token, () => pipeline(
392
+ Readable.fromWeb(response.body),
393
+ async function* (source) {
394
+ for await (const chunk of source) {
395
+ hash.update(chunk);
396
+ received += chunk.length;
397
+ onProgress(received);
398
+ yield chunk;
399
+ }
400
+ },
401
+ createWriteStream(destination)
402
+ ));
403
+ return hash.digest("hex");
404
+ }
405
+ export {
406
+ WORKBENCH_CACHE_ROOT,
407
+ WORKBENCH_LOCATOR_PATH,
408
+ projectKey,
409
+ readWorkbenchDeclaration,
410
+ resolveWorkbench,
411
+ resolveWorkbenchForProject,
412
+ workbenchDeclarationExample,
413
+ workbenchUrl,
414
+ writeWorkbenchDeclaration
415
+ };
416
+ //# sourceMappingURL=workbench-locator.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/workbench-locator.ts"],
4
+ "sourcesContent": ["\n\nimport { execFileSync } from 'node:child_process';\nimport { createHash } from 'node:crypto';\nimport {\n createWriteStream,\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n rmSync,\n writeFileSync,\n} from 'node:fs';\nimport { homedir } from 'node:os';\nimport { basename, isAbsolute, join, resolve, sep } from 'node:path';\nimport { Readable } from 'node:stream';\nimport { pipeline } from 'node:stream/promises';\nimport {\n PRODUCT_DECLARATION_KEY,\n type ProductIdentity,\n workbenchProductId,\n} from './product-locator';\n\n/** Where a project declares its workbench, relative to the project root. */\nexport const WORKBENCH_LOCATOR_PATH = '.volter/workbench.json';\n\n/** The release's own record, written beside the tarball by\n * `scripts/workbench/build-release.mjs`. */\nconst RELEASE_RECORD = 'BUILD.json';\n/** The REH launcher inside a fork checkout \u2014 the marker that says \"sources\". */\nconst SOURCES_LAUNCHER = join('scripts', 'code-server.sh');\n/** What `scripts/workbench/overlay.mjs` leaves in a checkout it has overlaid. */\nconst OVERLAY_RECORD = '.volter-overlay.json';\n\n/** What the session reports about the workbench it is running. */\nexport interface WorkbenchIdentity {\n readonly kind: 'release' | 'sources';\n /** The directory named by the declaration or the flag, resolved absolute. */\n readonly dir: string;\n /** The Code-OSS fork commit these bytes are. */\n readonly commit: string;\n\n readonly product: string;\n}\n\n/** Everything the session needs to run it, identity included. */\nexport interface ResolvedWorkbench extends WorkbenchIdentity {\n /** The executable to spawn, already known to exist. */\n readonly serverBin: string;\n /** Its working directory \u2014 the package root, or the checkout. */\n readonly cwd: string;\n}\n\n/** The exact file to write, quoted in every refusal that wants one. */\nexport function workbenchDeclarationExample(projectRoot: string): string {\n return (\n `${join(projectRoot, WORKBENCH_LOCATOR_PATH)}:\\n` +\n ' { \"workbench\": \"<path to an extracted Code-OSS release, or to a fork checkout>\" }'\n );\n}\n\n/**\n * The workbench directory this project declares, or `null` when it declares\n * none. Throws when the file exists and is not exactly `{ \"workbench\": <path> }`\n * \u2014 unrecognized keys are refused.\n */\nexport function readWorkbenchDeclaration(projectRoot: string): string | null {\n const file = join(projectRoot, WORKBENCH_LOCATOR_PATH);\n if (!existsSync(file)) return null;\n let parsed: unknown;\n try {\n parsed = JSON.parse(readFileSync(file, 'utf8'));\n } catch (error) {\n throw new Error(\n `${file} is not valid JSON (${error instanceof Error ? error.message : String(error)}). It says ` +\n `which Code-OSS workbench this project opens in, and nothing else:\\n${workbenchDeclarationExample(projectRoot)}`,\n );\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n throw new Error(\n `${file} must be a JSON object naming one workbench:\\n${workbenchDeclarationExample(projectRoot)}`,\n );\n }\n const record = parsed as Record<string, unknown>;\n const extra = Object.keys(record).filter((key) => key !== 'workbench');\n if (extra.length > 0) {\n throw new Error(\n `${file} carries ${extra.map((key) => `\"${key}\"`).join(', ')}, which this document has no meaning for. ` +\n `It names ONE key:\\n${workbenchDeclarationExample(projectRoot)}`,\n );\n }\n const declared = record['workbench'];\n if (typeof declared !== 'string' || declared.trim() === '') {\n throw new Error(\n `${file} names no workbench directory:\\n${workbenchDeclarationExample(projectRoot)}`,\n );\n }\n return isAbsolute(declared) ? resolve(declared) : resolve(projectRoot, declared);\n}\n\n/**\n * WRITE THE DECLARATION \u2014 the one record of which workbench THIS machine opens\n * this project in. Written by `<product> create --workbench <dir>`, and written\n * by the fetch below, so the two paths cannot leave two different shapes of\n * file behind.\n */\nexport function writeWorkbenchDeclaration(projectRoot: string, workbenchDir: string): void {\n mkdirSync(join(projectRoot, '.volter'), { recursive: true });\n writeFileSync(\n join(projectRoot, WORKBENCH_LOCATOR_PATH),\n `${JSON.stringify({ workbench: resolve(workbenchDir) }, null, 2)}\\n`,\n );\n}\n\n/**\n * The url the workbench answers on \u2014 the ONE url a person opens under the\n * frame. Spelled here so the CLI's launch line and the session's tab bijection\n * cannot disagree about it.\n *\n * `?project=<id>` is the one boot param the Volter editor carries; the session's\n * one-origin proxy redirects it to the workbench's own `?folder=`, and\n * `frame-proxy.ts` says why it must be a redirect.\n */\nexport function workbenchUrl(proxyPort: number, projectRoot: string): string {\n const id = basename(resolve(projectRoot));\n // Cookies ignore ports. A shared loopback hostname can inherit another\n // local VS Code app's secret-storage cookie and select its absent key server.\n // Give each project a stable host; browsers resolve *.localhost to loopback.\n return `http://editor-${projectKey(projectRoot)}.localhost:${proxyPort}/?project=${encodeURIComponent(id)}`;\n}\n\n/** A project's stable key on this machine: its page's host, and its workbench extensions folder. */\nexport function projectKey(projectRoot: string): string {\n return createHash('sha256').update(resolve(projectRoot)).digest('hex').slice(0, 16);\n}\n\n/** This machine in the build script's own platform vocabulary. */\nfunction machinePlatform(): string {\n return `${process.platform}-${process.arch}`;\n}\n\n\n/** The workbench at `dir`, refused where it is built for another product than `expectedProduct`; none named (a session\n * whose project's product cannot be resolved, which `/__editor/served-modules` explains) is not judged. */\nexport function resolveWorkbench(dir: string, expectedProduct?: string): ResolvedWorkbench {\n const root = resolve(dir);\n const resolved = existsSync(join(root, RELEASE_RECORD))\n ? resolveRelease(root)\n : existsSync(join(root, SOURCES_LAUNCHER))\n ? resolveSources(root)\n : null;\n if (resolved === null) {\n throw new Error(\n `${root} is neither a Code-OSS release nor a fork checkout: it carries no ${RELEASE_RECORD} (the record ` +\n `scripts/workbench/build-release.mjs writes beside its tarball) and no ${SOURCES_LAUNCHER}. Name the ` +\n 'directory the release was extracted into, or the fork checkout itself.',\n );\n }\n if (expectedProduct !== undefined && resolved.product !== expectedProduct) {\n throw new Error(\n `${root} is a ${resolved.product} workbench and this project opens in ${expectedProduct}. A workbench is ` +\n \"built for ONE product \u2014 the editor kit and that product's workbench half are overlaid on the fork \" +\n \"together \u2014 so its title, its look and its commands are the other product's, whatever this session \" +\n `serves into it. ${\n resolved.kind === 'sources'\n ? `Re-overlay the checkout:\\n node scripts/workbench/dev.mjs --checkout ${root} --product ${expectedProduct}`\n : `Name a ${expectedProduct} release in .volter/workbench.json, or cut one:\\n node scripts/workbench/build-release.mjs --product ${expectedProduct} --platform ${machinePlatform()} --checkout <fork dir>`\n }`,\n );\n }\n return resolved;\n}\n\n/**\n * The five fields the launch depends on \u2014 `target`, `platform`, `commit`,\n * `serverBin` and `product`. The rest of `BUILD.json` is the build's own\n * provenance (sizes, sha256, the node it was built with) and is read by a\n * person, not by this.\n */\nfunction resolveRelease(dir: string): ResolvedWorkbench {\n const record = join(dir, RELEASE_RECORD);\n const cut = `node scripts/workbench/build-release.mjs --product <id> --platform ${machinePlatform()} --checkout <fork dir> --out ${dir}`;\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(readFileSync(record, 'utf8')) as Record<string, unknown>;\n } catch (error) {\n throw new Error(`${record} could not be read: ${String(error)}`);\n }\n const needed = ['target', 'platform', 'commit', 'serverBin', 'product'] as const;\n const missing = needed.filter((key) => typeof parsed[key] !== 'string');\n if (missing.length > 0) {\n throw new Error(\n `${record} is not a release record this understands: ${missing.join(', ')} ` +\n `${missing.length === 1 ? 'is' : 'are'} missing or not a string. A release names ${needed.join(', ')} \u2014 ` +\n 'the five fields scripts/workbench/build-release.mjs writes and this one spawns from. ' +\n 'The record must name the product compiled into the workbench. Re-cut it:\\n ' +\n cut,\n );\n }\n const target = parsed['target'] as string;\n const platform = parsed['platform'] as string;\n const commit = parsed['commit'] as string;\n const serverBin = parsed['serverBin'] as string;\n const product = parsed['product'] as string;\n\n const machine = machinePlatform();\n if (platform !== machine) {\n throw new Error(\n `${dir} was built for ${platform} and this machine is ${machine}. A Code-OSS server package carries its ` +\n \"own platform's node binary and native modules, so it cannot run here \u2014 and this never falls back to a \" +\n `source checkout, because a boot that silently was not the release measures nothing. Cut the ${machine} ` +\n `release:\\n node scripts/workbench/build-release.mjs --product ${product} --platform ${machine} --checkout <fork dir>`,\n );\n }\n\n const packageRoot = join(dir, target);\n const serverBinPath = join(packageRoot, serverBin);\n if (!existsSync(serverBinPath)) {\n const tarball =\n typeof parsed['tarball'] === 'string'\n ? (parsed['tarball'] as string)\n : `${target}-<commit>.tar.gz`;\n throw new Error(\n `${dir} records ${target}, but ${serverBinPath} is not there \u2014 the tarball has not been extracted beside ` +\n `${RELEASE_RECORD}. Run:\\n tar -xzf ${join(dir, tarball)} -C ${dir}`,\n );\n }\n return { kind: 'release', dir, commit, product, serverBin: serverBinPath, cwd: packageRoot };\n}\n\n/**\n * A fork checkout. The commit is the working tree's, read with git: a checkout\n * has no file that states it, and a stale one would name bytes nobody is\n * running. The PRODUCT is the overlay's own record \u2014 a checkout with none has\n * no volter tier in it at all, and that is refused here rather than left to\n * surface as a workbench where `Volter: Open Workspace` does not exist.\n */\nfunction resolveSources(dir: string): ResolvedWorkbench {\n let commit: string;\n try {\n commit = execFileSync('git', ['rev-parse', 'HEAD'], { windowsHide: true, cwd: dir, encoding: 'utf8' }).trim();\n } catch (error) {\n throw new Error(\n `${dir} carries ${SOURCES_LAUNCHER}, so it reads as a Code-OSS fork checkout, but \\`git rev-parse HEAD\\` ` +\n `there failed (${error instanceof Error ? error.message : String(error)}). A checkout's commit is the ` +\n 'only record of which fork this workbench is.',\n );\n }\n const marker = join(dir, OVERLAY_RECORD);\n if (!existsSync(marker)) {\n throw new Error(\n `${dir} is a Code-OSS checkout with no volter overlay: ${OVERLAY_RECORD} is not there, so nothing of the ` +\n 'editor is compiled into it and the workbench would come up as plain Code-OSS. Overlay and compile it:\\n' +\n ` node scripts/workbench/dev.mjs --checkout ${dir} --product <product>`,\n );\n }\n let product: unknown;\n try {\n product = (JSON.parse(readFileSync(marker, 'utf8')) as Record<string, unknown>)['product'];\n } catch (error) {\n throw new Error(`${marker} could not be read: ${String(error)}`);\n }\n if (typeof product !== 'string' || product === '') {\n throw new Error(\n `${marker} names no product. It is written by scripts/workbench/overlay.mjs and says which product's ` +\n 'workbench half is in this checkout; re-run the overlay rather than editing it.',\n );\n }\n return {\n kind: 'sources',\n dir,\n commit,\n product,\n serverBin: join(dir, SOURCES_LAUNCHER),\n cwd: dir,\n };\n}\n\n// ---------------------------------------------------------------------------\n// THE PRODUCT'S OWN WORKBENCH \u2014 the third resolution step, and the only one\n// that needs nothing on the machine but the product.\n// ---------------------------------------------------------------------------\n\n/** The fork's own repository, where a cut release is published. Private today;\n * the fetch below is the same call either way, with a token or without one. */\nconst RELEASE_REPO = 'volter-ai/code-oss';\n\n/**\n * WHERE FETCHED BYTES LIVE \u2014 one directory per release tag, per user (`~/.volter/workbenches`).\n *\n * Keyed by the TAG and nothing else, because that is what makes it a cache and\n * not a decision: two projects on the same release share one directory,\n * a second `create` consults no network, and a release is immutable, so a tag\n * that is here is the tag that was published. Which workbench a project opens\n * in is still recorded in the PROJECT (`.volter/workbench.json`, written the\n * moment this resolves) \u2014 nothing ever searches this directory.\n */\nexport const WORKBENCH_CACHE_ROOT = join(homedir(), '.volter', 'workbenches');\n\n/** Where the fetch talks. `log` is a line; `progress` is ONE line rewritten in\n * place (216 MB is a wait, and a wait with no number is a hang). */\nexport interface WorkbenchFetchIO {\n readonly log: (line: string) => void;\n readonly progress?: (line: string) => void;\n}\n\n/**\n * THE WORKBENCH THIS PROJECT OPENS IN, resolved in three steps:\n *\n * 1. `--workbench <dir>` \u2014 one launch, writes nothing.\n * 2. `<project>/.volter/workbench.json` \u2014 this machine's record for this project.\n * 3. the PRODUCT's declared release \u2014 fetched once, then written into (2).\n *\n * Step 3 is what makes the product's `create` open something\n * on a machine that has never built anything, and it is why the CLI resolves\n * the product BEFORE the workbench.\n */\nexport async function resolveWorkbenchForProject(options: {\n projectRoot: string;\n product: ProductIdentity;\n /** `--workbench <dir>`, when the person passed one. */\n override?: string | undefined;\n io: WorkbenchFetchIO;\n}): Promise<ResolvedWorkbench> {\n const { projectRoot, product, override, io } = options;\n const productId = workbenchProductId(product.name);\n if (override !== undefined) return resolveWorkbench(resolve(override), productId);\n // A declaration under the cache root is the one the fetch below wrote: the\n // product's pin decides it, so a pin that moved, or a cache that was\n // cleared, fetches again instead of opening a stale release or refusing a\n // directory that is gone.\n const declared = readWorkbenchDeclaration(projectRoot);\n const fetchRecord = declared !== null && product.workbench !== null && declared.startsWith(`${WORKBENCH_CACHE_ROOT}${sep}`);\n if (declared !== null && !fetchRecord) return resolveWorkbench(declared, productId);\n\n if (product.workbench === null) throw new Error(\n `${product.name} is a private source product with no released workbench. ` +\n `Pass --workbench <compiled checkout> or declare it in ${WORKBENCH_LOCATOR_PATH}. ` +\n 'Public distribution requires a pinned workbench release and checksum.',\n );\n const tag = product.workbench.release;\n const dir = join(WORKBENCH_CACHE_ROOT, tag);\n // A CACHED TAG IS NEVER RE-FETCHED. The marker is the release's own record,\n // so a directory that lost its extraction reads as absent and is fetched\n // again rather than resolving into a refusal a person cannot act on.\n const fetched = !existsSync(join(dir, RELEASE_RECORD));\n if (fetched) await fetchDeclaredRelease(product, tag, dir, io);\n else io.log(`Workbench ${tag} is already installed (${dir}).`);\n const workbench = resolveWorkbench(dir, productId);\n writeWorkbenchDeclaration(projectRoot, dir);\n io.log(`Declared in ${WORKBENCH_LOCATOR_PATH}: ${dir}`);\n return workbench;\n}\n\n/** A GitHub release asset, as much of one as this reads. */\ninterface ReleaseAsset {\n readonly id: number;\n readonly name: string;\n readonly size: number;\n}\n\n/**\n * The token, from the two doors a person has: the environment, or the `gh` they\n * are already logged into. Deliberately not a file of ours, not a setting and\n * not a prompt \u2014 a credential this reads is one somebody else's tool already\n * owns.\n */\nfunction githubToken(): string | null {\n const fromEnv = process.env['GITHUB_TOKEN'];\n if (typeof fromEnv === 'string' && fromEnv.trim() !== '') return fromEnv.trim();\n try {\n const out = execFileSync('gh', ['auth', 'token'], {\n windowsHide: true,\n encoding: 'utf8',\n stdio: ['ignore', 'pipe', 'ignore'],\n }).trim();\n return out === '' ? null : out;\n } catch {\n return null;\n }\n}\n\nfunction apiHeaders(token: string | null): Record<string, string> {\n return {\n Accept: 'application/vnd.github+json',\n 'X-GitHub-Api-Version': '2022-11-28',\n 'User-Agent': 'volter-workbench-locator',\n ...(token === null ? {} : { Authorization: `Bearer ${token}` }),\n };\n}\n\nfunction megabytes(bytes: number): string {\n return (bytes / 1024 ** 2).toFixed(0);\n}\n\n/** The line a refusal prints when the release is not reachable \u2014 both doors,\n * named, because \"no credentials\" with no names is the same as no message. */\nfunction tokenDoors(): string {\n return (\n ' GITHUB_TOKEN=<a token with repo scope> \u2014 in this shell, or\\n' +\n ' gh auth login \u2014 so `gh auth token` answers'\n );\n}\n\n/** The CLI prints only Error.message. Keep the public request/stage and Node's\n * nested transport code there, without printing auth headers or signed redirects.\n * The original thrown value is retained as cause for callers that can inspect it. */\nasync function downloadOperation<T>(\n stage: string,\n url: string,\n token: string | null,\n operation: () => Promise<T>,\n): Promise<T> {\n try {\n return await operation();\n } catch (cause) {\n const seen = new Set<unknown>();\n const redact = (text: string): string => {\n const withoutToken = token === null ? text : text.replaceAll(token, '[redacted]');\n return withoutToken.replace(/https?:\\/\\/[^\\s\"<>]+/gi, (raw) => {\n try {\n const parsed = new URL(raw);\n parsed.username = '';\n parsed.password = '';\n parsed.search = '';\n parsed.hash = '';\n return parsed.href;\n } catch { return '[redacted URL]'; }\n }).slice(0, 1000);\n };\n const describe = (error: unknown, depth: number): string => {\n if (seen.has(error) || depth > 4) return '[cause omitted]';\n seen.add(error);\n if (typeof error !== 'object' || error === null) return redact(String(error));\n const fields = error as { name?: unknown; message?: unknown; code?: unknown; cause?: unknown; errors?: unknown };\n const name = typeof fields.name === 'string' ? fields.name : 'Error';\n const message = typeof fields.message === 'string' ? fields.message : 'Unknown transport error';\n const code = typeof fields.code === 'string' ? ` [${fields.code}]` : '';\n let detail = redact(`${name}${code}: ${message}`);\n if (fields.cause !== undefined) detail += `; caused by ${describe(fields.cause, depth + 1)}`;\n if (Array.isArray(fields.errors))\n detail += `; ${fields.errors.slice(0, 4).map((error) => describe(error, depth + 1)).join('; ')}`;\n return detail;\n };\n throw new Error(`Workbench download failed during ${stage} at ${url}: ${describe(cause, 0)}`, { cause });\n }\n}\n\nfunction assetUrl(asset: ReleaseAsset): string {\n return `https://api.github.com/repos/${RELEASE_REPO}/releases/assets/${asset.id}`;\n}\n\n/**\n * FETCH ONE PUBLISHED RELEASE into `dir`, atomically: everything lands in a\n * sibling `.partial` directory and is renamed into place at the end, so a\n * directory under `~/.volter/workbenches` either is a whole workbench or is not\n * there. Any failure \u2014 a refused download, a sha that does not match the\n * product's pin, a tar that dies \u2014 deletes the partial and refuses.\n */\nasync function fetchDeclaredRelease(\n product: ProductIdentity,\n tag: string,\n dir: string,\n io: WorkbenchFetchIO,\n): Promise<void> {\n if (product.workbench === null) throw new Error('Cannot download an unpinned workbench.');\n const productId = workbenchProductId(product.name);\n const machine = machinePlatform();\n const token = githubToken();\n const partial = join(WORKBENCH_CACHE_ROOT, `.${tag}.${process.pid}.partial`);\n const cutLine =\n ` node scripts/workbench/build-release.mjs --product ${productId} --platform ${machine} ` +\n '--checkout <fork dir> --publish';\n\n const releaseUrl = `https://api.github.com/repos/${RELEASE_REPO}/releases/tags/${encodeURIComponent(tag)}`;\n const response = await downloadOperation('release metadata request', releaseUrl, token,\n () => fetch(releaseUrl, { headers: apiHeaders(token) }));\n if (response.status === 404 && token === null)\n throw new Error(\n `${product.name} opens in the Code-OSS workbench published as ${tag} on ${RELEASE_REPO}, and ` +\n 'that repository answers 404 to this machine \u2014 it is private, and nothing here has a ' +\n 'GitHub token to read it with. Two doors, either one:\\n' +\n `${tokenDoors()}\\n` +\n 'Or name a workbench you already have, which needs no network at all:\\n' +\n ` ${product.command} edit --workbench <dir>`,\n );\n if (response.status === 404)\n throw new Error(\n `${RELEASE_REPO} has no release tagged ${tag}, and that is the workbench ${product.name} ` +\n `declares (package.json#${PRODUCT_DECLARATION_KEY}.workbench). Either the declaration names ` +\n 'a tag that was never published, or this token cannot see the repository. Cut and publish ' +\n `it:\\n${cutLine}`,\n );\n if (!response.ok)\n throw new Error(\n `${RELEASE_REPO}'s release ${tag} answered ${response.status} ${response.statusText}. That is ` +\n `the workbench ${product.name} declares; ` +\n `${token === null ? 'no token was found' : 'the token this machine has was used'}.` +\n (token === null ? `\\n${tokenDoors()}` : ''),\n );\n const metadata = await downloadOperation('release metadata response', releaseUrl, token, () => response.json());\n const assets = (metadata as { assets?: ReleaseAsset[] }).assets ?? [];\n const record = assets.find((asset) => asset.name === RELEASE_RECORD);\n const tarball = assets.find((asset) => asset.name.endsWith('.tar.gz'));\n if (record === undefined || tarball === undefined)\n throw new Error(\n `Release ${tag} on ${RELEASE_REPO} carries ` +\n `${assets.length === 0 ? 'no assets' : assets.map((asset) => asset.name).join(', ')}. ` +\n `A workbench release is a tarball and its ${RELEASE_RECORD}, both uploaded by ` +\n `\\`build-release.mjs --publish\\`; re-publish it:\\n${cutLine}`,\n );\n\n rmSync(partial, { recursive: true, force: true });\n mkdirSync(partial, { recursive: true });\n try {\n // Read the compatibility record before downloading the workbench artifact.\n const recordText = await downloadAssetText(record, token);\n const built = await downloadOperation('BUILD.json parse', assetUrl(record), token,\n async () => JSON.parse(recordText) as Record<string, unknown>);\n if (built['platform'] !== machine)\n throw new Error(\n `Release ${tag} was built for ${String(built['platform'])} and this machine is ${machine}. A ` +\n \"Code-OSS server package carries its own platform's node binary and native modules, so it \" +\n `cannot run here, and nothing falls back. Cut and publish the ${machine} release:\\n${cutLine}`,\n );\n if (built['tarballSha256'] !== product.workbench.tarballSha256)\n throw new Error(\n `Release ${tag}'s own ${RELEASE_RECORD} records tarballSha256 ${String(built['tarballSha256'])} ` +\n `and ${product.name} pins ${product.workbench.tarballSha256}. A release is immutable, so these ` +\n 'two cannot disagree about one tag: either the product declares the wrong release, or the ' +\n 'release was replaced. Nothing was downloaded.',\n );\n writeFileSync(join(partial, RELEASE_RECORD), recordText);\n\n io.log(\n `Fetching the ${productId} workbench ${tag} from ${RELEASE_REPO} \u2014 ` +\n `${megabytes(tarball.size)} MB, once for this user on this computer.`,\n );\n const tarballPath = join(partial, tarball.name);\n let announced = 0;\n const sha = await downloadAsset(tarball, token, tarballPath, (received) => {\n if (received - announced < 4 * 1024 ** 2 && received !== tarball.size) return;\n announced = received;\n io.progress?.(\n ` ${megabytes(received)} / ${megabytes(tarball.size)} MB ` +\n `(${Math.floor((received / tarball.size) * 100)}%)`,\n );\n });\n if (sha !== product.workbench.tarballSha256)\n throw new Error(\n `The download of ${tag} hashes to ${sha} and ${product.name} pins ` +\n `${product.workbench.tarballSha256}. These are not the bytes this product runs in; the ` +\n 'partial download was deleted and nothing was extracted.',\n );\n io.log(` sha256 ${sha.slice(0, 12)}\u2026 matches the pin. Extracting\u2026`);\n // Windows' own tar (bsdtar, System32) \u2014 Git's GNU tar, often first on PATH, reads the\n // \"C:\" of a path as a remote host.\n const tar = process.platform === 'win32'\n ? join(process.env['SystemRoot'] ?? 'C:\\\\Windows', 'System32', 'tar.exe') : 'tar';\n execFileSync(tar, ['-xzf', tarballPath, '-C', partial], {\n windowsHide: true,\n stdio: ['ignore', 'ignore', 'pipe'],\n });\n // The tarball has done its job and is 216 MB; the extraction is what runs.\n rmSync(tarballPath, { force: true });\n if (existsSync(join(dir, RELEASE_RECORD))) {\n // Another process won the same race. A release is immutable, so its\n // directory is ours too \u2014 take it and drop this copy.\n rmSync(partial, { recursive: true, force: true });\n } else {\n rmSync(dir, { recursive: true, force: true });\n renameSync(partial, dir);\n }\n io.log(`Workbench installed at ${dir}.`);\n } catch (error) {\n rmSync(partial, { recursive: true, force: true });\n throw error;\n }\n}\n\n/** One asset's bytes as text \u2014 for `BUILD.json`, which is a kilobyte. */\nasync function downloadAssetText(asset: ReleaseAsset, token: string | null): Promise<string> {\n const url = assetUrl(asset);\n const response = await downloadOperation('BUILD.json request', url, token,\n () => fetch(url, { headers: { ...apiHeaders(token), Accept: 'application/octet-stream' } }));\n if (!response.ok)\n throw new Error(\n `${asset.name} of ${RELEASE_REPO} answered ${response.status} ${response.statusText}.`,\n );\n return await downloadOperation('BUILD.json response', url, token, () => response.text());\n}\n\n/**\n * One asset's bytes to a file, hashing them ON THE WAY THROUGH \u2014 a 216 MB\n * tarball is not read twice, and it is never held in memory.\n */\nasync function downloadAsset(\n asset: ReleaseAsset,\n token: string | null,\n destination: string,\n onProgress: (received: number) => void,\n): Promise<string> {\n const url = assetUrl(asset);\n const response = await downloadOperation('archive request', url, token,\n () => fetch(url, { headers: { ...apiHeaders(token), Accept: 'application/octet-stream' } }));\n if (!response.ok || response.body === null)\n throw new Error(\n `${asset.name} of ${RELEASE_REPO} answered ${response.status} ${response.statusText}.`,\n );\n const hash = createHash('sha256');\n let received = 0;\n await downloadOperation('archive transfer', url, token, () => pipeline(\n Readable.fromWeb(response.body as never),\n async function* (source: AsyncIterable<Buffer>) {\n for await (const chunk of source) {\n hash.update(chunk);\n received += chunk.length;\n onProgress(received);\n yield chunk;\n }\n },\n createWriteStream(destination),\n ));\n return hash.digest('hex');\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["error"]
7
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@volter/live",
3
3
  "author": "Volter AI, Inc.",
4
- "version": "0.5.211",
4
+ "version": "0.5.213",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -24,14 +24,50 @@
24
24
  ".": {
25
25
  "types": "./dist/index.d.ts",
26
26
  "default": "./dist/index.js"
27
+ },
28
+ "./client": {
29
+ "types": "./dist/client.d.ts",
30
+ "default": "./dist/client.js"
31
+ },
32
+ "./asset-library": {
33
+ "types": "./dist/asset-library.d.ts",
34
+ "default": "./dist/asset-library.js"
35
+ },
36
+ "./registry-format": {
37
+ "types": "./dist/registry-format.d.ts",
38
+ "default": "./dist/registry-format.js"
39
+ },
40
+ "./discovery": {
41
+ "types": "./dist/discovery.d.ts",
42
+ "default": "./dist/discovery.js"
43
+ },
44
+ "./product-locator": {
45
+ "types": "./dist/product-locator.d.ts",
46
+ "default": "./dist/product-locator.js"
47
+ },
48
+ "./workbench-locator": {
49
+ "types": "./dist/workbench-locator.d.ts",
50
+ "default": "./dist/workbench-locator.js"
51
+ },
52
+ "./installed-package": {
53
+ "types": "./dist/installed-package.d.ts",
54
+ "default": "./dist/installed-package.js"
55
+ },
56
+ "./volter-manifest": {
57
+ "types": "./dist/volter-manifest.d.ts",
58
+ "default": "./dist/volter-manifest.js"
59
+ },
60
+ "./product-create": {
61
+ "types": "./dist/product-create.d.ts",
62
+ "default": "./dist/product-create.js"
27
63
  }
28
64
  },
29
65
  "engines": {
30
66
  "node": ">=22"
31
67
  },
32
68
  "dependencies": {
33
- "@volter/sdk": "0.5.211",
34
- "@volter/project": "0.5.211",
69
+ "@volter/sdk": "0.5.213",
70
+ "@volter/project": "0.5.213",
35
71
  "undici": "^7.28.0"
36
72
  },
37
73
  "devDependencies": {