usebeeline 0.1.180 → 0.1.183
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/dist/usebeeline.mjs +878 -638
- package/package.json +1 -1
package/dist/usebeeline.mjs
CHANGED
|
@@ -173,6 +173,121 @@ var init_lifecycle_test_guard = __esm({
|
|
|
173
173
|
}
|
|
174
174
|
});
|
|
175
175
|
|
|
176
|
+
// apps/body/dist/self-update-manifest.js
|
|
177
|
+
function resolveManifestUrl(env = process.env) {
|
|
178
|
+
const override = env.BEELINE_UPDATE_MANIFEST_URL?.trim();
|
|
179
|
+
if (override)
|
|
180
|
+
return override;
|
|
181
|
+
const channel = env.BEELINE_RELEASE_CHANNEL?.trim() || "latest";
|
|
182
|
+
if (!["latest", "next"].includes(channel))
|
|
183
|
+
throw new Error(`invalid helper release channel: ${channel}`);
|
|
184
|
+
return channel === "next" ? "https://usebeeline.app/dl/next/manifest.json" : DEFAULT_UPDATE_MANIFEST_URL;
|
|
185
|
+
}
|
|
186
|
+
function parseUpdateManifest(raw, platform) {
|
|
187
|
+
let parsed;
|
|
188
|
+
try {
|
|
189
|
+
parsed = JSON.parse(raw);
|
|
190
|
+
} catch (error) {
|
|
191
|
+
throw new Error(`update manifest is not valid JSON: ${error instanceof Error ? error.message : String(error)}`);
|
|
192
|
+
}
|
|
193
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
194
|
+
throw new Error("update manifest is not an object");
|
|
195
|
+
}
|
|
196
|
+
const manifest = parsed;
|
|
197
|
+
const bundles = manifest.bundles;
|
|
198
|
+
if (typeof bundles !== "object" || bundles === null) {
|
|
199
|
+
throw new Error("update manifest has no bundles table");
|
|
200
|
+
}
|
|
201
|
+
const entry = bundles[platform];
|
|
202
|
+
if (typeof entry !== "object" || entry === null) {
|
|
203
|
+
throw new Error(`update manifest has no bundle for platform ${platform}`);
|
|
204
|
+
}
|
|
205
|
+
const bundle = entry;
|
|
206
|
+
const file = typeof bundle.file === "string" ? bundle.file : "";
|
|
207
|
+
const sha256 = typeof bundle.sha256 === "string" ? bundle.sha256.toLowerCase() : "";
|
|
208
|
+
if (!file || !/^[a-z0-9][a-z0-9._-]*$/i.test(file)) {
|
|
209
|
+
throw new Error(`update manifest names an unusable bundle file: ${JSON.stringify(bundle.file)}`);
|
|
210
|
+
}
|
|
211
|
+
if (!/^[0-9a-f]{64}$/.test(sha256)) {
|
|
212
|
+
throw new Error(`update manifest carries no usable sha256 for ${platform}`);
|
|
213
|
+
}
|
|
214
|
+
const sourceCommit = typeof bundle.commit === "string" && bundle.commit ? bundle.commit : typeof manifest.sourceCommit === "string" ? manifest.sourceCommit : void 0;
|
|
215
|
+
const version = typeof bundle.version === "string" && bundle.version ? bundle.version : typeof manifest.version === "string" ? manifest.version : void 0;
|
|
216
|
+
return {
|
|
217
|
+
schemaVersion: typeof manifest.schemaVersion === "number" ? manifest.schemaVersion : 1,
|
|
218
|
+
...sourceCommit ? { sourceCommit } : {},
|
|
219
|
+
...version ? { version } : {},
|
|
220
|
+
bundles,
|
|
221
|
+
bundle: {
|
|
222
|
+
file,
|
|
223
|
+
sha256,
|
|
224
|
+
...typeof bundle.bytes === "number" ? { bytes: bundle.bytes } : {},
|
|
225
|
+
...sourceCommit ? { commit: sourceCommit } : {},
|
|
226
|
+
...version ? { version } : {},
|
|
227
|
+
...typeof bundle.node === "string" ? { node: bundle.node } : {}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
function compareBundleIdentity(installed, published) {
|
|
232
|
+
if (installed?.commit && published.commit) {
|
|
233
|
+
if (installed.commit === published.commit)
|
|
234
|
+
return { kind: "current" };
|
|
235
|
+
return { kind: "update-available", published };
|
|
236
|
+
}
|
|
237
|
+
if (installed?.version && published.version) {
|
|
238
|
+
const ordering = compareVersions(installed.version, published.version);
|
|
239
|
+
if (ordering > 0)
|
|
240
|
+
return { kind: "current" };
|
|
241
|
+
if (ordering < 0)
|
|
242
|
+
return { kind: "update-available", published };
|
|
243
|
+
if (installed.commit && published.commit)
|
|
244
|
+
return { kind: "current" };
|
|
245
|
+
return { kind: "current" };
|
|
246
|
+
}
|
|
247
|
+
const missing = [
|
|
248
|
+
...installed?.commit || installed?.version ? [] : ["installed identity"],
|
|
249
|
+
...published.commit || published.version ? [] : ["published identity"]
|
|
250
|
+
];
|
|
251
|
+
return {
|
|
252
|
+
kind: "indeterminate",
|
|
253
|
+
reason: `cannot compare: ${missing.join(" and ")} unknown`
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
function compareVersions(a, b) {
|
|
257
|
+
const parse = (value) => {
|
|
258
|
+
const parts = value.split(/[.+-]/).filter(Boolean);
|
|
259
|
+
if (parts.length === 0)
|
|
260
|
+
return void 0;
|
|
261
|
+
return parts.map((part) => /^\d+$/.test(part) ? Number(part) : part);
|
|
262
|
+
};
|
|
263
|
+
const left = parse(a);
|
|
264
|
+
const right = parse(b);
|
|
265
|
+
if (!left || !right)
|
|
266
|
+
return a === b ? 0 : a > b ? 1 : -1;
|
|
267
|
+
const length = Math.max(left.length, right.length);
|
|
268
|
+
for (let index = 0; index < length; index += 1) {
|
|
269
|
+
const l = left[index];
|
|
270
|
+
const r = right[index];
|
|
271
|
+
if (l === void 0)
|
|
272
|
+
return -1;
|
|
273
|
+
if (r === void 0)
|
|
274
|
+
return 1;
|
|
275
|
+
if (l === r)
|
|
276
|
+
continue;
|
|
277
|
+
if (typeof l === "number" && typeof r === "number")
|
|
278
|
+
return l > r ? 1 : -1;
|
|
279
|
+
return String(l) > String(r) ? 1 : -1;
|
|
280
|
+
}
|
|
281
|
+
return 0;
|
|
282
|
+
}
|
|
283
|
+
var DEFAULT_UPDATE_MANIFEST_URL;
|
|
284
|
+
var init_self_update_manifest = __esm({
|
|
285
|
+
"apps/body/dist/self-update-manifest.js"() {
|
|
286
|
+
"use strict";
|
|
287
|
+
DEFAULT_UPDATE_MANIFEST_URL = "https://usebeeline.app/dl/manifest.json";
|
|
288
|
+
}
|
|
289
|
+
});
|
|
290
|
+
|
|
176
291
|
// apps/body/dist/trusty-squire-storage.js
|
|
177
292
|
import { homedir as homedir2 } from "node:os";
|
|
178
293
|
import { isAbsolute, resolve as resolve4 } from "node:path";
|
|
@@ -328,151 +443,250 @@ visit(root)
|
|
|
328
443
|
}
|
|
329
444
|
});
|
|
330
445
|
|
|
331
|
-
// apps/body/dist/self-update-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
let
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
if (
|
|
344
|
-
|
|
446
|
+
// apps/body/dist/self-update-activate-release.js
|
|
447
|
+
import { join, dirname as dirname4, resolve as resolve6 } from "node:path";
|
|
448
|
+
import { access, mkdir as mkdir3, rename as rename2, rm as rm3, symlink, copyFile, readFile as readFile2, readdir as readdir3, lstat as lstat3 } from "node:fs/promises";
|
|
449
|
+
import { constants as fsConstants } from "node:fs";
|
|
450
|
+
async function activateRelease(layout, releaseId, options = {}) {
|
|
451
|
+
assertInstallTestIsolation(layout);
|
|
452
|
+
let releaseDir = join(layout.releasesRoot, releaseId);
|
|
453
|
+
let previousReleaseId = await activeReleaseId(layout);
|
|
454
|
+
await access(join(releaseDir, BUNDLE_ENTRYPOINT), fsConstants.F_OK);
|
|
455
|
+
await mkdir3(layout.releasesRoot, { recursive: true });
|
|
456
|
+
await mkdir3(layout.binDir, { recursive: true });
|
|
457
|
+
const kind = await pathKind(layout.libDir);
|
|
458
|
+
if (kind === "directory") {
|
|
459
|
+
const legacyIdentity = await readBundleJson(layout.libDir);
|
|
460
|
+
const legacyId = sanitizeReleaseId(legacyIdentity?.commit ?? legacyIdentity?.version ?? `legacy-${Date.now()}`);
|
|
461
|
+
const legacyDir = join(layout.releasesRoot, legacyId);
|
|
462
|
+
try {
|
|
463
|
+
await access(legacyDir, fsConstants.F_OK);
|
|
464
|
+
const preservedId = `${legacyId}-${Date.now()}`;
|
|
465
|
+
await rename2(layout.libDir, join(layout.releasesRoot, preservedId));
|
|
466
|
+
await normalizeLegacyBundleShape(join(layout.releasesRoot, preservedId));
|
|
467
|
+
previousReleaseId = preservedId;
|
|
468
|
+
} catch {
|
|
469
|
+
await rename2(layout.libDir, legacyDir);
|
|
470
|
+
await normalizeLegacyBundleShape(legacyDir);
|
|
471
|
+
previousReleaseId = legacyId;
|
|
472
|
+
}
|
|
345
473
|
}
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
474
|
+
const tempLink = `${layout.libDir}.new-${process.pid}`;
|
|
475
|
+
await rm3(tempLink, { force: true });
|
|
476
|
+
await symlink(join("beeline-releases", releaseId), tempLink);
|
|
477
|
+
await rename2(tempLink, layout.libDir);
|
|
478
|
+
await fsyncDir(dirname4(layout.libDir));
|
|
479
|
+
await installRecoveryLauncher(layout, releaseDir);
|
|
480
|
+
await writeBinForwarders(layout, releaseDir);
|
|
481
|
+
const state = await readUpdateState(layout);
|
|
482
|
+
await writeUpdateState(layout, {
|
|
483
|
+
...state,
|
|
484
|
+
stagedReleaseId: void 0,
|
|
485
|
+
previousReleaseId: previousReleaseId && previousReleaseId !== releaseId ? previousReleaseId : state.previousReleaseId
|
|
486
|
+
});
|
|
487
|
+
if (!options.deferPruning)
|
|
488
|
+
await pruneHelperReleases(layout);
|
|
489
|
+
}
|
|
490
|
+
async function installRecoveryLauncher(layout, releaseDir) {
|
|
491
|
+
const bootstrap = join(releaseDir, "lib/beeline/recovery-cli.mjs");
|
|
492
|
+
if (await access(bootstrap).then(() => true, () => false)) {
|
|
493
|
+
const stable = resolve6(layout.libDir, "../beeline-bootstrap.mjs");
|
|
494
|
+
const temporary = `${stable}.${process.pid}.tmp`;
|
|
495
|
+
await copyFile(bootstrap, temporary);
|
|
496
|
+
await rename2(temporary, stable);
|
|
497
|
+
await replaceFile(resolve6(layout.libDir, "../beeline-node-path"), `${process.execPath}
|
|
498
|
+
`, 384);
|
|
350
499
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
500
|
+
}
|
|
501
|
+
async function normalizeLegacyBundleShape(bundleDir) {
|
|
502
|
+
const innerLib = join(bundleDir, "lib", "beeline");
|
|
503
|
+
let anyFlat = false;
|
|
504
|
+
for (const name of LEGACY_FLAT_BUNDLE_FILES) {
|
|
505
|
+
try {
|
|
506
|
+
await access(join(bundleDir, name), fsConstants.F_OK);
|
|
507
|
+
anyFlat = true;
|
|
508
|
+
break;
|
|
509
|
+
} catch {
|
|
510
|
+
}
|
|
354
511
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
512
|
+
if (!anyFlat)
|
|
513
|
+
return;
|
|
514
|
+
await mkdir3(innerLib, { recursive: true });
|
|
515
|
+
for (const name of LEGACY_FLAT_BUNDLE_FILES) {
|
|
516
|
+
try {
|
|
517
|
+
await access(join(innerLib, name), fsConstants.F_OK);
|
|
518
|
+
continue;
|
|
519
|
+
} catch {
|
|
520
|
+
}
|
|
521
|
+
await rename2(join(bundleDir, name), join(innerLib, name)).catch(() => void 0);
|
|
360
522
|
}
|
|
361
|
-
|
|
362
|
-
|
|
523
|
+
}
|
|
524
|
+
async function writeBinForwarders(layout, activeBundleRoot) {
|
|
525
|
+
const entries = [
|
|
526
|
+
...FORWARDER_TOOLS.map((tool) => [tool, tool]),
|
|
527
|
+
...Object.entries(FORWARDER_ALIASES).map(([alias, tool]) => [alias, tool])
|
|
528
|
+
];
|
|
529
|
+
for (const [name, tool] of entries) {
|
|
530
|
+
const target = join(activeBundleRoot, "bin", tool);
|
|
531
|
+
try {
|
|
532
|
+
await access(target, fsConstants.X_OK);
|
|
533
|
+
} catch {
|
|
534
|
+
continue;
|
|
535
|
+
}
|
|
536
|
+
const independent = await access(resolve6(layout.libDir, "../beeline-bootstrap.mjs")).then(() => true, () => false);
|
|
537
|
+
await replaceFile(join(layout.binDir, name), independent || tool !== "beeline" ? forwarderScript(tool) : forwarderScript("legacy-beeline").replace("/bin/legacy-beeline", "/bin/beeline"), 493);
|
|
363
538
|
}
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
...version ? { version } : {},
|
|
377
|
-
...typeof bundle.node === "string" ? { node: bundle.node } : {}
|
|
539
|
+
}
|
|
540
|
+
async function repairInstallForwarders(layout, opts = {}) {
|
|
541
|
+
assertInstallTestIsolation(layout);
|
|
542
|
+
if (await pathKind(layout.libDir) !== "symlink")
|
|
543
|
+
return false;
|
|
544
|
+
await installRecoveryLauncher(layout, layout.libDir);
|
|
545
|
+
const forwarderHealthy = async (name, tool) => {
|
|
546
|
+
let current;
|
|
547
|
+
try {
|
|
548
|
+
current = await readFile2(join(layout.binDir, name), "utf8");
|
|
549
|
+
} catch {
|
|
550
|
+
current = void 0;
|
|
378
551
|
}
|
|
552
|
+
const independent = await access(resolve6(layout.libDir, "../beeline-bootstrap.mjs")).then(() => true, () => false);
|
|
553
|
+
const expected = independent || tool !== "beeline" ? forwarderScript(tool) : forwarderScript("legacy-beeline").replace("/bin/legacy-beeline", "/bin/beeline");
|
|
554
|
+
return current === expected;
|
|
379
555
|
};
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
return { kind: "current" };
|
|
385
|
-
return { kind: "update-available", published };
|
|
386
|
-
}
|
|
387
|
-
if (installed?.version && published.version) {
|
|
388
|
-
const ordering = compareVersions(installed.version, published.version);
|
|
389
|
-
if (ordering > 0)
|
|
390
|
-
return { kind: "current" };
|
|
391
|
-
if (ordering < 0)
|
|
392
|
-
return { kind: "update-available", published };
|
|
393
|
-
if (installed.commit && published.commit)
|
|
394
|
-
return { kind: "current" };
|
|
395
|
-
return { kind: "current" };
|
|
556
|
+
let healthy = await forwarderHealthy("beeline", "beeline");
|
|
557
|
+
for (const [alias, tool] of Object.entries(FORWARDER_ALIASES)) {
|
|
558
|
+
if (!await forwarderHealthy(alias, tool))
|
|
559
|
+
healthy = false;
|
|
396
560
|
}
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
reason: `cannot compare: ${missing.join(" and ")} unknown`
|
|
404
|
-
};
|
|
561
|
+
if (healthy)
|
|
562
|
+
return false;
|
|
563
|
+
await mkdir3(layout.binDir, { recursive: true });
|
|
564
|
+
await writeBinForwarders(layout, layout.libDir);
|
|
565
|
+
opts.logger?.(`[body] self-update: repaired <prefix>/bin forwarders to follow the active-bundle anchor (${layout.libDir})`);
|
|
566
|
+
return true;
|
|
405
567
|
}
|
|
406
|
-
function
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
568
|
+
function describeIdentity(identity) {
|
|
569
|
+
if (!identity)
|
|
570
|
+
return "unknown";
|
|
571
|
+
const parts = [];
|
|
572
|
+
if (identity.version)
|
|
573
|
+
parts.push(identity.version);
|
|
574
|
+
if (identity.commit)
|
|
575
|
+
parts.push(identity.commit.slice(0, 12));
|
|
576
|
+
return parts.join(" ") || "unknown";
|
|
577
|
+
}
|
|
578
|
+
async function pruneHelperReleases(layout, loadedRelease) {
|
|
579
|
+
assertInstallTestIsolation(layout);
|
|
580
|
+
if (!await ordinaryDirectory(layout.releasesRoot))
|
|
581
|
+
return [];
|
|
582
|
+
const active = await activeReleaseId(layout);
|
|
583
|
+
if (!active)
|
|
584
|
+
return [];
|
|
585
|
+
const state = await readUpdateState(layout);
|
|
586
|
+
const candidates = [];
|
|
587
|
+
for (const entry of await readdir3(layout.releasesRoot, { withFileTypes: true })) {
|
|
588
|
+
if (entry.name.startsWith("."))
|
|
589
|
+
continue;
|
|
590
|
+
if (entry.isSymbolicLink()) {
|
|
591
|
+
if (![active, state.previousReleaseId, state.stagedReleaseId, loadedRelease].includes(entry.name))
|
|
592
|
+
await rm3(join(layout.releasesRoot, entry.name), { force: true });
|
|
426
593
|
continue;
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
594
|
+
}
|
|
595
|
+
if (!entry.isDirectory())
|
|
596
|
+
continue;
|
|
597
|
+
const path = join(layout.releasesRoot, entry.name);
|
|
598
|
+
if (!await ordinaryDirectory(path))
|
|
599
|
+
continue;
|
|
600
|
+
candidates.push({
|
|
601
|
+
id: entry.name,
|
|
602
|
+
modified: (await lstat3(path)).mtimeMs,
|
|
603
|
+
bootable: await access(join(path, BUNDLE_ENTRYPOINT)).then(() => true, () => false)
|
|
604
|
+
});
|
|
430
605
|
}
|
|
431
|
-
|
|
606
|
+
const recordedPrevious = candidates.find((entry) => entry.id === state.previousReleaseId && entry.id !== active && entry.bootable)?.id;
|
|
607
|
+
const previous = recordedPrevious ?? candidates.filter((entry) => entry.bootable && entry.id !== active && entry.id !== state.stagedReleaseId).sort((a, b) => b.modified - a.modified)[0]?.id;
|
|
608
|
+
const keep = /* @__PURE__ */ new Set([active, previous, loadedRelease, state.stagedReleaseId]);
|
|
609
|
+
const removed = [];
|
|
610
|
+
for (const entry of candidates) {
|
|
611
|
+
if (keep.has(entry.id))
|
|
612
|
+
continue;
|
|
613
|
+
await removeStoragePath(join(layout.releasesRoot, entry.id));
|
|
614
|
+
removed.push(entry.id);
|
|
615
|
+
}
|
|
616
|
+
if (previous !== state.previousReleaseId)
|
|
617
|
+
await writeUpdateState(layout, { ...state, previousReleaseId: previous });
|
|
618
|
+
return removed;
|
|
432
619
|
}
|
|
433
|
-
var
|
|
434
|
-
var
|
|
435
|
-
"apps/body/dist/self-update-
|
|
620
|
+
var LEGACY_FLAT_BUNDLE_FILES;
|
|
621
|
+
var init_self_update_activate_release = __esm({
|
|
622
|
+
"apps/body/dist/self-update-activate-release.js"() {
|
|
436
623
|
"use strict";
|
|
437
|
-
|
|
624
|
+
init_lifecycle_test_guard();
|
|
625
|
+
init_storage_filesystem();
|
|
626
|
+
init_self_update();
|
|
627
|
+
LEGACY_FLAT_BUNDLE_FILES = [
|
|
628
|
+
"beeline-cli.mjs",
|
|
629
|
+
"beeline-readonly-mcp.mjs",
|
|
630
|
+
"pi-mcp-adapter.mjs",
|
|
631
|
+
"bundle.json"
|
|
632
|
+
];
|
|
438
633
|
}
|
|
439
634
|
});
|
|
440
635
|
|
|
441
636
|
// apps/body/dist/self-update.js
|
|
442
637
|
var self_update_exports = {};
|
|
443
638
|
__export(self_update_exports, {
|
|
639
|
+
BUNDLE_ENTRYPOINT: () => BUNDLE_ENTRYPOINT,
|
|
640
|
+
CODEGRAPH_ENTRYPOINT: () => CODEGRAPH_ENTRYPOINT,
|
|
641
|
+
FORWARDER_ALIASES: () => FORWARDER_ALIASES,
|
|
642
|
+
FORWARDER_TOOLS: () => FORWARDER_TOOLS,
|
|
643
|
+
PI_MCP_ADAPTER_ENTRYPOINT: () => PI_MCP_ADAPTER_ENTRYPOINT,
|
|
644
|
+
RELEASES_SEGMENT: () => RELEASES_SEGMENT,
|
|
444
645
|
STAGED_NODE_PATH_FILE: () => STAGED_NODE_PATH_FILE,
|
|
445
646
|
SelfUpdateManager: () => SelfUpdateManager,
|
|
446
647
|
activateRelease: () => activateRelease,
|
|
447
648
|
activeReleaseId: () => activeReleaseId,
|
|
649
|
+
anchorLayout: () => anchorLayout,
|
|
448
650
|
archiveUrlFor: () => archiveUrlFor,
|
|
449
651
|
beelineInstallLayout: () => beelineInstallLayout,
|
|
652
|
+
bundleJsonCandidates: () => bundleJsonCandidates,
|
|
450
653
|
defaultBeelineInstallLayout: () => defaultBeelineInstallLayout,
|
|
451
654
|
describeIdentity: () => describeIdentity,
|
|
452
655
|
discoveredBeelineInstallLayout: () => discoveredBeelineInstallLayout,
|
|
656
|
+
entrypointCandidates: () => entrypointCandidates,
|
|
657
|
+
fetchText: () => fetchText,
|
|
658
|
+
forwarderScript: () => forwarderScript,
|
|
659
|
+
fsyncDir: () => fsyncDir,
|
|
453
660
|
hostPlatformKey: () => hostPlatformKey,
|
|
454
661
|
nodeVersionAtLeast: () => nodeVersionAtLeast,
|
|
455
662
|
normalizeLegacyBundleShape: () => normalizeLegacyBundleShape,
|
|
663
|
+
pathKind: () => pathKind,
|
|
456
664
|
prepareLatestRelease: () => prepareLatestRelease,
|
|
457
665
|
pruneHelperReleases: () => pruneHelperReleases,
|
|
458
666
|
readBundleEngineMinimum: () => readBundleEngineMinimum,
|
|
667
|
+
readBundleJson: () => readBundleJson,
|
|
459
668
|
readInstalledBundleIdentity: () => readInstalledBundleIdentity,
|
|
460
669
|
readUpdateState: () => readUpdateState,
|
|
461
670
|
releaseIdFromPath: () => releaseIdFromPath,
|
|
462
671
|
repairInstallForwarders: () => repairInstallForwarders,
|
|
672
|
+
replaceFile: () => replaceFile,
|
|
673
|
+
requiredBundlePaths: () => requiredBundlePaths,
|
|
463
674
|
resolveBundleEntrypoint: () => resolveBundleEntrypoint,
|
|
675
|
+
run: () => run,
|
|
464
676
|
runningReleaseId: () => runningReleaseId,
|
|
677
|
+
sanitizeReleaseId: () => sanitizeReleaseId,
|
|
465
678
|
stageRelease: () => stageRelease,
|
|
679
|
+
updateStatePath: () => updateStatePath,
|
|
466
680
|
writeUpdateState: () => writeUpdateState
|
|
467
681
|
});
|
|
468
|
-
import {
|
|
469
|
-
import {
|
|
470
|
-
import { access, chmod as chmod2, copyFile, lstat as lstat3, mkdir as mkdir3, open, readFile as readFile2, readdir as readdir3, rename as rename2, rm as rm3, symlink, writeFile as writeFile2 } from "node:fs/promises";
|
|
471
|
-
import { spawn as spawn2 } from "node:child_process";
|
|
682
|
+
import { readFile as readFile3, mkdir as mkdir4, open, rename as rename3, lstat as lstat4, access as access2, writeFile as writeFile2, rm as rm4, chmod as chmod2 } from "node:fs/promises";
|
|
683
|
+
import { join as join2, resolve as resolve7, dirname as dirname5 } from "node:path";
|
|
472
684
|
import { homedir as homedir3 } from "node:os";
|
|
473
|
-
import {
|
|
685
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
686
|
+
import { constants as fsConstants2 } from "node:fs";
|
|
687
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
474
688
|
function anchorLayout(rawLibDir) {
|
|
475
|
-
const libDir =
|
|
689
|
+
const libDir = resolve7(rawLibDir);
|
|
476
690
|
const segments = libDir.split(/[/\\]/);
|
|
477
691
|
const idx = segments.lastIndexOf(RELEASES_SEGMENT);
|
|
478
692
|
if (idx >= 2 && segments[idx - 1] === "lib") {
|
|
@@ -488,9 +702,9 @@ function anchorLayout(rawLibDir) {
|
|
|
488
702
|
// prefix's bin, NOT <prefix>/lib/bin — deriving it one level up was the
|
|
489
703
|
// defect that made activateRelease write its stable forwarders where
|
|
490
704
|
// nothing executed them, leaving stale raw wrappers in <prefix>/bin.
|
|
491
|
-
binDir:
|
|
705
|
+
binDir: resolve7(libDir, "../../bin"),
|
|
492
706
|
libDir,
|
|
493
|
-
releasesRoot:
|
|
707
|
+
releasesRoot: resolve7(libDir, `../${RELEASES_SEGMENT}`)
|
|
494
708
|
};
|
|
495
709
|
}
|
|
496
710
|
function beelineInstallLayout(env = process.env) {
|
|
@@ -502,18 +716,18 @@ function beelineInstallLayout(env = process.env) {
|
|
|
502
716
|
function releaseIdFromPath(path) {
|
|
503
717
|
if (!path?.trim())
|
|
504
718
|
return void 0;
|
|
505
|
-
const segments =
|
|
719
|
+
const segments = resolve7(path.trim()).split(/[/\\]/);
|
|
506
720
|
const idx = segments.lastIndexOf(RELEASES_SEGMENT);
|
|
507
721
|
const id = idx >= 0 ? segments[idx + 1] : void 0;
|
|
508
722
|
return id ? sanitizeReleaseId(id) : void 0;
|
|
509
723
|
}
|
|
510
724
|
function runningReleaseId(layout, env = process.env, invocationPath = process.argv[1]) {
|
|
511
|
-
const releasesRoot =
|
|
512
|
-
const anchor =
|
|
725
|
+
const releasesRoot = resolve7(layout.releasesRoot);
|
|
726
|
+
const anchor = resolve7(layout.libDir);
|
|
513
727
|
for (const raw of [env.BEELINE_LIB_DIR, invocationPath]) {
|
|
514
728
|
if (!raw?.trim())
|
|
515
729
|
continue;
|
|
516
|
-
const resolved =
|
|
730
|
+
const resolved = resolve7(raw.trim());
|
|
517
731
|
if (resolved !== anchor && !resolved.startsWith(`${releasesRoot}/`))
|
|
518
732
|
continue;
|
|
519
733
|
const id = releaseIdFromPath(resolved);
|
|
@@ -524,7 +738,7 @@ function runningReleaseId(layout, env = process.env, invocationPath = process.ar
|
|
|
524
738
|
}
|
|
525
739
|
function defaultBeelineInstallLayout(env = process.env) {
|
|
526
740
|
const home2 = env.HOME?.trim() || homedir3();
|
|
527
|
-
return anchorLayout(
|
|
741
|
+
return anchorLayout(resolve7(home2, ".local", "lib", "beeline"));
|
|
528
742
|
}
|
|
529
743
|
function discoveredBeelineInstallLayout(env = process.env) {
|
|
530
744
|
const explicitAnchor = env.BEELINE_INSTALL_LIB_DIR?.trim();
|
|
@@ -532,7 +746,7 @@ function discoveredBeelineInstallLayout(env = process.env) {
|
|
|
532
746
|
return anchorLayout(explicitAnchor);
|
|
533
747
|
const explicitBinDir = env.BEELINE_INSTALL_DIR?.trim();
|
|
534
748
|
if (explicitBinDir)
|
|
535
|
-
return anchorLayout(
|
|
749
|
+
return anchorLayout(resolve7(dirname5(resolve7(explicitBinDir)), "lib", "beeline"));
|
|
536
750
|
return defaultBeelineInstallLayout(env);
|
|
537
751
|
}
|
|
538
752
|
function hostPlatformKey() {
|
|
@@ -543,13 +757,13 @@ function hostPlatformKey() {
|
|
|
543
757
|
return `${os}-${arch}`;
|
|
544
758
|
}
|
|
545
759
|
function bundleJsonCandidates(bundleDir) {
|
|
546
|
-
return [
|
|
760
|
+
return [join2(bundleDir, "lib", "beeline", "bundle.json"), join2(bundleDir, "bundle.json")];
|
|
547
761
|
}
|
|
548
762
|
async function readBundleJson(bundleDir) {
|
|
549
763
|
let raw;
|
|
550
764
|
for (const candidate of bundleJsonCandidates(bundleDir)) {
|
|
551
765
|
try {
|
|
552
|
-
raw = await
|
|
766
|
+
raw = await readFile3(candidate, "utf8");
|
|
553
767
|
break;
|
|
554
768
|
} catch {
|
|
555
769
|
}
|
|
@@ -569,7 +783,7 @@ async function readBundleJson(bundleDir) {
|
|
|
569
783
|
async function readBundleEngineMinimum(bundleDir) {
|
|
570
784
|
for (const candidate of bundleJsonCandidates(bundleDir)) {
|
|
571
785
|
try {
|
|
572
|
-
const parsed = JSON.parse(await
|
|
786
|
+
const parsed = JSON.parse(await readFile3(candidate, "utf8"));
|
|
573
787
|
const match = /^>=(\d+)\.(\d+)\.(\d+)$/.exec(parsed.node ?? "");
|
|
574
788
|
if (match)
|
|
575
789
|
return [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
@@ -589,17 +803,17 @@ function nodeVersionAtLeast(version, minimum) {
|
|
|
589
803
|
return true;
|
|
590
804
|
}
|
|
591
805
|
function updateStatePath(layout) {
|
|
592
|
-
return
|
|
806
|
+
return join2(layout.releasesRoot, ".state", "update-state.json");
|
|
593
807
|
}
|
|
594
808
|
async function readUpdateState(layout) {
|
|
595
809
|
try {
|
|
596
|
-
return JSON.parse(await
|
|
810
|
+
return JSON.parse(await readFile3(updateStatePath(layout), "utf8"));
|
|
597
811
|
} catch {
|
|
598
812
|
return {};
|
|
599
813
|
}
|
|
600
814
|
}
|
|
601
815
|
async function writeUpdateState(layout, state) {
|
|
602
|
-
await
|
|
816
|
+
await mkdir4(join2(layout.releasesRoot, ".state"), { recursive: true });
|
|
603
817
|
const path = updateStatePath(layout);
|
|
604
818
|
const temporary = `${path}.${process.pid}.tmp`;
|
|
605
819
|
const handle = await open(temporary, "w", 384);
|
|
@@ -610,8 +824,8 @@ async function writeUpdateState(layout, state) {
|
|
|
610
824
|
} finally {
|
|
611
825
|
await handle.close();
|
|
612
826
|
}
|
|
613
|
-
await
|
|
614
|
-
await fsyncDir(
|
|
827
|
+
await rename3(temporary, path);
|
|
828
|
+
await fsyncDir(dirname5(path));
|
|
615
829
|
}
|
|
616
830
|
async function readInstalledBundleIdentity(layout, _state = {}) {
|
|
617
831
|
const fromDisk = await readBundleJson(layout.libDir);
|
|
@@ -625,7 +839,7 @@ function sanitizeReleaseId(id) {
|
|
|
625
839
|
}
|
|
626
840
|
async function pathKind(path) {
|
|
627
841
|
try {
|
|
628
|
-
const info = await
|
|
842
|
+
const info = await lstat4(path);
|
|
629
843
|
if (info.isSymbolicLink())
|
|
630
844
|
return "symlink";
|
|
631
845
|
return info.isDirectory() ? "directory" : "missing";
|
|
@@ -688,12 +902,12 @@ function run(command2, args, _timeoutMs) {
|
|
|
688
902
|
});
|
|
689
903
|
}
|
|
690
904
|
function entrypointCandidates(bundleDir) {
|
|
691
|
-
return [
|
|
905
|
+
return [join2(bundleDir, BUNDLE_ENTRYPOINT), join2(bundleDir, "beeline-cli.mjs")];
|
|
692
906
|
}
|
|
693
907
|
async function resolveBundleEntrypoint(bundleDir) {
|
|
694
908
|
for (const candidate of entrypointCandidates(bundleDir)) {
|
|
695
909
|
try {
|
|
696
|
-
await
|
|
910
|
+
await access2(candidate, fsConstants2.F_OK);
|
|
697
911
|
return candidate;
|
|
698
912
|
} catch {
|
|
699
913
|
}
|
|
@@ -717,17 +931,17 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
717
931
|
});
|
|
718
932
|
const log2 = opts.logger ?? ((line) => console.log(`[body] self-update: ${line}`));
|
|
719
933
|
let releaseId = sanitizeReleaseId((published.commit ?? published.version ?? `release-${Date.now()}`) + (opts.force ? `-repair-${Date.now()}` : ""));
|
|
720
|
-
let releaseDir =
|
|
721
|
-
let okMarker =
|
|
934
|
+
let releaseDir = join2(layout.releasesRoot, releaseId);
|
|
935
|
+
let okMarker = join2(releaseDir, ".stage-ok");
|
|
722
936
|
let previouslyVerified = false;
|
|
723
937
|
try {
|
|
724
|
-
const recorded = await
|
|
938
|
+
const recorded = await readFile3(okMarker, "utf8");
|
|
725
939
|
if (recorded.trim() === published.sha256 && !opts.force)
|
|
726
940
|
return releaseId;
|
|
727
941
|
releaseId = sanitizeReleaseId(`${releaseId}-${published.sha256.slice(0, 12)}`);
|
|
728
|
-
releaseDir =
|
|
729
|
-
okMarker =
|
|
730
|
-
const matching = await
|
|
942
|
+
releaseDir = join2(layout.releasesRoot, releaseId);
|
|
943
|
+
okMarker = join2(releaseDir, ".stage-ok");
|
|
944
|
+
const matching = await readFile3(okMarker, "utf8").catch(() => "");
|
|
731
945
|
if (matching.trim() === published.sha256 && !opts.force)
|
|
732
946
|
return releaseId;
|
|
733
947
|
previouslyVerified = Boolean(matching);
|
|
@@ -735,12 +949,12 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
735
949
|
}
|
|
736
950
|
if (await activeReleaseId(layout) === releaseId) {
|
|
737
951
|
releaseId = sanitizeReleaseId(`${releaseId}-repair-${Date.now()}`);
|
|
738
|
-
releaseDir =
|
|
739
|
-
okMarker =
|
|
952
|
+
releaseDir = join2(layout.releasesRoot, releaseId);
|
|
953
|
+
okMarker = join2(releaseDir, ".stage-ok");
|
|
740
954
|
previouslyVerified = false;
|
|
741
955
|
}
|
|
742
|
-
await
|
|
743
|
-
const tempArchive =
|
|
956
|
+
await mkdir4(releaseDir, { recursive: true });
|
|
957
|
+
const tempArchive = join2(layout.releasesRoot, `.download-${releaseId}-${process.pid}.tar.gz`);
|
|
744
958
|
try {
|
|
745
959
|
log2(`downloading ${published.file}`);
|
|
746
960
|
const response = await fetchImpl(archiveUrlFor(manifestUrl, published.file), {
|
|
@@ -784,7 +998,7 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
784
998
|
throw new Error(`extracting bundle failed: ${extract.stderr}`);
|
|
785
999
|
for (const relative of requiredBundlePaths()) {
|
|
786
1000
|
try {
|
|
787
|
-
await
|
|
1001
|
+
await access2(join2(releaseDir, relative), fsConstants2.F_OK);
|
|
788
1002
|
} catch {
|
|
789
1003
|
throw new Error(`staged bundle is missing ${relative}`);
|
|
790
1004
|
}
|
|
@@ -797,11 +1011,11 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
797
1011
|
if (!nodeVersionAtLeast(process.versions.node, engineMinimum)) {
|
|
798
1012
|
throw new Error(`staged bundle requires Node.js >=${engineMinimum.join(".")}, but this process is running Node.js ${process.versions.node} \u2014 install a satisfying Node runtime and retry`);
|
|
799
1013
|
}
|
|
800
|
-
await writeFile2(
|
|
1014
|
+
await writeFile2(join2(releaseDir, STAGED_NODE_PATH_FILE), `${process.execPath}
|
|
801
1015
|
`, "utf8");
|
|
802
1016
|
}
|
|
803
1017
|
if (opts.smokeTestCli !== false) {
|
|
804
|
-
const probe = await run(process.execPath, [
|
|
1018
|
+
const probe = await run(process.execPath, [join2(releaseDir, BUNDLE_ENTRYPOINT), "--version"], Math.min(6e4, remaining()));
|
|
805
1019
|
if (probe.status !== 0) {
|
|
806
1020
|
throw new Error(`staged bundle failed its startup smoke test (--version exited ${probe.status})${probe.stderr ? `: ${probe.stderr.trim()}` : ""}`);
|
|
807
1021
|
}
|
|
@@ -812,10 +1026,10 @@ async function stageRelease(layout, manifestUrl, published, opts = {}) {
|
|
|
812
1026
|
return releaseId;
|
|
813
1027
|
} catch (error) {
|
|
814
1028
|
if (!previouslyVerified)
|
|
815
|
-
await
|
|
1029
|
+
await rm4(releaseDir, { recursive: true, force: true });
|
|
816
1030
|
throw error;
|
|
817
1031
|
} finally {
|
|
818
|
-
await
|
|
1032
|
+
await rm4(tempArchive, { force: true });
|
|
819
1033
|
}
|
|
820
1034
|
}
|
|
821
1035
|
function forwarderScript(tool) {
|
|
@@ -850,142 +1064,14 @@ async function replaceFile(path, contents, mode) {
|
|
|
850
1064
|
const temp = `${path}.new-${process.pid}`;
|
|
851
1065
|
await writeFile2(temp, contents, { mode });
|
|
852
1066
|
await chmod2(temp, mode);
|
|
853
|
-
await
|
|
854
|
-
}
|
|
855
|
-
async function activateRelease(layout, releaseId, options = {}) {
|
|
856
|
-
assertInstallTestIsolation(layout);
|
|
857
|
-
let releaseDir = join(layout.releasesRoot, releaseId);
|
|
858
|
-
let previousReleaseId = await activeReleaseId(layout);
|
|
859
|
-
await access(join(releaseDir, BUNDLE_ENTRYPOINT), fsConstants.F_OK);
|
|
860
|
-
await mkdir3(layout.releasesRoot, { recursive: true });
|
|
861
|
-
await mkdir3(layout.binDir, { recursive: true });
|
|
862
|
-
const kind = await pathKind(layout.libDir);
|
|
863
|
-
if (kind === "directory") {
|
|
864
|
-
const legacyIdentity = await readBundleJson(layout.libDir);
|
|
865
|
-
const legacyId = sanitizeReleaseId(legacyIdentity?.commit ?? legacyIdentity?.version ?? `legacy-${Date.now()}`);
|
|
866
|
-
const legacyDir = join(layout.releasesRoot, legacyId);
|
|
867
|
-
try {
|
|
868
|
-
await access(legacyDir, fsConstants.F_OK);
|
|
869
|
-
const preservedId = `${legacyId}-${Date.now()}`;
|
|
870
|
-
await rename2(layout.libDir, join(layout.releasesRoot, preservedId));
|
|
871
|
-
await normalizeLegacyBundleShape(join(layout.releasesRoot, preservedId));
|
|
872
|
-
previousReleaseId = preservedId;
|
|
873
|
-
} catch {
|
|
874
|
-
await rename2(layout.libDir, legacyDir);
|
|
875
|
-
await normalizeLegacyBundleShape(legacyDir);
|
|
876
|
-
previousReleaseId = legacyId;
|
|
877
|
-
}
|
|
878
|
-
}
|
|
879
|
-
const tempLink = `${layout.libDir}.new-${process.pid}`;
|
|
880
|
-
await rm3(tempLink, { force: true });
|
|
881
|
-
await symlink(join("beeline-releases", releaseId), tempLink);
|
|
882
|
-
await rename2(tempLink, layout.libDir);
|
|
883
|
-
await fsyncDir(dirname4(layout.libDir));
|
|
884
|
-
await installRecoveryLauncher(layout, releaseDir);
|
|
885
|
-
await writeBinForwarders(layout, releaseDir);
|
|
886
|
-
const state = await readUpdateState(layout);
|
|
887
|
-
await writeUpdateState(layout, {
|
|
888
|
-
...state,
|
|
889
|
-
stagedReleaseId: void 0,
|
|
890
|
-
previousReleaseId: previousReleaseId && previousReleaseId !== releaseId ? previousReleaseId : state.previousReleaseId
|
|
891
|
-
});
|
|
892
|
-
if (!options.deferPruning)
|
|
893
|
-
await pruneHelperReleases(layout);
|
|
894
|
-
}
|
|
895
|
-
async function installRecoveryLauncher(layout, releaseDir) {
|
|
896
|
-
const bootstrap = join(releaseDir, "lib/beeline/recovery-cli.mjs");
|
|
897
|
-
if (await access(bootstrap).then(() => true, () => false)) {
|
|
898
|
-
const stable = resolve6(layout.libDir, "../beeline-bootstrap.mjs");
|
|
899
|
-
const temporary = `${stable}.${process.pid}.tmp`;
|
|
900
|
-
await copyFile(bootstrap, temporary);
|
|
901
|
-
await rename2(temporary, stable);
|
|
902
|
-
await replaceFile(resolve6(layout.libDir, "../beeline-node-path"), `${process.execPath}
|
|
903
|
-
`, 384);
|
|
904
|
-
}
|
|
905
|
-
}
|
|
906
|
-
async function normalizeLegacyBundleShape(bundleDir) {
|
|
907
|
-
const innerLib = join(bundleDir, "lib", "beeline");
|
|
908
|
-
let anyFlat = false;
|
|
909
|
-
for (const name of LEGACY_FLAT_BUNDLE_FILES) {
|
|
910
|
-
try {
|
|
911
|
-
await access(join(bundleDir, name), fsConstants.F_OK);
|
|
912
|
-
anyFlat = true;
|
|
913
|
-
break;
|
|
914
|
-
} catch {
|
|
915
|
-
}
|
|
916
|
-
}
|
|
917
|
-
if (!anyFlat)
|
|
918
|
-
return;
|
|
919
|
-
await mkdir3(innerLib, { recursive: true });
|
|
920
|
-
for (const name of LEGACY_FLAT_BUNDLE_FILES) {
|
|
921
|
-
try {
|
|
922
|
-
await access(join(innerLib, name), fsConstants.F_OK);
|
|
923
|
-
continue;
|
|
924
|
-
} catch {
|
|
925
|
-
}
|
|
926
|
-
await rename2(join(bundleDir, name), join(innerLib, name)).catch(() => void 0);
|
|
927
|
-
}
|
|
928
|
-
}
|
|
929
|
-
async function writeBinForwarders(layout, activeBundleRoot) {
|
|
930
|
-
const entries = [
|
|
931
|
-
...FORWARDER_TOOLS.map((tool) => [tool, tool]),
|
|
932
|
-
...Object.entries(FORWARDER_ALIASES).map(([alias, tool]) => [alias, tool])
|
|
933
|
-
];
|
|
934
|
-
for (const [name, tool] of entries) {
|
|
935
|
-
const target = join(activeBundleRoot, "bin", tool);
|
|
936
|
-
try {
|
|
937
|
-
await access(target, fsConstants.X_OK);
|
|
938
|
-
} catch {
|
|
939
|
-
continue;
|
|
940
|
-
}
|
|
941
|
-
const independent = await access(resolve6(layout.libDir, "../beeline-bootstrap.mjs")).then(() => true, () => false);
|
|
942
|
-
await replaceFile(join(layout.binDir, name), independent || tool !== "beeline" ? forwarderScript(tool) : forwarderScript("legacy-beeline").replace("/bin/legacy-beeline", "/bin/beeline"), 493);
|
|
943
|
-
}
|
|
944
|
-
}
|
|
945
|
-
async function repairInstallForwarders(layout, opts = {}) {
|
|
946
|
-
assertInstallTestIsolation(layout);
|
|
947
|
-
if (await pathKind(layout.libDir) !== "symlink")
|
|
948
|
-
return false;
|
|
949
|
-
await installRecoveryLauncher(layout, layout.libDir);
|
|
950
|
-
const forwarderHealthy = async (name, tool) => {
|
|
951
|
-
let current;
|
|
952
|
-
try {
|
|
953
|
-
current = await readFile2(join(layout.binDir, name), "utf8");
|
|
954
|
-
} catch {
|
|
955
|
-
current = void 0;
|
|
956
|
-
}
|
|
957
|
-
const independent = await access(resolve6(layout.libDir, "../beeline-bootstrap.mjs")).then(() => true, () => false);
|
|
958
|
-
const expected = independent || tool !== "beeline" ? forwarderScript(tool) : forwarderScript("legacy-beeline").replace("/bin/legacy-beeline", "/bin/beeline");
|
|
959
|
-
return current === expected;
|
|
960
|
-
};
|
|
961
|
-
let healthy = await forwarderHealthy("beeline", "beeline");
|
|
962
|
-
for (const [alias, tool] of Object.entries(FORWARDER_ALIASES)) {
|
|
963
|
-
if (!await forwarderHealthy(alias, tool))
|
|
964
|
-
healthy = false;
|
|
965
|
-
}
|
|
966
|
-
if (healthy)
|
|
967
|
-
return false;
|
|
968
|
-
await mkdir3(layout.binDir, { recursive: true });
|
|
969
|
-
await writeBinForwarders(layout, layout.libDir);
|
|
970
|
-
opts.logger?.(`[body] self-update: repaired <prefix>/bin forwarders to follow the active-bundle anchor (${layout.libDir})`);
|
|
971
|
-
return true;
|
|
972
|
-
}
|
|
973
|
-
function describeIdentity(identity) {
|
|
974
|
-
if (!identity)
|
|
975
|
-
return "unknown";
|
|
976
|
-
const parts = [];
|
|
977
|
-
if (identity.version)
|
|
978
|
-
parts.push(identity.version);
|
|
979
|
-
if (identity.commit)
|
|
980
|
-
parts.push(identity.commit.slice(0, 12));
|
|
981
|
-
return parts.join(" ") || "unknown";
|
|
1067
|
+
await rename3(temp, path);
|
|
982
1068
|
}
|
|
983
1069
|
async function prepareLatestRelease(layout, options = {}) {
|
|
984
1070
|
try {
|
|
985
1071
|
const manifestUrl = options.manifest?.url ?? resolveManifestUrl(options.env ?? process.env);
|
|
986
1072
|
const bundle = options.manifest?.bundle ?? parseUpdateManifest(await fetchText(manifestUrl, options.fetchImpl ?? fetch), hostPlatformKey()).bundle;
|
|
987
1073
|
const pending = (await readUpdateState(layout)).stagedReleaseId;
|
|
988
|
-
const pendingDigest = pending ? await
|
|
1074
|
+
const pendingDigest = pending ? await readFile3(join2(layout.releasesRoot, pending, ".stage-ok"), "utf8").catch(() => "") : "";
|
|
989
1075
|
const releaseId = !options.force && pending && pendingDigest.trim() === bundle.sha256 ? pending : await stageRelease(layout, manifestUrl, bundle, {
|
|
990
1076
|
fetchImpl: options.fetchImpl,
|
|
991
1077
|
logger: options.logger,
|
|
@@ -1009,55 +1095,18 @@ async function prepareLatestRelease(layout, options = {}) {
|
|
|
1009
1095
|
throw error;
|
|
1010
1096
|
}
|
|
1011
1097
|
}
|
|
1012
|
-
|
|
1013
|
-
assertInstallTestIsolation(layout);
|
|
1014
|
-
if (!await ordinaryDirectory(layout.releasesRoot))
|
|
1015
|
-
return [];
|
|
1016
|
-
const active = await activeReleaseId(layout);
|
|
1017
|
-
if (!active)
|
|
1018
|
-
return [];
|
|
1019
|
-
const state = await readUpdateState(layout);
|
|
1020
|
-
const candidates = [];
|
|
1021
|
-
for (const entry of await readdir3(layout.releasesRoot, { withFileTypes: true })) {
|
|
1022
|
-
if (entry.name.startsWith("."))
|
|
1023
|
-
continue;
|
|
1024
|
-
if (entry.isSymbolicLink()) {
|
|
1025
|
-
if (![active, state.previousReleaseId, state.stagedReleaseId, loadedRelease].includes(entry.name))
|
|
1026
|
-
await rm3(join(layout.releasesRoot, entry.name), { force: true });
|
|
1027
|
-
continue;
|
|
1028
|
-
}
|
|
1029
|
-
if (!entry.isDirectory())
|
|
1030
|
-
continue;
|
|
1031
|
-
const path = join(layout.releasesRoot, entry.name);
|
|
1032
|
-
if (!await ordinaryDirectory(path))
|
|
1033
|
-
continue;
|
|
1034
|
-
candidates.push({
|
|
1035
|
-
id: entry.name,
|
|
1036
|
-
modified: (await lstat3(path)).mtimeMs,
|
|
1037
|
-
bootable: await access(join(path, BUNDLE_ENTRYPOINT)).then(() => true, () => false)
|
|
1038
|
-
});
|
|
1039
|
-
}
|
|
1040
|
-
const recordedPrevious = candidates.find((entry) => entry.id === state.previousReleaseId && entry.id !== active && entry.bootable)?.id;
|
|
1041
|
-
const previous = recordedPrevious ?? candidates.filter((entry) => entry.bootable && entry.id !== active && entry.id !== state.stagedReleaseId).sort((a, b) => b.modified - a.modified)[0]?.id;
|
|
1042
|
-
const keep = /* @__PURE__ */ new Set([active, previous, loadedRelease, state.stagedReleaseId]);
|
|
1043
|
-
const removed = [];
|
|
1044
|
-
for (const entry of candidates) {
|
|
1045
|
-
if (keep.has(entry.id))
|
|
1046
|
-
continue;
|
|
1047
|
-
await removeStoragePath(join(layout.releasesRoot, entry.id));
|
|
1048
|
-
removed.push(entry.id);
|
|
1049
|
-
}
|
|
1050
|
-
if (previous !== state.previousReleaseId)
|
|
1051
|
-
await writeUpdateState(layout, { ...state, previousReleaseId: previous });
|
|
1052
|
-
return removed;
|
|
1053
|
-
}
|
|
1054
|
-
var RELEASES_SEGMENT, STAGED_NODE_PATH_FILE, BUNDLE_ENTRYPOINT, PI_MCP_ADAPTER_ENTRYPOINT, CODEGRAPH_ENTRYPOINT, FORWARDER_TOOLS, FORWARDER_ALIASES, LEGACY_FLAT_BUNDLE_FILES, SelfUpdateManager;
|
|
1098
|
+
var RELEASES_SEGMENT, STAGED_NODE_PATH_FILE, BUNDLE_ENTRYPOINT, PI_MCP_ADAPTER_ENTRYPOINT, CODEGRAPH_ENTRYPOINT, FORWARDER_TOOLS, FORWARDER_ALIASES, SelfUpdateManager;
|
|
1055
1099
|
var init_self_update = __esm({
|
|
1056
1100
|
"apps/body/dist/self-update.js"() {
|
|
1057
1101
|
"use strict";
|
|
1058
|
-
init_storage_filesystem();
|
|
1059
1102
|
init_lifecycle_test_guard();
|
|
1060
1103
|
init_self_update_manifest();
|
|
1104
|
+
init_self_update_activate_release();
|
|
1105
|
+
init_self_update_activate_release();
|
|
1106
|
+
init_self_update_activate_release();
|
|
1107
|
+
init_self_update_activate_release();
|
|
1108
|
+
init_self_update_activate_release();
|
|
1109
|
+
init_self_update_activate_release();
|
|
1061
1110
|
RELEASES_SEGMENT = "beeline-releases";
|
|
1062
1111
|
STAGED_NODE_PATH_FILE = ".node-path";
|
|
1063
1112
|
BUNDLE_ENTRYPOINT = "lib/beeline/beeline-cli.mjs";
|
|
@@ -1073,12 +1122,6 @@ var init_self_update = __esm({
|
|
|
1073
1122
|
FORWARDER_ALIASES = {
|
|
1074
1123
|
usebeeline: "beeline"
|
|
1075
1124
|
};
|
|
1076
|
-
LEGACY_FLAT_BUNDLE_FILES = [
|
|
1077
|
-
"beeline-cli.mjs",
|
|
1078
|
-
"beeline-readonly-mcp.mjs",
|
|
1079
|
-
"pi-mcp-adapter.mjs",
|
|
1080
|
-
"bundle.json"
|
|
1081
|
-
];
|
|
1082
1125
|
SelfUpdateManager = class {
|
|
1083
1126
|
options;
|
|
1084
1127
|
constructor(options) {
|
|
@@ -1108,9 +1151,9 @@ __export(managed_update_exports, {
|
|
|
1108
1151
|
withInstallLock: () => withInstallLock
|
|
1109
1152
|
});
|
|
1110
1153
|
import { spawn as spawn3 } from "node:child_process";
|
|
1111
|
-
import { resolve as
|
|
1154
|
+
import { resolve as resolve8 } from "node:path";
|
|
1112
1155
|
function withInstallLock(layout, work, options = {}) {
|
|
1113
|
-
return withKernelLock(`beeline-install:${
|
|
1156
|
+
return withKernelLock(`beeline-install:${resolve8(layout.libDir)}`, work, options.waitMs);
|
|
1114
1157
|
}
|
|
1115
1158
|
function versionAtLeast(actual, minimum) {
|
|
1116
1159
|
const parse = (value) => /^v?(\d+)\.(\d+)\.(\d+)$/.exec(value)?.slice(1).map(Number);
|
|
@@ -1135,7 +1178,7 @@ async function runManagedUpdateWorker() {
|
|
|
1135
1178
|
}
|
|
1136
1179
|
async function prepareReleaseInWorker(env, deadlineAt, entrypoint) {
|
|
1137
1180
|
const layout = beelineInstallLayout(env);
|
|
1138
|
-
const bootstrap = entrypoint ??
|
|
1181
|
+
const bootstrap = entrypoint ?? resolve8(layout.libDir, "../beeline-bootstrap.mjs");
|
|
1139
1182
|
return new Promise((done, reject) => {
|
|
1140
1183
|
const child = spawn3(process.execPath, [bootstrap, "managed-update-worker"], {
|
|
1141
1184
|
detached: true,
|
|
@@ -1193,7 +1236,6 @@ var init_managed_update = __esm({
|
|
|
1193
1236
|
#interruptAt;
|
|
1194
1237
|
#deadlineAt;
|
|
1195
1238
|
#handingOff;
|
|
1196
|
-
#notice;
|
|
1197
1239
|
#completed = false;
|
|
1198
1240
|
#draining = false;
|
|
1199
1241
|
constructor(options) {
|
|
@@ -1205,10 +1247,7 @@ var init_managed_update = __esm({
|
|
|
1205
1247
|
get pending() {
|
|
1206
1248
|
return this.#preparing ?? this.#handingOff;
|
|
1207
1249
|
}
|
|
1208
|
-
notify(
|
|
1209
|
-
if (releaseKey && releaseKey === this.#notice)
|
|
1210
|
-
return;
|
|
1211
|
-
this.#notice = releaseKey;
|
|
1250
|
+
notify(_releaseKey, minimum) {
|
|
1212
1251
|
if (minimum && (!this.#minimum || !versionAtLeast(this.#minimum, minimum))) {
|
|
1213
1252
|
this.#minimum = minimum;
|
|
1214
1253
|
this.#handoffAt = this.now();
|
|
@@ -1227,7 +1266,7 @@ var init_managed_update = __esm({
|
|
|
1227
1266
|
if (this.#minimum) {
|
|
1228
1267
|
const identity = await readInstalledBundleIdentity({
|
|
1229
1268
|
...this.options.layout,
|
|
1230
|
-
libDir:
|
|
1269
|
+
libDir: resolve8(this.options.layout.releasesRoot, releaseId)
|
|
1231
1270
|
});
|
|
1232
1271
|
if (!identity?.version || !versionAtLeast(identity.version, this.#minimum)) {
|
|
1233
1272
|
this.#prepared = void 0;
|
|
@@ -3407,9 +3446,9 @@ var require_dispatcher_base = __commonJS({
|
|
|
3407
3446
|
}
|
|
3408
3447
|
close(callback) {
|
|
3409
3448
|
if (callback === void 0) {
|
|
3410
|
-
return new Promise((
|
|
3449
|
+
return new Promise((resolve13, reject) => {
|
|
3411
3450
|
this.close((err, data) => {
|
|
3412
|
-
return err ? reject(err) :
|
|
3451
|
+
return err ? reject(err) : resolve13(data);
|
|
3413
3452
|
});
|
|
3414
3453
|
});
|
|
3415
3454
|
}
|
|
@@ -3447,12 +3486,12 @@ var require_dispatcher_base = __commonJS({
|
|
|
3447
3486
|
err = null;
|
|
3448
3487
|
}
|
|
3449
3488
|
if (callback === void 0) {
|
|
3450
|
-
return new Promise((
|
|
3489
|
+
return new Promise((resolve13, reject) => {
|
|
3451
3490
|
this.destroy(err, (err2, data) => {
|
|
3452
3491
|
return err2 ? (
|
|
3453
3492
|
/* istanbul ignore next: should never error */
|
|
3454
3493
|
reject(err2)
|
|
3455
|
-
) :
|
|
3494
|
+
) : resolve13(data);
|
|
3456
3495
|
});
|
|
3457
3496
|
});
|
|
3458
3497
|
}
|
|
@@ -5719,8 +5758,8 @@ var require_util2 = __commonJS({
|
|
|
5719
5758
|
function createDeferredPromise() {
|
|
5720
5759
|
let res;
|
|
5721
5760
|
let rej;
|
|
5722
|
-
const promise = new Promise((
|
|
5723
|
-
res =
|
|
5761
|
+
const promise = new Promise((resolve13, reject) => {
|
|
5762
|
+
res = resolve13;
|
|
5724
5763
|
rej = reject;
|
|
5725
5764
|
});
|
|
5726
5765
|
return { promise, resolve: res, reject: rej };
|
|
@@ -7966,12 +8005,12 @@ upgrade: ${upgrade}\r
|
|
|
7966
8005
|
cb();
|
|
7967
8006
|
}
|
|
7968
8007
|
}
|
|
7969
|
-
const waitForDrain = () => new Promise((
|
|
8008
|
+
const waitForDrain = () => new Promise((resolve13, reject) => {
|
|
7970
8009
|
assert(callback === null);
|
|
7971
8010
|
if (socket[kError]) {
|
|
7972
8011
|
reject(socket[kError]);
|
|
7973
8012
|
} else {
|
|
7974
|
-
callback =
|
|
8013
|
+
callback = resolve13;
|
|
7975
8014
|
}
|
|
7976
8015
|
});
|
|
7977
8016
|
socket.on("close", onDrain).on("drain", onDrain);
|
|
@@ -8608,12 +8647,12 @@ var require_client_h2 = __commonJS({
|
|
|
8608
8647
|
cb();
|
|
8609
8648
|
}
|
|
8610
8649
|
}
|
|
8611
|
-
const waitForDrain = () => new Promise((
|
|
8650
|
+
const waitForDrain = () => new Promise((resolve13, reject) => {
|
|
8612
8651
|
assert(callback === null);
|
|
8613
8652
|
if (socket[kError]) {
|
|
8614
8653
|
reject(socket[kError]);
|
|
8615
8654
|
} else {
|
|
8616
|
-
callback =
|
|
8655
|
+
callback = resolve13;
|
|
8617
8656
|
}
|
|
8618
8657
|
});
|
|
8619
8658
|
h2stream.on("close", onDrain).on("drain", onDrain);
|
|
@@ -9091,16 +9130,16 @@ var require_client = __commonJS({
|
|
|
9091
9130
|
return this[kNeedDrain] < 2;
|
|
9092
9131
|
}
|
|
9093
9132
|
async [kClose]() {
|
|
9094
|
-
return new Promise((
|
|
9133
|
+
return new Promise((resolve13) => {
|
|
9095
9134
|
if (this[kSize]) {
|
|
9096
|
-
this[kClosedResolve] =
|
|
9135
|
+
this[kClosedResolve] = resolve13;
|
|
9097
9136
|
} else {
|
|
9098
|
-
|
|
9137
|
+
resolve13(null);
|
|
9099
9138
|
}
|
|
9100
9139
|
});
|
|
9101
9140
|
}
|
|
9102
9141
|
async [kDestroy](err) {
|
|
9103
|
-
return new Promise((
|
|
9142
|
+
return new Promise((resolve13) => {
|
|
9104
9143
|
const requests = this[kQueue].splice(this[kPendingIdx]);
|
|
9105
9144
|
for (let i = 0; i < requests.length; i++) {
|
|
9106
9145
|
const request2 = requests[i];
|
|
@@ -9111,7 +9150,7 @@ var require_client = __commonJS({
|
|
|
9111
9150
|
this[kClosedResolve]();
|
|
9112
9151
|
this[kClosedResolve] = null;
|
|
9113
9152
|
}
|
|
9114
|
-
|
|
9153
|
+
resolve13(null);
|
|
9115
9154
|
};
|
|
9116
9155
|
if (this[kHTTPContext]) {
|
|
9117
9156
|
this[kHTTPContext].destroy(err, callback);
|
|
@@ -9162,7 +9201,7 @@ var require_client = __commonJS({
|
|
|
9162
9201
|
});
|
|
9163
9202
|
}
|
|
9164
9203
|
try {
|
|
9165
|
-
const socket = await new Promise((
|
|
9204
|
+
const socket = await new Promise((resolve13, reject) => {
|
|
9166
9205
|
client[kConnector]({
|
|
9167
9206
|
host,
|
|
9168
9207
|
hostname,
|
|
@@ -9174,7 +9213,7 @@ var require_client = __commonJS({
|
|
|
9174
9213
|
if (err) {
|
|
9175
9214
|
reject(err);
|
|
9176
9215
|
} else {
|
|
9177
|
-
|
|
9216
|
+
resolve13(socket2);
|
|
9178
9217
|
}
|
|
9179
9218
|
});
|
|
9180
9219
|
});
|
|
@@ -9510,8 +9549,8 @@ var require_pool_base = __commonJS({
|
|
|
9510
9549
|
if (this[kQueue].isEmpty()) {
|
|
9511
9550
|
await Promise.all(this[kClients].map((c) => c.close()));
|
|
9512
9551
|
} else {
|
|
9513
|
-
await new Promise((
|
|
9514
|
-
this[kClosedResolve] =
|
|
9552
|
+
await new Promise((resolve13) => {
|
|
9553
|
+
this[kClosedResolve] = resolve13;
|
|
9515
9554
|
});
|
|
9516
9555
|
}
|
|
9517
9556
|
}
|
|
@@ -10754,7 +10793,7 @@ var require_readable = __commonJS({
|
|
|
10754
10793
|
if (this._readableState.closeEmitted) {
|
|
10755
10794
|
return null;
|
|
10756
10795
|
}
|
|
10757
|
-
return await new Promise((
|
|
10796
|
+
return await new Promise((resolve13, reject) => {
|
|
10758
10797
|
if (this[kContentLength] > limit) {
|
|
10759
10798
|
this.destroy(new AbortError());
|
|
10760
10799
|
}
|
|
@@ -10767,7 +10806,7 @@ var require_readable = __commonJS({
|
|
|
10767
10806
|
if (signal?.aborted) {
|
|
10768
10807
|
reject(signal.reason ?? new AbortError());
|
|
10769
10808
|
} else {
|
|
10770
|
-
|
|
10809
|
+
resolve13(null);
|
|
10771
10810
|
}
|
|
10772
10811
|
}).on("error", noop).on("data", function(chunk) {
|
|
10773
10812
|
limit -= chunk.length;
|
|
@@ -10786,7 +10825,7 @@ var require_readable = __commonJS({
|
|
|
10786
10825
|
}
|
|
10787
10826
|
async function consume(stream, type) {
|
|
10788
10827
|
assert(!stream[kConsume]);
|
|
10789
|
-
return new Promise((
|
|
10828
|
+
return new Promise((resolve13, reject) => {
|
|
10790
10829
|
if (isUnusable(stream)) {
|
|
10791
10830
|
const rState = stream._readableState;
|
|
10792
10831
|
if (rState.destroyed && rState.closeEmitted === false) {
|
|
@@ -10803,7 +10842,7 @@ var require_readable = __commonJS({
|
|
|
10803
10842
|
stream[kConsume] = {
|
|
10804
10843
|
type,
|
|
10805
10844
|
stream,
|
|
10806
|
-
resolve:
|
|
10845
|
+
resolve: resolve13,
|
|
10807
10846
|
reject,
|
|
10808
10847
|
length: 0,
|
|
10809
10848
|
body: []
|
|
@@ -10873,18 +10912,18 @@ var require_readable = __commonJS({
|
|
|
10873
10912
|
return buffer;
|
|
10874
10913
|
}
|
|
10875
10914
|
function consumeEnd(consume2) {
|
|
10876
|
-
const { type, body, resolve:
|
|
10915
|
+
const { type, body, resolve: resolve13, stream, length } = consume2;
|
|
10877
10916
|
try {
|
|
10878
10917
|
if (type === "text") {
|
|
10879
|
-
|
|
10918
|
+
resolve13(chunksDecode(body, length));
|
|
10880
10919
|
} else if (type === "json") {
|
|
10881
|
-
|
|
10920
|
+
resolve13(JSON.parse(chunksDecode(body, length)));
|
|
10882
10921
|
} else if (type === "arrayBuffer") {
|
|
10883
|
-
|
|
10922
|
+
resolve13(chunksConcat(body, length).buffer);
|
|
10884
10923
|
} else if (type === "blob") {
|
|
10885
|
-
|
|
10924
|
+
resolve13(new Blob(body, { type: stream[kContentType] }));
|
|
10886
10925
|
} else if (type === "bytes") {
|
|
10887
|
-
|
|
10926
|
+
resolve13(chunksConcat(body, length));
|
|
10888
10927
|
}
|
|
10889
10928
|
consumeFinish(consume2);
|
|
10890
10929
|
} catch (err) {
|
|
@@ -11141,9 +11180,9 @@ var require_api_request = __commonJS({
|
|
|
11141
11180
|
};
|
|
11142
11181
|
function request2(opts, callback) {
|
|
11143
11182
|
if (callback === void 0) {
|
|
11144
|
-
return new Promise((
|
|
11183
|
+
return new Promise((resolve13, reject) => {
|
|
11145
11184
|
request2.call(this, opts, (err, data) => {
|
|
11146
|
-
return err ? reject(err) :
|
|
11185
|
+
return err ? reject(err) : resolve13(data);
|
|
11147
11186
|
});
|
|
11148
11187
|
});
|
|
11149
11188
|
}
|
|
@@ -11366,9 +11405,9 @@ var require_api_stream = __commonJS({
|
|
|
11366
11405
|
};
|
|
11367
11406
|
function stream(opts, factory, callback) {
|
|
11368
11407
|
if (callback === void 0) {
|
|
11369
|
-
return new Promise((
|
|
11408
|
+
return new Promise((resolve13, reject) => {
|
|
11370
11409
|
stream.call(this, opts, factory, (err, data) => {
|
|
11371
|
-
return err ? reject(err) :
|
|
11410
|
+
return err ? reject(err) : resolve13(data);
|
|
11372
11411
|
});
|
|
11373
11412
|
});
|
|
11374
11413
|
}
|
|
@@ -11653,9 +11692,9 @@ var require_api_upgrade = __commonJS({
|
|
|
11653
11692
|
};
|
|
11654
11693
|
function upgrade(opts, callback) {
|
|
11655
11694
|
if (callback === void 0) {
|
|
11656
|
-
return new Promise((
|
|
11695
|
+
return new Promise((resolve13, reject) => {
|
|
11657
11696
|
upgrade.call(this, opts, (err, data) => {
|
|
11658
|
-
return err ? reject(err) :
|
|
11697
|
+
return err ? reject(err) : resolve13(data);
|
|
11659
11698
|
});
|
|
11660
11699
|
});
|
|
11661
11700
|
}
|
|
@@ -11747,9 +11786,9 @@ var require_api_connect = __commonJS({
|
|
|
11747
11786
|
};
|
|
11748
11787
|
function connect(opts, callback) {
|
|
11749
11788
|
if (callback === void 0) {
|
|
11750
|
-
return new Promise((
|
|
11789
|
+
return new Promise((resolve13, reject) => {
|
|
11751
11790
|
connect.call(this, opts, (err, data) => {
|
|
11752
|
-
return err ? reject(err) :
|
|
11791
|
+
return err ? reject(err) : resolve13(data);
|
|
11753
11792
|
});
|
|
11754
11793
|
});
|
|
11755
11794
|
}
|
|
@@ -12976,16 +13015,16 @@ var require_dns = __commonJS({
|
|
|
12976
13015
|
setRecords(origin, addresses) {
|
|
12977
13016
|
const timestamp = Date.now();
|
|
12978
13017
|
const records = { records: { 4: null, 6: null } };
|
|
12979
|
-
for (const
|
|
12980
|
-
|
|
12981
|
-
if (typeof
|
|
12982
|
-
|
|
13018
|
+
for (const record2 of addresses) {
|
|
13019
|
+
record2.timestamp = timestamp;
|
|
13020
|
+
if (typeof record2.ttl === "number") {
|
|
13021
|
+
record2.ttl = Math.min(record2.ttl, this.#maxTTL);
|
|
12983
13022
|
} else {
|
|
12984
|
-
|
|
13023
|
+
record2.ttl = this.#maxTTL;
|
|
12985
13024
|
}
|
|
12986
|
-
const familyRecords = records.records[
|
|
12987
|
-
familyRecords.ips.push(
|
|
12988
|
-
records.records[
|
|
13025
|
+
const familyRecords = records.records[record2.family] ?? { ips: [] };
|
|
13026
|
+
familyRecords.ips.push(record2);
|
|
13027
|
+
records.records[record2.family] = familyRecords;
|
|
12989
13028
|
}
|
|
12990
13029
|
this.#records.set(origin.hostname, records);
|
|
12991
13030
|
}
|
|
@@ -15611,7 +15650,7 @@ var require_fetch = __commonJS({
|
|
|
15611
15650
|
function dispatch({ body }) {
|
|
15612
15651
|
const url = requestCurrentURL(request2);
|
|
15613
15652
|
const agent = fetchParams.controller.dispatcher;
|
|
15614
|
-
return new Promise((
|
|
15653
|
+
return new Promise((resolve13, reject) => agent.dispatch(
|
|
15615
15654
|
{
|
|
15616
15655
|
path: url.pathname + url.search,
|
|
15617
15656
|
origin: url.origin,
|
|
@@ -15687,7 +15726,7 @@ var require_fetch = __commonJS({
|
|
|
15687
15726
|
}
|
|
15688
15727
|
}
|
|
15689
15728
|
const onError = this.onError.bind(this);
|
|
15690
|
-
|
|
15729
|
+
resolve13({
|
|
15691
15730
|
status,
|
|
15692
15731
|
statusText,
|
|
15693
15732
|
headersList,
|
|
@@ -15733,7 +15772,7 @@ var require_fetch = __commonJS({
|
|
|
15733
15772
|
for (let i = 0; i < rawHeaders.length; i += 2) {
|
|
15734
15773
|
headersList.append(bufferToLowerCasedHeaderName(rawHeaders[i]), rawHeaders[i + 1].toString("latin1"), true);
|
|
15735
15774
|
}
|
|
15736
|
-
|
|
15775
|
+
resolve13({
|
|
15737
15776
|
status,
|
|
15738
15777
|
statusText: STATUS_CODES[status],
|
|
15739
15778
|
headersList,
|
|
@@ -19463,8 +19502,8 @@ var require_util8 = __commonJS({
|
|
|
19463
19502
|
return true;
|
|
19464
19503
|
}
|
|
19465
19504
|
function delay(ms) {
|
|
19466
|
-
return new Promise((
|
|
19467
|
-
setTimeout(
|
|
19505
|
+
return new Promise((resolve13) => {
|
|
19506
|
+
setTimeout(resolve13, ms).unref();
|
|
19468
19507
|
});
|
|
19469
19508
|
}
|
|
19470
19509
|
module.exports = {
|
|
@@ -19630,41 +19669,41 @@ var require_eventsource_stream = __commonJS({
|
|
|
19630
19669
|
if (colonPosition === 0) {
|
|
19631
19670
|
return;
|
|
19632
19671
|
}
|
|
19633
|
-
let
|
|
19672
|
+
let field2 = "";
|
|
19634
19673
|
let value = "";
|
|
19635
19674
|
if (colonPosition !== -1) {
|
|
19636
|
-
|
|
19675
|
+
field2 = line.subarray(0, colonPosition).toString("utf8");
|
|
19637
19676
|
let valueStart = colonPosition + 1;
|
|
19638
19677
|
if (line[valueStart] === SPACE) {
|
|
19639
19678
|
++valueStart;
|
|
19640
19679
|
}
|
|
19641
19680
|
value = line.subarray(valueStart).toString("utf8");
|
|
19642
19681
|
} else {
|
|
19643
|
-
|
|
19682
|
+
field2 = line.toString("utf8");
|
|
19644
19683
|
value = "";
|
|
19645
19684
|
}
|
|
19646
|
-
switch (
|
|
19685
|
+
switch (field2) {
|
|
19647
19686
|
case "data":
|
|
19648
|
-
if (event[
|
|
19649
|
-
event[
|
|
19687
|
+
if (event[field2] === void 0) {
|
|
19688
|
+
event[field2] = value;
|
|
19650
19689
|
} else {
|
|
19651
|
-
event[
|
|
19690
|
+
event[field2] += `
|
|
19652
19691
|
${value}`;
|
|
19653
19692
|
}
|
|
19654
19693
|
break;
|
|
19655
19694
|
case "retry":
|
|
19656
19695
|
if (isASCIINumber(value)) {
|
|
19657
|
-
event[
|
|
19696
|
+
event[field2] = value;
|
|
19658
19697
|
}
|
|
19659
19698
|
break;
|
|
19660
19699
|
case "id":
|
|
19661
19700
|
if (isValidLastEventId(value)) {
|
|
19662
|
-
event[
|
|
19701
|
+
event[field2] = value;
|
|
19663
19702
|
}
|
|
19664
19703
|
break;
|
|
19665
19704
|
case "event":
|
|
19666
19705
|
if (value.length > 0) {
|
|
19667
|
-
event[
|
|
19706
|
+
event[field2] = value;
|
|
19668
19707
|
}
|
|
19669
19708
|
break;
|
|
19670
19709
|
}
|
|
@@ -20147,9 +20186,9 @@ var require_undici = __commonJS({
|
|
|
20147
20186
|
// apps/body/dist/filesystem-change.js
|
|
20148
20187
|
import { watch as watch2 } from "node:fs";
|
|
20149
20188
|
import { stat as stat2 } from "node:fs/promises";
|
|
20150
|
-
import { dirname as
|
|
20189
|
+
import { dirname as dirname6 } from "node:path";
|
|
20151
20190
|
function waitForPathRemoval(path) {
|
|
20152
|
-
return new Promise((
|
|
20191
|
+
return new Promise((resolve13, reject) => {
|
|
20153
20192
|
let reading = false, dirty = false, ended = false;
|
|
20154
20193
|
const finish = (error) => {
|
|
20155
20194
|
if (ended)
|
|
@@ -20159,7 +20198,7 @@ function waitForPathRemoval(path) {
|
|
|
20159
20198
|
if (error)
|
|
20160
20199
|
reject(error);
|
|
20161
20200
|
else
|
|
20162
|
-
|
|
20201
|
+
resolve13();
|
|
20163
20202
|
};
|
|
20164
20203
|
const inspect = async () => {
|
|
20165
20204
|
dirty = true;
|
|
@@ -20185,7 +20224,7 @@ function waitForPathRemoval(path) {
|
|
|
20185
20224
|
reading = false;
|
|
20186
20225
|
}
|
|
20187
20226
|
};
|
|
20188
|
-
const watcher = watch2(
|
|
20227
|
+
const watcher = watch2(dirname6(path), () => {
|
|
20189
20228
|
void inspect();
|
|
20190
20229
|
});
|
|
20191
20230
|
watcher.once("error", finish);
|
|
@@ -20219,9 +20258,9 @@ __export(store_exports, {
|
|
|
20219
20258
|
import { createHash as createHash4, randomUUID } from "node:crypto";
|
|
20220
20259
|
import { chmodSync, mkdirSync, readFileSync as readFileSync3, readdirSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
20221
20260
|
import { homedir as homedir4 } from "node:os";
|
|
20222
|
-
import { join as
|
|
20261
|
+
import { join as join3 } from "node:path";
|
|
20223
20262
|
function stateDir(env = process.env) {
|
|
20224
|
-
return
|
|
20263
|
+
return join3(env.XDG_STATE_HOME || join3(env.HOME || homedir4(), ".local/state"), "beeline-sessions");
|
|
20225
20264
|
}
|
|
20226
20265
|
function pidAlive(pid) {
|
|
20227
20266
|
try {
|
|
@@ -20243,17 +20282,17 @@ function writePrivate(path, text) {
|
|
|
20243
20282
|
}
|
|
20244
20283
|
function readState(dir = stateDir()) {
|
|
20245
20284
|
try {
|
|
20246
|
-
const value = JSON.parse(readFileSync3(
|
|
20285
|
+
const value = JSON.parse(readFileSync3(join3(dir, "state.json"), "utf8"));
|
|
20247
20286
|
return Array.isArray(value.sessions) ? value : { sessions: [] };
|
|
20248
20287
|
} catch {
|
|
20249
20288
|
return { sessions: [] };
|
|
20250
20289
|
}
|
|
20251
20290
|
}
|
|
20252
20291
|
function writeState(dir, state) {
|
|
20253
|
-
writePrivate(
|
|
20292
|
+
writePrivate(join3(ensureDir(dir), "state.json"), JSON.stringify(state, null, 2) + "\n");
|
|
20254
20293
|
}
|
|
20255
20294
|
async function withLock(dir, run2) {
|
|
20256
|
-
const lock =
|
|
20295
|
+
const lock = join3(ensureDir(dir), "state.lock");
|
|
20257
20296
|
for (let attempt = 0; ; attempt++) {
|
|
20258
20297
|
try {
|
|
20259
20298
|
mkdirSync(lock);
|
|
@@ -20292,16 +20331,16 @@ function safe(value) {
|
|
|
20292
20331
|
return value.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 120);
|
|
20293
20332
|
}
|
|
20294
20333
|
function inboxPath(dir, key) {
|
|
20295
|
-
return
|
|
20334
|
+
return join3(dir, "inbox", `${createHash4("sha256").update(key).digest("hex").slice(0, 24)}.txt`);
|
|
20296
20335
|
}
|
|
20297
20336
|
function queueInbox(dir, key, text) {
|
|
20298
20337
|
adoptInboxText(dir, key);
|
|
20299
20338
|
queueInboxOnce(dir, key, `local:${randomUUID()}`, text);
|
|
20300
20339
|
}
|
|
20301
20340
|
function adoptInboxText(dir, key) {
|
|
20302
|
-
const folder = ensureDir(
|
|
20341
|
+
const folder = ensureDir(join3(dir, "deliveries", createHash4("sha256").update(key).digest("hex").slice(0, 24)));
|
|
20303
20342
|
try {
|
|
20304
|
-
renameSync(inboxPath(dir, key),
|
|
20343
|
+
renameSync(inboxPath(dir, key), join3(folder, `${randomUUID()}.text.pending`));
|
|
20305
20344
|
} catch (error) {
|
|
20306
20345
|
if (error.code !== "ENOENT")
|
|
20307
20346
|
throw error;
|
|
@@ -20312,8 +20351,8 @@ function queueInboxOnce(dir, key, deliveryId, text) {
|
|
|
20312
20351
|
const queuedAt = lastInboxOrder;
|
|
20313
20352
|
if (!deliveryId || deliveryId.length > 256)
|
|
20314
20353
|
throw new Error("Invalid inbox delivery identity");
|
|
20315
|
-
const folder = ensureDir(
|
|
20316
|
-
const stem =
|
|
20354
|
+
const folder = ensureDir(join3(dir, "deliveries", createHash4("sha256").update(key).digest("hex").slice(0, 24)));
|
|
20355
|
+
const stem = join3(folder, createHash4("sha256").update(deliveryId).digest("hex"));
|
|
20317
20356
|
if (existsDelivery(stem + ".pending") || existsDelivery(stem + ".done"))
|
|
20318
20357
|
return false;
|
|
20319
20358
|
writePrivate(stem + ".pending", JSON.stringify({ id: deliveryId, text, queuedAt }));
|
|
@@ -20328,7 +20367,7 @@ function existsDelivery(path) {
|
|
|
20328
20367
|
}
|
|
20329
20368
|
}
|
|
20330
20369
|
function takeDeliveries(dir, key) {
|
|
20331
|
-
const folder =
|
|
20370
|
+
const folder = join3(dir, "deliveries", createHash4("sha256").update(key).digest("hex").slice(0, 24));
|
|
20332
20371
|
let names;
|
|
20333
20372
|
try {
|
|
20334
20373
|
names = readdirSync(folder);
|
|
@@ -20337,7 +20376,7 @@ function takeDeliveries(dir, key) {
|
|
|
20337
20376
|
}
|
|
20338
20377
|
const pending = names.filter((name) => name.endsWith(".pending")).flatMap((name) => {
|
|
20339
20378
|
try {
|
|
20340
|
-
const contents = readFileSync3(
|
|
20379
|
+
const contents = readFileSync3(join3(folder, name), "utf8");
|
|
20341
20380
|
const item = name.endsWith(".text.pending") ? { text: contents, queuedAt: 0 } : JSON.parse(contents);
|
|
20342
20381
|
return typeof item.text === "string" ? [{ name, ...item }] : [];
|
|
20343
20382
|
} catch {
|
|
@@ -20346,7 +20385,7 @@ function takeDeliveries(dir, key) {
|
|
|
20346
20385
|
}).sort((a, b) => a.queuedAt - b.queuedAt || a.name.localeCompare(b.name));
|
|
20347
20386
|
const text = [];
|
|
20348
20387
|
for (const item of pending) {
|
|
20349
|
-
const path =
|
|
20388
|
+
const path = join3(folder, item.name), done = path.replace(/\.pending$/, ".done");
|
|
20350
20389
|
try {
|
|
20351
20390
|
renameSync(path, done);
|
|
20352
20391
|
} catch {
|
|
@@ -20362,15 +20401,15 @@ function takeInbox(dir, key) {
|
|
|
20362
20401
|
return takeDeliveries(dir, key).join("\n\n");
|
|
20363
20402
|
}
|
|
20364
20403
|
function recordHookSession(dir, session2) {
|
|
20365
|
-
writePrivate(
|
|
20404
|
+
writePrivate(join3(ensureDir(join3(dir, "hooks")), `${safe(session2.agent)}-${safe(session2.sessionId)}.json`), JSON.stringify(session2));
|
|
20366
20405
|
}
|
|
20367
20406
|
function forgetHookSession(dir, agent, sessionId) {
|
|
20368
|
-
rmSync(
|
|
20407
|
+
rmSync(join3(dir, "hooks", `${safe(agent)}-${safe(sessionId)}.json`), { force: true });
|
|
20369
20408
|
}
|
|
20370
20409
|
function hookSessions(dir, now = Date.now(), alive = pidAlive) {
|
|
20371
20410
|
let names;
|
|
20372
20411
|
try {
|
|
20373
|
-
names = readdirSync(
|
|
20412
|
+
names = readdirSync(join3(dir, "hooks"));
|
|
20374
20413
|
} catch {
|
|
20375
20414
|
return [];
|
|
20376
20415
|
}
|
|
@@ -20379,7 +20418,7 @@ function hookSessions(dir, now = Date.now(), alive = pidAlive) {
|
|
|
20379
20418
|
if (!name.endsWith(".json"))
|
|
20380
20419
|
continue;
|
|
20381
20420
|
try {
|
|
20382
|
-
const session2 = JSON.parse(readFileSync3(
|
|
20421
|
+
const session2 = JSON.parse(readFileSync3(join3(dir, "hooks", name), "utf8"));
|
|
20383
20422
|
if (now - session2.seenAt <= HOOK_TTL_MS && (session2.pid === void 0 || alive(session2.pid)))
|
|
20384
20423
|
found.push(session2);
|
|
20385
20424
|
} catch {
|
|
@@ -20404,7 +20443,7 @@ function admitHeldMcpCompletion(url, body) {
|
|
|
20404
20443
|
if (!["https:", "http:"].includes(target.protocol) || target.username || target.password || target.hash || target.search || target.pathname !== "/mcp/oauth/handoff" || !body || typeof body !== "object" || Object.getPrototypeOf(body) !== Object.prototype)
|
|
20405
20444
|
throw new Error("Held MCP completion route unavailable");
|
|
20406
20445
|
const fields = Object.getOwnPropertyDescriptors(body);
|
|
20407
|
-
if (Object.getOwnPropertySymbols(body).length || Object.keys(fields).some((key) => !["state", "completionV1", "waitMs"].includes(key)) || Object.values(fields).some((
|
|
20446
|
+
if (Object.getOwnPropertySymbols(body).length || Object.keys(fields).some((key) => !["state", "completionV1", "waitMs"].includes(key)) || Object.values(fields).some((field2) => !("value" in field2)) || fields.completionV1?.value !== true || typeof fields.state?.value !== "string" || !/^[A-Za-z0-9_-]{32,128}$/.test(fields.state.value) || !Number.isSafeInteger(fields.waitMs?.value) || fields.waitMs.value < 1 || fields.waitMs.value > 6e5)
|
|
20408
20447
|
throw new Error("Held MCP completion admission invalid");
|
|
20409
20448
|
}
|
|
20410
20449
|
async function request(url, body, headers, stream, cancellation, held = false) {
|
|
@@ -20636,10 +20675,47 @@ var init_beeline_api = __esm({
|
|
|
20636
20675
|
}
|
|
20637
20676
|
});
|
|
20638
20677
|
|
|
20678
|
+
// apps/body/dist/process-exit.js
|
|
20679
|
+
import { spawn as spawn5 } from "node:child_process";
|
|
20680
|
+
function waitForProcessExit(pid, signal) {
|
|
20681
|
+
return new Promise((resolve13, reject) => {
|
|
20682
|
+
const child = spawn5("/usr/bin/python3", ["-c", WAIT, String(pid)], { stdio: "ignore", signal });
|
|
20683
|
+
child.once("error", reject);
|
|
20684
|
+
child.once("close", (code) => code === 0 ? resolve13() : reject(new Error(`process exit observer failed (${code})`)));
|
|
20685
|
+
});
|
|
20686
|
+
}
|
|
20687
|
+
var WAIT;
|
|
20688
|
+
var init_process_exit = __esm({
|
|
20689
|
+
"apps/body/dist/process-exit.js"() {
|
|
20690
|
+
"use strict";
|
|
20691
|
+
WAIT = `import os,sys,select
|
|
20692
|
+
pid=int(sys.argv[1])
|
|
20693
|
+
try:
|
|
20694
|
+
if hasattr(os,'pidfd_open'):
|
|
20695
|
+
fd=os.pidfd_open(pid)
|
|
20696
|
+
try: select.select([fd],[],[])
|
|
20697
|
+
finally: os.close(fd)
|
|
20698
|
+
else:
|
|
20699
|
+
queue=select.kqueue()
|
|
20700
|
+
try: queue.control([select.kevent(pid,filter=select.KQ_FILTER_PROC,flags=select.KQ_EV_ADD|select.KQ_EV_ONESHOT,fflags=select.KQ_NOTE_EXIT)],1)
|
|
20701
|
+
finally: queue.close()
|
|
20702
|
+
except ProcessLookupError: pass
|
|
20703
|
+
`;
|
|
20704
|
+
}
|
|
20705
|
+
});
|
|
20706
|
+
|
|
20707
|
+
// packages/api-contract/dist/phone-types-room-live-delta.js
|
|
20708
|
+
var init_phone_types_room_live_delta = __esm({
|
|
20709
|
+
"packages/api-contract/dist/phone-types-room-live-delta.js"() {
|
|
20710
|
+
"use strict";
|
|
20711
|
+
}
|
|
20712
|
+
});
|
|
20713
|
+
|
|
20639
20714
|
// packages/api-contract/dist/phone-types.js
|
|
20640
20715
|
var init_phone_types = __esm({
|
|
20641
20716
|
"packages/api-contract/dist/phone-types.js"() {
|
|
20642
20717
|
"use strict";
|
|
20718
|
+
init_phone_types_room_live_delta();
|
|
20643
20719
|
}
|
|
20644
20720
|
});
|
|
20645
20721
|
|
|
@@ -20650,21 +20726,12 @@ var init_model_choice = __esm({
|
|
|
20650
20726
|
}
|
|
20651
20727
|
});
|
|
20652
20728
|
|
|
20653
|
-
// packages/api-contract/dist/system-message-catalog.js
|
|
20654
|
-
|
|
20655
|
-
|
|
20656
|
-
|
|
20657
|
-
throw new Error(`System message ${key} needs ${entry.variables.length} variables`);
|
|
20658
|
-
let text = entry.parts[0];
|
|
20659
|
-
for (let index = 0; index < values.length; index++)
|
|
20660
|
-
text += `${values[index]}${entry.parts[index + 1]}`;
|
|
20661
|
-
return text;
|
|
20662
|
-
}
|
|
20663
|
-
var SYSTEM_MESSAGE_CATALOG;
|
|
20664
|
-
var init_system_message_catalog = __esm({
|
|
20665
|
-
"packages/api-contract/dist/system-message-catalog.js"() {
|
|
20729
|
+
// packages/api-contract/dist/system-message-catalog-away-auto-pause.js
|
|
20730
|
+
var SYSTEM_MESSAGE_AWAY_AUTO_PAUSE;
|
|
20731
|
+
var init_system_message_catalog_away_auto_pause = __esm({
|
|
20732
|
+
"packages/api-contract/dist/system-message-catalog-away-auto-pause.js"() {
|
|
20666
20733
|
"use strict";
|
|
20667
|
-
|
|
20734
|
+
SYSTEM_MESSAGE_AWAY_AUTO_PAUSE = {
|
|
20668
20735
|
"away-auto-pause.warning": { parts: ["will pause schedules and subscriptions for"], variables: [] },
|
|
20669
20736
|
"away-auto-pause.come-back": { parts: ["You have been away for 3 days. Come back within 1 day to keep them running. After they pause, ask your agent to resume."], variables: [] },
|
|
20670
20737
|
"agent-command.agent-mention": {
|
|
@@ -21312,7 +21379,17 @@ var init_system_message_catalog = __esm({
|
|
|
21312
21379
|
"daemon-service.instead-of": {
|
|
21313
21380
|
parts: ["instead of ", ""],
|
|
21314
21381
|
variables: ["input_from"]
|
|
21315
|
-
}
|
|
21382
|
+
}
|
|
21383
|
+
};
|
|
21384
|
+
}
|
|
21385
|
+
});
|
|
21386
|
+
|
|
21387
|
+
// packages/api-contract/dist/system-message-catalog-daemon-service.js
|
|
21388
|
+
var SYSTEM_MESSAGE_DAEMON_SERVICE;
|
|
21389
|
+
var init_system_message_catalog_daemon_service = __esm({
|
|
21390
|
+
"packages/api-contract/dist/system-message-catalog-daemon-service.js"() {
|
|
21391
|
+
"use strict";
|
|
21392
|
+
SYSTEM_MESSAGE_DAEMON_SERVICE = {
|
|
21316
21393
|
"daemon-service.needs-a-connection-to": {
|
|
21317
21394
|
parts: ["needs a connection to"],
|
|
21318
21395
|
variables: []
|
|
@@ -21960,7 +22037,17 @@ var init_system_message_catalog = __esm({
|
|
|
21960
22037
|
"vault-save-http.list-separator": {
|
|
21961
22038
|
parts: [", "],
|
|
21962
22039
|
variables: []
|
|
21963
|
-
}
|
|
22040
|
+
}
|
|
22041
|
+
};
|
|
22042
|
+
}
|
|
22043
|
+
});
|
|
22044
|
+
|
|
22045
|
+
// packages/api-contract/dist/system-message-catalog-voice-service.js
|
|
22046
|
+
var SYSTEM_MESSAGE_VOICE_SERVICE;
|
|
22047
|
+
var init_system_message_catalog_voice_service = __esm({
|
|
22048
|
+
"packages/api-contract/dist/system-message-catalog-voice-service.js"() {
|
|
22049
|
+
"use strict";
|
|
22050
|
+
SYSTEM_MESSAGE_VOICE_SERVICE = {
|
|
21964
22051
|
"voice-service.voice-call": {
|
|
21965
22052
|
parts: ["Voice call"],
|
|
21966
22053
|
variables: []
|
|
@@ -22605,7 +22692,17 @@ var init_system_message_catalog = __esm({
|
|
|
22605
22692
|
"turn-silence.the-helper-couldn-t-get-a-working-copy-of-check-the-repository-is": {
|
|
22606
22693
|
parts: ["the helper couldn't get a working copy of ", ". Check the repository is reachable."],
|
|
22607
22694
|
variables: ["classified_repo_the_repository"]
|
|
22608
|
-
}
|
|
22695
|
+
}
|
|
22696
|
+
};
|
|
22697
|
+
}
|
|
22698
|
+
});
|
|
22699
|
+
|
|
22700
|
+
// packages/api-contract/dist/system-message-catalog-turn-silence.js
|
|
22701
|
+
var SYSTEM_MESSAGE_TURN_SILENCE;
|
|
22702
|
+
var init_system_message_catalog_turn_silence = __esm({
|
|
22703
|
+
"packages/api-contract/dist/system-message-catalog-turn-silence.js"() {
|
|
22704
|
+
"use strict";
|
|
22705
|
+
SYSTEM_MESSAGE_TURN_SILENCE = {
|
|
22609
22706
|
"turn-silence.the-helper-is-out-of-date-run-beeline-start-on-the-helper-s-machi": {
|
|
22610
22707
|
parts: ["the helper is out of date. Run `beeline start` on the helper's machine."],
|
|
22611
22708
|
variables: []
|
|
@@ -22812,6 +22909,33 @@ var init_system_message_catalog = __esm({
|
|
|
22812
22909
|
}
|
|
22813
22910
|
});
|
|
22814
22911
|
|
|
22912
|
+
// packages/api-contract/dist/system-message-catalog.js
|
|
22913
|
+
function systemMessage(key, ...values) {
|
|
22914
|
+
const entry = SYSTEM_MESSAGE_CATALOG[key];
|
|
22915
|
+
if (values.length !== entry.variables.length)
|
|
22916
|
+
throw new Error(`System message ${key} needs ${entry.variables.length} variables`);
|
|
22917
|
+
let text = entry.parts[0];
|
|
22918
|
+
for (let index = 0; index < values.length; index++)
|
|
22919
|
+
text += `${values[index]}${entry.parts[index + 1]}`;
|
|
22920
|
+
return text;
|
|
22921
|
+
}
|
|
22922
|
+
var SYSTEM_MESSAGE_CATALOG;
|
|
22923
|
+
var init_system_message_catalog = __esm({
|
|
22924
|
+
"packages/api-contract/dist/system-message-catalog.js"() {
|
|
22925
|
+
"use strict";
|
|
22926
|
+
init_system_message_catalog_away_auto_pause();
|
|
22927
|
+
init_system_message_catalog_daemon_service();
|
|
22928
|
+
init_system_message_catalog_voice_service();
|
|
22929
|
+
init_system_message_catalog_turn_silence();
|
|
22930
|
+
SYSTEM_MESSAGE_CATALOG = {
|
|
22931
|
+
...SYSTEM_MESSAGE_AWAY_AUTO_PAUSE,
|
|
22932
|
+
...SYSTEM_MESSAGE_DAEMON_SERVICE,
|
|
22933
|
+
...SYSTEM_MESSAGE_VOICE_SERVICE,
|
|
22934
|
+
...SYSTEM_MESSAGE_TURN_SILENCE
|
|
22935
|
+
};
|
|
22936
|
+
}
|
|
22937
|
+
});
|
|
22938
|
+
|
|
22815
22939
|
// packages/api-contract/dist/voice.js
|
|
22816
22940
|
var init_voice = __esm({
|
|
22817
22941
|
"packages/api-contract/dist/voice.js"() {
|
|
@@ -22852,20 +22976,6 @@ var init_artifacts = __esm({
|
|
|
22852
22976
|
}
|
|
22853
22977
|
});
|
|
22854
22978
|
|
|
22855
|
-
// packages/api-contract/dist/repository-onboarding.js
|
|
22856
|
-
var init_repository_onboarding = __esm({
|
|
22857
|
-
"packages/api-contract/dist/repository-onboarding.js"() {
|
|
22858
|
-
"use strict";
|
|
22859
|
-
}
|
|
22860
|
-
});
|
|
22861
|
-
|
|
22862
|
-
// packages/api-contract/dist/vault-save.js
|
|
22863
|
-
var init_vault_save = __esm({
|
|
22864
|
-
"packages/api-contract/dist/vault-save.js"() {
|
|
22865
|
-
"use strict";
|
|
22866
|
-
}
|
|
22867
|
-
});
|
|
22868
|
-
|
|
22869
22979
|
// packages/api-contract/dist/agent-usage.js
|
|
22870
22980
|
var USAGE_OLD_SECONDS, USAGE_WINDOW_LABELS;
|
|
22871
22981
|
var init_agent_usage = __esm({
|
|
@@ -22885,52 +22995,6 @@ var init_agent_usage = __esm({
|
|
|
22885
22995
|
}
|
|
22886
22996
|
});
|
|
22887
22997
|
|
|
22888
|
-
// packages/api-contract/dist/system-events.js
|
|
22889
|
-
function isPerItemEventKind(value) {
|
|
22890
|
-
return PER_ITEM_EVENT_KINDS.includes(value);
|
|
22891
|
-
}
|
|
22892
|
-
var SYSTEM_LINE_SEPARATOR, SERVER_EVENT_KINDS, PER_ITEM_EVENT_KINDS, SUBSCRIBABLE_EVENT_KINDS, AGENT_EVENT_SLUG_MAX_LENGTH, AGENT_KIND;
|
|
22893
|
-
var init_system_events = __esm({
|
|
22894
|
-
"packages/api-contract/dist/system-events.js"() {
|
|
22895
|
-
"use strict";
|
|
22896
|
-
init_system_message_catalog();
|
|
22897
|
-
SYSTEM_LINE_SEPARATOR = systemMessage("system-events.separator");
|
|
22898
|
-
SERVER_EVENT_KINDS = [
|
|
22899
|
-
"joined",
|
|
22900
|
-
"left",
|
|
22901
|
-
"schedule-ran",
|
|
22902
|
-
"corner-opened",
|
|
22903
|
-
"check-passed",
|
|
22904
|
-
"check-failed",
|
|
22905
|
-
"merged",
|
|
22906
|
-
"grant-decided",
|
|
22907
|
-
"squire-approval-decided",
|
|
22908
|
-
"connector-offer-decided",
|
|
22909
|
-
"turn-cancelled",
|
|
22910
|
-
"choice-answered",
|
|
22911
|
-
"choice-skipped",
|
|
22912
|
-
"poll-closed",
|
|
22913
|
-
"workflow-handoff",
|
|
22914
|
-
"subscription-fired",
|
|
22915
|
-
"computer-session-activity"
|
|
22916
|
-
];
|
|
22917
|
-
PER_ITEM_EVENT_KINDS = [
|
|
22918
|
-
"grant-decided",
|
|
22919
|
-
"squire-approval-decided",
|
|
22920
|
-
"connector-offer-decided",
|
|
22921
|
-
"turn-cancelled",
|
|
22922
|
-
"choice-answered",
|
|
22923
|
-
"choice-skipped",
|
|
22924
|
-
"poll-closed",
|
|
22925
|
-
"subscription-fired",
|
|
22926
|
-
"computer-session-activity"
|
|
22927
|
-
];
|
|
22928
|
-
SUBSCRIBABLE_EVENT_KINDS = SERVER_EVENT_KINDS.filter((kind) => !isPerItemEventKind(kind) && kind !== "merged");
|
|
22929
|
-
AGENT_EVENT_SLUG_MAX_LENGTH = 40;
|
|
22930
|
-
AGENT_KIND = new RegExp(`^agent:[a-z0-9-]{1,${AGENT_EVENT_SLUG_MAX_LENGTH}}$`);
|
|
22931
|
-
}
|
|
22932
|
-
});
|
|
22933
|
-
|
|
22934
22998
|
// packages/api-contract/dist/agent-sign-in.js
|
|
22935
22999
|
var AGENT_SIGN_IN_ATTEMPT_TTL_MS, AGENT_SIGN_IN_SERVICE_LABELS;
|
|
22936
23000
|
var init_agent_sign_in = __esm({
|
|
@@ -22950,15 +23014,6 @@ var init_agent_sign_in = __esm({
|
|
|
22950
23014
|
}
|
|
22951
23015
|
});
|
|
22952
23016
|
|
|
22953
|
-
// packages/api-contract/dist/agent-access.js
|
|
22954
|
-
var ACCESS_NOTICE_WINDOW_MS;
|
|
22955
|
-
var init_agent_access = __esm({
|
|
22956
|
-
"packages/api-contract/dist/agent-access.js"() {
|
|
22957
|
-
"use strict";
|
|
22958
|
-
ACCESS_NOTICE_WINDOW_MS = 10 * 6e4;
|
|
22959
|
-
}
|
|
22960
|
-
});
|
|
22961
|
-
|
|
22962
23017
|
// packages/api-contract/dist/agent-grants.js
|
|
22963
23018
|
var AGENT_GRANT_KINDS, REQUESTABLE_AGENT_GRANT_KINDS, DECISION_LINE;
|
|
22964
23019
|
var init_agent_grants = __esm({
|
|
@@ -23049,23 +23104,124 @@ var init_room_choices = __esm({
|
|
|
23049
23104
|
}
|
|
23050
23105
|
});
|
|
23051
23106
|
|
|
23107
|
+
// packages/api-contract/dist/repository-onboarding.js
|
|
23108
|
+
var init_repository_onboarding = __esm({
|
|
23109
|
+
"packages/api-contract/dist/repository-onboarding.js"() {
|
|
23110
|
+
"use strict";
|
|
23111
|
+
}
|
|
23112
|
+
});
|
|
23113
|
+
|
|
23114
|
+
// packages/api-contract/dist/vault-save.js
|
|
23115
|
+
var init_vault_save = __esm({
|
|
23116
|
+
"packages/api-contract/dist/vault-save.js"() {
|
|
23117
|
+
"use strict";
|
|
23118
|
+
}
|
|
23119
|
+
});
|
|
23120
|
+
|
|
23121
|
+
// packages/api-contract/dist/system-events.js
|
|
23122
|
+
function isPerItemEventKind(value) {
|
|
23123
|
+
return PER_ITEM_EVENT_KINDS.includes(value);
|
|
23124
|
+
}
|
|
23125
|
+
var SYSTEM_LINE_SEPARATOR, SERVER_EVENT_KINDS, PER_ITEM_EVENT_KINDS, SUBSCRIBABLE_EVENT_KINDS, AGENT_EVENT_SLUG_MAX_LENGTH, AGENT_KIND;
|
|
23126
|
+
var init_system_events = __esm({
|
|
23127
|
+
"packages/api-contract/dist/system-events.js"() {
|
|
23128
|
+
"use strict";
|
|
23129
|
+
init_system_message_catalog();
|
|
23130
|
+
SYSTEM_LINE_SEPARATOR = systemMessage("system-events.separator");
|
|
23131
|
+
SERVER_EVENT_KINDS = [
|
|
23132
|
+
"joined",
|
|
23133
|
+
"left",
|
|
23134
|
+
"schedule-ran",
|
|
23135
|
+
"corner-opened",
|
|
23136
|
+
"check-passed",
|
|
23137
|
+
"check-failed",
|
|
23138
|
+
"merged",
|
|
23139
|
+
"grant-decided",
|
|
23140
|
+
"squire-approval-decided",
|
|
23141
|
+
"connector-offer-decided",
|
|
23142
|
+
"turn-cancelled",
|
|
23143
|
+
"choice-answered",
|
|
23144
|
+
"choice-skipped",
|
|
23145
|
+
"poll-closed",
|
|
23146
|
+
"workflow-handoff",
|
|
23147
|
+
"subscription-fired",
|
|
23148
|
+
"computer-session-activity"
|
|
23149
|
+
];
|
|
23150
|
+
PER_ITEM_EVENT_KINDS = [
|
|
23151
|
+
"grant-decided",
|
|
23152
|
+
"squire-approval-decided",
|
|
23153
|
+
"connector-offer-decided",
|
|
23154
|
+
"turn-cancelled",
|
|
23155
|
+
"choice-answered",
|
|
23156
|
+
"choice-skipped",
|
|
23157
|
+
"poll-closed",
|
|
23158
|
+
"subscription-fired",
|
|
23159
|
+
"computer-session-activity"
|
|
23160
|
+
];
|
|
23161
|
+
SUBSCRIBABLE_EVENT_KINDS = SERVER_EVENT_KINDS.filter((kind) => !isPerItemEventKind(kind) && kind !== "merged");
|
|
23162
|
+
AGENT_EVENT_SLUG_MAX_LENGTH = 40;
|
|
23163
|
+
AGENT_KIND = new RegExp(`^agent:[a-z0-9-]{1,${AGENT_EVENT_SLUG_MAX_LENGTH}}$`);
|
|
23164
|
+
}
|
|
23165
|
+
});
|
|
23166
|
+
|
|
23167
|
+
// packages/api-contract/dist/phone-guards-read-choice-card.js
|
|
23168
|
+
var init_phone_guards_read_choice_card = __esm({
|
|
23169
|
+
"packages/api-contract/dist/phone-guards-read-choice-card.js"() {
|
|
23170
|
+
"use strict";
|
|
23171
|
+
init_repository_onboarding();
|
|
23172
|
+
init_vault_save();
|
|
23173
|
+
init_system_events();
|
|
23174
|
+
init_voice();
|
|
23175
|
+
init_phone_types();
|
|
23176
|
+
init_room_choices();
|
|
23177
|
+
init_phone_guards();
|
|
23178
|
+
}
|
|
23179
|
+
});
|
|
23180
|
+
|
|
23181
|
+
// packages/api-contract/dist/agent-access.js
|
|
23182
|
+
var ACCESS_NOTICE_WINDOW_MS;
|
|
23183
|
+
var init_agent_access = __esm({
|
|
23184
|
+
"packages/api-contract/dist/agent-access.js"() {
|
|
23185
|
+
"use strict";
|
|
23186
|
+
ACCESS_NOTICE_WINDOW_MS = 10 * 6e4;
|
|
23187
|
+
}
|
|
23188
|
+
});
|
|
23189
|
+
|
|
23190
|
+
// packages/api-contract/dist/phone-guards-read-corner-lifecycle.js
|
|
23191
|
+
var init_phone_guards_read_corner_lifecycle = __esm({
|
|
23192
|
+
"packages/api-contract/dist/phone-guards-read-corner-lifecycle.js"() {
|
|
23193
|
+
"use strict";
|
|
23194
|
+
init_agent_access();
|
|
23195
|
+
init_phone_types();
|
|
23196
|
+
init_phone_guards();
|
|
23197
|
+
init_phone_guards_read_choice_card();
|
|
23198
|
+
}
|
|
23199
|
+
});
|
|
23200
|
+
|
|
23201
|
+
// packages/api-contract/dist/phone-guards-read-agent-detail-view.js
|
|
23202
|
+
var init_phone_guards_read_agent_detail_view = __esm({
|
|
23203
|
+
"packages/api-contract/dist/phone-guards-read-agent-detail-view.js"() {
|
|
23204
|
+
"use strict";
|
|
23205
|
+
init_agent_usage();
|
|
23206
|
+
init_phone_guards();
|
|
23207
|
+
init_phone_guards_read_corner_lifecycle();
|
|
23208
|
+
}
|
|
23209
|
+
});
|
|
23210
|
+
|
|
23052
23211
|
// packages/api-contract/dist/phone-guards.js
|
|
23053
23212
|
var CLOSED_VIEWER;
|
|
23054
23213
|
var init_phone_guards = __esm({
|
|
23055
23214
|
"packages/api-contract/dist/phone-guards.js"() {
|
|
23056
23215
|
"use strict";
|
|
23057
|
-
init_repository_onboarding();
|
|
23058
|
-
init_vault_save();
|
|
23059
23216
|
init_agent_usage();
|
|
23060
|
-
init_system_events();
|
|
23061
23217
|
init_agent_sign_in();
|
|
23062
|
-
init_agent_access();
|
|
23063
|
-
init_voice();
|
|
23064
|
-
init_phone_types();
|
|
23065
23218
|
init_agent_grants();
|
|
23066
23219
|
init_connector_offers();
|
|
23067
23220
|
init_workbench();
|
|
23068
23221
|
init_room_choices();
|
|
23222
|
+
init_phone_guards_read_choice_card();
|
|
23223
|
+
init_phone_guards_read_corner_lifecycle();
|
|
23224
|
+
init_phone_guards_read_agent_detail_view();
|
|
23069
23225
|
CLOSED_VIEWER = {
|
|
23070
23226
|
identity: { pubkey: "0".repeat(64), kind: "human", name: "" },
|
|
23071
23227
|
role: "member",
|
|
@@ -23697,9 +23853,9 @@ var init_stream_frame = __esm({
|
|
|
23697
23853
|
import { execFile as execFile3 } from "node:child_process";
|
|
23698
23854
|
import { closeSync, fstatSync, openSync, readSync, readdirSync as readdirSync2, readlinkSync, statSync as statSync2 } from "node:fs";
|
|
23699
23855
|
import { homedir as homedir5 } from "node:os";
|
|
23700
|
-
import { basename as basename3, join as
|
|
23856
|
+
import { basename as basename3, join as join4 } from "node:path";
|
|
23701
23857
|
function codexHome(env = process.env) {
|
|
23702
|
-
return env.CODEX_HOME ||
|
|
23858
|
+
return env.CODEX_HOME || join4(env.HOME || homedir5(), ".codex");
|
|
23703
23859
|
}
|
|
23704
23860
|
function turnEvent(line) {
|
|
23705
23861
|
if (!line.includes("event_msg") || !(line.includes("task_") || line.includes("turn_")))
|
|
@@ -23763,14 +23919,14 @@ function scanCodex(proc = "/proc") {
|
|
|
23763
23919
|
continue;
|
|
23764
23920
|
let fds;
|
|
23765
23921
|
try {
|
|
23766
|
-
fds = readdirSync2(
|
|
23922
|
+
fds = readdirSync2(join4(proc, name, "fd"));
|
|
23767
23923
|
} catch {
|
|
23768
23924
|
continue;
|
|
23769
23925
|
}
|
|
23770
23926
|
for (const fd of fds) {
|
|
23771
23927
|
let target;
|
|
23772
23928
|
try {
|
|
23773
|
-
target = readlinkSync(
|
|
23929
|
+
target = readlinkSync(join4(proc, name, "fd", fd));
|
|
23774
23930
|
} catch {
|
|
23775
23931
|
continue;
|
|
23776
23932
|
}
|
|
@@ -23779,7 +23935,7 @@ function scanCodex(proc = "/proc") {
|
|
|
23779
23935
|
continue;
|
|
23780
23936
|
let cwd;
|
|
23781
23937
|
try {
|
|
23782
|
-
cwd = readlinkSync(
|
|
23938
|
+
cwd = readlinkSync(join4(proc, name, "cwd"));
|
|
23783
23939
|
} catch {
|
|
23784
23940
|
}
|
|
23785
23941
|
if (!found.some((s) => s.threadId === threadId))
|
|
@@ -23789,12 +23945,12 @@ function scanCodex(proc = "/proc") {
|
|
|
23789
23945
|
return found;
|
|
23790
23946
|
}
|
|
23791
23947
|
function codexQueue(threadId, text, bin = "codex", timeoutMs = 3e4) {
|
|
23792
|
-
return new Promise((
|
|
23948
|
+
return new Promise((resolve13, reject) => {
|
|
23793
23949
|
execFile3(bin, ["queue", "--thread", threadId, "--message", text], { timeout: timeoutMs }, (error, _stdout, stderr) => {
|
|
23794
23950
|
if (error)
|
|
23795
23951
|
reject(new Error(String(stderr).trim() || error.message));
|
|
23796
23952
|
else
|
|
23797
|
-
|
|
23953
|
+
resolve13();
|
|
23798
23954
|
});
|
|
23799
23955
|
});
|
|
23800
23956
|
}
|
|
@@ -23812,12 +23968,12 @@ var init_codex = __esm({
|
|
|
23812
23968
|
import { closeSync as closeSync2, fstatSync as fstatSync2, openSync as openSync2, readFileSync as readFileSync4, readSync as readSync2, readdirSync as readdirSync3, statSync as statSync3 } from "node:fs";
|
|
23813
23969
|
import { createConnection as createConnection3 } from "node:net";
|
|
23814
23970
|
import { homedir as homedir6 } from "node:os";
|
|
23815
|
-
import { join as
|
|
23971
|
+
import { join as join5 } from "node:path";
|
|
23816
23972
|
function claudeConfigDir(env = process.env) {
|
|
23817
|
-
return env.CLAUDE_CONFIG_DIR ||
|
|
23973
|
+
return env.CLAUDE_CONFIG_DIR || join5(env.HOME || homedir6(), ".claude");
|
|
23818
23974
|
}
|
|
23819
23975
|
function scanClaude(env = process.env, alive = pidAlive) {
|
|
23820
|
-
const dir =
|
|
23976
|
+
const dir = join5(claudeConfigDir(env), "sessions");
|
|
23821
23977
|
let names;
|
|
23822
23978
|
try {
|
|
23823
23979
|
names = readdirSync3(dir);
|
|
@@ -23829,7 +23985,7 @@ function scanClaude(env = process.env, alive = pidAlive) {
|
|
|
23829
23985
|
if (!/^\d+\.json$/.test(name))
|
|
23830
23986
|
continue;
|
|
23831
23987
|
try {
|
|
23832
|
-
const value = JSON.parse(readFileSync4(
|
|
23988
|
+
const value = JSON.parse(readFileSync4(join5(dir, name), "utf8"));
|
|
23833
23989
|
if (Number.isInteger(value.pid) && alive(value.pid))
|
|
23834
23990
|
sessions.push(value);
|
|
23835
23991
|
} catch {
|
|
@@ -23841,7 +23997,7 @@ function chosenName(session2) {
|
|
|
23841
23997
|
return ["user", "peer", "hook"].includes(session2.nameSource ?? "") ? session2.name : void 0;
|
|
23842
23998
|
}
|
|
23843
23999
|
function postToClaude(socket, text, _timeoutMs = 5e3) {
|
|
23844
|
-
return new Promise((
|
|
24000
|
+
return new Promise((resolve13, reject) => {
|
|
23845
24001
|
const connection = createConnection3(socket.path);
|
|
23846
24002
|
connection.once("error", (error) => {
|
|
23847
24003
|
reject(error);
|
|
@@ -23850,13 +24006,13 @@ function postToClaude(socket, text, _timeoutMs = 5e3) {
|
|
|
23850
24006
|
if (socket.token)
|
|
23851
24007
|
connection.write(JSON.stringify({ type: "auth", token: socket.token }) + "\n");
|
|
23852
24008
|
connection.end(JSON.stringify({ type: "user", message: { role: "user", content: text } }) + "\n", () => {
|
|
23853
|
-
|
|
24009
|
+
resolve13();
|
|
23854
24010
|
});
|
|
23855
24011
|
});
|
|
23856
24012
|
});
|
|
23857
24013
|
}
|
|
23858
24014
|
function claudeTranscript(sessionId, env = process.env) {
|
|
23859
|
-
const root =
|
|
24015
|
+
const root = join5(claudeConfigDir(env), "projects");
|
|
23860
24016
|
let projects;
|
|
23861
24017
|
try {
|
|
23862
24018
|
projects = readdirSync3(root);
|
|
@@ -23864,7 +24020,7 @@ function claudeTranscript(sessionId, env = process.env) {
|
|
|
23864
24020
|
return void 0;
|
|
23865
24021
|
}
|
|
23866
24022
|
for (const project of projects) {
|
|
23867
|
-
const path =
|
|
24023
|
+
const path = join5(root, project, `${sessionId}.jsonl`);
|
|
23868
24024
|
try {
|
|
23869
24025
|
if (statSync3(path).isFile())
|
|
23870
24026
|
return path;
|
|
@@ -23903,7 +24059,7 @@ function heldBy(mode, setting) {
|
|
|
23903
24059
|
}
|
|
23904
24060
|
function inboundSetting(env = process.env) {
|
|
23905
24061
|
try {
|
|
23906
|
-
const value = JSON.parse(readFileSync4(
|
|
24062
|
+
const value = JSON.parse(readFileSync4(join5(claudeConfigDir(env), "settings.json"), "utf8"));
|
|
23907
24063
|
return typeof value.crossSessionInbound === "string" ? value.crossSessionInbound : void 0;
|
|
23908
24064
|
} catch {
|
|
23909
24065
|
return void 0;
|
|
@@ -23918,20 +24074,20 @@ var init_claude = __esm({
|
|
|
23918
24074
|
|
|
23919
24075
|
// apps/body/dist/session-join/claude-mcp.js
|
|
23920
24076
|
import { watch as watch3, mkdirSync as mkdirSync2, readFileSync as readFileSync5, readdirSync as readdirSync4, rmSync as rmSync2, writeFileSync as writeFileSync2 } from "node:fs";
|
|
23921
|
-
import { join as
|
|
24077
|
+
import { join as join6 } from "node:path";
|
|
23922
24078
|
import { createInterface } from "node:readline";
|
|
23923
24079
|
function hasClaudeMcp(dir, claudePid) {
|
|
23924
24080
|
if (!claudePid)
|
|
23925
24081
|
return false;
|
|
23926
24082
|
let files;
|
|
23927
24083
|
try {
|
|
23928
|
-
files = readdirSync4(
|
|
24084
|
+
files = readdirSync4(join6(dir, "claude-mcp"));
|
|
23929
24085
|
} catch {
|
|
23930
24086
|
return false;
|
|
23931
24087
|
}
|
|
23932
24088
|
return files.some((file) => {
|
|
23933
24089
|
try {
|
|
23934
|
-
const entry = JSON.parse(readFileSync5(
|
|
24090
|
+
const entry = JSON.parse(readFileSync5(join6(dir, "claude-mcp", file), "utf8"));
|
|
23935
24091
|
return entry.claudePid === claudePid && pidAlive(entry.pid);
|
|
23936
24092
|
} catch {
|
|
23937
24093
|
return false;
|
|
@@ -23940,17 +24096,19 @@ function hasClaudeMcp(dir, claudePid) {
|
|
|
23940
24096
|
}
|
|
23941
24097
|
async function flushClaudeMcp(dir, session2, token, post = postToClaude) {
|
|
23942
24098
|
if (!session2.messagingSocketPath)
|
|
23943
|
-
return;
|
|
24099
|
+
return false;
|
|
23944
24100
|
const joined2 = readState(dir).sessions.find((s) => s.agent === "claude-code" && (s.pid === session2.pid || s.sessionId === session2.sessionId));
|
|
23945
24101
|
if (!joined2)
|
|
23946
|
-
return;
|
|
24102
|
+
return false;
|
|
23947
24103
|
const text = takeInbox(dir, joined2.key);
|
|
23948
24104
|
if (!text)
|
|
23949
|
-
return;
|
|
24105
|
+
return false;
|
|
23950
24106
|
try {
|
|
23951
24107
|
await post({ path: session2.messagingSocketPath, token }, text);
|
|
24108
|
+
return true;
|
|
23952
24109
|
} catch {
|
|
23953
24110
|
queueInbox(dir, joined2.key, text);
|
|
24111
|
+
return false;
|
|
23954
24112
|
}
|
|
23955
24113
|
}
|
|
23956
24114
|
function joinedClaude(dir, env, chain) {
|
|
@@ -23960,32 +24118,38 @@ function joinedClaude(dir, env, chain) {
|
|
|
23960
24118
|
return void 0;
|
|
23961
24119
|
return readState(dir).sessions.find((s) => s.agent === "claude-code" && (s.pid === session2.pid || s.sessionId === session2.sessionId));
|
|
23962
24120
|
}
|
|
23963
|
-
async function runClaudeMcp(dir, env, rulesFor) {
|
|
24121
|
+
async function runClaudeMcp(dir, env, rulesFor, post = postToClaude) {
|
|
23964
24122
|
const chain = ancestors(process.pid);
|
|
23965
24123
|
let registration;
|
|
23966
|
-
let flushing = false;
|
|
24124
|
+
let flushing = false, dirty = false;
|
|
23967
24125
|
const flush2 = async () => {
|
|
24126
|
+
dirty = true;
|
|
23968
24127
|
if (flushing || !env.CLAUDE_CODE_MESSAGING_TOKEN)
|
|
23969
24128
|
return;
|
|
23970
24129
|
flushing = true;
|
|
23971
24130
|
try {
|
|
23972
|
-
|
|
23973
|
-
|
|
23974
|
-
|
|
23975
|
-
|
|
23976
|
-
|
|
23977
|
-
|
|
23978
|
-
|
|
23979
|
-
|
|
23980
|
-
|
|
24131
|
+
while (dirty) {
|
|
24132
|
+
dirty = false;
|
|
24133
|
+
const live = scanClaude(env);
|
|
24134
|
+
const session2 = chain.map((pid) => live.find((s) => s.pid === pid)).find(Boolean);
|
|
24135
|
+
if (!session2)
|
|
24136
|
+
return;
|
|
24137
|
+
if (!registration) {
|
|
24138
|
+
const folder = join6(dir, "claude-mcp");
|
|
24139
|
+
mkdirSync2(folder, { recursive: true, mode: 448 });
|
|
24140
|
+
registration = join6(folder, `${process.pid}.json`);
|
|
24141
|
+
writeFileSync2(registration, JSON.stringify({ pid: process.pid, claudePid: session2.pid }), { mode: 384 });
|
|
24142
|
+
}
|
|
24143
|
+
if (!await flushClaudeMcp(dir, session2, env.CLAUDE_CODE_MESSAGING_TOKEN, post))
|
|
24144
|
+
break;
|
|
23981
24145
|
}
|
|
23982
|
-
await flushClaudeMcp(dir, session2, env.CLAUDE_CODE_MESSAGING_TOKEN);
|
|
23983
24146
|
} finally {
|
|
23984
24147
|
flushing = false;
|
|
23985
24148
|
}
|
|
23986
24149
|
};
|
|
23987
24150
|
const watcher = watch3(dir, { recursive: true }, (_event, name) => {
|
|
23988
|
-
|
|
24151
|
+
const path = String(name ?? "");
|
|
24152
|
+
if (path === "state.json" || path.startsWith("inbox/"))
|
|
23989
24153
|
void flush2().catch(() => void 0);
|
|
23990
24154
|
});
|
|
23991
24155
|
try {
|
|
@@ -24074,10 +24238,10 @@ var init_sessions = __esm({
|
|
|
24074
24238
|
});
|
|
24075
24239
|
|
|
24076
24240
|
// apps/body/dist/session-join/bridge.js
|
|
24077
|
-
import { spawn as
|
|
24241
|
+
import { execFileSync, spawn as spawn6 } from "node:child_process";
|
|
24078
24242
|
import { chmodSync as chmodSync2, closeSync as closeSync3, existsSync as existsSync2, mkdirSync as mkdirSync3, openSync as openSync3, readFileSync as readFileSync6, readdirSync as readdirSync5, renameSync as renameSync2, rmSync as rmSync3, writeFileSync as writeFileSync3, watch as watch4 } from "node:fs";
|
|
24079
24243
|
import { createConnection as createConnection4, createServer as createServer3 } from "node:net";
|
|
24080
|
-
import { join as
|
|
24244
|
+
import { basename as basename4, join as join7, resolve as resolve10 } from "node:path";
|
|
24081
24245
|
import { createHash as createHash6 } from "node:crypto";
|
|
24082
24246
|
function command(runner2, joined2, args) {
|
|
24083
24247
|
const q = (v) => /^[A-Za-z0-9_./:@=-]+$/.test(v) ? v : `"${v.replace(/(["\\$`])/g, "\\$1")}"`;
|
|
@@ -24179,7 +24343,7 @@ async function acceptMemberDelivery(dir, key, runner2, raw) {
|
|
|
24179
24343
|
}
|
|
24180
24344
|
function log(dir, line) {
|
|
24181
24345
|
try {
|
|
24182
|
-
writeFileSync3(
|
|
24346
|
+
writeFileSync3(join7(dir, "bridge.log"), `${(/* @__PURE__ */ new Date()).toISOString()} ${line}
|
|
24183
24347
|
`, { flag: "a", mode: 384 });
|
|
24184
24348
|
} catch {
|
|
24185
24349
|
}
|
|
@@ -24205,7 +24369,7 @@ async function flush(dir, sources, deps = realDeps) {
|
|
|
24205
24369
|
}
|
|
24206
24370
|
}
|
|
24207
24371
|
function serveTools(dir) {
|
|
24208
|
-
const path =
|
|
24372
|
+
const path = join7(dir, "bridge.sock");
|
|
24209
24373
|
rmSync3(path, { force: true });
|
|
24210
24374
|
const server = createServer3((connection) => {
|
|
24211
24375
|
let buffer = "", taken = false;
|
|
@@ -24233,7 +24397,7 @@ function serveTools(dir) {
|
|
|
24233
24397
|
server.unref();
|
|
24234
24398
|
}
|
|
24235
24399
|
function outboxDir(cwd) {
|
|
24236
|
-
return
|
|
24400
|
+
return join7(cwd, ".beeline", "outbox");
|
|
24237
24401
|
}
|
|
24238
24402
|
async function serveOutboxes(dir) {
|
|
24239
24403
|
let served = 0;
|
|
@@ -24245,7 +24409,7 @@ async function serveOutboxes(dir) {
|
|
|
24245
24409
|
continue;
|
|
24246
24410
|
}
|
|
24247
24411
|
for (const name of names.filter((n) => n.endsWith(".request.json"))) {
|
|
24248
|
-
const path =
|
|
24412
|
+
const path = join7(outboxDir(joined2.cwd), name);
|
|
24249
24413
|
const taking = `${path}.taking`;
|
|
24250
24414
|
try {
|
|
24251
24415
|
renameSync2(path, taking);
|
|
@@ -24271,19 +24435,19 @@ async function serveOutboxes(dir) {
|
|
|
24271
24435
|
async function toolViaOutbox(cwd, name, args) {
|
|
24272
24436
|
const dirPath = outboxDir(cwd);
|
|
24273
24437
|
mkdirSync3(dirPath, { recursive: true });
|
|
24274
|
-
writeFileSync3(
|
|
24438
|
+
writeFileSync3(join7(cwd, ".beeline", ".gitignore"), "*\n");
|
|
24275
24439
|
const id = `${Date.now()}-${process.pid}`;
|
|
24276
|
-
const request2 =
|
|
24440
|
+
const request2 = join7(dirPath, `${id}.request.json`), result = join7(dirPath, `${id}.result.json`);
|
|
24277
24441
|
writeFileSync3(`${request2}.tmp`, JSON.stringify({ name, args }));
|
|
24278
24442
|
renameSync2(`${request2}.tmp`, request2);
|
|
24279
|
-
return new Promise((
|
|
24443
|
+
return new Promise((resolve13) => {
|
|
24280
24444
|
let settled = false;
|
|
24281
24445
|
const finish = (answer) => {
|
|
24282
24446
|
if (settled)
|
|
24283
24447
|
return;
|
|
24284
24448
|
settled = true;
|
|
24285
24449
|
watcher.close();
|
|
24286
|
-
|
|
24450
|
+
resolve13(answer);
|
|
24287
24451
|
};
|
|
24288
24452
|
const inspect = () => {
|
|
24289
24453
|
try {
|
|
@@ -24301,15 +24465,15 @@ async function toolViaOutbox(cwd, name, args) {
|
|
|
24301
24465
|
});
|
|
24302
24466
|
}
|
|
24303
24467
|
function toolViaBridge(dir, key, name, args) {
|
|
24304
|
-
return new Promise((
|
|
24305
|
-
const connection = createConnection4(
|
|
24468
|
+
return new Promise((resolve13) => {
|
|
24469
|
+
const connection = createConnection4(join7(dir, "bridge.sock"));
|
|
24306
24470
|
let text = "", sent = false, settled = false;
|
|
24307
24471
|
const unknown = { ok: false, error: "Beeline tool result is awaiting confirmation" };
|
|
24308
24472
|
const finish = (answer) => {
|
|
24309
24473
|
if (settled)
|
|
24310
24474
|
return;
|
|
24311
24475
|
settled = true;
|
|
24312
|
-
|
|
24476
|
+
resolve13(answer);
|
|
24313
24477
|
connection.destroy();
|
|
24314
24478
|
};
|
|
24315
24479
|
connection.setEncoding("utf8");
|
|
@@ -24331,7 +24495,7 @@ function toolViaBridge(dir, key, name, args) {
|
|
|
24331
24495
|
});
|
|
24332
24496
|
}
|
|
24333
24497
|
async function runBridge(dir, runner2) {
|
|
24334
|
-
const pidFile =
|
|
24498
|
+
const pidFile = join7(dir, "bridge.pid");
|
|
24335
24499
|
try {
|
|
24336
24500
|
const fd = openSync3(pidFile, "wx", 384);
|
|
24337
24501
|
writeFileSync3(fd, String(process.pid));
|
|
@@ -24351,6 +24515,7 @@ async function runBridge(dir, runner2) {
|
|
|
24351
24515
|
wake?.();
|
|
24352
24516
|
};
|
|
24353
24517
|
serveTools(dir);
|
|
24518
|
+
writeFileSync3(join7(dir, "bridge-owner.json"), JSON.stringify({ pid: process.pid, digest: bundleDigest(runner2) }), { mode: 384 });
|
|
24354
24519
|
const localWatch = watch4(dir, { recursive: true }, (_event, name) => {
|
|
24355
24520
|
const path = String(name ?? "");
|
|
24356
24521
|
if (path === "state.json" || path.startsWith("hooks/") || path.startsWith("inbox/") || path.startsWith("deliveries/"))
|
|
@@ -24364,7 +24529,7 @@ async function runBridge(dir, runner2) {
|
|
|
24364
24529
|
for (const watcher of outboxWatches.values())
|
|
24365
24530
|
watcher.close();
|
|
24366
24531
|
rmSync3(pidFile, { force: true });
|
|
24367
|
-
rmSync3(
|
|
24532
|
+
rmSync3(join7(dir, "bridge.sock"), { force: true });
|
|
24368
24533
|
process.exit(0);
|
|
24369
24534
|
};
|
|
24370
24535
|
process.once("SIGTERM", stop);
|
|
@@ -24435,7 +24600,7 @@ async function runBridge(dir, runner2) {
|
|
|
24435
24600
|
const path = outboxDir(joined2.cwd);
|
|
24436
24601
|
if (!outboxWatches.has(path)) {
|
|
24437
24602
|
mkdirSync3(path, { recursive: true, mode: 448 });
|
|
24438
|
-
const ignore =
|
|
24603
|
+
const ignore = join7(joined2.cwd, ".beeline", ".gitignore");
|
|
24439
24604
|
if (!existsSync2(ignore))
|
|
24440
24605
|
writeFileSync3(ignore, "*\n", { mode: 384 });
|
|
24441
24606
|
outboxWatches.set(path, watch4(path, (_event, name) => {
|
|
@@ -24447,8 +24612,8 @@ async function runBridge(dir, runner2) {
|
|
|
24447
24612
|
await serveOutboxes(dir).catch((error) => log(dir, `outbox: ${String(error)}`));
|
|
24448
24613
|
await flush(dir, sources).catch((error) => log(dir, `flush: ${String(error)}`));
|
|
24449
24614
|
if (!localDirty)
|
|
24450
|
-
await new Promise((
|
|
24451
|
-
wake =
|
|
24615
|
+
await new Promise((resolve13) => {
|
|
24616
|
+
wake = resolve13;
|
|
24452
24617
|
});
|
|
24453
24618
|
wake = void 0;
|
|
24454
24619
|
}
|
|
@@ -24462,30 +24627,101 @@ async function runBridge(dir, runner2) {
|
|
|
24462
24627
|
}
|
|
24463
24628
|
log(dir, `bridge ${process.pid} stopped: no joined sessions`);
|
|
24464
24629
|
rmSync3(pidFile, { force: true });
|
|
24465
|
-
rmSync3(
|
|
24630
|
+
rmSync3(join7(dir, "bridge.sock"), { force: true });
|
|
24466
24631
|
process.exit(0);
|
|
24467
24632
|
}
|
|
24468
24633
|
function bridgeRunning(dir) {
|
|
24469
24634
|
try {
|
|
24470
|
-
const holder = Number(readFileSync6(
|
|
24635
|
+
const holder = Number(readFileSync6(join7(dir, "bridge.pid"), "utf8"));
|
|
24471
24636
|
return Boolean(holder) && pidAlive(holder);
|
|
24472
24637
|
} catch {
|
|
24473
24638
|
return false;
|
|
24474
24639
|
}
|
|
24475
24640
|
}
|
|
24476
|
-
function
|
|
24477
|
-
|
|
24478
|
-
|
|
24479
|
-
|
|
24480
|
-
|
|
24481
|
-
|
|
24482
|
-
|
|
24641
|
+
function bundleDigest(runner2) {
|
|
24642
|
+
return createHash6("sha256").update(readFileSync6(runner2.bundle)).digest("hex");
|
|
24643
|
+
}
|
|
24644
|
+
function bridgeOwner(dir) {
|
|
24645
|
+
try {
|
|
24646
|
+
return JSON.parse(readFileSync6(join7(dir, "bridge-owner.json"), "utf8"));
|
|
24647
|
+
} catch {
|
|
24648
|
+
return void 0;
|
|
24649
|
+
}
|
|
24650
|
+
}
|
|
24651
|
+
function isBridgeProcess(pid) {
|
|
24652
|
+
try {
|
|
24653
|
+
if (process.platform === "linux") {
|
|
24654
|
+
const args2 = readFileSync6(`/proc/${pid}/cmdline`, "utf8").split("\0").filter(Boolean);
|
|
24655
|
+
return args2.length === 4 && /^node(?:\.exe)?$/.test(basename4(args2[0])) && /^(?:beeline|usebeeline\.mjs|recovery-cli\.mjs)$/.test(basename4(args2[1])) && args2[2] === "session" && args2[3] === "bridge";
|
|
24656
|
+
}
|
|
24657
|
+
const args = execFileSync("ps", ["-ww", "-p", String(pid), "-o", "args="], { encoding: "utf8" }).trim();
|
|
24658
|
+
return /(?:^|\/)node\s+.*\/(?:beeline|usebeeline\.mjs|recovery-cli\.mjs) session bridge$/.test(args);
|
|
24659
|
+
} catch {
|
|
24660
|
+
return false;
|
|
24661
|
+
}
|
|
24662
|
+
}
|
|
24663
|
+
async function ensureBridge(dir, runner2, env = process.env) {
|
|
24664
|
+
await withKernelLock(`beeline-session-bridge:${resolve10(dir)}`, async () => {
|
|
24665
|
+
const digest = bundleDigest(runner2);
|
|
24666
|
+
const pidFile = join7(dir, "bridge.pid");
|
|
24667
|
+
if (bridgeRunning(dir)) {
|
|
24668
|
+
const pid = Number(readFileSync6(pidFile, "utf8"));
|
|
24669
|
+
if (!isBridgeProcess(pid))
|
|
24670
|
+
throw new Error("Beeline bridge PID belongs to an unrecognized process; refusing takeover");
|
|
24671
|
+
const owner = bridgeOwner(dir);
|
|
24672
|
+
if (owner?.pid === pid && owner.digest === digest)
|
|
24673
|
+
return;
|
|
24674
|
+
log(dir, `replacing stale bridge ${pid}`);
|
|
24675
|
+
await withLock(dir, async () => {
|
|
24676
|
+
try {
|
|
24677
|
+
process.kill(pid, "SIGTERM");
|
|
24678
|
+
} catch (error) {
|
|
24679
|
+
if (error.code !== "ESRCH")
|
|
24680
|
+
throw error;
|
|
24681
|
+
}
|
|
24682
|
+
await waitForProcessExit(pid);
|
|
24683
|
+
});
|
|
24684
|
+
if (existsSync2(pidFile) && Number(readFileSync6(pidFile, "utf8")) === pid)
|
|
24685
|
+
rmSync3(pidFile);
|
|
24686
|
+
}
|
|
24687
|
+
const out = openSync3(join7(dir, "bridge.log"), "a", 384);
|
|
24688
|
+
const child = spawn6(runner2.node, [runner2.bundle, "session", "bridge"], { detached: true, stdio: ["ignore", out, out], env });
|
|
24689
|
+
closeSync3(out);
|
|
24690
|
+
child.unref();
|
|
24691
|
+
await new Promise((done, fail) => {
|
|
24692
|
+
const finish = (error) => {
|
|
24693
|
+
watcher.close();
|
|
24694
|
+
child.removeListener("error", failed);
|
|
24695
|
+
child.removeListener("exit", exited);
|
|
24696
|
+
if (error)
|
|
24697
|
+
fail(error);
|
|
24698
|
+
else
|
|
24699
|
+
done();
|
|
24700
|
+
};
|
|
24701
|
+
const inspect = () => {
|
|
24702
|
+
const owner = bridgeOwner(dir);
|
|
24703
|
+
if (owner && owner.pid === child.pid && owner.digest === digest)
|
|
24704
|
+
finish();
|
|
24705
|
+
};
|
|
24706
|
+
const failed = (error) => finish(error);
|
|
24707
|
+
const exited = () => finish(new Error("Beeline bridge exited before readiness; see bridge.log"));
|
|
24708
|
+
const watcher = watch4(dir, (_event, name) => {
|
|
24709
|
+
if (String(name) === "bridge-owner.json")
|
|
24710
|
+
inspect();
|
|
24711
|
+
});
|
|
24712
|
+
child.once("error", failed);
|
|
24713
|
+
child.once("exit", exited);
|
|
24714
|
+
inspect();
|
|
24715
|
+
});
|
|
24716
|
+
});
|
|
24483
24717
|
}
|
|
24484
24718
|
var realDeps;
|
|
24485
24719
|
var init_bridge = __esm({
|
|
24486
24720
|
"apps/body/dist/session-join/bridge.js"() {
|
|
24487
24721
|
"use strict";
|
|
24488
24722
|
init_agent_command();
|
|
24723
|
+
init_kernel_lock();
|
|
24724
|
+
init_process_exit();
|
|
24489
24725
|
init_phone();
|
|
24490
24726
|
init_beeline_api();
|
|
24491
24727
|
init_stream_frame();
|
|
@@ -24735,7 +24971,7 @@ def register(ctx):
|
|
|
24735
24971
|
import { spawnSync } from "node:child_process";
|
|
24736
24972
|
import { copyFileSync, existsSync as existsSync3, mkdirSync as mkdirSync4, readFileSync as readFileSync7, renameSync as renameSync3, rmSync as rmSync4, statSync as statSync4, writeFileSync as writeFileSync4, chmodSync as chmodSync3 } from "node:fs";
|
|
24737
24973
|
import { homedir as homedir7 } from "node:os";
|
|
24738
|
-
import { dirname as
|
|
24974
|
+
import { dirname as dirname7, join as join8 } from "node:path";
|
|
24739
24975
|
function home(env) {
|
|
24740
24976
|
return env.HOME || homedir7();
|
|
24741
24977
|
}
|
|
@@ -24771,7 +25007,7 @@ function writeFile3(path, content, expected) {
|
|
|
24771
25007
|
}
|
|
24772
25008
|
if (before === content)
|
|
24773
25009
|
return false;
|
|
24774
|
-
mkdirSync4(
|
|
25010
|
+
mkdirSync4(dirname7(path), { recursive: true });
|
|
24775
25011
|
const backup = `${path}.bak-${NAME}`;
|
|
24776
25012
|
if (before !== void 0 && !existsSync3(backup) && !before.includes(" session hook "))
|
|
24777
25013
|
copyFileSync(path, backup);
|
|
@@ -24881,18 +25117,18 @@ function saveJson(path, value, remove) {
|
|
|
24881
25117
|
function claudeCode(context) {
|
|
24882
25118
|
const command2 = (event) => ({ hooks: [{ type: "command", command: hookCommand(context, "claude-code", event), timeout: 10 }] });
|
|
24883
25119
|
const remove = Boolean(context.remove);
|
|
24884
|
-
const path = context.env.CLAUDE_CONFIG_DIR ?
|
|
24885
|
-
return [...mergeClaudeMcp(path, context), ...hooksFile(
|
|
25120
|
+
const path = context.env.CLAUDE_CONFIG_DIR ? join8(context.env.CLAUDE_CONFIG_DIR, ".claude.json") : join8(home(context.env), ".claude.json");
|
|
25121
|
+
return [...mergeClaudeMcp(path, context), ...hooksFile(join8(claudeConfigDir(context.env), "settings.json"), "claude-code", [["SessionStart", command2("session-start")]], remove)];
|
|
24886
25122
|
}
|
|
24887
25123
|
function codex(context) {
|
|
24888
25124
|
const group = (event) => ({ matcher: "*", hooks: [{ type: "command", command: hookCommand(context, "codex", event), timeout: 10 }] });
|
|
24889
|
-
const lines = hooksFile(
|
|
25125
|
+
const lines = hooksFile(join8(codexHome(context.env), "hooks.json"), "codex", [["SessionStart", group("session-start")]], Boolean(context.remove));
|
|
24890
25126
|
if (lines.length && !context.remove)
|
|
24891
25127
|
lines.push("Codex asks once to trust Beeline\u2019s SessionStart hook if automatic trust is unavailable: open /hooks and trust only Beeline.");
|
|
24892
25128
|
return lines;
|
|
24893
25129
|
}
|
|
24894
25130
|
function geminiHome(env) {
|
|
24895
|
-
return env.GEMINI_CLI_HOME ||
|
|
25131
|
+
return env.GEMINI_CLI_HOME || join8(home(env), ".gemini");
|
|
24896
25132
|
}
|
|
24897
25133
|
function gemini(context) {
|
|
24898
25134
|
const group = (event, timeout) => ({ matcher: "*", hooks: [{
|
|
@@ -24901,7 +25137,7 @@ function gemini(context) {
|
|
|
24901
25137
|
command: hookCommand(context, "gemini", event),
|
|
24902
25138
|
timeout
|
|
24903
25139
|
}] });
|
|
24904
|
-
return hooksFile(
|
|
25140
|
+
return hooksFile(join8(geminiHome(context.env), "settings.json"), "gemini", [
|
|
24905
25141
|
["SessionStart", group("session-start", 1e4)],
|
|
24906
25142
|
["BeforeAgent", group("user-prompt-submit", 1e4)],
|
|
24907
25143
|
["AfterTool", group("post-tool-use", 1e4)],
|
|
@@ -24910,9 +25146,9 @@ function gemini(context) {
|
|
|
24910
25146
|
], Boolean(context.remove));
|
|
24911
25147
|
}
|
|
24912
25148
|
function antigravity(context) {
|
|
24913
|
-
const dir =
|
|
25149
|
+
const dir = join8(home(context.env), ".gemini/config");
|
|
24914
25150
|
const lines = [];
|
|
24915
|
-
const hooksPath =
|
|
25151
|
+
const hooksPath = join8(dir, "hooks.json");
|
|
24916
25152
|
const hooks = readJson(hooksPath);
|
|
24917
25153
|
if (context.remove)
|
|
24918
25154
|
delete hooks[NAME];
|
|
@@ -24928,13 +25164,13 @@ function antigravity(context) {
|
|
|
24928
25164
|
};
|
|
24929
25165
|
}
|
|
24930
25166
|
lines.push(...saveJson(hooksPath, hooks, Boolean(context.remove)));
|
|
24931
|
-
const sidecar =
|
|
24932
|
-
const configPath =
|
|
25167
|
+
const sidecar = join8(dir, "sidecars", NAME, "sidecar.json");
|
|
25168
|
+
const configPath = join8(dir, "config.json");
|
|
24933
25169
|
const config = readJson(configPath);
|
|
24934
25170
|
const sidecars = object2(config, "sidecars");
|
|
24935
25171
|
if (context.remove) {
|
|
24936
25172
|
delete sidecars[NAME];
|
|
24937
|
-
rmSync4(
|
|
25173
|
+
rmSync4(dirname7(sidecar), { recursive: true, force: true });
|
|
24938
25174
|
} else {
|
|
24939
25175
|
if (writeJson(sidecar, {
|
|
24940
25176
|
command: context.node,
|
|
@@ -24961,31 +25197,31 @@ function pluginFile(path, content, remove) {
|
|
|
24961
25197
|
return writeFile3(path, content) ? [`updated ${path}`] : [];
|
|
24962
25198
|
}
|
|
24963
25199
|
function opencode(context) {
|
|
24964
|
-
return pluginFile(
|
|
25200
|
+
return pluginFile(join8(home(context.env), ".config/opencode/plugins", `${NAME}.ts`), fill(OPENCODE_PLUGIN, context.node, context.bundle), Boolean(context.remove));
|
|
24965
25201
|
}
|
|
24966
25202
|
function piHome(env) {
|
|
24967
|
-
return env.PI_CODING_AGENT_DIR ||
|
|
25203
|
+
return env.PI_CODING_AGENT_DIR || join8(home(env), ".pi/agent");
|
|
24968
25204
|
}
|
|
24969
25205
|
function pi(context) {
|
|
24970
|
-
return pluginFile(
|
|
25206
|
+
return pluginFile(join8(piHome(context.env), "extensions", `${NAME}.ts`), fill(PI_EXTENSION, context.node, context.bundle), Boolean(context.remove));
|
|
24971
25207
|
}
|
|
24972
25208
|
function hermesRoot(env) {
|
|
24973
|
-
const base = env.HERMES_HOME ? env.HERMES_HOME.replace(/^~(?=\/|$)/, home(env)) :
|
|
25209
|
+
const base = env.HERMES_HOME ? env.HERMES_HOME.replace(/^~(?=\/|$)/, home(env)) : join8(home(env), `.hermes${env.HERMES_DATA_DIR_SUFFIX ?? ""}`);
|
|
24974
25210
|
let active = "";
|
|
24975
25211
|
try {
|
|
24976
|
-
active = readFileSync7(
|
|
25212
|
+
active = readFileSync7(join8(base, "active_profile"), "utf8").trim();
|
|
24977
25213
|
} catch {
|
|
24978
25214
|
}
|
|
24979
|
-
if (active && active !== "default" && active !== "." && active !== ".." && !/[/\\]/.test(active) && existsSync3(
|
|
24980
|
-
return
|
|
25215
|
+
if (active && active !== "default" && active !== "." && active !== ".." && !/[/\\]/.test(active) && existsSync3(join8(base, "profiles", active)))
|
|
25216
|
+
return join8(base, "profiles", active);
|
|
24981
25217
|
return base;
|
|
24982
25218
|
}
|
|
24983
25219
|
function hermes(context) {
|
|
24984
|
-
const dir =
|
|
25220
|
+
const dir = join8(hermesRoot(context.env), "plugins", NAME);
|
|
24985
25221
|
const remove = Boolean(context.remove);
|
|
24986
25222
|
const lines = [
|
|
24987
|
-
...pluginFile(
|
|
24988
|
-
...pluginFile(
|
|
25223
|
+
...pluginFile(join8(dir, "__init__.py"), fill(HERMES_PLUGIN, context.node, context.bundle), remove),
|
|
25224
|
+
...pluginFile(join8(dir, "plugin.yaml"), HERMES_MANIFEST, remove)
|
|
24989
25225
|
];
|
|
24990
25226
|
if (remove)
|
|
24991
25227
|
rmSync4(dir, { recursive: true, force: true });
|
|
@@ -24995,7 +25231,7 @@ function hermes(context) {
|
|
|
24995
25231
|
return lines;
|
|
24996
25232
|
}
|
|
24997
25233
|
function zcodeIn(homeDir, context) {
|
|
24998
|
-
const native =
|
|
25234
|
+
const native = join8(homeDir, ".zcode/cli/config.json"), fallback = join8(homeDir, ".agents/mcp.json");
|
|
24999
25235
|
const servers = (value, isNative) => isNative ? object2(object2(value, "mcp"), "servers") : object2(value, "mcpServers");
|
|
25000
25236
|
const remove = Boolean(context.remove);
|
|
25001
25237
|
const toFallback = !remove && !Object.keys(servers(readJson(native), true)).some((key) => key !== NAME) && Object.keys(servers(readJson(fallback), false)).length > 0;
|
|
@@ -25045,11 +25281,11 @@ var init_setup = __esm({
|
|
|
25045
25281
|
|
|
25046
25282
|
// apps/body/dist/session-join/claude-inbound.js
|
|
25047
25283
|
import { existsSync as existsSync4, readFileSync as readFileSync8, rmSync as rmSync5 } from "node:fs";
|
|
25048
|
-
import { join as
|
|
25284
|
+
import { join as join9 } from "node:path";
|
|
25049
25285
|
function assertClaudePolicy(env) {
|
|
25050
25286
|
const paths = [
|
|
25051
25287
|
env.CLAUDE_CODE_MANAGED_SETTINGS_PATH,
|
|
25052
|
-
|
|
25288
|
+
join9(claudeConfigDir(env), "managed-settings.json"),
|
|
25053
25289
|
process.platform === "darwin" ? "/Library/Application Support/ClaudeCode/managed-settings.json" : "/etc/claude-code/managed-settings.json"
|
|
25054
25290
|
];
|
|
25055
25291
|
for (const path of paths) {
|
|
@@ -25064,8 +25300,8 @@ async function acceptClaudeInbound(env) {
|
|
|
25064
25300
|
const dir = stateDir(env);
|
|
25065
25301
|
await withLock(dir, () => {
|
|
25066
25302
|
assertClaudePolicy(env);
|
|
25067
|
-
const path =
|
|
25068
|
-
const saved =
|
|
25303
|
+
const path = join9(claudeConfigDir(env), "settings.json");
|
|
25304
|
+
const saved = join9(dir, "claude-inbound.json");
|
|
25069
25305
|
const value = readJson(path);
|
|
25070
25306
|
if (!existsSync4(saved))
|
|
25071
25307
|
writeFile3(saved, JSON.stringify({ present: Object.hasOwn(value, "crossSessionInbound"), value: value.crossSessionInbound }));
|
|
@@ -25079,12 +25315,12 @@ async function restoreClaudeInbound(env) {
|
|
|
25079
25315
|
await withLock(dir, () => {
|
|
25080
25316
|
if (readState(dir).sessions.length)
|
|
25081
25317
|
return;
|
|
25082
|
-
const saved =
|
|
25318
|
+
const saved = join9(dir, "claude-inbound.json");
|
|
25083
25319
|
if (!existsSync4(saved))
|
|
25084
25320
|
return;
|
|
25085
25321
|
assertClaudePolicy(env);
|
|
25086
25322
|
const old = JSON.parse(readFileSync8(saved, "utf8"));
|
|
25087
|
-
const path =
|
|
25323
|
+
const path = join9(claudeConfigDir(env), "settings.json");
|
|
25088
25324
|
const value = readJson(path);
|
|
25089
25325
|
if (value.crossSessionInbound === "accept") {
|
|
25090
25326
|
if (old.present)
|
|
@@ -25106,10 +25342,10 @@ var init_claude_inbound = __esm({
|
|
|
25106
25342
|
});
|
|
25107
25343
|
|
|
25108
25344
|
// apps/body/dist/session-join/codex-trust.js
|
|
25109
|
-
import { spawn as
|
|
25110
|
-
import { join as
|
|
25345
|
+
import { spawn as spawn7 } from "node:child_process";
|
|
25346
|
+
import { join as join10 } from "node:path";
|
|
25111
25347
|
function beelineTrustEdits(hooks, context) {
|
|
25112
|
-
const path =
|
|
25348
|
+
const path = join10(codexHome(context.env), "hooks.json");
|
|
25113
25349
|
const expected = hookCommand(context, "codex", "session-start");
|
|
25114
25350
|
const own2 = hooks.filter((h) => h.sourcePath === path && h.source === "user" && !h.isManaged && h.pluginId === null && h.eventName === "sessionStart" && h.handlerType === "command" && h.command === expected && h.matcher === "*" && h.timeoutSec === 10 && h.key.startsWith(path) && /^:session_start:\d+:\d+$/.test(h.key.slice(path.length)) && /^sha256:[0-9a-f]{64}$/.test(h.currentHash));
|
|
25115
25351
|
if (own2.length !== 1)
|
|
@@ -25118,7 +25354,7 @@ function beelineTrustEdits(hooks, context) {
|
|
|
25118
25354
|
return [{ keyPath: `hooks.state.${JSON.stringify(hook.key)}.trusted_hash`, value: hook.currentHash, mergeStrategy: "replace" }];
|
|
25119
25355
|
}
|
|
25120
25356
|
async function trustCodexHook(context, bin, cwd) {
|
|
25121
|
-
const child =
|
|
25357
|
+
const child = spawn7(bin, ["app-server", "--stdio"], { env: context.env, cwd, stdio: ["pipe", "pipe", "ignore"] });
|
|
25122
25358
|
let id = 0, buffer = "";
|
|
25123
25359
|
const pending = /* @__PURE__ */ new Map();
|
|
25124
25360
|
const fail = () => {
|
|
@@ -25156,9 +25392,9 @@ async function trustCodexHook(context, bin, cwd) {
|
|
|
25156
25392
|
}
|
|
25157
25393
|
}
|
|
25158
25394
|
});
|
|
25159
|
-
const request2 = (method, params) => new Promise((
|
|
25395
|
+
const request2 = (method, params) => new Promise((resolve13, reject) => {
|
|
25160
25396
|
const key = ++id;
|
|
25161
|
-
pending.set(key, { resolve:
|
|
25397
|
+
pending.set(key, { resolve: resolve13, reject: () => reject(new Error("Codex hook trust unavailable")) });
|
|
25162
25398
|
child.stdin.write(JSON.stringify({ id: key, method, params }) + "\n");
|
|
25163
25399
|
});
|
|
25164
25400
|
try {
|
|
@@ -25339,7 +25575,7 @@ var init_pull_apps = __esm({
|
|
|
25339
25575
|
"use strict";
|
|
25340
25576
|
init_store();
|
|
25341
25577
|
init_beeline_api();
|
|
25342
|
-
agentapi = (sessionId, text) => new Promise((
|
|
25578
|
+
agentapi = (sessionId, text) => new Promise((resolve13, reject) => execFile4("agentapi", ["send-message", sessionId, text], { timeout: 3e4 }, (error) => error ? reject(error) : resolve13()));
|
|
25343
25579
|
}
|
|
25344
25580
|
});
|
|
25345
25581
|
|
|
@@ -25349,9 +25585,9 @@ __export(command_exports, {
|
|
|
25349
25585
|
findOwnSession: () => findOwnSession,
|
|
25350
25586
|
runSessionCommand: () => runSessionCommand
|
|
25351
25587
|
});
|
|
25352
|
-
import { spawn as
|
|
25588
|
+
import { spawn as spawn8, spawnSync as spawnSync2 } from "node:child_process";
|
|
25353
25589
|
import { closeSync as closeSync4, copyFileSync as copyFileSync2, existsSync as existsSync5, fsyncSync, mkdirSync as mkdirSync5, openSync as openSync4, readFileSync as readFileSync9, readdirSync as readdirSync6, renameSync as renameSync4, rmSync as rmSync6, writeFileSync as writeFileSync5 } from "node:fs";
|
|
25354
|
-
import { delimiter, dirname as
|
|
25590
|
+
import { delimiter, dirname as dirname8, join as join11, resolve as resolve11 } from "node:path";
|
|
25355
25591
|
import { createHash as createHash7, randomUUID as randomUUID2 } from "node:crypto";
|
|
25356
25592
|
function writePending(file, pending) {
|
|
25357
25593
|
const temporary = file + "." + randomUUID2() + ".tmp";
|
|
@@ -25365,7 +25601,7 @@ function writePending(file, pending) {
|
|
|
25365
25601
|
}
|
|
25366
25602
|
renameSync4(temporary, file);
|
|
25367
25603
|
if (process.platform !== "win32") {
|
|
25368
|
-
const directory = openSync4(
|
|
25604
|
+
const directory = openSync4(dirname8(file), "r");
|
|
25369
25605
|
try {
|
|
25370
25606
|
fsyncSync(directory);
|
|
25371
25607
|
} finally {
|
|
@@ -25379,14 +25615,14 @@ function writePending(file, pending) {
|
|
|
25379
25615
|
function existingPending(dir, own2, server) {
|
|
25380
25616
|
let names;
|
|
25381
25617
|
try {
|
|
25382
|
-
names = readdirSync6(
|
|
25618
|
+
names = readdirSync6(join11(dir, "pending"));
|
|
25383
25619
|
} catch {
|
|
25384
25620
|
return;
|
|
25385
25621
|
}
|
|
25386
25622
|
if (names.length > 256)
|
|
25387
25623
|
throw new Error("Too many pending Beeline sign-ins");
|
|
25388
25624
|
return names.filter((name) => /^[a-f0-9]{24}\.json$/.test(name)).flatMap((name) => {
|
|
25389
|
-
const file =
|
|
25625
|
+
const file = join11(dir, "pending", name);
|
|
25390
25626
|
try {
|
|
25391
25627
|
const pending = JSON.parse(readFileSync9(file, "utf8"));
|
|
25392
25628
|
return pending.agent === own2.agent && pending.cwd === own2.cwd && pending.server === server && (!pending.sessionId || !own2.sessionId || pending.sessionId === own2.sessionId) ? [{ file, pending }] : [];
|
|
@@ -25411,7 +25647,7 @@ function words(args, valued) {
|
|
|
25411
25647
|
}
|
|
25412
25648
|
function which(bin, env) {
|
|
25413
25649
|
for (const dir of (env.PATH ?? "").split(delimiter)) {
|
|
25414
|
-
const path =
|
|
25650
|
+
const path = join11(dir, bin);
|
|
25415
25651
|
if (dir && existsSync5(path))
|
|
25416
25652
|
return path;
|
|
25417
25653
|
}
|
|
@@ -25420,8 +25656,8 @@ function which(bin, env) {
|
|
|
25420
25656
|
function runner(dir, env) {
|
|
25421
25657
|
if (env.BEELINE_SESSION_BUNDLE)
|
|
25422
25658
|
return { node: process.execPath, bundle: env.BEELINE_SESSION_BUNDLE };
|
|
25423
|
-
const bundle =
|
|
25424
|
-
const running =
|
|
25659
|
+
const bundle = join11(dir, "usebeeline.mjs");
|
|
25660
|
+
const running = resolve11(process.argv[1] ?? "");
|
|
25425
25661
|
if (running !== bundle && running.endsWith(".mjs")) {
|
|
25426
25662
|
mkdirSync5(dir, { recursive: true, mode: 448 });
|
|
25427
25663
|
copyFileSync2(running, bundle);
|
|
@@ -25474,6 +25710,7 @@ async function joinCommand(args, env) {
|
|
|
25474
25710
|
const server = serverUrl(args, env);
|
|
25475
25711
|
const existing = readState(dir).sessions.find((s) => s.key === key && s.server === server);
|
|
25476
25712
|
if (existing) {
|
|
25713
|
+
let connected = false;
|
|
25477
25714
|
try {
|
|
25478
25715
|
await accessToken(dir, key);
|
|
25479
25716
|
await updateState(dir, (state) => {
|
|
@@ -25483,10 +25720,13 @@ async function joinCommand(args, env) {
|
|
|
25483
25720
|
s.pid = own2.pid ?? s.pid;
|
|
25484
25721
|
}
|
|
25485
25722
|
});
|
|
25486
|
-
|
|
25723
|
+
connected = true;
|
|
25724
|
+
} catch {
|
|
25725
|
+
}
|
|
25726
|
+
if (connected) {
|
|
25727
|
+
await ensureBridge(dir, run2, env);
|
|
25487
25728
|
console.log(`This ${agentLabel(own2.agent)} session is on Beeline as @${existing.handle ?? existing.name}. Tags in its Rooms arrive here.`);
|
|
25488
25729
|
return;
|
|
25489
|
-
} catch {
|
|
25490
25730
|
}
|
|
25491
25731
|
}
|
|
25492
25732
|
const taken = new Set(readState(dir).sessions.filter((s) => s.key !== key).map((s) => s.name));
|
|
@@ -25511,14 +25751,14 @@ async function joinCommand(args, env) {
|
|
|
25511
25751
|
startedAt: Date.now(),
|
|
25512
25752
|
claudeInboundFallback: own2.claudeInboundFallback
|
|
25513
25753
|
};
|
|
25514
|
-
mkdirSync5(
|
|
25515
|
-
const file =
|
|
25754
|
+
mkdirSync5(join11(dir, "pending"), { recursive: true, mode: 448 });
|
|
25755
|
+
const file = join11(dir, "pending", `${createHash7("sha256").update(signIn.state).digest("hex").slice(0, 24)}.json`);
|
|
25516
25756
|
if (!resume)
|
|
25517
25757
|
writePending(file, pending);
|
|
25518
25758
|
if (!resume && previous && previous.file !== file)
|
|
25519
25759
|
rmSync6(previous.file, { force: true });
|
|
25520
|
-
const out =
|
|
25521
|
-
const child =
|
|
25760
|
+
const out = join11(dir, "bridge.log");
|
|
25761
|
+
const child = spawn8(run2.node, [run2.bundle, "session", "finish-join", file], { detached: true, stdio: "ignore", env: { ...env, BEELINE_SESSION_BUNDLE: run2.bundle } });
|
|
25522
25762
|
child.unref();
|
|
25523
25763
|
console.log([
|
|
25524
25764
|
`Show your person this link. They open it on any device (a phone works) and sign in with GitHub or Google:`,
|
|
@@ -25595,7 +25835,7 @@ async function finishJoinOwned(file, env) {
|
|
|
25595
25835
|
changes.splice(prompt, 1);
|
|
25596
25836
|
changes.push("Trusted only Beeline\u2019s SessionStart hook, pinned to its current Codex hash.");
|
|
25597
25837
|
}
|
|
25598
|
-
ensureBridge(dir, run2, env);
|
|
25838
|
+
await ensureBridge(dir, run2, env);
|
|
25599
25839
|
const rooms = me.rooms.map((r) => r.name).slice(0, 5).join(", ");
|
|
25600
25840
|
await announce(joined2, `Beeline: you joined as @${joined2.handle ?? joined2.name}${rooms ? ` in ${rooms}` : ""}. When someone tags you there, the message arrives here with the command that answers it.${changes.length ? `
|
|
25601
25841
|
(${changes.join("; ")})` : ""}
|
|
@@ -25643,7 +25883,7 @@ function own(args, env) {
|
|
|
25643
25883
|
}
|
|
25644
25884
|
async function ownTool(dir, joined2, name, args) {
|
|
25645
25885
|
let bridged = await toolViaBridge(dir, joined2.key, name, args);
|
|
25646
|
-
if (!bridged && existsSync5(
|
|
25886
|
+
if (!bridged && existsSync5(join11(dir, "bridge.pid")) && process.cwd().startsWith(joined2.cwd))
|
|
25647
25887
|
bridged = await toolViaOutbox(joined2.cwd, name, args);
|
|
25648
25888
|
if (bridged) {
|
|
25649
25889
|
if (!bridged.ok)
|
|
@@ -25689,7 +25929,7 @@ async function session(args, env) {
|
|
|
25689
25929
|
if (out)
|
|
25690
25930
|
process.stdout.write(out + "\n");
|
|
25691
25931
|
if (event === "session-start" && readState(dir).sessions.length)
|
|
25692
|
-
ensureBridge(dir, runner(dir, env), env);
|
|
25932
|
+
await ensureBridge(dir, runner(dir, env), env);
|
|
25693
25933
|
} catch {
|
|
25694
25934
|
}
|
|
25695
25935
|
return;
|
|
@@ -25752,14 +25992,14 @@ async function session(args, env) {
|
|
|
25752
25992
|
throw new Error("Usage: usebeeline join | usebeeline session reply|read|tool|status|leave");
|
|
25753
25993
|
}
|
|
25754
25994
|
function readStdin(_limitMs) {
|
|
25755
|
-
return new Promise((
|
|
25995
|
+
return new Promise((resolve13) => {
|
|
25756
25996
|
let text = "";
|
|
25757
25997
|
process.stdin.setEncoding("utf8");
|
|
25758
25998
|
process.stdin.on("data", (chunk) => {
|
|
25759
25999
|
text += chunk;
|
|
25760
26000
|
});
|
|
25761
26001
|
process.stdin.on("end", () => {
|
|
25762
|
-
|
|
26002
|
+
resolve13(text);
|
|
25763
26003
|
});
|
|
25764
26004
|
});
|
|
25765
26005
|
}
|
|
@@ -25797,19 +26037,19 @@ var init_command = __esm({
|
|
|
25797
26037
|
init_setup();
|
|
25798
26038
|
init_store();
|
|
25799
26039
|
init_kernel_lock();
|
|
25800
|
-
finisherKey = (file) => "beeline-session-sign-in:" +
|
|
26040
|
+
finisherKey = (file) => "beeline-session-sign-in:" + resolve11(file);
|
|
25801
26041
|
VALUED = ["--as", "--room", "--reply-to", "--server", "--name", "--session", "--state", "--limit"];
|
|
25802
26042
|
}
|
|
25803
26043
|
});
|
|
25804
26044
|
|
|
25805
26045
|
// apps/body/dist/recovery-cli.js
|
|
25806
|
-
import { spawn as
|
|
25807
|
-
import { readFile as
|
|
25808
|
-
import { resolve as
|
|
26046
|
+
import { spawn as spawn9 } from "node:child_process";
|
|
26047
|
+
import { readFile as readFile5, readdir as readdir5, stat as stat3, unlink } from "node:fs/promises";
|
|
26048
|
+
import { resolve as resolve12 } from "node:path";
|
|
25809
26049
|
|
|
25810
26050
|
// apps/body/dist/recovery.js
|
|
25811
|
-
import { readFile as
|
|
25812
|
-
import { resolve as
|
|
26051
|
+
import { readFile as readFile4, readdir as readdir4, stat } from "node:fs/promises";
|
|
26052
|
+
import { resolve as resolve9 } from "node:path";
|
|
25813
26053
|
|
|
25814
26054
|
// apps/body/dist/machine-control.js
|
|
25815
26055
|
import { watch } from "node:fs";
|
|
@@ -26170,8 +26410,8 @@ async function prepareMachineRelease(layout, options = {}) {
|
|
|
26170
26410
|
return withInstallLock(layout, () => prepareLatestRelease(layout, { ...options, deadlineAt }), {
|
|
26171
26411
|
waitMs: Math.max(0, deadlineAt - Date.now())
|
|
26172
26412
|
});
|
|
26173
|
-
const stable =
|
|
26174
|
-
const entrypoint = env.BEELINE_RECOVERY_ENTRY || await
|
|
26413
|
+
const stable = resolve9(layout.libDir, "../beeline-bootstrap.mjs");
|
|
26414
|
+
const entrypoint = env.BEELINE_RECOVERY_ENTRY || await readFile4(stable).then(() => stable, () => process.argv[1]);
|
|
26175
26415
|
return prepareReleaseInWorker({ ...env, ...options?.force ? { BEELINE_FORCE_REPAIR: "1" } : {} }, deadlineAt, entrypoint);
|
|
26176
26416
|
}
|
|
26177
26417
|
async function convergeMachine(options = {}) {
|
|
@@ -26179,9 +26419,9 @@ async function convergeMachine(options = {}) {
|
|
|
26179
26419
|
assertLifecycleTestIsolation(env, Boolean(options.run));
|
|
26180
26420
|
const layout = options.layout ?? beelineInstallLayout(env) ?? discoveredBeelineInstallLayout(env);
|
|
26181
26421
|
const deadlineAt = options.deadlineAt ?? Date.now() + (options.timeoutMs ?? 6e5);
|
|
26182
|
-
const stateRoot = env.XDG_STATE_HOME ||
|
|
26183
|
-
const root =
|
|
26184
|
-
const configured = await Promise.all((await readdir4(root).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/i.test(id)).map(async (id) => await stat(
|
|
26422
|
+
const stateRoot = env.XDG_STATE_HOME || resolve9(env.HOME || "", ".local/state");
|
|
26423
|
+
const root = resolve9(stateRoot, "beeline/agents");
|
|
26424
|
+
const configured = await Promise.all((await readdir4(root).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/i.test(id)).map(async (id) => await stat(resolve9(root, id, "runtime.json")).then(() => true, () => false) && !await stat(resolve9(root, id, "stopped")).then(() => true, () => false) ? id : void 0));
|
|
26185
26425
|
const required = /* @__PURE__ */ new Set([
|
|
26186
26426
|
...configured.filter((id) => Boolean(id)),
|
|
26187
26427
|
...options.agentIds ?? []
|
|
@@ -26202,7 +26442,7 @@ async function convergeMachine(options = {}) {
|
|
|
26202
26442
|
let expectedRelease = options.releaseId;
|
|
26203
26443
|
const targetIdentity = options.releaseId ? await readInstalledBundleIdentity({
|
|
26204
26444
|
...layout,
|
|
26205
|
-
libDir:
|
|
26445
|
+
libDir: resolve9(layout.releasesRoot, options.releaseId)
|
|
26206
26446
|
}) : void 0;
|
|
26207
26447
|
const request2 = options.releaseId && hasControl ? {
|
|
26208
26448
|
operation: "update",
|
|
@@ -26239,8 +26479,8 @@ async function bootstrapMachine(env = process.env) {
|
|
|
26239
26479
|
for (const id of [state.stagedReleaseId, active]) {
|
|
26240
26480
|
if (!id || !/^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(id))
|
|
26241
26481
|
continue;
|
|
26242
|
-
const digest = await
|
|
26243
|
-
if (/^[0-9a-f]{64}$/i.test(digest.trim()) && await resolveBundleEntrypoint(
|
|
26482
|
+
const digest = await readFile4(resolve9(layout.releasesRoot, id, ".stage-ok"), "utf8").catch(() => "");
|
|
26483
|
+
if (/^[0-9a-f]{64}$/i.test(digest.trim()) && await resolveBundleEntrypoint(resolve9(layout.releasesRoot, id))) {
|
|
26244
26484
|
releaseId = id;
|
|
26245
26485
|
break;
|
|
26246
26486
|
}
|
|
@@ -26256,7 +26496,7 @@ async function bootstrapMachine(env = process.env) {
|
|
|
26256
26496
|
await withInstallLock(layout, () => activateRelease(layout, releaseId, { deferPruning: true }), {
|
|
26257
26497
|
waitMs: Math.max(0, bootDeadlineAt - Date.now())
|
|
26258
26498
|
});
|
|
26259
|
-
const entry = await resolveBundleEntrypoint(
|
|
26499
|
+
const entry = await resolveBundleEntrypoint(resolve9(layout.releasesRoot, releaseId));
|
|
26260
26500
|
if (!entry)
|
|
26261
26501
|
throw new Error(`selected release ${releaseId} has no body entry`);
|
|
26262
26502
|
return entry;
|
|
@@ -26322,18 +26562,18 @@ async function main() {
|
|
|
26322
26562
|
if (args[i] === "--manifest-url" && !args[++i])
|
|
26323
26563
|
throw new Error("--manifest-url requires a URL");
|
|
26324
26564
|
}
|
|
26325
|
-
const stateRoot2 = process.env.XDG_STATE_HOME ||
|
|
26565
|
+
const stateRoot2 = process.env.XDG_STATE_HOME || resolve12(process.env.HOME || "", ".local/state");
|
|
26326
26566
|
if (args.includes("--status")) {
|
|
26327
26567
|
const [native, helper] = await Promise.all([
|
|
26328
26568
|
nativeHelperStatus(),
|
|
26329
26569
|
requestMachine(stateRoot2, { operation: "status" }, () => true, 2e3).catch(() => void 0)
|
|
26330
26570
|
]);
|
|
26331
|
-
const root =
|
|
26571
|
+
const root = resolve12(stateRoot2, "beeline/agents");
|
|
26332
26572
|
const agents = await Promise.all((await readdir5(root).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/.test(id)).map(async (id) => ({
|
|
26333
26573
|
agentId: id,
|
|
26334
|
-
enabled: !await stat3(
|
|
26574
|
+
enabled: !await stat3(resolve12(root, id, "stopped")).then(() => true, () => false),
|
|
26335
26575
|
...helper?.agents[id] ?? { state: "not hosted" },
|
|
26336
|
-
validRecord: await
|
|
26576
|
+
validRecord: await readFile5(resolve12(root, id, "runtime.json"), "utf8").then((raw) => Boolean(JSON.parse(raw).agent)).catch(() => false)
|
|
26337
26577
|
})));
|
|
26338
26578
|
console.log(JSON.stringify({
|
|
26339
26579
|
native,
|
|
@@ -26382,7 +26622,7 @@ async function main() {
|
|
|
26382
26622
|
console.log(`[beeline] executing release ${status.loadedRelease}; helper ${status.pid}; every enabled agent serving`);
|
|
26383
26623
|
return;
|
|
26384
26624
|
}
|
|
26385
|
-
const stateRoot = process.env.XDG_STATE_HOME ||
|
|
26625
|
+
const stateRoot = process.env.XDG_STATE_HOME || resolve12(process.env.HOME || "", ".local/state");
|
|
26386
26626
|
let selectedRelease;
|
|
26387
26627
|
if (command2 === "start") {
|
|
26388
26628
|
for (let i = 1; i < args.length; i++) {
|
|
@@ -26397,13 +26637,13 @@ async function main() {
|
|
|
26397
26637
|
const requested = agentFlag >= 0 ? args[agentFlag + 1] : args[1] && !args[1].startsWith("--") ? args[1] : void 0;
|
|
26398
26638
|
if (agentFlag >= 0 && !requested)
|
|
26399
26639
|
throw new Error("--agent requires an agent public key");
|
|
26400
|
-
const agentRoot =
|
|
26640
|
+
const agentRoot = resolve12(stateRoot, "beeline/agents");
|
|
26401
26641
|
const ids = (await readdir5(agentRoot).catch(() => [])).filter((id) => /^[0-9a-f]{64}$/.test(id));
|
|
26402
26642
|
const selected = requested ? ids.filter((id) => id.startsWith(requested)) : args.includes("--all") ? ids : [];
|
|
26403
26643
|
if (requested && selected.length !== 1)
|
|
26404
26644
|
throw new Error(`no unique paired agent matches ${requested}`);
|
|
26405
26645
|
for (const id of selected)
|
|
26406
|
-
await unlink(
|
|
26646
|
+
await unlink(resolve12(agentRoot, id, "stopped")).catch((error) => {
|
|
26407
26647
|
if (error.code !== "ENOENT")
|
|
26408
26648
|
throw error;
|
|
26409
26649
|
});
|
|
@@ -26427,7 +26667,7 @@ async function main() {
|
|
|
26427
26667
|
const entry = await resolveBundleEntrypoint(layout.libDir);
|
|
26428
26668
|
if (!entry)
|
|
26429
26669
|
throw new Error("no installed Beeline body; run npx usebeeline connect");
|
|
26430
|
-
const child =
|
|
26670
|
+
const child = spawn9(process.execPath, [entry, ...args], {
|
|
26431
26671
|
env: {
|
|
26432
26672
|
...process.env,
|
|
26433
26673
|
BEELINE_LIB_DIR: layout.libDir,
|
|
@@ -26445,7 +26685,7 @@ async function convergeDependencies(layout, _deadlineAt) {
|
|
|
26445
26685
|
if (!entry)
|
|
26446
26686
|
throw new Error("dependency phase has no selected body");
|
|
26447
26687
|
await new Promise((done, reject) => {
|
|
26448
|
-
const child =
|
|
26688
|
+
const child = spawn9(process.execPath, [entry, "converge-dependencies"], {
|
|
26449
26689
|
env: { ...process.env, BEELINE_LIB_DIR: layout.libDir, BEELINE_INTERNAL_RECOVERY: "1" },
|
|
26450
26690
|
stdio: "inherit"
|
|
26451
26691
|
});
|