@astrale-os/cli 1.0.0-beta.25 → 1.0.0-beta.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -2
- package/dist/astrale.js +963 -287
- package/package.json +3 -2
- package/src/commands/update.ts +61 -40
- package/src/lib/__tests__/skills.test.ts +803 -0
- package/src/lib/skills/lock.ts +117 -0
- package/src/lib/skills/sync.ts +814 -0
- package/src/lib/skills.ts +1 -52
- package/src/program/__tests__/program.test.ts +1 -1
- package/src/setup/steps/skills.ts +40 -38
- package/studio/client/dist/assets/{index-OeJK1TjG.js → index-CpBed0V1.js} +3 -3
- package/studio/client/dist/assets/{schema-studio-DRdfu_cQ.js → schema-studio-DJm9guI8.js} +1 -1
- package/studio/client/dist/index.html +1 -1
- package/studio/server/cli-consumers.test.ts +31 -2
- package/studio/server/workspace/updates.ts +23 -1
- package/studio/shared/contracts/runtime.ts +4 -0
- package/tsconfig.json +1 -1
package/dist/astrale.js
CHANGED
|
@@ -2578,7 +2578,7 @@ var package_default;
|
|
|
2578
2578
|
var init_package = __esm(() => {
|
|
2579
2579
|
package_default = {
|
|
2580
2580
|
name: "@astrale-os/cli",
|
|
2581
|
-
version: "1.0.0-beta.
|
|
2581
|
+
version: "1.0.0-beta.27",
|
|
2582
2582
|
description: "Astrale CLI — connect to existing Astrale kernels",
|
|
2583
2583
|
keywords: [
|
|
2584
2584
|
"astrale",
|
|
@@ -2638,6 +2638,7 @@ var init_package = __esm(() => {
|
|
|
2638
2638
|
format: "pnpm exec oxfmt --write .",
|
|
2639
2639
|
"format:check": "pnpm exec oxfmt --check .",
|
|
2640
2640
|
test: "node scripts/qualification/source-boundary.mjs --target && bun test src studio/client/src studio/server studio/shared && node --test scripts/*.test.mjs",
|
|
2641
|
+
"test:skills-e2e": "node scripts/qualification/skills-update-e2e.mjs",
|
|
2641
2642
|
"test:studio": "pnpm --dir studio test",
|
|
2642
2643
|
"test:watch": "bun test --watch src"
|
|
2643
2644
|
},
|
|
@@ -2660,8 +2661,8 @@ var init_package = __esm(() => {
|
|
|
2660
2661
|
"@astrale/commitlint-config": "jsr:~2.0.1",
|
|
2661
2662
|
"@commitlint/cli": "21.2.2",
|
|
2662
2663
|
"@commitlint/config-conventional": "21.2.2",
|
|
2663
|
-
"@types/bun": "^1.1.16",
|
|
2664
2664
|
"@types/node": "^22.0.0",
|
|
2665
|
+
"bun-types": "1.4.0",
|
|
2665
2666
|
husky: "~9.1.7",
|
|
2666
2667
|
"lint-staged": "17.3.0",
|
|
2667
2668
|
msgpackr: "^2.0.5",
|
|
@@ -41750,7 +41751,7 @@ var require_node_gyp_build_optional_packages = __commonJS(function(exports, modu
|
|
|
41750
41751
|
|
|
41751
41752
|
// node_modules/.pnpm/msgpackr-extract@3.0.4/node_modules/msgpackr-extract/index.js
|
|
41752
41753
|
var require_msgpackr_extract = __commonJS(function(exports, module) {
|
|
41753
|
-
var __dirname = "/
|
|
41754
|
+
var __dirname = "/private/tmp/astrale-cli-beta27-a3227da/node_modules/.pnpm/msgpackr-extract@3.0.4/node_modules/msgpackr-extract";
|
|
41754
41755
|
module.exports = require_node_gyp_build_optional_packages()(__dirname);
|
|
41755
41756
|
});
|
|
41756
41757
|
|
|
@@ -61295,38 +61296,668 @@ var init_browser = __esm(() => {
|
|
|
61295
61296
|
AUTH_EVAL = "fetch('/auth/me',{credentials:'include'})" + ".then(r=>r.json())" + ".then(j=>({authed:!!j.authenticated,email:j.user&&j.user.email}))" + ".catch(()=>({authed:false}))";
|
|
61296
61297
|
});
|
|
61297
61298
|
|
|
61298
|
-
// src/lib/skills.ts
|
|
61299
|
-
import {
|
|
61300
|
-
import {
|
|
61299
|
+
// src/lib/skills/lock.ts
|
|
61300
|
+
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
61301
|
+
import { lstat, mkdir as mkdir9, readFile as readFile10, readdir as readdir2, rm as rm2, stat as stat2, unlink as unlink4, writeFile as writeFile5 } from "node:fs/promises";
|
|
61301
61302
|
import { dirname as dirname8, join as join6 } from "node:path";
|
|
61302
|
-
async function
|
|
61303
|
-
const
|
|
61304
|
-
|
|
61305
|
-
|
|
61306
|
-
|
|
61307
|
-
|
|
61308
|
-
|
|
61309
|
-
|
|
61310
|
-
|
|
61311
|
-
|
|
61312
|
-
|
|
61303
|
+
async function withFileLock2(lockPath, fn, opts = {}) {
|
|
61304
|
+
const pollIntervalMs = opts.pollIntervalMs ?? 100;
|
|
61305
|
+
const staleAfterMs = opts.staleAfterMs ?? 30000;
|
|
61306
|
+
const timeoutMs = opts.timeoutMs ?? 60000;
|
|
61307
|
+
const deadline = Date.now() + timeoutMs;
|
|
61308
|
+
const claimsRoot = `${lockPath}.claims`;
|
|
61309
|
+
const token = randomUUID4();
|
|
61310
|
+
const claimDirectory = join6(claimsRoot, token);
|
|
61311
|
+
await mkdir9(dirname8(lockPath), { recursive: true });
|
|
61312
|
+
await mkdir9(claimsRoot, { recursive: true });
|
|
61313
|
+
await mkdir9(claimDirectory);
|
|
61314
|
+
await writeFile5(join6(claimDirectory, "owner.json"), JSON.stringify({ pid: process.pid }), {
|
|
61315
|
+
mode: 384
|
|
61316
|
+
});
|
|
61317
|
+
await writeFile5(join6(claimDirectory, "choosing"), "", { mode: 384 });
|
|
61318
|
+
try {
|
|
61319
|
+
const claims = await liveClaims(claimsRoot, staleAfterMs);
|
|
61320
|
+
const ticket = Math.max(0, ...claims.flatMap((claim) => claim.ticket ?? [])) + 1;
|
|
61321
|
+
await writeFile5(join6(claimDirectory, "ticket"), String(ticket), { mode: 384 });
|
|
61322
|
+
await unlink4(join6(claimDirectory, "choosing"));
|
|
61323
|
+
for (;; ) {
|
|
61324
|
+
const contenders = await liveClaims(claimsRoot, staleAfterMs);
|
|
61325
|
+
const blocked = contenders.some((claim) => claim.directory !== claimDirectory && (claim.choosing || claim.ticket === null || claim.ticket < ticket || claim.ticket === ticket && claim.directory < claimDirectory));
|
|
61326
|
+
if (!blocked)
|
|
61327
|
+
return await fn();
|
|
61328
|
+
if (Date.now() >= deadline)
|
|
61329
|
+
throw new Error("Timed out waiting for another skill update");
|
|
61330
|
+
await new Promise((resolve3) => setTimeout(resolve3, pollIntervalMs));
|
|
61331
|
+
}
|
|
61332
|
+
} finally {
|
|
61333
|
+
await rm2(claimDirectory, { recursive: true, force: true });
|
|
61334
|
+
}
|
|
61335
|
+
}
|
|
61336
|
+
async function liveClaims(root, staleAfterMs) {
|
|
61337
|
+
const directories = (await readdir2(root, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory()).map((entry) => join6(root, entry.name));
|
|
61338
|
+
const claims = await Promise.all(directories.map(async (directory) => {
|
|
61339
|
+
try {
|
|
61340
|
+
const owner4 = JSON.parse(await readFile10(join6(directory, "owner.json"), "utf8"));
|
|
61341
|
+
if (typeof owner4.pid !== "number")
|
|
61342
|
+
return await discardIfStale(directory, staleAfterMs);
|
|
61343
|
+
if (!isPidAlive2(owner4.pid)) {
|
|
61344
|
+
await rm2(directory, { recursive: true, force: true });
|
|
61345
|
+
return null;
|
|
61346
|
+
}
|
|
61347
|
+
const choosing = await lstat(join6(directory, "choosing")).then(() => true).catch(() => false);
|
|
61348
|
+
const ticket = await readFile10(join6(directory, "ticket"), "utf8").then((value2) => {
|
|
61349
|
+
const parsed = Number(value2);
|
|
61350
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;
|
|
61351
|
+
}).catch(() => null);
|
|
61352
|
+
return { directory, pid: owner4.pid, ticket, choosing };
|
|
61353
|
+
} catch {
|
|
61354
|
+
return await discardIfStale(directory, staleAfterMs);
|
|
61355
|
+
}
|
|
61356
|
+
}));
|
|
61357
|
+
return claims.filter((claim) => claim !== null);
|
|
61358
|
+
}
|
|
61359
|
+
async function discardIfStale(directory, staleAfterMs) {
|
|
61360
|
+
try {
|
|
61361
|
+
if (Date.now() - (await stat2(directory)).mtimeMs > staleAfterMs) {
|
|
61362
|
+
await rm2(directory, { recursive: true, force: true });
|
|
61363
|
+
}
|
|
61364
|
+
} catch {}
|
|
61365
|
+
return null;
|
|
61366
|
+
}
|
|
61367
|
+
function isPidAlive2(pid) {
|
|
61368
|
+
try {
|
|
61369
|
+
process.kill(pid, 0);
|
|
61370
|
+
return true;
|
|
61371
|
+
} catch (error52) {
|
|
61372
|
+
return error52.code === "EPERM";
|
|
61373
|
+
}
|
|
61374
|
+
}
|
|
61375
|
+
var init_lock = () => {};
|
|
61376
|
+
|
|
61377
|
+
// src/lib/skills/sync.ts
|
|
61378
|
+
import { createHash as createHash2 } from "node:crypto";
|
|
61379
|
+
import {
|
|
61380
|
+
cp,
|
|
61381
|
+
lstat as lstat2,
|
|
61382
|
+
mkdir as mkdir10,
|
|
61383
|
+
mkdtemp as mkdtemp2,
|
|
61384
|
+
readFile as readFile11,
|
|
61385
|
+
readdir as readdir3,
|
|
61386
|
+
readlink,
|
|
61387
|
+
rename as rename3,
|
|
61388
|
+
rm as rm3,
|
|
61389
|
+
symlink,
|
|
61390
|
+
writeFile as writeFile6
|
|
61391
|
+
} from "node:fs/promises";
|
|
61392
|
+
import { homedir as homedir2, tmpdir as tmpdir2 } from "node:os";
|
|
61393
|
+
import { dirname as dirname9, join as join7, relative, resolve as resolve3 } from "node:path";
|
|
61394
|
+
function resolvedDependencies(overrides = {}) {
|
|
61395
|
+
const home = overrides.home ?? homedir2();
|
|
61396
|
+
const xdgStateHome = process.env.XDG_STATE_HOME;
|
|
61397
|
+
return {
|
|
61398
|
+
home,
|
|
61399
|
+
lockPath: overrides.lockPath ?? (xdgStateHome ? join7(xdgStateHome, "skills", ".skill-lock.json") : join7(home, ".agents", ".skill-lock.json")),
|
|
61400
|
+
run: overrides.run ?? run,
|
|
61401
|
+
resolveSource: overrides.resolveSource
|
|
61402
|
+
};
|
|
61403
|
+
}
|
|
61404
|
+
function sourceOwned(entry) {
|
|
61405
|
+
return entry.source === ASTRALE_CLI_SKILL_SOURCE || entry.sourceUrl === SOURCE_REPOSITORY_URL || entry.sourceUrl === `https://github.com/${ASTRALE_CLI_SKILL_SOURCE}`;
|
|
61406
|
+
}
|
|
61407
|
+
function folderName(entry) {
|
|
61408
|
+
const match = entry.skillPath?.match(/^skills\/([^/]+)\/SKILL\.md$/u);
|
|
61409
|
+
return match?.[1] ?? null;
|
|
61410
|
+
}
|
|
61411
|
+
async function resolveAstraleSkillSource(execute) {
|
|
61412
|
+
const checkout = await mkdtemp2(join7(tmpdir2(), "astrale-skill-source-"));
|
|
61413
|
+
try {
|
|
61414
|
+
const cloned = await execute("git", [
|
|
61415
|
+
"clone",
|
|
61416
|
+
"--quiet",
|
|
61417
|
+
"--depth",
|
|
61418
|
+
"1",
|
|
61419
|
+
"--filter=blob:none",
|
|
61420
|
+
"--no-checkout",
|
|
61421
|
+
"--single-branch",
|
|
61422
|
+
"--branch",
|
|
61423
|
+
"main",
|
|
61424
|
+
SOURCE_REPOSITORY_URL,
|
|
61425
|
+
checkout
|
|
61426
|
+
]);
|
|
61427
|
+
if (cloned.code !== 0)
|
|
61428
|
+
throw new Error(cloned.stderr || cloned.stdout || "git clone failed");
|
|
61429
|
+
const revision = await execute("git", ["-C", checkout, "rev-parse", "HEAD"]);
|
|
61430
|
+
if (revision.code !== 0) {
|
|
61431
|
+
throw new Error(revision.stderr || revision.stdout || "git rev-parse failed");
|
|
61432
|
+
}
|
|
61433
|
+
const folders = await execute("git", ["-C", checkout, "ls-tree", "HEAD:skills"]);
|
|
61434
|
+
const files = await execute("git", [
|
|
61435
|
+
"-C",
|
|
61436
|
+
checkout,
|
|
61437
|
+
"ls-tree",
|
|
61438
|
+
"-r",
|
|
61439
|
+
"--name-only",
|
|
61440
|
+
"HEAD:skills"
|
|
61441
|
+
]);
|
|
61442
|
+
if (folders.code !== 0 || files.code !== 0) {
|
|
61443
|
+
throw new Error(folders.stderr || files.stderr || "git ls-tree failed");
|
|
61444
|
+
}
|
|
61445
|
+
const skillFiles = new Set(files.stdout.split(`
|
|
61446
|
+
`).filter((path4) => /^[^/]+\/SKILL\.md$/u.test(path4)).map((path4) => path4.slice(0, -"/SKILL.md".length)));
|
|
61447
|
+
const skills = folders.stdout.split(`
|
|
61448
|
+
`).flatMap((line) => {
|
|
61449
|
+
const match = line.match(/^040000 tree ([0-9a-f]{40})\t([^/]+)$/u);
|
|
61450
|
+
if (!match || !SAFE_NAME.test(match[2]) || !skillFiles.has(match[2]))
|
|
61451
|
+
return [];
|
|
61452
|
+
return [{ name: match[2], path: `skills/${match[2]}/SKILL.md`, tree: match[1] }];
|
|
61453
|
+
});
|
|
61454
|
+
skills.sort((a, b) => a.name.localeCompare(b.name));
|
|
61455
|
+
if (skills.length === 0)
|
|
61456
|
+
throw new Error("astrale-os/cli publishes no top-level skills");
|
|
61457
|
+
return { ref: "main", revision: revision.stdout.trim(), skills };
|
|
61458
|
+
} finally {
|
|
61459
|
+
await rm3(checkout, { recursive: true, force: true });
|
|
61460
|
+
}
|
|
61461
|
+
}
|
|
61462
|
+
async function readSkillLock(path4) {
|
|
61463
|
+
let raw2;
|
|
61464
|
+
try {
|
|
61465
|
+
raw2 = await readFile11(path4, "utf8");
|
|
61466
|
+
} catch (error52) {
|
|
61467
|
+
if (error52.code === "ENOENT")
|
|
61468
|
+
return { lock: null, raw: null };
|
|
61469
|
+
throw error52;
|
|
61470
|
+
}
|
|
61471
|
+
try {
|
|
61472
|
+
const parsed = JSON.parse(raw2);
|
|
61473
|
+
if (parsed === null || typeof parsed !== "object" || !("skills" in parsed) || parsed.skills === null || typeof parsed.skills !== "object") {
|
|
61474
|
+
return { lock: null, raw: raw2 };
|
|
61475
|
+
}
|
|
61476
|
+
return { lock: parsed, raw: raw2 };
|
|
61477
|
+
} catch {
|
|
61478
|
+
return { lock: null, raw: raw2 };
|
|
61479
|
+
}
|
|
61480
|
+
}
|
|
61481
|
+
async function writeSkillLock(path4, lock) {
|
|
61482
|
+
await mkdir10(dirname9(path4), { recursive: true });
|
|
61483
|
+
const next = `${path4}.next`;
|
|
61484
|
+
await writeFile6(next, `${JSON.stringify(lock, null, 2)}
|
|
61485
|
+
`, { mode: 384 });
|
|
61486
|
+
await rename3(next, path4);
|
|
61487
|
+
}
|
|
61488
|
+
function gitObjectHash(type, body) {
|
|
61489
|
+
return createHash2("sha1").update(Buffer.from(`${type} ${body.length}\x00`)).update(body).digest();
|
|
61490
|
+
}
|
|
61491
|
+
async function computeSkillTreeHash(root) {
|
|
61492
|
+
async function treeHash(directory) {
|
|
61493
|
+
const entries = await Promise.all((await readdir3(directory)).map(async (name) => {
|
|
61494
|
+
const path4 = join7(directory, name);
|
|
61495
|
+
const stat3 = await lstat2(path4);
|
|
61496
|
+
if (stat3.isDirectory()) {
|
|
61497
|
+
return { name, sort: `${name}/`, mode: "40000", hash: await treeHash(path4) };
|
|
61498
|
+
}
|
|
61499
|
+
if (stat3.isSymbolicLink()) {
|
|
61500
|
+
return {
|
|
61501
|
+
name,
|
|
61502
|
+
sort: name,
|
|
61503
|
+
mode: "120000",
|
|
61504
|
+
hash: gitObjectHash("blob", Buffer.from(await readlink(path4)))
|
|
61505
|
+
};
|
|
61506
|
+
}
|
|
61507
|
+
return {
|
|
61508
|
+
name,
|
|
61509
|
+
sort: name,
|
|
61510
|
+
mode: stat3.mode & 73 ? "100755" : "100644",
|
|
61511
|
+
hash: gitObjectHash("blob", await readFile11(path4))
|
|
61512
|
+
};
|
|
61513
|
+
}));
|
|
61514
|
+
entries.sort((a, b) => Buffer.compare(Buffer.from(a.sort), Buffer.from(b.sort)));
|
|
61515
|
+
const body = Buffer.concat(entries.flatMap((entry) => [Buffer.from(`${entry.mode} ${entry.name}\x00`), entry.hash]));
|
|
61516
|
+
return gitObjectHash("tree", body);
|
|
61517
|
+
}
|
|
61518
|
+
return (await treeHash(root)).toString("hex");
|
|
61519
|
+
}
|
|
61520
|
+
async function computeInstallerFolderHash(root) {
|
|
61521
|
+
const files = [];
|
|
61522
|
+
async function collect(directory) {
|
|
61523
|
+
await Promise.all((await readdir3(directory, { withFileTypes: true })).map(async (entry) => {
|
|
61524
|
+
if (entry.name === ".git" || entry.name === "node_modules")
|
|
61525
|
+
return;
|
|
61526
|
+
const path4 = join7(directory, entry.name);
|
|
61527
|
+
if (entry.isDirectory())
|
|
61528
|
+
await collect(path4);
|
|
61529
|
+
else if (entry.isFile()) {
|
|
61530
|
+
files.push({
|
|
61531
|
+
path: relative(root, path4).split("\\").join("/"),
|
|
61532
|
+
content: await readFile11(path4)
|
|
61533
|
+
});
|
|
61534
|
+
}
|
|
61535
|
+
}));
|
|
61536
|
+
}
|
|
61537
|
+
await collect(root);
|
|
61538
|
+
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
61539
|
+
const hash2 = createHash2("sha256");
|
|
61540
|
+
for (const file2 of files)
|
|
61541
|
+
hash2.update(file2.path).update(file2.content);
|
|
61542
|
+
return hash2.digest("hex");
|
|
61543
|
+
}
|
|
61544
|
+
async function inspectAstraleSkills(snapshot2, home, lockPath) {
|
|
61545
|
+
const { lock } = await readSkillLock(lockPath);
|
|
61546
|
+
const managed = Object.entries(lock?.skills ?? {}).filter(([, entry]) => sourceOwned(entry));
|
|
61547
|
+
const expected = new Map(snapshot2.skills.map((skill) => [skill.name, skill]));
|
|
61548
|
+
const expectedPresence = await Promise.all(snapshot2.skills.map(async (skill) => {
|
|
61549
|
+
try {
|
|
61550
|
+
return (await lstat2(join7(home, ".agents", "skills", skill.name))).isDirectory();
|
|
61551
|
+
} catch {
|
|
61552
|
+
return false;
|
|
61553
|
+
}
|
|
61554
|
+
}));
|
|
61555
|
+
if (managed.length === 0 && expectedPresence.every((present2) => !present2)) {
|
|
61556
|
+
return { state: "absent", managedNames: [], managedFolders: [] };
|
|
61557
|
+
}
|
|
61558
|
+
const folders = managed.flatMap(([name, entry]) => {
|
|
61559
|
+
const folder = folderName(entry);
|
|
61560
|
+
return folder ? [{ key: name, folder, entry }] : [];
|
|
61561
|
+
});
|
|
61562
|
+
const uniqueFolders = new Set(folders.map((entry) => entry.folder));
|
|
61563
|
+
let coherent = folders.length === managed.length && uniqueFolders.size === folders.length;
|
|
61564
|
+
const actualHashes = new Map;
|
|
61565
|
+
for (const item of folders) {
|
|
61566
|
+
try {
|
|
61567
|
+
const root = join7(home, ".agents", "skills", item.folder);
|
|
61568
|
+
const actual = await computeSkillTreeHash(root);
|
|
61569
|
+
actualHashes.set(item.folder, actual);
|
|
61570
|
+
const receiptHash = item.entry.skillFolderHash;
|
|
61571
|
+
if (!receiptHash || (receiptHash.length === 40 ? actual !== receiptHash : receiptHash.length === 64 ? await computeInstallerFolderHash(root) !== receiptHash : true)) {
|
|
61572
|
+
coherent = false;
|
|
61573
|
+
}
|
|
61574
|
+
if (item.entry.skillPath !== `skills/${item.folder}/SKILL.md`)
|
|
61575
|
+
coherent = false;
|
|
61576
|
+
} catch {
|
|
61577
|
+
coherent = false;
|
|
61578
|
+
}
|
|
61579
|
+
}
|
|
61580
|
+
for (const [index, skill] of snapshot2.skills.entries()) {
|
|
61581
|
+
if (expectedPresence[index] && !uniqueFolders.has(skill.name))
|
|
61582
|
+
coherent = false;
|
|
61583
|
+
}
|
|
61584
|
+
if (await directoryExists(join7(home, ".claude"))) {
|
|
61585
|
+
for (const skill of snapshot2.skills) {
|
|
61586
|
+
const link = join7(home, ".claude", "skills", skill.name);
|
|
61587
|
+
try {
|
|
61588
|
+
if (!(await lstat2(link)).isSymbolicLink())
|
|
61589
|
+
coherent = false;
|
|
61590
|
+
else if (resolve3(dirname9(link), await readlink(link)) !== join7(home, ".agents", "skills", skill.name)) {
|
|
61591
|
+
coherent = false;
|
|
61592
|
+
}
|
|
61593
|
+
} catch {
|
|
61594
|
+
coherent = false;
|
|
61595
|
+
}
|
|
61596
|
+
}
|
|
61597
|
+
}
|
|
61598
|
+
const exactCurrent = coherent && managed.length === snapshot2.skills.length && folders.every(({ key, folder, entry }) => {
|
|
61599
|
+
const skill = expected.get(folder);
|
|
61600
|
+
return key === folder && skill !== undefined && entry.ref === snapshot2.ref && actualHashes.get(folder) === skill.tree;
|
|
61601
|
+
});
|
|
61602
|
+
return {
|
|
61603
|
+
state: exactCurrent ? "current" : coherent ? "outdated" : "unhealthy",
|
|
61604
|
+
managedNames: managed.map(([name]) => name),
|
|
61605
|
+
managedFolders: [...uniqueFolders]
|
|
61606
|
+
};
|
|
61607
|
+
}
|
|
61608
|
+
async function directoryExists(path4) {
|
|
61609
|
+
try {
|
|
61610
|
+
return (await lstat2(path4)).isDirectory();
|
|
61611
|
+
} catch {
|
|
61612
|
+
return false;
|
|
61613
|
+
}
|
|
61614
|
+
}
|
|
61615
|
+
async function sourceSnapshot(dependencies) {
|
|
61616
|
+
return dependencies.resolveSource ? await dependencies.resolveSource() : await resolveAstraleSkillSource(dependencies.run);
|
|
61617
|
+
}
|
|
61618
|
+
function installerArgs(...args) {
|
|
61619
|
+
return ["--yes", SKILLS_INSTALLER_PACKAGE, ...args];
|
|
61620
|
+
}
|
|
61621
|
+
async function installSnapshot(snapshot2, execute, selectedAgents) {
|
|
61622
|
+
return await execute("npx", installerArgs("add", `${ASTRALE_CLI_SKILL_SOURCE}#${snapshot2.ref}`, "-g", "-y", "--skill", ...snapshot2.skills.map((skill) => skill.name), ...selectedAgents.length > 0 ? ["--agent", ...selectedAgents] : []));
|
|
61623
|
+
}
|
|
61624
|
+
async function selectedAgents(home, lockPath) {
|
|
61625
|
+
const { lock } = await readSkillLock(lockPath);
|
|
61626
|
+
const agents = new Set((lock?.lastSelectedAgents ?? []).filter((agent) => typeof agent === "string" && SAFE_NAME.test(agent)));
|
|
61627
|
+
agents.add("codex");
|
|
61628
|
+
if (await directoryExists(join7(home, ".claude")))
|
|
61629
|
+
agents.add("claude-code");
|
|
61630
|
+
return [...agents];
|
|
61631
|
+
}
|
|
61632
|
+
async function cleanManagedState(names, home, lockPath) {
|
|
61633
|
+
for (const name of names) {
|
|
61634
|
+
await rm3(join7(home, ".agents", "skills", name), { recursive: true, force: true });
|
|
61635
|
+
}
|
|
61636
|
+
const { lock, raw: raw2 } = await readSkillLock(lockPath);
|
|
61637
|
+
if (!lock) {
|
|
61638
|
+
if (raw2 !== null)
|
|
61639
|
+
await rm3(lockPath, { force: true });
|
|
61640
|
+
return;
|
|
61641
|
+
}
|
|
61642
|
+
for (const [name, entry] of Object.entries(lock.skills)) {
|
|
61643
|
+
if (sourceOwned(entry))
|
|
61644
|
+
delete lock.skills[name];
|
|
61645
|
+
}
|
|
61646
|
+
await writeSkillLock(lockPath, lock);
|
|
61647
|
+
}
|
|
61648
|
+
async function removeKnownAgentLinks(names, home) {
|
|
61649
|
+
const roots = await readdir3(home, { withFileTypes: true }).catch(() => []);
|
|
61650
|
+
for (const root of roots) {
|
|
61651
|
+
if (!root.isDirectory() || !root.name.startsWith(".") || root.name === ".agents")
|
|
61652
|
+
continue;
|
|
61653
|
+
for (const name of names) {
|
|
61654
|
+
const link = join7(home, root.name, "skills", name);
|
|
61655
|
+
try {
|
|
61656
|
+
const stat3 = await lstat2(link);
|
|
61657
|
+
if (!stat3.isSymbolicLink())
|
|
61658
|
+
continue;
|
|
61659
|
+
const target2 = await readlink(link);
|
|
61660
|
+
if (resolve3(dirname9(link), target2) === join7(home, ".agents", "skills", name)) {
|
|
61661
|
+
await rm3(link, { force: true });
|
|
61662
|
+
}
|
|
61663
|
+
} catch {}
|
|
61664
|
+
}
|
|
61665
|
+
}
|
|
61666
|
+
}
|
|
61667
|
+
async function pruneObsoleteEntries(snapshot2, home, lockPath, execute, knownRetired) {
|
|
61668
|
+
const expected = new Set(snapshot2.skills.map((skill) => skill.name));
|
|
61669
|
+
const { lock } = await readSkillLock(lockPath);
|
|
61670
|
+
const retiredEntries = Object.entries(lock?.skills ?? {}).filter(([, entry]) => {
|
|
61671
|
+
const folder = folderName(entry);
|
|
61672
|
+
return sourceOwned(entry) && folder !== null && !expected.has(folder);
|
|
61673
|
+
});
|
|
61674
|
+
const retired = [
|
|
61675
|
+
...new Set([
|
|
61676
|
+
...knownRetired,
|
|
61677
|
+
...retiredEntries.flatMap(([, entry]) => folderName(entry) ?? [])
|
|
61678
|
+
])
|
|
61679
|
+
];
|
|
61680
|
+
if (retired.length > 0) {
|
|
61681
|
+
const result = await execute("npx", installerArgs("remove", ...retired, "-g", "-y"));
|
|
61682
|
+
if (result.code !== 0)
|
|
61683
|
+
throw new Error(result.stderr || result.stdout || "skill removal failed");
|
|
61684
|
+
}
|
|
61685
|
+
const refreshed = await readSkillLock(lockPath);
|
|
61686
|
+
if (!refreshed.lock)
|
|
61687
|
+
return;
|
|
61688
|
+
let changed = false;
|
|
61689
|
+
for (const [name, entry] of Object.entries(refreshed.lock.skills)) {
|
|
61690
|
+
if (!sourceOwned(entry))
|
|
61691
|
+
continue;
|
|
61692
|
+
const folder = folderName(entry);
|
|
61693
|
+
if (folder === null || name !== folder || !expected.has(folder)) {
|
|
61694
|
+
delete refreshed.lock.skills[name];
|
|
61695
|
+
changed = true;
|
|
61696
|
+
}
|
|
61697
|
+
}
|
|
61698
|
+
if (changed)
|
|
61699
|
+
await writeSkillLock(lockPath, refreshed.lock);
|
|
61700
|
+
await removeKnownAgentLinks(retired, home);
|
|
61701
|
+
for (const name of retired) {
|
|
61702
|
+
await rm3(join7(home, ".agents", "skills", name), { recursive: true, force: true });
|
|
61703
|
+
}
|
|
61704
|
+
}
|
|
61705
|
+
async function captureAgentLinks(home, names) {
|
|
61706
|
+
const links = [];
|
|
61707
|
+
const roots = await readdir3(home, { withFileTypes: true }).catch(() => []);
|
|
61708
|
+
for (const root of roots) {
|
|
61709
|
+
if (!root.isDirectory() || !root.name.startsWith(".") || root.name === ".agents")
|
|
61710
|
+
continue;
|
|
61711
|
+
for (const name of names) {
|
|
61712
|
+
const path4 = join7(home, root.name, "skills", name);
|
|
61713
|
+
try {
|
|
61714
|
+
if ((await lstat2(path4)).isSymbolicLink()) {
|
|
61715
|
+
links.push({ root: root.name, name, target: await readlink(path4) });
|
|
61716
|
+
}
|
|
61717
|
+
} catch {}
|
|
61718
|
+
}
|
|
61719
|
+
}
|
|
61720
|
+
return links;
|
|
61721
|
+
}
|
|
61722
|
+
async function writeBackupManifest(backup) {
|
|
61723
|
+
const next = join7(backup.root, `${BACKUP_MANIFEST}.next`);
|
|
61724
|
+
await writeFile6(next, JSON.stringify(backup), { mode: 384 });
|
|
61725
|
+
await rename3(next, join7(backup.root, BACKUP_MANIFEST));
|
|
61726
|
+
}
|
|
61727
|
+
async function captureBackup(home, lockPath, names) {
|
|
61728
|
+
const agentsRoot = join7(home, ".agents");
|
|
61729
|
+
await mkdir10(agentsRoot, { recursive: true });
|
|
61730
|
+
const root = await mkdtemp2(join7(agentsRoot, BACKUP_PREFIX));
|
|
61731
|
+
const copied = [];
|
|
61732
|
+
for (const name of names) {
|
|
61733
|
+
const source2 = join7(agentsRoot, "skills", name);
|
|
61734
|
+
try {
|
|
61735
|
+
await cp(source2, join7(root, name), { recursive: true, dereference: false });
|
|
61736
|
+
copied.push(name);
|
|
61737
|
+
} catch (error52) {
|
|
61738
|
+
if (error52.code !== "ENOENT")
|
|
61739
|
+
throw error52;
|
|
61740
|
+
}
|
|
61741
|
+
}
|
|
61742
|
+
const lock = await readSkillLock(lockPath);
|
|
61743
|
+
const backup = {
|
|
61744
|
+
root,
|
|
61745
|
+
names,
|
|
61746
|
+
copied,
|
|
61747
|
+
links: await captureAgentLinks(home, names),
|
|
61748
|
+
lockRaw: lock.raw,
|
|
61749
|
+
createdAt: new Date().toISOString(),
|
|
61750
|
+
phase: "prepared"
|
|
61751
|
+
};
|
|
61752
|
+
await writeBackupManifest(backup);
|
|
61753
|
+
return backup;
|
|
61754
|
+
}
|
|
61755
|
+
async function extendBackup(backup, home, names) {
|
|
61756
|
+
const additions = names.filter((name) => !backup.names.includes(name));
|
|
61757
|
+
if (additions.length === 0)
|
|
61758
|
+
return;
|
|
61759
|
+
for (const name of additions) {
|
|
61760
|
+
const source2 = join7(home, ".agents", "skills", name);
|
|
61761
|
+
try {
|
|
61762
|
+
await cp(source2, join7(backup.root, name), { recursive: true, dereference: false });
|
|
61763
|
+
backup.copied.push(name);
|
|
61764
|
+
} catch (error52) {
|
|
61765
|
+
if (error52.code !== "ENOENT")
|
|
61766
|
+
throw error52;
|
|
61767
|
+
}
|
|
61768
|
+
}
|
|
61769
|
+
backup.names.push(...additions);
|
|
61770
|
+
backup.links.push(...await captureAgentLinks(home, additions));
|
|
61771
|
+
await writeBackupManifest(backup);
|
|
61772
|
+
}
|
|
61773
|
+
async function restoreAgentLinks(backup, home, onlyForeign = false) {
|
|
61774
|
+
for (const link of backup.links) {
|
|
61775
|
+
const path4 = join7(home, link.root, "skills", link.name);
|
|
61776
|
+
const canonical = join7(home, ".agents", "skills", link.name);
|
|
61777
|
+
if (onlyForeign && resolve3(dirname9(path4), link.target) === canonical)
|
|
61778
|
+
continue;
|
|
61779
|
+
await mkdir10(dirname9(path4), { recursive: true });
|
|
61780
|
+
await rm3(path4, { recursive: true, force: true });
|
|
61781
|
+
await symlink(link.target, path4);
|
|
61782
|
+
}
|
|
61783
|
+
}
|
|
61784
|
+
async function restoreBackup(backup, home, lockPath) {
|
|
61785
|
+
for (const name of backup.names) {
|
|
61786
|
+
await rm3(join7(home, ".agents", "skills", name), { recursive: true, force: true });
|
|
61787
|
+
}
|
|
61788
|
+
await mkdir10(join7(home, ".agents", "skills"), { recursive: true });
|
|
61789
|
+
for (const name of backup.copied) {
|
|
61790
|
+
await cp(join7(backup.root, name), join7(home, ".agents", "skills", name), {
|
|
61791
|
+
recursive: true,
|
|
61792
|
+
dereference: false
|
|
61793
|
+
});
|
|
61794
|
+
}
|
|
61795
|
+
if (backup.lockRaw === null)
|
|
61796
|
+
await rm3(lockPath, { force: true });
|
|
61797
|
+
else {
|
|
61798
|
+
await mkdir10(dirname9(lockPath), { recursive: true });
|
|
61799
|
+
const next = `${lockPath}.restore`;
|
|
61800
|
+
await writeFile6(next, backup.lockRaw, { mode: 384 });
|
|
61801
|
+
await rename3(next, lockPath);
|
|
61802
|
+
}
|
|
61803
|
+
await removeKnownAgentLinks(backup.names, home);
|
|
61804
|
+
await restoreAgentLinks(backup, home);
|
|
61805
|
+
}
|
|
61806
|
+
async function recoverInterruptedBackup(home, lockPath) {
|
|
61807
|
+
const agentsRoot = join7(home, ".agents");
|
|
61808
|
+
const candidates = (await readdir3(agentsRoot, { withFileTypes: true }).catch(() => [])).filter((entry) => entry.isDirectory() && entry.name.startsWith(BACKUP_PREFIX)).map((entry) => join7(agentsRoot, entry.name));
|
|
61809
|
+
const backups = [];
|
|
61810
|
+
for (const root of candidates) {
|
|
61811
|
+
try {
|
|
61812
|
+
const parsed = JSON.parse(await readFile11(join7(root, BACKUP_MANIFEST), "utf8"));
|
|
61813
|
+
if (Array.isArray(parsed.names) && parsed.names.every((name) => typeof name === "string" && SAFE_NAME.test(name)) && Array.isArray(parsed.copied) && parsed.copied.every((name) => typeof name === "string" && parsed.names.includes(name)) && Array.isArray(parsed.links) && (typeof parsed.lockRaw === "string" || parsed.lockRaw === null) && typeof parsed.createdAt === "string" && (parsed.phase === "prepared" || parsed.phase === "verified") && parsed.links.every((link) => link !== null && typeof link === "object" && typeof link.root === "string" && /^\.[^/]+$/u.test(link.root) && typeof link.name === "string" && parsed.names.includes(link.name) && typeof link.target === "string")) {
|
|
61814
|
+
const backup = { ...parsed, root };
|
|
61815
|
+
if (backup.phase === "verified")
|
|
61816
|
+
await rm3(root, { recursive: true, force: true });
|
|
61817
|
+
else
|
|
61818
|
+
backups.push(backup);
|
|
61819
|
+
} else {
|
|
61820
|
+
await rm3(root, { recursive: true, force: true });
|
|
61821
|
+
}
|
|
61822
|
+
} catch {
|
|
61823
|
+
await rm3(root, { recursive: true, force: true });
|
|
61824
|
+
}
|
|
61825
|
+
}
|
|
61826
|
+
if (backups.length === 0)
|
|
61827
|
+
return;
|
|
61828
|
+
backups.sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
61829
|
+
await restoreBackup(backups[0], home, lockPath);
|
|
61830
|
+
await Promise.all(candidates.map((root) => rm3(root, { recursive: true, force: true })));
|
|
61313
61831
|
}
|
|
61832
|
+
async function markBackupVerified(backup) {
|
|
61833
|
+
backup.phase = "verified";
|
|
61834
|
+
await writeBackupManifest(backup);
|
|
61835
|
+
}
|
|
61836
|
+
function skillFailure(error52) {
|
|
61837
|
+
const detail = error52 instanceof Error && error52.message.trim() ? `: ${error52.message}` : "";
|
|
61838
|
+
return new AstraleError("SKILL_UPDATE_FAILED", `Astrale could not install and verify its agent skills${detail}`, `Retry with \`${ASTRALE_SKILL_REPAIR_COMMAND}\`.`, error52 instanceof Error ? { cause: error52 } : undefined);
|
|
61839
|
+
}
|
|
61840
|
+
async function checkAstraleSkills(overrides = {}) {
|
|
61841
|
+
const dependencies = resolvedDependencies(overrides);
|
|
61842
|
+
try {
|
|
61843
|
+
const snapshot2 = await sourceSnapshot(dependencies);
|
|
61844
|
+
const inspection = await inspectAstraleSkills(snapshot2, dependencies.home, dependencies.lockPath);
|
|
61845
|
+
return {
|
|
61846
|
+
status: inspection.state === "current" ? "current" : inspection.state === "unhealthy" ? "repair-needed" : "update-available"
|
|
61847
|
+
};
|
|
61848
|
+
} catch (error52) {
|
|
61849
|
+
return { status: "unavailable", error: error52 instanceof Error ? error52.message : String(error52) };
|
|
61850
|
+
}
|
|
61851
|
+
}
|
|
61852
|
+
async function syncAstraleSkills(overrides = {}) {
|
|
61853
|
+
const dependencies = resolvedDependencies(overrides);
|
|
61854
|
+
let snapshot2;
|
|
61855
|
+
try {
|
|
61856
|
+
snapshot2 = await sourceSnapshot(dependencies);
|
|
61857
|
+
} catch (error52) {
|
|
61858
|
+
throw skillFailure(error52);
|
|
61859
|
+
}
|
|
61860
|
+
const lockFile = join7(process.env.ASTRALE_HOME ?? join7(dependencies.home, ".astrale"), "locks", "skills-update.lock");
|
|
61861
|
+
try {
|
|
61862
|
+
return await withFileLock2(lockFile, async () => {
|
|
61863
|
+
await recoverInterruptedBackup(dependencies.home, dependencies.lockPath);
|
|
61864
|
+
const initial = await inspectAstraleSkills(snapshot2, dependencies.home, dependencies.lockPath);
|
|
61865
|
+
if (initial.state === "current")
|
|
61866
|
+
return { status: "unchanged" };
|
|
61867
|
+
let expectedNames = snapshot2.skills.map((skill) => skill.name);
|
|
61868
|
+
let managedFolders = [...new Set([...expectedNames, ...initial.managedFolders])];
|
|
61869
|
+
let knownRetired = initial.managedFolders.filter((name) => !expectedNames.includes(name));
|
|
61870
|
+
const agents = await selectedAgents(dependencies.home, dependencies.lockPath);
|
|
61871
|
+
const backup = await captureBackup(dependencies.home, dependencies.lockPath, managedFolders);
|
|
61872
|
+
let lastError;
|
|
61873
|
+
try {
|
|
61874
|
+
for (let attempt = 0;attempt < 2; attempt++) {
|
|
61875
|
+
try {
|
|
61876
|
+
if (attempt === 1) {
|
|
61877
|
+
snapshot2 = await sourceSnapshot(dependencies);
|
|
61878
|
+
expectedNames = snapshot2.skills.map((skill) => skill.name);
|
|
61879
|
+
managedFolders = [...new Set([...managedFolders, ...expectedNames])];
|
|
61880
|
+
await extendBackup(backup, dependencies.home, managedFolders);
|
|
61881
|
+
knownRetired = [
|
|
61882
|
+
...new Set([
|
|
61883
|
+
...knownRetired,
|
|
61884
|
+
...managedFolders.filter((name) => !expectedNames.includes(name))
|
|
61885
|
+
])
|
|
61886
|
+
];
|
|
61887
|
+
}
|
|
61888
|
+
if (initial.state === "unhealthy" || attempt === 1) {
|
|
61889
|
+
await cleanManagedState(managedFolders, dependencies.home, dependencies.lockPath);
|
|
61890
|
+
}
|
|
61891
|
+
const installed = await installSnapshot(snapshot2, dependencies.run, agents);
|
|
61892
|
+
if (installed.code !== 0) {
|
|
61893
|
+
throw new Error(installed.stderr || installed.stdout || "skill installer failed");
|
|
61894
|
+
}
|
|
61895
|
+
await pruneObsoleteEntries(snapshot2, dependencies.home, dependencies.lockPath, dependencies.run, knownRetired);
|
|
61896
|
+
const verified = await inspectAstraleSkills(snapshot2, dependencies.home, dependencies.lockPath);
|
|
61897
|
+
if (verified.state !== "current") {
|
|
61898
|
+
throw new Error("installed Astrale skills did not pass verification");
|
|
61899
|
+
}
|
|
61900
|
+
const latest = await sourceSnapshot(dependencies);
|
|
61901
|
+
if (latest.revision !== snapshot2.revision) {
|
|
61902
|
+
throw new Error("Astrale skill source changed during installation");
|
|
61903
|
+
}
|
|
61904
|
+
await markBackupVerified(backup);
|
|
61905
|
+
await rm3(backup.root, { recursive: true, force: true });
|
|
61906
|
+
return {
|
|
61907
|
+
status: initial.state === "absent" ? "installed" : initial.state === "outdated" ? "updated" : "repaired"
|
|
61908
|
+
};
|
|
61909
|
+
} catch (error52) {
|
|
61910
|
+
lastError = error52;
|
|
61911
|
+
}
|
|
61912
|
+
}
|
|
61913
|
+
throw lastError;
|
|
61914
|
+
} catch (error52) {
|
|
61915
|
+
if (initial.state === "absent" || initial.state === "unhealthy") {
|
|
61916
|
+
await cleanManagedState(managedFolders, dependencies.home, dependencies.lockPath);
|
|
61917
|
+
await removeKnownAgentLinks(managedFolders, dependencies.home);
|
|
61918
|
+
await restoreAgentLinks(backup, dependencies.home, true);
|
|
61919
|
+
} else {
|
|
61920
|
+
await restoreBackup(backup, dependencies.home, dependencies.lockPath);
|
|
61921
|
+
}
|
|
61922
|
+
await rm3(backup.root, { recursive: true, force: true });
|
|
61923
|
+
throw skillFailure(error52);
|
|
61924
|
+
}
|
|
61925
|
+
});
|
|
61926
|
+
} catch (error52) {
|
|
61927
|
+
if (error52 instanceof AstraleError)
|
|
61928
|
+
throw error52;
|
|
61929
|
+
throw skillFailure(error52);
|
|
61930
|
+
}
|
|
61931
|
+
}
|
|
61932
|
+
var ASTRALE_CLI_SKILL_SOURCE = "astrale-os/cli", ASTRALE_SKILL_REPAIR_COMMAND = "astrale update --yes --no-deps", SKILLS_INSTALLER_PACKAGE = "skills@1.5.23", SKILL_INSTALL_HINT, SOURCE_REPOSITORY_URL = "https://github.com/astrale-os/cli.git", SAFE_NAME, BACKUP_PREFIX = ".astrale-skill-backup-", BACKUP_MANIFEST = ".manifest.json";
|
|
61933
|
+
var init_sync = __esm(() => {
|
|
61934
|
+
init_errors2();
|
|
61935
|
+
init_proc();
|
|
61936
|
+
init_lock();
|
|
61937
|
+
SKILL_INSTALL_HINT = ASTRALE_SKILL_REPAIR_COMMAND;
|
|
61938
|
+
SAFE_NAME = /^[a-z0-9][a-z0-9._-]*$/iu;
|
|
61939
|
+
});
|
|
61940
|
+
|
|
61941
|
+
// src/lib/skills.ts
|
|
61942
|
+
import { existsSync, lstatSync, mkdirSync, readlinkSync, symlinkSync } from "node:fs";
|
|
61943
|
+
import { homedir as homedir3 } from "node:os";
|
|
61944
|
+
import { dirname as dirname10, join as join8 } from "node:path";
|
|
61314
61945
|
function skillSearchDirs() {
|
|
61315
61946
|
const dirs = [];
|
|
61316
61947
|
let cur = process.cwd();
|
|
61317
61948
|
for (;; ) {
|
|
61318
|
-
dirs.push(
|
|
61319
|
-
const parent =
|
|
61949
|
+
dirs.push(join8(cur, ".claude", "skills"));
|
|
61950
|
+
const parent = dirname10(cur);
|
|
61320
61951
|
if (parent === cur)
|
|
61321
61952
|
break;
|
|
61322
61953
|
cur = parent;
|
|
61323
61954
|
}
|
|
61324
|
-
dirs.push(
|
|
61955
|
+
dirs.push(join8(homedir3(), ".claude", "skills"));
|
|
61325
61956
|
return dirs;
|
|
61326
61957
|
}
|
|
61327
61958
|
function detectSkill(name) {
|
|
61328
61959
|
for (const dir of skillSearchDirs()) {
|
|
61329
|
-
const file2 =
|
|
61960
|
+
const file2 = join8(dir, name, "SKILL.md");
|
|
61330
61961
|
if (existsSync(file2))
|
|
61331
61962
|
return { installed: true, location: file2 };
|
|
61332
61963
|
}
|
|
@@ -61345,9 +61976,9 @@ function isSymlink(p) {
|
|
|
61345
61976
|
function findAgentsSkillsRoot(fromDir) {
|
|
61346
61977
|
let cur = fromDir;
|
|
61347
61978
|
for (;; ) {
|
|
61348
|
-
if (existsSync(
|
|
61979
|
+
if (existsSync(join8(cur, ".agents", "skills")))
|
|
61349
61980
|
return cur;
|
|
61350
|
-
const parent =
|
|
61981
|
+
const parent = dirname10(cur);
|
|
61351
61982
|
if (parent === cur)
|
|
61352
61983
|
return null;
|
|
61353
61984
|
cur = parent;
|
|
@@ -61357,7 +61988,7 @@ function skillsBridgeStatus(fromDir = process.cwd()) {
|
|
|
61357
61988
|
const root = findAgentsSkillsRoot(fromDir);
|
|
61358
61989
|
if (!root)
|
|
61359
61990
|
return { kind: "none" };
|
|
61360
|
-
const link =
|
|
61991
|
+
const link = join8(root, ".claude", "skills");
|
|
61361
61992
|
if (isSymlink(link)) {
|
|
61362
61993
|
try {
|
|
61363
61994
|
if (readlinkSync(link) === BRIDGE_TARGET)
|
|
@@ -61373,16 +62004,15 @@ function ensureSkillsBridge(fromDir = process.cwd()) {
|
|
|
61373
62004
|
const status = skillsBridgeStatus(fromDir);
|
|
61374
62005
|
if (status.kind !== "unbridged")
|
|
61375
62006
|
return status;
|
|
61376
|
-
mkdirSync(
|
|
62007
|
+
mkdirSync(dirname10(status.link), { recursive: true });
|
|
61377
62008
|
symlinkSync(BRIDGE_TARGET, status.link);
|
|
61378
62009
|
return { kind: "bridged", root: status.root };
|
|
61379
62010
|
}
|
|
61380
|
-
var
|
|
62011
|
+
var AGENT_BROWSER_SKILL = "agent-browser", BRIDGE_TARGET;
|
|
61381
62012
|
var init_skills = __esm(() => {
|
|
61382
62013
|
init_browser();
|
|
61383
|
-
|
|
61384
|
-
|
|
61385
|
-
BRIDGE_TARGET = join6("..", ".agents", "skills");
|
|
62014
|
+
init_sync();
|
|
62015
|
+
BRIDGE_TARGET = join8("..", ".agents", "skills");
|
|
61386
62016
|
});
|
|
61387
62017
|
|
|
61388
62018
|
// src/setup/steps/agent-browser.ts
|
|
@@ -61625,9 +62255,9 @@ var init_auth5 = __esm(() => {
|
|
|
61625
62255
|
|
|
61626
62256
|
// src/setup/steps/domain.ts
|
|
61627
62257
|
import { existsSync as existsSync2 } from "node:fs";
|
|
61628
|
-
import { join as
|
|
62258
|
+
import { join as join9 } from "node:path";
|
|
61629
62259
|
function hasDomainProject() {
|
|
61630
|
-
return existsSync2(
|
|
62260
|
+
return existsSync2(join9(process.cwd(), "astrale.config.ts"));
|
|
61631
62261
|
}
|
|
61632
62262
|
var FIX4 = "npx create-astrale-domain <name> --instance <slug>", domainStep;
|
|
61633
62263
|
var init_domain2 = __esm(() => {
|
|
@@ -70385,7 +71015,7 @@ function createClasses(definitions, validation) {
|
|
|
70385
71015
|
const declarations2 = new Map(definitions.filter((value2) => value2.ref.kind === "class").map((value2) => [Key.of(value2.ref), value2]));
|
|
70386
71016
|
const resolved = new Map;
|
|
70387
71017
|
const visiting = new Set;
|
|
70388
|
-
const
|
|
71018
|
+
const resolve4 = (ref) => {
|
|
70389
71019
|
const key = Key.of(ref);
|
|
70390
71020
|
const cached3 = resolved.get(key);
|
|
70391
71021
|
if (cached3 !== undefined)
|
|
@@ -70396,7 +71026,7 @@ function createClasses(definitions, validation) {
|
|
|
70396
71026
|
if (definition === undefined)
|
|
70397
71027
|
throw new TypeError(`Class ${key} is absent from Domain input.`);
|
|
70398
71028
|
visiting.add(key);
|
|
70399
|
-
const parents = definition.extends.map(
|
|
71029
|
+
const parents = definition.extends.map(resolve4);
|
|
70400
71030
|
if (parents.some((parent) => parent.kind !== definition.kind)) {
|
|
70401
71031
|
throw new TypeError(`Class ${key} extends a Class of another graph kind.`);
|
|
70402
71032
|
}
|
|
@@ -70510,7 +71140,7 @@ function createClasses(definitions, validation) {
|
|
|
70510
71140
|
return value2;
|
|
70511
71141
|
};
|
|
70512
71142
|
for (const definition of declarations2.values())
|
|
70513
|
-
|
|
71143
|
+
resolve4(definition.ref);
|
|
70514
71144
|
return resolved;
|
|
70515
71145
|
}
|
|
70516
71146
|
function uniquePolicyRefs(values) {
|
|
@@ -70981,7 +71611,7 @@ var init_program = __esm(() => {
|
|
|
70981
71611
|
});
|
|
70982
71612
|
|
|
70983
71613
|
// node_modules/.pnpm/@astrale-os+kernel-dsl@0.2.0-beta.13/node_modules/@astrale-os/kernel-dsl/dist/v1/schema/resolution/domain.js
|
|
70984
|
-
function
|
|
71614
|
+
function resolve4(schema) {
|
|
70985
71615
|
const cached3 = resolvedSchemas.get(schema);
|
|
70986
71616
|
if (cached3 !== undefined)
|
|
70987
71617
|
return cached3;
|
|
@@ -71106,7 +71736,7 @@ var init_schema5 = __esm(() => {
|
|
|
71106
71736
|
|
|
71107
71737
|
// node_modules/.pnpm/@astrale-os+kernel-dsl@0.2.0-beta.13/node_modules/@astrale-os/kernel-dsl/dist/v1/schema/compatibility/meaning.js
|
|
71108
71738
|
function compareDependencyMeaning(dependent, target2) {
|
|
71109
|
-
|
|
71739
|
+
resolve4(dependent);
|
|
71110
71740
|
const closure2 = knownDomainClosure(dependent) ?? [];
|
|
71111
71741
|
const source2 = closure2.find((candidate) => candidate.schema.origin === target2.origin)?.schema;
|
|
71112
71742
|
if (source2 === undefined) {
|
|
@@ -71132,7 +71762,7 @@ function compareMemberMeaning(source2, target2, roots) {
|
|
|
71132
71762
|
diagnostic2("DM_MEMBER_ROOT_INVALID", "/roots", "Member comparison roots must be one non-empty duplicate-free Key set.")
|
|
71133
71763
|
]);
|
|
71134
71764
|
}
|
|
71135
|
-
|
|
71765
|
+
resolve4(source2);
|
|
71136
71766
|
const closure2 = knownDomainClosure(source2) ?? [];
|
|
71137
71767
|
const schemas3 = new Map([
|
|
71138
71768
|
[source2.origin, source2],
|
|
@@ -71143,7 +71773,7 @@ function compareMemberMeaning(source2, target2, roots) {
|
|
|
71143
71773
|
return compareSourceMeanings(source2, target2, sourceMeanings);
|
|
71144
71774
|
}
|
|
71145
71775
|
function compareSourceMeanings(source2, target2, sourceMeanings) {
|
|
71146
|
-
|
|
71776
|
+
resolve4(target2);
|
|
71147
71777
|
const footprint = Object.freeze([...sourceMeanings.keys()].sort(compareUnicode));
|
|
71148
71778
|
const changes = [];
|
|
71149
71779
|
const comparisonCoordinates = [];
|
|
@@ -73942,12 +74572,12 @@ __export(exports_schema, {
|
|
|
73942
74572
|
encode: () => encodeDomainSchema,
|
|
73943
74573
|
header: () => header,
|
|
73944
74574
|
load: () => load2,
|
|
73945
|
-
resolve: () =>
|
|
74575
|
+
resolve: () => resolve5,
|
|
73946
74576
|
revision: () => revisionOfDomainSchema,
|
|
73947
74577
|
serialize: () => serializeDomainSchema,
|
|
73948
74578
|
values: () => exports_value_api
|
|
73949
74579
|
});
|
|
73950
|
-
var
|
|
74580
|
+
var resolve5;
|
|
73951
74581
|
var init_schema6 = __esm(() => {
|
|
73952
74582
|
init_domain7();
|
|
73953
74583
|
init_accept3();
|
|
@@ -73958,7 +74588,7 @@ var init_schema6 = __esm(() => {
|
|
|
73958
74588
|
init_compiled();
|
|
73959
74589
|
init_diagnostic2();
|
|
73960
74590
|
init_value_api();
|
|
73961
|
-
|
|
74591
|
+
resolve5 = resolve4;
|
|
73962
74592
|
});
|
|
73963
74593
|
|
|
73964
74594
|
// node_modules/.pnpm/@astrale-os+kernel-dsl@0.2.0-beta.13/node_modules/@astrale-os/kernel-dsl/dist/v1/bundle/diagnostic.js
|
|
@@ -75709,12 +76339,12 @@ var init_view_resolution = __esm(() => {
|
|
|
75709
76339
|
});
|
|
75710
76340
|
|
|
75711
76341
|
// node_modules/.pnpm/@astrale-os+kernel-core@0.9.0-beta.16/node_modules/@astrale-os/kernel-core/dist/schema/kernel/syscalls/descriptors/view.js
|
|
75712
|
-
var
|
|
76342
|
+
var resolve6;
|
|
75713
76343
|
var init_view5 = __esm(() => {
|
|
75714
76344
|
init_kernel();
|
|
75715
76345
|
init_view();
|
|
75716
76346
|
init_view_resolution();
|
|
75717
|
-
|
|
76347
|
+
resolve6 = methodSyscall(resolve, K.classes.View.static.methods.resolve);
|
|
75718
76348
|
});
|
|
75719
76349
|
|
|
75720
76350
|
// node_modules/.pnpm/@astrale-os+kernel-core@0.9.0-beta.16/node_modules/@astrale-os/kernel-core/dist/schema/kernel/syscalls/descriptors/index.js
|
|
@@ -78542,14 +79172,14 @@ async function boundedResponse(response2, maximum, signal) {
|
|
|
78542
79172
|
signal.removeEventListener("abort", abort);
|
|
78543
79173
|
reader.releaseLock();
|
|
78544
79174
|
}
|
|
78545
|
-
return
|
|
79175
|
+
return join10(chunks, total);
|
|
78546
79176
|
}
|
|
78547
79177
|
function requireExactResponse(response2, expected, label) {
|
|
78548
79178
|
if (response2.redirected || response2.url !== expected) {
|
|
78549
79179
|
throw new ClientError(`${label} did not return the exact requested URL.`);
|
|
78550
79180
|
}
|
|
78551
79181
|
}
|
|
78552
|
-
function
|
|
79182
|
+
function join10(parts, length) {
|
|
78553
79183
|
if (parts.length === 1)
|
|
78554
79184
|
return new Uint8Array(parts[0]);
|
|
78555
79185
|
const output3 = new Uint8Array(length);
|
|
@@ -79426,7 +80056,7 @@ function requestUrl(input) {
|
|
|
79426
80056
|
return new URL(input.url);
|
|
79427
80057
|
}
|
|
79428
80058
|
function fetchWithNode(url3, init, ca) {
|
|
79429
|
-
return new Promise((
|
|
80059
|
+
return new Promise((resolve7, reject) => {
|
|
79430
80060
|
const request = httpsRequest(url3, {
|
|
79431
80061
|
method: init?.method ?? "GET",
|
|
79432
80062
|
headers: headersInitToRecord(init?.headers),
|
|
@@ -79443,7 +80073,7 @@ function fetchWithNode(url3, init, ca) {
|
|
|
79443
80073
|
headers: responseHeaders(response2.headers)
|
|
79444
80074
|
});
|
|
79445
80075
|
Object.defineProperty(result, "url", { value: url3.toString() });
|
|
79446
|
-
|
|
80076
|
+
resolve7(result);
|
|
79447
80077
|
});
|
|
79448
80078
|
});
|
|
79449
80079
|
request.on("error", reject);
|
|
@@ -80705,49 +81335,65 @@ var init_instance3 = __esm(() => {
|
|
|
80705
81335
|
});
|
|
80706
81336
|
|
|
80707
81337
|
// src/setup/steps/skills.ts
|
|
80708
|
-
var FIX5,
|
|
81338
|
+
var FIX5, skillsStep;
|
|
80709
81339
|
var init_skills2 = __esm(() => {
|
|
80710
81340
|
init_log();
|
|
80711
81341
|
init_skills();
|
|
80712
81342
|
FIX5 = SKILL_INSTALL_HINT;
|
|
80713
81343
|
skillsStep = {
|
|
80714
81344
|
id: "skills",
|
|
80715
|
-
title: "
|
|
81345
|
+
title: "Astrale agent skills",
|
|
80716
81346
|
group: "equip",
|
|
80717
81347
|
async detect() {
|
|
80718
|
-
|
|
80719
|
-
|
|
81348
|
+
const result = await checkAstraleSkills();
|
|
81349
|
+
if (result.status === "current") {
|
|
81350
|
+
return { state: "satisfied", summary: "Astrale skills are installed and up to date" };
|
|
80720
81351
|
}
|
|
80721
|
-
|
|
80722
|
-
|
|
81352
|
+
if (result.status === "unavailable") {
|
|
81353
|
+
return {
|
|
81354
|
+
state: "broken",
|
|
81355
|
+
summary: "Astrale skills could not be verified",
|
|
81356
|
+
detail: result.error,
|
|
81357
|
+
fixHint: FIX5
|
|
81358
|
+
};
|
|
81359
|
+
}
|
|
81360
|
+
return {
|
|
81361
|
+
state: "gap",
|
|
81362
|
+
summary: result.status === "repair-needed" ? "Astrale skills need repair" : "Astrale skills need installation or update",
|
|
81363
|
+
fixHint: FIX5
|
|
81364
|
+
};
|
|
80723
81365
|
},
|
|
80724
81366
|
async ensure() {
|
|
80725
|
-
|
|
80726
|
-
|
|
80727
|
-
|
|
80728
|
-
|
|
80729
|
-
|
|
80730
|
-
|
|
80731
|
-
|
|
81367
|
+
log.step("Ensuring Astrale agent skills are current and healthy");
|
|
81368
|
+
try {
|
|
81369
|
+
const result = await syncAstraleSkills();
|
|
81370
|
+
if (result.status === "unchanged") {
|
|
81371
|
+
log.success("Astrale skills already up to date");
|
|
81372
|
+
return "unchanged";
|
|
81373
|
+
}
|
|
81374
|
+
if (result.status === "installed")
|
|
81375
|
+
log.success("Astrale skills installed");
|
|
81376
|
+
else if (result.status === "updated")
|
|
81377
|
+
log.success("Astrale skills updated");
|
|
81378
|
+
else if (result.status === "repaired")
|
|
81379
|
+
log.success("Astrale skills repaired and updated");
|
|
81380
|
+
return "fixed";
|
|
81381
|
+
} catch (error52) {
|
|
81382
|
+
log.warn(`Astrale skills could not be installed safely${error52 instanceof Error ? `: ${error52.message}` : ""}`);
|
|
81383
|
+
log.dim(` Retry: ${FIX5}`);
|
|
80732
81384
|
return "failed";
|
|
80733
81385
|
}
|
|
80734
|
-
if (bothInstalled()) {
|
|
80735
|
-
log.success("astrale-cli + astrale-domain skills installed");
|
|
80736
|
-
} else {
|
|
80737
|
-
log.success("astrale-cli skill installed");
|
|
80738
|
-
}
|
|
80739
|
-
return "fixed";
|
|
80740
81386
|
}
|
|
80741
81387
|
};
|
|
80742
81388
|
});
|
|
80743
81389
|
|
|
80744
81390
|
// src/setup/steps/skills-bridge.ts
|
|
80745
81391
|
import { existsSync as existsSync3, readdirSync } from "node:fs";
|
|
80746
|
-
import { join as
|
|
81392
|
+
import { join as join11 } from "node:path";
|
|
80747
81393
|
function countStaged(root) {
|
|
80748
81394
|
try {
|
|
80749
|
-
const dir =
|
|
80750
|
-
return readdirSync(dir).filter((e) => existsSync3(
|
|
81395
|
+
const dir = join11(root, ".agents", "skills");
|
|
81396
|
+
return readdirSync(dir).filter((e) => existsSync3(join11(dir, e, "SKILL.md"))).length;
|
|
80751
81397
|
} catch {
|
|
80752
81398
|
return 0;
|
|
80753
81399
|
}
|
|
@@ -80785,7 +81431,7 @@ var init_skills_bridge = __esm(() => {
|
|
|
80785
81431
|
}
|
|
80786
81432
|
const after = ensureSkillsBridge();
|
|
80787
81433
|
if (after.kind === "bridged") {
|
|
80788
|
-
log.success(`Workspace skills bridged — ${
|
|
81434
|
+
log.success(`Workspace skills bridged — ${join11(after.root, ".agents/skills")} → .claude/skills`);
|
|
80789
81435
|
return "fixed";
|
|
80790
81436
|
}
|
|
80791
81437
|
log.warn("Could not create the skills bridge — create it manually: ln -s ../.agents/skills .claude/skills");
|
|
@@ -81253,18 +81899,18 @@ Examples:
|
|
|
81253
81899
|
|
|
81254
81900
|
// src/lib/sdk-deps.ts
|
|
81255
81901
|
import { existsSync as existsSync4 } from "node:fs";
|
|
81256
|
-
import { join as
|
|
81902
|
+
import { join as join12 } from "node:path";
|
|
81257
81903
|
function inDomainProject(cwd = process.cwd()) {
|
|
81258
|
-
return existsSync4(
|
|
81904
|
+
return existsSync4(join12(cwd, "astrale.config.ts"));
|
|
81259
81905
|
}
|
|
81260
81906
|
function foreignPackageManager(cwd = process.cwd()) {
|
|
81261
|
-
if (existsSync4(
|
|
81907
|
+
if (existsSync4(join12(cwd, "pnpm-lock.yaml")))
|
|
81262
81908
|
return null;
|
|
81263
|
-
if (existsSync4(
|
|
81909
|
+
if (existsSync4(join12(cwd, "package-lock.json")))
|
|
81264
81910
|
return "npm";
|
|
81265
|
-
if (existsSync4(
|
|
81911
|
+
if (existsSync4(join12(cwd, "yarn.lock")))
|
|
81266
81912
|
return "yarn";
|
|
81267
|
-
if (existsSync4(
|
|
81913
|
+
if (existsSync4(join12(cwd, "bun.lockb")) || existsSync4(join12(cwd, "bun.lock")))
|
|
81268
81914
|
return "bun";
|
|
81269
81915
|
return null;
|
|
81270
81916
|
}
|
|
@@ -81317,15 +81963,30 @@ __export(exports_update, {
|
|
|
81317
81963
|
fetchNpmTargetVersion: () => fetchNpmTargetVersion
|
|
81318
81964
|
});
|
|
81319
81965
|
async function refreshSkills() {
|
|
81320
|
-
|
|
81321
|
-
|
|
81322
|
-
|
|
81323
|
-
|
|
81324
|
-
|
|
81325
|
-
|
|
81326
|
-
|
|
81327
|
-
|
|
81328
|
-
|
|
81966
|
+
log.step("Ensuring Astrale agent skills are current and healthy");
|
|
81967
|
+
const result = await syncAstraleSkills();
|
|
81968
|
+
if (result.status === "unchanged")
|
|
81969
|
+
log.success("Astrale skills already up to date");
|
|
81970
|
+
else if (result.status === "installed")
|
|
81971
|
+
log.success("Astrale skills installed");
|
|
81972
|
+
else if (result.status === "updated")
|
|
81973
|
+
log.success("Astrale skills updated");
|
|
81974
|
+
else if (result.status === "repaired")
|
|
81975
|
+
log.success("Astrale skills repaired and updated");
|
|
81976
|
+
return result;
|
|
81977
|
+
}
|
|
81978
|
+
function skillCheckStale(skills) {
|
|
81979
|
+
return skills.status === "update-available" || skills.status === "repair-needed";
|
|
81980
|
+
}
|
|
81981
|
+
function printSkillCheck(skills) {
|
|
81982
|
+
if (skills.status === "current")
|
|
81983
|
+
log.success("Astrale skills are up to date");
|
|
81984
|
+
else if (skills.status === "update-available")
|
|
81985
|
+
log.info("Astrale skills update available");
|
|
81986
|
+
else if (skills.status === "repair-needed")
|
|
81987
|
+
log.warn("Astrale skills need repair");
|
|
81988
|
+
else if (skills.status === "unavailable") {
|
|
81989
|
+
log.warn(`Could not verify Astrale skills${skills.error ? `: ${skills.error}` : ""}`);
|
|
81329
81990
|
}
|
|
81330
81991
|
}
|
|
81331
81992
|
async function refreshSdkDeps(check3, assumeYes = false) {
|
|
@@ -81452,7 +82113,7 @@ var init_update2 = __esm(() => {
|
|
|
81452
82113
|
default: DEFAULT_UPDATE_CHANNEL
|
|
81453
82114
|
},
|
|
81454
82115
|
{ flags: "--version <version>", description: "Update to an exact version tag" },
|
|
81455
|
-
{ flags: "--no-skills", description: "Skip
|
|
82116
|
+
{ flags: "--no-skills", description: "Skip ensuring the Astrale agent skills" },
|
|
81456
82117
|
{ flags: "--no-deps", description: "Skip checking @astrale-os SDK dependency versions" },
|
|
81457
82118
|
{
|
|
81458
82119
|
flags: "--yes",
|
|
@@ -81465,23 +82126,22 @@ Behavior:
|
|
|
81465
82126
|
Keeps three things current, in order. (1) The CLI binary: updates official
|
|
81466
82127
|
script installs only — if Astrale was installed by another package manager this
|
|
81467
82128
|
command refuses so that manager stays in charge; downloads are checksum-verified
|
|
81468
|
-
before the binary is replaced. (2) The agent skills:
|
|
81469
|
-
|
|
81470
|
-
|
|
81471
|
-
|
|
82129
|
+
before the binary is replaced. (2) The Astrale agent skills: installs every
|
|
82130
|
+
top-level skill published from astrale-os/cli main, updates healthy older
|
|
82131
|
+
installs, repairs inconsistent installs, and verifies the result before
|
|
82132
|
+
reporting success. (3) SDK deps: inside a pnpm domain
|
|
81472
82133
|
project, proposes any @astrale-os/* dependency with a newer release and, on
|
|
81473
82134
|
confirm, runs "pnpm update --latest --lockfile-only" (updates package.json AND
|
|
81474
82135
|
the lockfile, honoring your registry + supply-chain age policy; run "pnpm
|
|
81475
82136
|
install" to materialize).
|
|
81476
82137
|
|
|
81477
82138
|
The default release channel is beta; --channel overrides it for one run.
|
|
81478
|
-
--check is a dry run (binary + SDK deps; exit 10 if anything is available) and
|
|
82139
|
+
--check is a dry run (binary + skills + SDK deps; exit 10 if anything is available) and
|
|
81479
82140
|
never writes. With --json it emits a unified staleness report
|
|
81480
|
-
({ stale, cli, sdk }) for tooling
|
|
81481
|
-
along with an update). --yes applies all three non-interactively (no prompts) and
|
|
82141
|
+
({ stale, cli, skills, sdk }) for tooling. --yes applies all three non-interactively and
|
|
81482
82142
|
is resilient — a binary that can't self-update (package-managed) warns but never
|
|
81483
|
-
blocks the skills/deps steps;
|
|
81484
|
-
--no-skills / --no-deps skip those
|
|
82143
|
+
blocks the skills/deps steps; a skill failure fails the command rather than
|
|
82144
|
+
claiming a partial success. --no-skills / --no-deps explicitly skip those axes.
|
|
81485
82145
|
|
|
81486
82146
|
Examples:
|
|
81487
82147
|
$ astrale update
|
|
@@ -81496,8 +82156,14 @@ Examples:
|
|
|
81496
82156
|
try {
|
|
81497
82157
|
if (opts.check && isMachine(opts)) {
|
|
81498
82158
|
const cli = await cliStale(opts);
|
|
82159
|
+
const skills = opts.skills === false ? { status: "skipped" } : await checkAstraleSkills();
|
|
81499
82160
|
const sdk = await sdkStale();
|
|
81500
|
-
const report = {
|
|
82161
|
+
const report = {
|
|
82162
|
+
stale: cli.stale || skillCheckStale(skills) || sdk.stale,
|
|
82163
|
+
cli,
|
|
82164
|
+
skills,
|
|
82165
|
+
sdk
|
|
82166
|
+
};
|
|
81501
82167
|
output(report, opts);
|
|
81502
82168
|
if (report.stale)
|
|
81503
82169
|
process.exitCode = 10;
|
|
@@ -81536,22 +82202,32 @@ Examples:
|
|
|
81536
82202
|
throw error52;
|
|
81537
82203
|
log.warn(`CLI self-update skipped: ${error52.message}`);
|
|
81538
82204
|
}
|
|
81539
|
-
if (
|
|
81540
|
-
|
|
82205
|
+
if (opts.skills !== false) {
|
|
82206
|
+
if (opts.check) {
|
|
82207
|
+
const skills = await checkAstraleSkills();
|
|
82208
|
+
printSkillCheck(skills);
|
|
82209
|
+
if (skillCheckStale(skills))
|
|
82210
|
+
anyAvailable = true;
|
|
82211
|
+
} else {
|
|
82212
|
+
await refreshSkills();
|
|
82213
|
+
}
|
|
82214
|
+
} else if (!opts.check) {
|
|
82215
|
+
log.dim(" Astrale skills skipped (--no-skills)");
|
|
82216
|
+
}
|
|
81541
82217
|
if (opts.deps !== false && await refreshSdkDeps(opts.check === true, opts.yes === true)) {
|
|
81542
82218
|
anyAvailable = true;
|
|
81543
82219
|
}
|
|
81544
82220
|
if (opts.check && anyAvailable)
|
|
81545
82221
|
process.exitCode = 10;
|
|
81546
82222
|
} catch (e) {
|
|
81547
|
-
fatal(e);
|
|
82223
|
+
fatal(e, opts);
|
|
81548
82224
|
}
|
|
81549
82225
|
}
|
|
81550
82226
|
};
|
|
81551
82227
|
});
|
|
81552
82228
|
|
|
81553
82229
|
// src/lib/binary.ts
|
|
81554
|
-
import { writeFile as
|
|
82230
|
+
import { writeFile as writeFile7 } from "node:fs/promises";
|
|
81555
82231
|
async function readBinaryBody(body) {
|
|
81556
82232
|
if (body instanceof Uint8Array)
|
|
81557
82233
|
return new Uint8Array(body);
|
|
@@ -81603,7 +82279,7 @@ function jsonEnvelope(resp, bytes) {
|
|
|
81603
82279
|
async function presentBinary(resp, opts, io) {
|
|
81604
82280
|
const bytes = await readBinaryBody(resp.body);
|
|
81605
82281
|
if (io?.outFile) {
|
|
81606
|
-
await
|
|
82282
|
+
await writeFile7(io.outFile, bytes);
|
|
81607
82283
|
process.stderr.write(source_default.dim(` wrote ${humanSize(bytes.length)} (${resp.mediaType}) → ${io.outFile}
|
|
81608
82284
|
`));
|
|
81609
82285
|
return;
|
|
@@ -82114,7 +82790,7 @@ __export(exports_mutate, {
|
|
|
82114
82790
|
default: () => mutate_default,
|
|
82115
82791
|
mutateCommand: () => mutateCommand
|
|
82116
82792
|
});
|
|
82117
|
-
import { readFile as
|
|
82793
|
+
import { readFile as readFile12 } from "node:fs/promises";
|
|
82118
82794
|
async function mutateCommand(opts) {
|
|
82119
82795
|
let mutation;
|
|
82120
82796
|
try {
|
|
@@ -82147,7 +82823,7 @@ async function readDocument(opts) {
|
|
|
82147
82823
|
if (opts.file !== undefined) {
|
|
82148
82824
|
let raw3;
|
|
82149
82825
|
try {
|
|
82150
|
-
raw3 = await
|
|
82826
|
+
raw3 = await readFile12(opts.file, "utf8");
|
|
82151
82827
|
} catch (error52) {
|
|
82152
82828
|
throw new AstraleError("FILE_READ_FAILED", `Cannot read --file ${opts.file}.`, undefined, {
|
|
82153
82829
|
cause: error52
|
|
@@ -82231,7 +82907,7 @@ __export(exports_query, {
|
|
|
82231
82907
|
default: () => query_default,
|
|
82232
82908
|
queryCommand: () => queryCommand
|
|
82233
82909
|
});
|
|
82234
|
-
import { readFile as
|
|
82910
|
+
import { readFile as readFile13 } from "node:fs/promises";
|
|
82235
82911
|
async function queryCommand(sources2, opts) {
|
|
82236
82912
|
let input;
|
|
82237
82913
|
try {
|
|
@@ -82282,7 +82958,7 @@ async function readAst(opts) {
|
|
|
82282
82958
|
return;
|
|
82283
82959
|
let raw2;
|
|
82284
82960
|
try {
|
|
82285
|
-
raw2 = await
|
|
82961
|
+
raw2 = await readFile13(opts.file, "utf8");
|
|
82286
82962
|
} catch (error52) {
|
|
82287
82963
|
throw new AstraleError("FILE_READ_FAILED", `Cannot read --file ${opts.file}.`, undefined, {
|
|
82288
82964
|
cause: error52
|
|
@@ -82608,7 +83284,7 @@ async function runOnce(opts) {
|
|
|
82608
83284
|
}
|
|
82609
83285
|
async function followLogs(opts, dependencies = {
|
|
82610
83286
|
run: runKernelCommand,
|
|
82611
|
-
pause: (milliseconds) => new Promise((
|
|
83287
|
+
pause: (milliseconds) => new Promise((resolve7) => setTimeout(resolve7, milliseconds))
|
|
82612
83288
|
}) {
|
|
82613
83289
|
validateLogsOpts(opts);
|
|
82614
83290
|
await dependencies.run({
|
|
@@ -82814,10 +83490,10 @@ Examples:
|
|
|
82814
83490
|
// src/lib/port.ts
|
|
82815
83491
|
import net from "node:net";
|
|
82816
83492
|
function portFree(port, host = LOOPBACK) {
|
|
82817
|
-
return new Promise((
|
|
83493
|
+
return new Promise((resolve7) => {
|
|
82818
83494
|
const srv = net.createServer();
|
|
82819
|
-
srv.once("error", () =>
|
|
82820
|
-
srv.once("listening", () => srv.close(() =>
|
|
83495
|
+
srv.once("error", () => resolve7(false));
|
|
83496
|
+
srv.once("listening", () => srv.close(() => resolve7(true)));
|
|
82821
83497
|
srv.listen({ port, host, exclusive: true });
|
|
82822
83498
|
});
|
|
82823
83499
|
}
|
|
@@ -82859,10 +83535,10 @@ var init_external_open_origins = __esm(() => {
|
|
|
82859
83535
|
|
|
82860
83536
|
// src/lib/view/session.ts
|
|
82861
83537
|
import { closeSync, fchmodSync, openSync } from "node:fs";
|
|
82862
|
-
import { chmod as chmod3, mkdir as
|
|
82863
|
-
import { join as
|
|
83538
|
+
import { chmod as chmod3, mkdir as mkdir11, readdir as readdir4, readFile as readFile14, rm as rm4 } from "node:fs/promises";
|
|
83539
|
+
import { join as join13 } from "node:path";
|
|
82864
83540
|
async function ensureViewDirectory(directory = VIEW_DIR) {
|
|
82865
|
-
await
|
|
83541
|
+
await mkdir11(directory, { recursive: true, mode: 448 });
|
|
82866
83542
|
await chmod3(directory, 448);
|
|
82867
83543
|
}
|
|
82868
83544
|
async function saveRecord(record12, directory = VIEW_DIR) {
|
|
@@ -82888,9 +83564,9 @@ async function openSessionLog(id, directory = VIEW_DIR) {
|
|
|
82888
83564
|
}
|
|
82889
83565
|
async function removeSessionFiles(id, directory = VIEW_DIR) {
|
|
82890
83566
|
await Promise.all([
|
|
82891
|
-
|
|
82892
|
-
|
|
82893
|
-
|
|
83567
|
+
rm4(recordPath(id, directory), { force: true }),
|
|
83568
|
+
rm4(configPath(id, directory), { force: true }),
|
|
83569
|
+
rm4(logPath(id, directory), { force: true })
|
|
82894
83570
|
]);
|
|
82895
83571
|
}
|
|
82896
83572
|
function isAlive(pid) {
|
|
@@ -82904,7 +83580,7 @@ function isAlive(pid) {
|
|
|
82904
83580
|
async function listSessions() {
|
|
82905
83581
|
let entries;
|
|
82906
83582
|
try {
|
|
82907
|
-
entries = await
|
|
83583
|
+
entries = await readdir4(VIEW_DIR);
|
|
82908
83584
|
} catch {
|
|
82909
83585
|
return [];
|
|
82910
83586
|
}
|
|
@@ -82914,7 +83590,7 @@ async function listSessions() {
|
|
|
82914
83590
|
continue;
|
|
82915
83591
|
let record12;
|
|
82916
83592
|
try {
|
|
82917
|
-
record12 = JSON.parse(await
|
|
83593
|
+
record12 = JSON.parse(await readFile14(join13(VIEW_DIR, entry2), "utf8"));
|
|
82918
83594
|
} catch {
|
|
82919
83595
|
continue;
|
|
82920
83596
|
}
|
|
@@ -82932,7 +83608,7 @@ async function closeSession(record12) {
|
|
|
82932
83608
|
} catch {}
|
|
82933
83609
|
const deadline = Date.now() + CLOSE_GRACE_MS;
|
|
82934
83610
|
while (isAlive(record12.pid) && Date.now() < deadline) {
|
|
82935
|
-
await new Promise((
|
|
83611
|
+
await new Promise((resolve7) => setTimeout(resolve7, 100));
|
|
82936
83612
|
}
|
|
82937
83613
|
if (isAlive(record12.pid)) {
|
|
82938
83614
|
try {
|
|
@@ -82942,14 +83618,14 @@ async function closeSession(record12) {
|
|
|
82942
83618
|
}
|
|
82943
83619
|
await removeSessionFiles(record12.id);
|
|
82944
83620
|
}
|
|
82945
|
-
var VIEW_DIR, recordPath = (id, directory = VIEW_DIR) =>
|
|
83621
|
+
var VIEW_DIR, recordPath = (id, directory = VIEW_DIR) => join13(directory, `${id}.json`), logPath = (id, directory = VIEW_DIR) => join13(directory, `${id}.log`), configPath = (id, directory = VIEW_DIR) => join13(directory, `${id}.config.json`), CLOSE_GRACE_MS = 2000;
|
|
82946
83622
|
var init_session5 = __esm(() => {
|
|
82947
83623
|
init_state();
|
|
82948
|
-
VIEW_DIR =
|
|
83624
|
+
VIEW_DIR = join13(paths2.home, "view");
|
|
82949
83625
|
});
|
|
82950
83626
|
|
|
82951
83627
|
// src/lib/view/port-allocation.ts
|
|
82952
|
-
import { join as
|
|
83628
|
+
import { join as join14 } from "node:path";
|
|
82953
83629
|
function withViewPortAllocationLock(fn, lockPath = VIEW_PORT_LOCK) {
|
|
82954
83630
|
return withFileLock(lockPath, fn);
|
|
82955
83631
|
}
|
|
@@ -82957,7 +83633,7 @@ var VIEW_PORT_LOCK;
|
|
|
82957
83633
|
var init_port_allocation = __esm(() => {
|
|
82958
83634
|
init_state();
|
|
82959
83635
|
init_session5();
|
|
82960
|
-
VIEW_PORT_LOCK =
|
|
83636
|
+
VIEW_PORT_LOCK = join14(VIEW_DIR, "ports.lock");
|
|
82961
83637
|
});
|
|
82962
83638
|
|
|
82963
83639
|
// src/lib/view/resolve.ts
|
|
@@ -83027,33 +83703,33 @@ var init_resolve2 = __esm(() => {
|
|
|
83027
83703
|
// src/lib/view/assets.ts
|
|
83028
83704
|
import { existsSync as existsSync5, statSync } from "node:fs";
|
|
83029
83705
|
import { copyFile as copyFile2 } from "node:fs/promises";
|
|
83030
|
-
import { dirname as
|
|
83706
|
+
import { dirname as dirname11, join as join15 } from "node:path";
|
|
83031
83707
|
import { fileURLToPath } from "node:url";
|
|
83032
83708
|
function viewerDistDir(moduleUrl = import.meta.url, entry2 = process.argv[1] ?? ".", executable = process.execPath) {
|
|
83033
83709
|
const override = process.env.ASTRALE_VIEWER_DIR;
|
|
83034
83710
|
if (override)
|
|
83035
83711
|
return override;
|
|
83036
|
-
const moduleDirectory =
|
|
83037
|
-
const published =
|
|
83038
|
-
const source2 =
|
|
83039
|
-
const legacy =
|
|
83040
|
-
const standalone = entry2.startsWith("/$bunfs/") ?
|
|
83712
|
+
const moduleDirectory = dirname11(fileURLToPath(moduleUrl));
|
|
83713
|
+
const published = join15(moduleDirectory, "..", "viewer", "dist");
|
|
83714
|
+
const source2 = join15(moduleDirectory, "..", "..", "..", "viewer", "dist");
|
|
83715
|
+
const legacy = join15(dirname11(entry2), "..", "viewer", "dist");
|
|
83716
|
+
const standalone = entry2.startsWith("/$bunfs/") ? join15(dirname11(executable), "viewer", "dist") : undefined;
|
|
83041
83717
|
const complete = [standalone, published, source2, legacy].find((candidate2) => candidate2 !== undefined && hasViewerBundle(candidate2));
|
|
83042
83718
|
if (complete)
|
|
83043
83719
|
return complete;
|
|
83044
|
-
if (hasViewerSource(
|
|
83720
|
+
if (hasViewerSource(join15(source2, "..")))
|
|
83045
83721
|
return source2;
|
|
83046
83722
|
return published;
|
|
83047
83723
|
}
|
|
83048
83724
|
async function ensureViewerAssets(moduleUrl = import.meta.url, entry2 = process.argv[1] ?? ".") {
|
|
83049
83725
|
const dist = viewerDistDir(moduleUrl, entry2);
|
|
83050
|
-
const srcDir =
|
|
83726
|
+
const srcDir = join15(dist, "..");
|
|
83051
83727
|
if (hasViewerBundle(dist) && !viewerSourceIsNewer(srcDir, dist))
|
|
83052
83728
|
return dist;
|
|
83053
83729
|
const bun = globalThis.Bun;
|
|
83054
83730
|
if (bun && hasViewerSource(srcDir)) {
|
|
83055
83731
|
const result = await bun.build({
|
|
83056
|
-
entrypoints: [
|
|
83732
|
+
entrypoints: [join15(srcDir, "main.ts")],
|
|
83057
83733
|
outdir: dist,
|
|
83058
83734
|
target: "browser",
|
|
83059
83735
|
minify: false
|
|
@@ -83061,32 +83737,32 @@ async function ensureViewerAssets(moduleUrl = import.meta.url, entry2 = process.
|
|
|
83061
83737
|
if (!result.success)
|
|
83062
83738
|
throw new Error(`viewer build failed: ${result.logs.join(`
|
|
83063
83739
|
`)}`);
|
|
83064
|
-
await copyFile2(
|
|
83740
|
+
await copyFile2(join15(srcDir, "index.html"), join15(dist, "index.html"));
|
|
83065
83741
|
return dist;
|
|
83066
83742
|
}
|
|
83067
83743
|
throw new Error(`viewer bundle missing at ${dist} — reinstall the CLI (or run \`bun scripts/build.ts\` in a dev checkout)`);
|
|
83068
83744
|
}
|
|
83069
83745
|
function hasViewerBundle(directory) {
|
|
83070
|
-
return existsSync5(
|
|
83746
|
+
return existsSync5(join15(directory, "main.js")) && existsSync5(join15(directory, "index.html"));
|
|
83071
83747
|
}
|
|
83072
83748
|
function hasViewerSource(directory) {
|
|
83073
|
-
return existsSync5(
|
|
83749
|
+
return existsSync5(join15(directory, "main.ts")) && existsSync5(join15(directory, "index.html"));
|
|
83074
83750
|
}
|
|
83075
83751
|
function viewerSourceIsNewer(source2, dist) {
|
|
83076
83752
|
if (!hasViewerSource(source2))
|
|
83077
83753
|
return false;
|
|
83078
83754
|
if (!hasViewerBundle(dist))
|
|
83079
83755
|
return true;
|
|
83080
|
-
const newestSource = Math.max(statSync(
|
|
83081
|
-
const oldestOutput = Math.min(statSync(
|
|
83756
|
+
const newestSource = Math.max(statSync(join15(source2, "main.ts")).mtimeMs, statSync(join15(source2, "index.html")).mtimeMs);
|
|
83757
|
+
const oldestOutput = Math.min(statSync(join15(dist, "main.js")).mtimeMs, statSync(join15(dist, "index.html")).mtimeMs);
|
|
83082
83758
|
return newestSource > oldestOutput;
|
|
83083
83759
|
}
|
|
83084
83760
|
var init_assets = () => {};
|
|
83085
83761
|
|
|
83086
83762
|
// src/lib/view/server.ts
|
|
83087
|
-
import { readFile as
|
|
83763
|
+
import { readFile as readFile15 } from "node:fs/promises";
|
|
83088
83764
|
import { createServer } from "node:http";
|
|
83089
|
-
import { join as
|
|
83765
|
+
import { join as join16 } from "node:path";
|
|
83090
83766
|
import { Readable } from "node:stream";
|
|
83091
83767
|
function startViewServer(config2) {
|
|
83092
83768
|
const { session: session3, proxy } = config2;
|
|
@@ -83134,11 +83810,11 @@ function startViewServer(config2) {
|
|
|
83134
83810
|
return;
|
|
83135
83811
|
}
|
|
83136
83812
|
if (sub === "/" || sub === "/index.html") {
|
|
83137
|
-
await serveAsset(res,
|
|
83813
|
+
await serveAsset(res, join16(hostDir, "index.html"), "text/html; charset=utf-8");
|
|
83138
83814
|
return;
|
|
83139
83815
|
}
|
|
83140
83816
|
if (sub === "/main.js") {
|
|
83141
|
-
await serveAsset(res,
|
|
83817
|
+
await serveAsset(res, join16(hostDir, "main.js"), "text/javascript; charset=utf-8");
|
|
83142
83818
|
return;
|
|
83143
83819
|
}
|
|
83144
83820
|
if (sub === "/config.json" && req.method === "GET") {
|
|
@@ -83258,7 +83934,7 @@ function json3(res, code, body) {
|
|
|
83258
83934
|
}
|
|
83259
83935
|
async function serveAsset(res, file2, contentType) {
|
|
83260
83936
|
try {
|
|
83261
|
-
const content = await
|
|
83937
|
+
const content = await readFile15(file2);
|
|
83262
83938
|
res.writeHead(200, { "content-type": contentType, "cache-control": "no-store" });
|
|
83263
83939
|
res.end(content);
|
|
83264
83940
|
} catch {
|
|
@@ -83350,7 +84026,7 @@ var SETTLE_TIMEOUT_MS = 8000, QUIET_WINDOW_MS = 750, POLL_MS = 250, realClock, d
|
|
|
83350
84026
|
var init_snapshot = __esm(() => {
|
|
83351
84027
|
realClock = {
|
|
83352
84028
|
now: Date.now,
|
|
83353
|
-
sleep: (ms) => new Promise((
|
|
84029
|
+
sleep: (ms) => new Promise((resolve7) => setTimeout(resolve7, ms))
|
|
83354
84030
|
};
|
|
83355
84031
|
defaultPolicy = {
|
|
83356
84032
|
timeoutMs: SETTLE_TIMEOUT_MS,
|
|
@@ -83374,8 +84050,8 @@ __export(exports_view3, {
|
|
|
83374
84050
|
});
|
|
83375
84051
|
import { randomBytes } from "node:crypto";
|
|
83376
84052
|
import { closeSync as closeSync2, existsSync as existsSync6, statSync as statSync2 } from "node:fs";
|
|
83377
|
-
import { readdir as
|
|
83378
|
-
import { dirname as
|
|
84053
|
+
import { readdir as readdir5, readFile as readFile16 } from "node:fs/promises";
|
|
84054
|
+
import { dirname as dirname12, join as join17 } from "node:path";
|
|
83379
84055
|
async function resolveSession(spec, opts) {
|
|
83380
84056
|
rejectUnrepresentableOverrides(opts);
|
|
83381
84057
|
const parsed = parseViewSpec(spec);
|
|
@@ -83430,7 +84106,7 @@ async function resolveServeRuntime(environment = {}) {
|
|
|
83430
84106
|
if (node4 && entry2?.endsWith(".js") && exists(entry2))
|
|
83431
84107
|
return { file: node4, args: [entry2] };
|
|
83432
84108
|
if (node4 && entry2?.endsWith(".ts")) {
|
|
83433
|
-
const dist =
|
|
84109
|
+
const dist = join17(dirname12(entry2), "..", "dist", "astrale.js");
|
|
83434
84110
|
await ensureDevDist(entry2, dist);
|
|
83435
84111
|
if (exists(dist))
|
|
83436
84112
|
return { file: node4, args: [dist] };
|
|
@@ -83456,8 +84132,8 @@ async function findOnPath(name) {
|
|
|
83456
84132
|
async function ensureDevDist(entry2, dist) {
|
|
83457
84133
|
if (!await devDistIsStale(entry2, dist))
|
|
83458
84134
|
return;
|
|
83459
|
-
const projectDir =
|
|
83460
|
-
const buildScript =
|
|
84135
|
+
const projectDir = join17(dirname12(entry2), "..");
|
|
84136
|
+
const buildScript = join17(projectDir, "scripts", "build.ts");
|
|
83461
84137
|
const bun = await findOnPath("bun");
|
|
83462
84138
|
if (!bun || !existsSync6(buildScript))
|
|
83463
84139
|
return;
|
|
@@ -83473,13 +84149,13 @@ async function ensureDevDist(entry2, dist) {
|
|
|
83473
84149
|
async function devDistIsStale(entry2, dist) {
|
|
83474
84150
|
if (!existsSync6(dist))
|
|
83475
84151
|
return true;
|
|
83476
|
-
const projectDir =
|
|
84152
|
+
const projectDir = join17(dirname12(entry2), "..");
|
|
83477
84153
|
const builtAt = statSync2(dist).mtimeMs;
|
|
83478
|
-
const directories = [
|
|
84154
|
+
const directories = [join17(projectDir, "src"), join17(projectDir, "bin"), join17(projectDir, "vendor")];
|
|
83479
84155
|
const files = [
|
|
83480
|
-
|
|
83481
|
-
|
|
83482
|
-
|
|
84156
|
+
join17(projectDir, "scripts", "build.ts"),
|
|
84157
|
+
join17(projectDir, "package.json"),
|
|
84158
|
+
join17(projectDir, "pnpm-lock.yaml")
|
|
83483
84159
|
];
|
|
83484
84160
|
for (const directory of directories) {
|
|
83485
84161
|
if (existsSync6(directory) && await newerThan(directory, builtAt))
|
|
@@ -83488,11 +84164,11 @@ async function devDistIsStale(entry2, dist) {
|
|
|
83488
84164
|
return files.some((file2) => existsSync6(file2) && statSync2(file2).mtimeMs > builtAt);
|
|
83489
84165
|
}
|
|
83490
84166
|
async function newerThan(dir, mtimeMs) {
|
|
83491
|
-
const entries = await
|
|
84167
|
+
const entries = await readdir5(dir, { withFileTypes: true, recursive: true });
|
|
83492
84168
|
for (const item of entries) {
|
|
83493
84169
|
if (!item.isFile())
|
|
83494
84170
|
continue;
|
|
83495
|
-
if (statSync2(
|
|
84171
|
+
if (statSync2(join17(item.parentPath, item.name)).mtimeMs > mtimeMs)
|
|
83496
84172
|
return true;
|
|
83497
84173
|
}
|
|
83498
84174
|
return false;
|
|
@@ -83570,7 +84246,7 @@ async function startSessionLocked(view2, opts, kernelTarget, activeInstance, def
|
|
|
83570
84246
|
break;
|
|
83571
84247
|
await sleep2(POLL_MS2);
|
|
83572
84248
|
}
|
|
83573
|
-
const tail = await
|
|
84249
|
+
const tail = await readFile16(logPath(id), "utf8").catch(() => "");
|
|
83574
84250
|
await closeSession(live);
|
|
83575
84251
|
throw new Error(`View session server did not come up.${tail ? `
|
|
83576
84252
|
--- server log ---
|
|
@@ -83705,7 +84381,7 @@ async function sessionsCommand(opts) {
|
|
|
83705
84381
|
console.log(`${source_default.bold(s.id)} /:${s.view.route.key} target ${s.view.target} ${source_default.dim(s.pageUrl)}`);
|
|
83706
84382
|
}
|
|
83707
84383
|
}
|
|
83708
|
-
var VIEW_PORT_BASE = 4419, VIEW_PORT_SPAN = 20, IDLE_MS, READY_TIMEOUT_MS = 8000, STATE_TIMEOUT_MS = 25000, POLL_MS2 = 250, VIEW_PROFILE, sleep2 = (ms) => new Promise((
|
|
84384
|
+
var VIEW_PORT_BASE = 4419, VIEW_PORT_SPAN = 20, IDLE_MS, READY_TIMEOUT_MS = 8000, STATE_TIMEOUT_MS = 25000, POLL_MS2 = 250, VIEW_PROFILE, sleep2 = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms)), view_default;
|
|
83709
84385
|
var init_view7 = __esm(() => {
|
|
83710
84386
|
init_source();
|
|
83711
84387
|
init_connection2();
|
|
@@ -83844,7 +84520,7 @@ Examples:
|
|
|
83844
84520
|
if (state2?.state === "failed") {
|
|
83845
84521
|
await reportOpened(record12, state2, mode, opts);
|
|
83846
84522
|
if (opts.debug) {
|
|
83847
|
-
const tail = await
|
|
84523
|
+
const tail = await readFile16(logPath(record12.id), "utf8").catch(() => "");
|
|
83848
84524
|
if (tail)
|
|
83849
84525
|
console.error(`--- server log ---
|
|
83850
84526
|
${tail.slice(-3000)}`);
|
|
@@ -83966,7 +84642,7 @@ function reportConnected(session3, machine, opts) {
|
|
|
83966
84642
|
console.log(` agent-browser ${drive} open ${session3.url}`);
|
|
83967
84643
|
console.log(` agent-browser ${drive} click @e3`);
|
|
83968
84644
|
}
|
|
83969
|
-
var LOGIN_TIMEOUT_MS = 180000, POLL_INTERVAL_MS = 2500, sleep3 = (ms) => new Promise((
|
|
84645
|
+
var LOGIN_TIMEOUT_MS = 180000, POLL_INTERVAL_MS = 2500, sleep3 = (ms) => new Promise((resolve7) => setTimeout(resolve7, ms)), browser_default;
|
|
83970
84646
|
var init_browser2 = __esm(() => {
|
|
83971
84647
|
init_source();
|
|
83972
84648
|
init_browser();
|
|
@@ -84083,7 +84759,7 @@ var exports_view_serve = {};
|
|
|
84083
84759
|
__export(exports_view_serve, {
|
|
84084
84760
|
default: () => view_serve_default
|
|
84085
84761
|
});
|
|
84086
|
-
import { readFile as
|
|
84762
|
+
import { readFile as readFile17 } from "node:fs/promises";
|
|
84087
84763
|
var view_serve_default;
|
|
84088
84764
|
var init_view_serve = __esm(() => {
|
|
84089
84765
|
init_server();
|
|
@@ -84095,7 +84771,7 @@ var init_view_serve = __esm(() => {
|
|
|
84095
84771
|
action: async (opts) => {
|
|
84096
84772
|
if (!opts.config)
|
|
84097
84773
|
throw new Error("--config is required");
|
|
84098
|
-
const config2 = JSON.parse(await
|
|
84774
|
+
const config2 = JSON.parse(await readFile17(opts.config, "utf8"));
|
|
84099
84775
|
startViewServer(config2);
|
|
84100
84776
|
console.log(`view session ${config2.session.id} listening on ${config2.session.pageUrl}`);
|
|
84101
84777
|
await new Promise(() => {});
|
|
@@ -84110,7 +84786,7 @@ __export(exports_studio, {
|
|
|
84110
84786
|
encodeStudioCliDescriptor: () => encodeStudioCliDescriptor
|
|
84111
84787
|
});
|
|
84112
84788
|
import { existsSync as existsSync8, realpathSync } from "node:fs";
|
|
84113
|
-
import { dirname as
|
|
84789
|
+
import { dirname as dirname13, join as join18, resolve as resolve7 } from "node:path";
|
|
84114
84790
|
function encodeStudioCliDescriptor(executable = process.execPath, entry2 = process.argv[1]) {
|
|
84115
84791
|
const args = entry2 && entry2 !== executable && !entry2.startsWith("/$bunfs") && existsSync8(entry2) ? [realpathSync(entry2)] : [];
|
|
84116
84792
|
return JSON.stringify({ version: 1, executable, args });
|
|
@@ -84120,22 +84796,22 @@ function resolveStudioDir() {
|
|
|
84120
84796
|
if (process.env.ASTRALE_STUDIO_DIR)
|
|
84121
84797
|
candidates.push(process.env.ASTRALE_STUDIO_DIR);
|
|
84122
84798
|
try {
|
|
84123
|
-
const entryDir =
|
|
84124
|
-
candidates.push(
|
|
84799
|
+
const entryDir = dirname13(realpathSync(process.argv[1] ?? ""));
|
|
84800
|
+
candidates.push(join18(entryDir, "..", "studio"), join18(entryDir, "studio"));
|
|
84125
84801
|
} catch {}
|
|
84126
84802
|
for (const c of candidates) {
|
|
84127
|
-
if (existsSync8(
|
|
84128
|
-
return
|
|
84803
|
+
if (existsSync8(join18(c, "server", "index.ts")))
|
|
84804
|
+
return resolve7(c);
|
|
84129
84805
|
}
|
|
84130
84806
|
throw new Error(`Domain Studio assets not found (looked in: ${candidates.join(", ") || "<none>"}). ` + `Reinstall the astrale CLI, or set ASTRALE_STUDIO_DIR to a studio checkout.`);
|
|
84131
84807
|
}
|
|
84132
84808
|
function isDevSource(studioDir) {
|
|
84133
|
-
return existsSync8(
|
|
84809
|
+
return existsSync8(join18(studioDir, "vite.config.ts")) && existsSync8(join18(studioDir, "client", "src"));
|
|
84134
84810
|
}
|
|
84135
84811
|
function resolveViteBin(studioDir) {
|
|
84136
84812
|
for (const c of [
|
|
84137
|
-
|
|
84138
|
-
|
|
84813
|
+
join18(studioDir, "node_modules", ".bin", "vite"),
|
|
84814
|
+
join18(studioDir, "..", "..", "node_modules", ".bin", "vite")
|
|
84139
84815
|
]) {
|
|
84140
84816
|
if (existsSync8(c))
|
|
84141
84817
|
return c;
|
|
@@ -84256,11 +84932,11 @@ Examples:
|
|
|
84256
84932
|
`,
|
|
84257
84933
|
action: async (pathArg, opts) => {
|
|
84258
84934
|
try {
|
|
84259
|
-
const workspace =
|
|
84935
|
+
const workspace = resolve7(pathArg ?? process.cwd());
|
|
84260
84936
|
if (!existsSync8(workspace))
|
|
84261
84937
|
throw new Error(`path not found: ${workspace}`);
|
|
84262
84938
|
const studioDir = resolveStudioDir();
|
|
84263
|
-
if (process.env.ASTRALE_STUDIO_DIR && studioDir ===
|
|
84939
|
+
if (process.env.ASTRALE_STUDIO_DIR && studioDir === resolve7(process.env.ASTRALE_STUDIO_DIR)) {
|
|
84264
84940
|
log.dim(` using ASTRALE_STUDIO_DIR=${studioDir}`);
|
|
84265
84941
|
}
|
|
84266
84942
|
await ensureBun();
|
|
@@ -84360,8 +85036,8 @@ Examples:
|
|
|
84360
85036
|
}
|
|
84361
85037
|
}), "server");
|
|
84362
85038
|
} else {
|
|
84363
|
-
const dist =
|
|
84364
|
-
if (!existsSync8(
|
|
85039
|
+
const dist = join18(studioDir, "client", "dist");
|
|
85040
|
+
if (!existsSync8(join18(dist, "index.html"))) {
|
|
84365
85041
|
throw new Error(`studio client not built at ${dist} — run: pnpm --filter @astrale-os/studio build`);
|
|
84366
85042
|
}
|
|
84367
85043
|
serverChild = supervise(spawnHandle("bun", ["server/index.ts", workspace, "--port", String(studioPort), "--no-open"], {
|
|
@@ -84414,10 +85090,10 @@ var init_model7 = __esm(() => {
|
|
|
84414
85090
|
});
|
|
84415
85091
|
|
|
84416
85092
|
// src/ui/lock.ts
|
|
84417
|
-
import { createHash as
|
|
84418
|
-
import { readFile as
|
|
85093
|
+
import { createHash as createHash3 } from "node:crypto";
|
|
85094
|
+
import { readFile as readFile18 } from "node:fs/promises";
|
|
84419
85095
|
function digest5(value3) {
|
|
84420
|
-
return
|
|
85096
|
+
return createHash3("sha256").update(value3).digest("hex");
|
|
84421
85097
|
}
|
|
84422
85098
|
function parseUiLock(value3) {
|
|
84423
85099
|
const lock = value3;
|
|
@@ -84453,14 +85129,14 @@ function pathIsAbsolute(value3) {
|
|
|
84453
85129
|
}
|
|
84454
85130
|
async function readUiLock(target2) {
|
|
84455
85131
|
try {
|
|
84456
|
-
return parseUiLock(JSON.parse(await
|
|
85132
|
+
return parseUiLock(JSON.parse(await readFile18(target2, "utf8")));
|
|
84457
85133
|
} catch (cause) {
|
|
84458
85134
|
if (cause instanceof UiError)
|
|
84459
85135
|
throw cause;
|
|
84460
85136
|
throw new UiError("UI_CONFIG_MISSING", "Unable to read " + UI_LOCK_FILE + ".", "Run astrale ui init.", { cause });
|
|
84461
85137
|
}
|
|
84462
85138
|
}
|
|
84463
|
-
var
|
|
85139
|
+
var init_lock2 = __esm(() => {
|
|
84464
85140
|
init_model7();
|
|
84465
85141
|
});
|
|
84466
85142
|
|
|
@@ -86484,14 +87160,14 @@ var require_lib5 = __commonJS(function(exports) {
|
|
|
86484
87160
|
});
|
|
86485
87161
|
|
|
86486
87162
|
// src/ui/project.ts
|
|
86487
|
-
import { access as access2, lstat, readFile as
|
|
87163
|
+
import { access as access2, lstat as lstat3, readFile as readFile19, realpath as realpath2 } from "node:fs/promises";
|
|
86488
87164
|
import path5 from "node:path";
|
|
86489
87165
|
async function exists(target2) {
|
|
86490
87166
|
return access2(target2).then(() => true, () => false);
|
|
86491
87167
|
}
|
|
86492
87168
|
async function readManifest(target2) {
|
|
86493
87169
|
try {
|
|
86494
|
-
return JSON.parse(await
|
|
87170
|
+
return JSON.parse(await readFile19(target2, "utf8"));
|
|
86495
87171
|
} catch (cause) {
|
|
86496
87172
|
throw new UiError("UI_PROJECT_UNSUPPORTED", "package.json is not valid JSON.", undefined, {
|
|
86497
87173
|
cause
|
|
@@ -86561,7 +87237,7 @@ async function resolveAlias(project2, candidate2) {
|
|
|
86561
87237
|
async function resolveUiRegistryTarget(project2, declaredTarget) {
|
|
86562
87238
|
if (!declaredTarget.startsWith("components/"))
|
|
86563
87239
|
return declaredTarget;
|
|
86564
|
-
const components = await
|
|
87240
|
+
const components = await readFile19(project2.componentsPath, "utf8").then((value3) => JSON.parse(value3)).catch(() => {
|
|
86565
87241
|
return;
|
|
86566
87242
|
});
|
|
86567
87243
|
const componentsAlias = components?.aliases?.components;
|
|
@@ -86573,11 +87249,11 @@ async function resolveUiRegistryTarget(project2, declaredTarget) {
|
|
|
86573
87249
|
if (!resolved) {
|
|
86574
87250
|
throw new UiError("UI_PROJECT_UNSUPPORTED", "components.json alias cannot be resolved through tsconfig.json or jsconfig.json.", "Define a matching compilerOptions.paths entry for " + componentsAlias + ".");
|
|
86575
87251
|
}
|
|
86576
|
-
const
|
|
86577
|
-
if (
|
|
87252
|
+
const relative2 = path5.relative(project2.root, path5.join(resolved, suffix));
|
|
87253
|
+
if (relative2 === ".." || relative2.startsWith(".." + path5.sep) || path5.isAbsolute(relative2)) {
|
|
86578
87254
|
throw new UiError("UI_PROJECT_UNSUPPORTED", "components.json alias escapes the project.");
|
|
86579
87255
|
}
|
|
86580
|
-
return
|
|
87256
|
+
return relative2.split(path5.sep).join("/");
|
|
86581
87257
|
}
|
|
86582
87258
|
function hasReactTailwind(manifest) {
|
|
86583
87259
|
const dependencies = {
|
|
@@ -86597,8 +87273,8 @@ async function assertPhysicalProjectPath(root, target2) {
|
|
|
86597
87273
|
existing = parent;
|
|
86598
87274
|
}
|
|
86599
87275
|
const physicalTarget = await realpath2(existing);
|
|
86600
|
-
const
|
|
86601
|
-
if (
|
|
87276
|
+
const relative2 = path5.relative(physicalRoot, physicalTarget);
|
|
87277
|
+
if (relative2 === ".." || relative2.startsWith(".." + path5.sep) || path5.isAbsolute(relative2)) {
|
|
86602
87278
|
throw new UiError("UI_PROJECT_UNSUPPORTED", "components.json CSS path escapes the project.");
|
|
86603
87279
|
}
|
|
86604
87280
|
}
|
|
@@ -86607,7 +87283,7 @@ async function discoverUiProject(input = process.cwd()) {
|
|
|
86607
87283
|
if (!await exists(root)) {
|
|
86608
87284
|
throw new UiError("UI_PROJECT_UNSUPPORTED", "Project path does not exist: " + root);
|
|
86609
87285
|
}
|
|
86610
|
-
if (!(await
|
|
87286
|
+
if (!(await lstat3(root)).isDirectory())
|
|
86611
87287
|
root = path5.dirname(root);
|
|
86612
87288
|
while (true) {
|
|
86613
87289
|
const manifestPath = path5.join(root, "package.json");
|
|
@@ -86663,17 +87339,17 @@ async function discoverUiProject(input = process.cwd()) {
|
|
|
86663
87339
|
"frontend/src/styles.css"
|
|
86664
87340
|
];
|
|
86665
87341
|
const componentsPath = path5.join(root, "components.json");
|
|
86666
|
-
const configuredCss = await
|
|
87342
|
+
const configuredCss = await readFile19(componentsPath, "utf8").then((value3) => {
|
|
86667
87343
|
const components = JSON.parse(value3);
|
|
86668
87344
|
const css = components.tailwind?.css;
|
|
86669
87345
|
if (typeof css !== "string" || css.length === 0)
|
|
86670
87346
|
return;
|
|
86671
87347
|
const target2 = path5.resolve(root, css);
|
|
86672
|
-
const
|
|
86673
|
-
if (
|
|
87348
|
+
const relative2 = path5.relative(root, target2);
|
|
87349
|
+
if (relative2 === ".." || relative2.startsWith(".." + path5.sep) || path5.isAbsolute(relative2)) {
|
|
86674
87350
|
throw new UiError("UI_PROJECT_UNSUPPORTED", "components.json CSS path escapes the project.");
|
|
86675
87351
|
}
|
|
86676
|
-
return { relative:
|
|
87352
|
+
return { relative: relative2.split(path5.sep).join("/"), target: target2 };
|
|
86677
87353
|
}).catch((error52) => {
|
|
86678
87354
|
if (error52 instanceof UiError)
|
|
86679
87355
|
throw error52;
|
|
@@ -86712,11 +87388,11 @@ function assertSupportedUiProject(project2) {
|
|
|
86712
87388
|
}
|
|
86713
87389
|
}
|
|
86714
87390
|
function projectRelative(project2, target2) {
|
|
86715
|
-
const
|
|
86716
|
-
if (
|
|
87391
|
+
const relative2 = path5.relative(project2.root, target2);
|
|
87392
|
+
if (relative2 === "" || relative2 === ".." || relative2.startsWith(".." + path5.sep) || path5.isAbsolute(relative2)) {
|
|
86717
87393
|
throw new UiError("UI_LOCK_INVALID", "Path escapes the project root: " + target2);
|
|
86718
87394
|
}
|
|
86719
|
-
return
|
|
87395
|
+
return relative2.split(path5.sep).join("/");
|
|
86720
87396
|
}
|
|
86721
87397
|
var import_tsconfig_paths, MANAGERS;
|
|
86722
87398
|
var init_project3 = __esm(() => {
|
|
@@ -86971,13 +87647,13 @@ var init_runner = __esm(() => {
|
|
|
86971
87647
|
});
|
|
86972
87648
|
|
|
86973
87649
|
// src/ui/operations.ts
|
|
86974
|
-
import { access as access3, lstat as
|
|
87650
|
+
import { access as access3, lstat as lstat4, mkdir as mkdir12, readFile as readFile20, realpath as realpath3, rm as rm5, writeFile as writeFile8 } from "node:fs/promises";
|
|
86975
87651
|
import path6 from "node:path";
|
|
86976
87652
|
async function exists2(target2) {
|
|
86977
87653
|
return access3(target2).then(() => true, () => false);
|
|
86978
87654
|
}
|
|
86979
87655
|
async function readOptional(target2) {
|
|
86980
|
-
return
|
|
87656
|
+
return readFile20(target2, "utf8").catch(() => {
|
|
86981
87657
|
return;
|
|
86982
87658
|
});
|
|
86983
87659
|
}
|
|
@@ -86993,10 +87669,10 @@ function admitLocalThemeCss(source2, slug) {
|
|
|
86993
87669
|
}
|
|
86994
87670
|
}
|
|
86995
87671
|
function themeImport(project2, target2) {
|
|
86996
|
-
let
|
|
86997
|
-
if (!
|
|
86998
|
-
|
|
86999
|
-
return "@import '" +
|
|
87672
|
+
let relative2 = path6.relative(path6.dirname(project2.cssPath), target2).split(path6.sep).join("/");
|
|
87673
|
+
if (!relative2.startsWith("."))
|
|
87674
|
+
relative2 = "./" + relative2;
|
|
87675
|
+
return "@import '" + relative2 + "';";
|
|
87000
87676
|
}
|
|
87001
87677
|
function activateTheme(current, statement) {
|
|
87002
87678
|
const lines = current.split(/\r?\n/u).filter((line) => !/^@import\s+['"][^'"]*components\/astrale\/theme\/[a-z][a-z0-9-]*\.css['"];?\s*$/u.test(line));
|
|
@@ -87067,7 +87743,7 @@ async function appendPnpmWorkspace(project2, workspace) {
|
|
|
87067
87743
|
const target2 = pnpmWorkspacePath(project2);
|
|
87068
87744
|
const source2 = await readOptional(target2);
|
|
87069
87745
|
if (source2 === undefined) {
|
|
87070
|
-
await
|
|
87746
|
+
await writeFile8(target2, `packages:
|
|
87071
87747
|
- '` + workspace + `'
|
|
87072
87748
|
`, "utf8");
|
|
87073
87749
|
return;
|
|
@@ -87086,12 +87762,12 @@ async function appendPnpmWorkspace(project2, workspace) {
|
|
|
87086
87762
|
}
|
|
87087
87763
|
if (!values.includes(workspace))
|
|
87088
87764
|
packages.add(workspace);
|
|
87089
|
-
await
|
|
87765
|
+
await writeFile8(target2, String(document), "utf8");
|
|
87090
87766
|
}
|
|
87091
87767
|
async function hasDomainRegistryWorkspace(project2) {
|
|
87092
87768
|
if (!project2.isAstraleDomain || !await exists2(domainRegistryPackagePath(project2)))
|
|
87093
87769
|
return false;
|
|
87094
|
-
const registryManifest = JSON.parse(await
|
|
87770
|
+
const registryManifest = JSON.parse(await readFile20(domainRegistryPackagePath(project2), "utf8"));
|
|
87095
87771
|
if (registryManifest.private !== true || typeof registryManifest.name !== "string" || registryManifest.name === UI_PACKAGE || registryManifest.name === project2.packageJson.name) {
|
|
87096
87772
|
return false;
|
|
87097
87773
|
}
|
|
@@ -87211,8 +87887,8 @@ async function initUi(options, dependencies = {}) {
|
|
|
87211
87887
|
"@import '" + UI_PACKAGE + "/presets/" + preset + ".css';"
|
|
87212
87888
|
];
|
|
87213
87889
|
const withoutAstrale = currentCss.replace(/^@import\s+['"]@astrale-os\/ui\/(?:theme\.css|presets\/[a-z-]+\.css)['"];?\s*$/gmu, "").trimStart();
|
|
87214
|
-
await
|
|
87215
|
-
await
|
|
87890
|
+
await mkdir12(path6.dirname(project2.cssPath), { recursive: true });
|
|
87891
|
+
await writeFile8(project2.cssPath, imports.join(`
|
|
87216
87892
|
`) + `
|
|
87217
87893
|
|
|
87218
87894
|
` + withoutAstrale, "utf8");
|
|
@@ -87269,15 +87945,15 @@ async function initUi(options, dependencies = {}) {
|
|
|
87269
87945
|
} catch (error52) {
|
|
87270
87946
|
for (const [target2, value3] of snapshots) {
|
|
87271
87947
|
if (value3 !== undefined)
|
|
87272
|
-
await
|
|
87948
|
+
await writeFile8(target2, value3, "utf8");
|
|
87273
87949
|
else
|
|
87274
|
-
await
|
|
87950
|
+
await rm5(target2, { force: true });
|
|
87275
87951
|
}
|
|
87276
87952
|
throw error52;
|
|
87277
87953
|
}
|
|
87278
87954
|
}
|
|
87279
87955
|
async function pinUiDependency(project2, version2, section, runner) {
|
|
87280
|
-
const manifest = JSON.parse(await
|
|
87956
|
+
const manifest = JSON.parse(await readFile20(project2.packageJsonPath, "utf8"));
|
|
87281
87957
|
const current = manifestDependencies(manifest, section)[UI_PACKAGE];
|
|
87282
87958
|
const other = section === "dependencies" ? "devDependencies" : "dependencies";
|
|
87283
87959
|
if (current === version2 && manifestDependencies(manifest, other)[UI_PACKAGE] === undefined)
|
|
@@ -87316,7 +87992,7 @@ async function lockedRelease(project2, fetcher) {
|
|
|
87316
87992
|
}
|
|
87317
87993
|
async function addLocalTheme(address, project2, options) {
|
|
87318
87994
|
const sourcePath = path6.resolve(project2.root, address);
|
|
87319
|
-
const sourceInfo = await
|
|
87995
|
+
const sourceInfo = await lstat4(sourcePath).catch(() => {
|
|
87320
87996
|
return;
|
|
87321
87997
|
});
|
|
87322
87998
|
if (!sourceInfo?.isFile() || sourceInfo.isSymbolicLink()) {
|
|
@@ -87326,7 +88002,7 @@ async function addLocalTheme(address, project2, options) {
|
|
|
87326
88002
|
if (!THEME_SLUG.test(slug)) {
|
|
87327
88003
|
throw new UiError("UI_ITEM_CONFLICT", "Local theme filename must be a kebab-case theme name.", "Rename it to a name such as observatory.css.");
|
|
87328
88004
|
}
|
|
87329
|
-
const source2 = await
|
|
88005
|
+
const source2 = await readFile20(sourcePath, "utf8");
|
|
87330
88006
|
admitLocalThemeCss(source2, slug);
|
|
87331
88007
|
return installThemeCss(slug, source2, digest5(source2), address, project2, options);
|
|
87332
88008
|
}
|
|
@@ -87361,10 +88037,10 @@ async function installThemeCss(slug, source2, sourceDigest, sourceLabel, project
|
|
|
87361
88037
|
snapshots.set(mutation, await readOptional(mutation));
|
|
87362
88038
|
}
|
|
87363
88039
|
try {
|
|
87364
|
-
await
|
|
87365
|
-
await
|
|
88040
|
+
await mkdir12(path6.dirname(target2), { recursive: true });
|
|
88041
|
+
await writeFile8(target2, source2, "utf8");
|
|
87366
88042
|
const css = await readOptional(project2.cssPath) ?? "";
|
|
87367
|
-
await
|
|
88043
|
+
await writeFile8(project2.cssPath, activateTheme(css, statement), "utf8");
|
|
87368
88044
|
lock.items[canonicalAddress] = {
|
|
87369
88045
|
address: canonicalAddress,
|
|
87370
88046
|
sourceDigest,
|
|
@@ -87375,9 +88051,9 @@ async function installThemeCss(slug, source2, sourceDigest, sourceLabel, project
|
|
|
87375
88051
|
} catch (error52) {
|
|
87376
88052
|
for (const [mutation, previous] of snapshots) {
|
|
87377
88053
|
if (previous === undefined)
|
|
87378
|
-
await
|
|
88054
|
+
await rm5(mutation, { force: true });
|
|
87379
88055
|
else
|
|
87380
|
-
await
|
|
88056
|
+
await writeFile8(mutation, previous, "utf8");
|
|
87381
88057
|
}
|
|
87382
88058
|
throw error52;
|
|
87383
88059
|
}
|
|
@@ -87464,15 +88140,15 @@ async function addUi(addresses, options, dependencies = {}) {
|
|
|
87464
88140
|
if (themeTarget) {
|
|
87465
88141
|
const target2 = await safeTarget(project2, themeTarget);
|
|
87466
88142
|
const css = await readOptional(project2.cssPath) ?? "";
|
|
87467
|
-
await
|
|
88143
|
+
await writeFile8(project2.cssPath, activateTheme(css, themeImport(project2, target2)), "utf8");
|
|
87468
88144
|
}
|
|
87469
88145
|
}
|
|
87470
88146
|
} catch (error52) {
|
|
87471
88147
|
for (const [target2, previous] of snapshots) {
|
|
87472
88148
|
if (previous === undefined)
|
|
87473
|
-
await
|
|
88149
|
+
await rm5(target2, { force: true });
|
|
87474
88150
|
else
|
|
87475
|
-
await
|
|
88151
|
+
await writeFile8(target2, previous, "utf8");
|
|
87476
88152
|
}
|
|
87477
88153
|
throw error52;
|
|
87478
88154
|
}
|
|
@@ -87501,7 +88177,7 @@ async function addUi(addresses, options, dependencies = {}) {
|
|
|
87501
88177
|
if (!file2.target)
|
|
87502
88178
|
continue;
|
|
87503
88179
|
const target2 = await safeTarget(project2, resolvedTargets.get(file2.target));
|
|
87504
|
-
files[projectRelative(project2, target2)] = digest5(await
|
|
88180
|
+
files[projectRelative(project2, target2)] = digest5(await readFile20(target2));
|
|
87505
88181
|
}
|
|
87506
88182
|
lock.items[item.meta.canonicalAddress] = {
|
|
87507
88183
|
address: item.meta.canonicalAddress,
|
|
@@ -87513,9 +88189,9 @@ async function addUi(addresses, options, dependencies = {}) {
|
|
|
87513
88189
|
} catch (error52) {
|
|
87514
88190
|
for (const [target2, previous] of snapshots) {
|
|
87515
88191
|
if (previous === undefined)
|
|
87516
|
-
await
|
|
88192
|
+
await rm5(target2, { force: true });
|
|
87517
88193
|
else
|
|
87518
|
-
await
|
|
88194
|
+
await writeFile8(target2, previous, "utf8");
|
|
87519
88195
|
}
|
|
87520
88196
|
throw error52;
|
|
87521
88197
|
}
|
|
@@ -87533,7 +88209,7 @@ async function doctorUi(input) {
|
|
|
87533
88209
|
const checks3 = [];
|
|
87534
88210
|
let lock;
|
|
87535
88211
|
try {
|
|
87536
|
-
lock = parseUiLock(JSON.parse(await
|
|
88212
|
+
lock = parseUiLock(JSON.parse(await readFile20(project2.uiLockPath, "utf8")));
|
|
87537
88213
|
checks3.push({ check: "lock", ok: true });
|
|
87538
88214
|
} catch (error52) {
|
|
87539
88215
|
checks3.push({
|
|
@@ -87561,7 +88237,7 @@ async function doctorUi(input) {
|
|
|
87561
88237
|
if (lock) {
|
|
87562
88238
|
for (const item of Object.values(lock.items)) {
|
|
87563
88239
|
for (const [file2, expected] of Object.entries(item.files)) {
|
|
87564
|
-
const actual = await
|
|
88240
|
+
const actual = await readFile20(path6.join(project2.root, file2)).then(digest5).catch(() => "");
|
|
87565
88241
|
checks3.push({ check: "item:" + item.address + ":" + file2, ok: actual === expected });
|
|
87566
88242
|
}
|
|
87567
88243
|
}
|
|
@@ -87586,7 +88262,7 @@ async function applyPreset(preset, options) {
|
|
|
87586
88262
|
throw new UiError("UI_CONFIG_MISSING", "No Astrale preset import was found.");
|
|
87587
88263
|
}
|
|
87588
88264
|
if (!options.dryRun) {
|
|
87589
|
-
await
|
|
88265
|
+
await writeFile8(project2.cssPath, next, "utf8");
|
|
87590
88266
|
lock.preset = preset;
|
|
87591
88267
|
await writeJson(project2.uiLockPath, lock);
|
|
87592
88268
|
}
|
|
@@ -87614,34 +88290,34 @@ async function rejectLocalChanges(project2, lock, items, overwrite) {
|
|
|
87614
88290
|
if (!installed)
|
|
87615
88291
|
continue;
|
|
87616
88292
|
for (const [file2, expected] of Object.entries(installed.files)) {
|
|
87617
|
-
const actual = await
|
|
88293
|
+
const actual = await readFile20(path6.join(project2.root, file2)).then(digest5).catch(() => "");
|
|
87618
88294
|
if (actual !== expected) {
|
|
87619
88295
|
throw new UiError("UI_LOCAL_CHANGES", "Installed UI file has local changes: " + file2, "Review the file, then repeat add with explicit --overwrite --yes.");
|
|
87620
88296
|
}
|
|
87621
88297
|
}
|
|
87622
88298
|
}
|
|
87623
88299
|
}
|
|
87624
|
-
async function safeTarget(project2,
|
|
87625
|
-
if (path6.isAbsolute(
|
|
87626
|
-
throw new UiError("UI_LOCK_INVALID", "Unsafe registry target: " +
|
|
88300
|
+
async function safeTarget(project2, relative2) {
|
|
88301
|
+
if (path6.isAbsolute(relative2) || relative2.split(/[\\/]/u).includes("..")) {
|
|
88302
|
+
throw new UiError("UI_LOCK_INVALID", "Unsafe registry target: " + relative2);
|
|
87627
88303
|
}
|
|
87628
|
-
const target2 = path6.resolve(project2.root,
|
|
88304
|
+
const target2 = path6.resolve(project2.root, relative2);
|
|
87629
88305
|
projectRelative(project2, target2);
|
|
87630
88306
|
const parent = await realpath3(path6.dirname(target2));
|
|
87631
88307
|
const root = await realpath3(project2.root);
|
|
87632
88308
|
if (parent !== root && !parent.startsWith(root + path6.sep)) {
|
|
87633
|
-
throw new UiError("UI_LOCK_INVALID", "Registry target escapes through a symlink: " +
|
|
88309
|
+
throw new UiError("UI_LOCK_INVALID", "Registry target escapes through a symlink: " + relative2);
|
|
87634
88310
|
}
|
|
87635
|
-
if (await exists2(target2) && (await
|
|
87636
|
-
throw new UiError("UI_LOCK_INVALID", "Registry target is a symlink: " +
|
|
88311
|
+
if (await exists2(target2) && (await lstat4(target2)).isSymbolicLink()) {
|
|
88312
|
+
throw new UiError("UI_LOCK_INVALID", "Registry target is a symlink: " + relative2);
|
|
87637
88313
|
}
|
|
87638
88314
|
return target2;
|
|
87639
88315
|
}
|
|
87640
|
-
async function assertSafePlannedTarget(project2,
|
|
87641
|
-
if (path6.isAbsolute(
|
|
87642
|
-
throw new UiError("UI_LOCK_INVALID", "Unsafe registry target: " +
|
|
88316
|
+
async function assertSafePlannedTarget(project2, relative2) {
|
|
88317
|
+
if (path6.isAbsolute(relative2) || relative2.split(/[\\/]/u).includes("..")) {
|
|
88318
|
+
throw new UiError("UI_LOCK_INVALID", "Unsafe registry target: " + relative2);
|
|
87643
88319
|
}
|
|
87644
|
-
const target2 = path6.resolve(project2.root,
|
|
88320
|
+
const target2 = path6.resolve(project2.root, relative2);
|
|
87645
88321
|
projectRelative(project2, target2);
|
|
87646
88322
|
const root = await realpath3(project2.root);
|
|
87647
88323
|
const physicalTarget = path6.resolve(root, path6.relative(project2.root, target2));
|
|
@@ -87650,21 +88326,21 @@ async function assertSafePlannedTarget(project2, relative) {
|
|
|
87650
88326
|
current = path6.join(current, segment);
|
|
87651
88327
|
if (!await exists2(current))
|
|
87652
88328
|
break;
|
|
87653
|
-
if ((await
|
|
87654
|
-
throw new UiError("UI_LOCK_INVALID", "Registry target traverses a symlink: " +
|
|
88329
|
+
if ((await lstat4(current)).isSymbolicLink()) {
|
|
88330
|
+
throw new UiError("UI_LOCK_INVALID", "Registry target traverses a symlink: " + relative2);
|
|
87655
88331
|
}
|
|
87656
88332
|
}
|
|
87657
88333
|
return target2;
|
|
87658
88334
|
}
|
|
87659
88335
|
async function writeJson(target2, value3) {
|
|
87660
|
-
await
|
|
87661
|
-
await
|
|
88336
|
+
await mkdir12(path6.dirname(target2), { recursive: true });
|
|
88337
|
+
await writeFile8(target2, JSON.stringify(value3, null, 2) + `
|
|
87662
88338
|
`, "utf8");
|
|
87663
88339
|
}
|
|
87664
88340
|
var LOCAL_THEME_MAX_BYTES = 131072, THEME_SLUG, REQUIRED_THEME_TOKENS;
|
|
87665
88341
|
var init_operations3 = __esm(() => {
|
|
87666
88342
|
init_dist();
|
|
87667
|
-
|
|
88343
|
+
init_lock2();
|
|
87668
88344
|
init_model7();
|
|
87669
88345
|
init_project3();
|
|
87670
88346
|
init_release();
|
|
@@ -89813,9 +90489,9 @@ __export(exports_register, {
|
|
|
89813
90489
|
formatIdentityRegistration: () => formatIdentityRegistration,
|
|
89814
90490
|
prepareIdentityProvision: () => prepareIdentityProvision
|
|
89815
90491
|
});
|
|
89816
|
-
import { readFile as
|
|
90492
|
+
import { readFile as readFile21 } from "node:fs/promises";
|
|
89817
90493
|
async function readJwk(path8) {
|
|
89818
|
-
return JSON.parse(await
|
|
90494
|
+
return JSON.parse(await readFile21(path8, "utf8"));
|
|
89819
90495
|
}
|
|
89820
90496
|
function formatIdentityRegistration(result, format3, machine) {
|
|
89821
90497
|
output(result, format3);
|
|
@@ -90075,7 +90751,7 @@ __export(exports_sync, {
|
|
|
90075
90751
|
default: () => sync_default
|
|
90076
90752
|
});
|
|
90077
90753
|
var sync_default;
|
|
90078
|
-
var
|
|
90754
|
+
var init_sync2 = __esm(() => {
|
|
90079
90755
|
init_identity7();
|
|
90080
90756
|
init_log();
|
|
90081
90757
|
init_output();
|
|
@@ -90196,7 +90872,7 @@ var exports_import = {};
|
|
|
90196
90872
|
__export(exports_import, {
|
|
90197
90873
|
default: () => import_default
|
|
90198
90874
|
});
|
|
90199
|
-
import { readFile as
|
|
90875
|
+
import { readFile as readFile22 } from "node:fs/promises";
|
|
90200
90876
|
var import_default;
|
|
90201
90877
|
var init_import2 = __esm(() => {
|
|
90202
90878
|
init_identity7();
|
|
@@ -90224,7 +90900,7 @@ var init_import2 = __esm(() => {
|
|
|
90224
90900
|
],
|
|
90225
90901
|
action: async (path8, opts) => {
|
|
90226
90902
|
try {
|
|
90227
|
-
const raw2 = await
|
|
90903
|
+
const raw2 = await readFile22(path8, "utf-8");
|
|
90228
90904
|
const passphrase = isEncryptedIdentityExport(raw2) ? await readPassphrase("Passphrase: ") : undefined;
|
|
90229
90905
|
const envelope = await decodeIdentityExport(raw2, passphrase);
|
|
90230
90906
|
const name = opts.name ?? envelope.subject;
|
|
@@ -90578,21 +91254,21 @@ var init_status4 = __esm(() => {
|
|
|
90578
91254
|
|
|
90579
91255
|
// src/telemetry/store.ts
|
|
90580
91256
|
import { existsSync as existsSync9, readdirSync as readdirSync2, readFileSync as readFileSync3, statSync as statSync3 } from "node:fs";
|
|
90581
|
-
import { join as
|
|
91257
|
+
import { join as join19 } from "node:path";
|
|
90582
91258
|
function sessionsRoot() {
|
|
90583
|
-
return
|
|
91259
|
+
return join19(createPaths().home, "sessions");
|
|
90584
91260
|
}
|
|
90585
91261
|
function sessionDir(id) {
|
|
90586
|
-
return
|
|
91262
|
+
return join19(sessionsRoot(), id);
|
|
90587
91263
|
}
|
|
90588
91264
|
function eventsPath(id) {
|
|
90589
|
-
return
|
|
91265
|
+
return join19(sessionDir(id), "events.jsonl");
|
|
90590
91266
|
}
|
|
90591
91267
|
function metaPath(id) {
|
|
90592
|
-
return
|
|
91268
|
+
return join19(sessionDir(id), "meta.json");
|
|
90593
91269
|
}
|
|
90594
91270
|
function markerPath(id) {
|
|
90595
|
-
return
|
|
91271
|
+
return join19(sessionDir(id), ".analyzed");
|
|
90596
91272
|
}
|
|
90597
91273
|
function readJsonSafe(path8) {
|
|
90598
91274
|
try {
|
|
@@ -90669,13 +91345,13 @@ var init_list5 = __esm(() => {
|
|
|
90669
91345
|
|
|
90670
91346
|
// src/telemetry/adapters/claude-code.ts
|
|
90671
91347
|
import { existsSync as existsSync10, readdirSync as readdirSync3, statSync as statSync4 } from "node:fs";
|
|
90672
|
-
import { homedir as
|
|
90673
|
-
import { join as
|
|
91348
|
+
import { homedir as homedir4 } from "node:os";
|
|
91349
|
+
import { join as join20 } from "node:path";
|
|
90674
91350
|
function mungeCwd(cwd) {
|
|
90675
91351
|
return cwd.replace(/[^a-zA-Z0-9]/g, "-");
|
|
90676
91352
|
}
|
|
90677
|
-
function claudeCodeAdapter(base2 =
|
|
90678
|
-
const projectsDir =
|
|
91353
|
+
function claudeCodeAdapter(base2 = join20(homedir4(), ".claude")) {
|
|
91354
|
+
const projectsDir = join20(base2, "projects");
|
|
90679
91355
|
function detect2() {
|
|
90680
91356
|
try {
|
|
90681
91357
|
return existsSync10(projectsDir);
|
|
@@ -90699,7 +91375,7 @@ function claudeCodeAdapter(base2 = join18(homedir3(), ".claude")) {
|
|
|
90699
91375
|
for (const dir of dirs) {
|
|
90700
91376
|
if (dir !== munged && !dir.startsWith(prefix))
|
|
90701
91377
|
continue;
|
|
90702
|
-
const projectPath =
|
|
91378
|
+
const projectPath = join20(projectsDir, dir);
|
|
90703
91379
|
let files;
|
|
90704
91380
|
try {
|
|
90705
91381
|
files = readdirSync3(projectPath);
|
|
@@ -90709,7 +91385,7 @@ function claudeCodeAdapter(base2 = join18(homedir3(), ".claude")) {
|
|
|
90709
91385
|
for (const file2 of files) {
|
|
90710
91386
|
if (!file2.endsWith(".jsonl"))
|
|
90711
91387
|
continue;
|
|
90712
|
-
const transcriptPath =
|
|
91388
|
+
const transcriptPath = join20(projectPath, file2);
|
|
90713
91389
|
try {
|
|
90714
91390
|
const st = statSync4(transcriptPath);
|
|
90715
91391
|
const mtimeMs = st.mtime.getTime();
|
|
@@ -90744,8 +91420,8 @@ var init_claude_code = __esm(() => {
|
|
|
90744
91420
|
// src/telemetry/adapters/codex.ts
|
|
90745
91421
|
import { existsSync as existsSync11, openSync as openSync2, readdirSync as readdirSync4, readSync, statSync as statSync5 } from "node:fs";
|
|
90746
91422
|
import { closeSync as closeSync3 } from "node:fs";
|
|
90747
|
-
import { homedir as
|
|
90748
|
-
import { join as
|
|
91423
|
+
import { homedir as homedir5 } from "node:os";
|
|
91424
|
+
import { join as join21 } from "node:path";
|
|
90749
91425
|
function readFirstLine(path8) {
|
|
90750
91426
|
let fd = null;
|
|
90751
91427
|
try {
|
|
@@ -90785,8 +91461,8 @@ function numericDirs(path8) {
|
|
|
90785
91461
|
return [];
|
|
90786
91462
|
}
|
|
90787
91463
|
}
|
|
90788
|
-
function codexAdapter(base2 =
|
|
90789
|
-
const sessionsDir =
|
|
91464
|
+
function codexAdapter(base2 = join21(homedir5(), ".codex")) {
|
|
91465
|
+
const sessionsDir = join21(base2, "sessions");
|
|
90790
91466
|
function detect2() {
|
|
90791
91467
|
try {
|
|
90792
91468
|
return existsSync11(sessionsDir);
|
|
@@ -90801,12 +91477,12 @@ function codexAdapter(base2 = join19(homedir4(), ".codex")) {
|
|
|
90801
91477
|
const endMs = window2.end.getTime();
|
|
90802
91478
|
const lowerMs = startMs - DAY_MS;
|
|
90803
91479
|
for (const yyyy of numericDirs(sessionsDir)) {
|
|
90804
|
-
for (const mm of numericDirs(
|
|
90805
|
-
for (const dd of numericDirs(
|
|
91480
|
+
for (const mm of numericDirs(join21(sessionsDir, yyyy))) {
|
|
91481
|
+
for (const dd of numericDirs(join21(sessionsDir, yyyy, mm))) {
|
|
90806
91482
|
const dayStart = Date.UTC(Number(yyyy), Number(mm) - 1, Number(dd));
|
|
90807
91483
|
if (dayStart > endMs + DAY_MS || dayStart + DAY_MS <= lowerMs)
|
|
90808
91484
|
continue;
|
|
90809
|
-
scanDay(
|
|
91485
|
+
scanDay(join21(sessionsDir, yyyy, mm, dd), root, startMs, endMs, sessions);
|
|
90810
91486
|
}
|
|
90811
91487
|
}
|
|
90812
91488
|
}
|
|
@@ -90828,7 +91504,7 @@ function scanDay(dayPath, root, startMs, endMs, out) {
|
|
|
90828
91504
|
for (const file2 of files) {
|
|
90829
91505
|
if (!file2.startsWith("rollout-") || !file2.endsWith(".jsonl"))
|
|
90830
91506
|
continue;
|
|
90831
|
-
const transcriptPath =
|
|
91507
|
+
const transcriptPath = join21(dayPath, file2);
|
|
90832
91508
|
try {
|
|
90833
91509
|
const st = statSync5(transcriptPath);
|
|
90834
91510
|
const mtimeMs = st.mtime.getTime();
|
|
@@ -90975,7 +91651,7 @@ var init_gate = () => {};
|
|
|
90975
91651
|
// src/telemetry/analyze.ts
|
|
90976
91652
|
import { spawn as spawn3 } from "node:child_process";
|
|
90977
91653
|
import { appendFileSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
90978
|
-
import { join as
|
|
91654
|
+
import { join as join22 } from "node:path";
|
|
90979
91655
|
function writeMarker(id, marker) {
|
|
90980
91656
|
writeFileSync2(markerPath(id), JSON.stringify(marker, null, 2) + `
|
|
90981
91657
|
`);
|
|
@@ -91071,7 +91747,7 @@ async function analyzeSession(id, opts = {}) {
|
|
|
91071
91747
|
const guides = new Map(adapters.map((a) => [a.name, a.readingGuide]));
|
|
91072
91748
|
const prompt = buildPrompt({ id, root, signals: signals2, guides, file: opts.file ?? false });
|
|
91073
91749
|
const dir = sessionDir(id);
|
|
91074
|
-
writeFileSync2(
|
|
91750
|
+
writeFileSync2(join22(dir, "analyzer-prompt.md"), prompt);
|
|
91075
91751
|
const outcome = await runClaude(prompt, dir, opts);
|
|
91076
91752
|
const marker = {
|
|
91077
91753
|
analyzedAt: new Date().toISOString(),
|
|
@@ -91079,10 +91755,10 @@ async function analyzeSession(id, opts = {}) {
|
|
|
91079
91755
|
note: outcome.note
|
|
91080
91756
|
};
|
|
91081
91757
|
writeMarker(id, marker);
|
|
91082
|
-
return { ...marker, reportPath:
|
|
91758
|
+
return { ...marker, reportPath: join22(dir, "report.md") };
|
|
91083
91759
|
}
|
|
91084
91760
|
function runClaude(prompt, cwd, opts) {
|
|
91085
|
-
return new Promise((
|
|
91761
|
+
return new Promise((resolve8) => {
|
|
91086
91762
|
const env2 = { ASTRALE_TELEMETRY: "0" };
|
|
91087
91763
|
for (const [k, v] of Object.entries(process.env)) {
|
|
91088
91764
|
if (v !== undefined && !k.startsWith("CLAUDE"))
|
|
@@ -91095,10 +91771,10 @@ function runClaude(prompt, cwd, opts) {
|
|
|
91095
91771
|
try {
|
|
91096
91772
|
child3 = spawn3("claude", args, { cwd, env: env2, stdio: ["ignore", "pipe", "pipe"] });
|
|
91097
91773
|
} catch (e) {
|
|
91098
|
-
|
|
91774
|
+
resolve8({ ok: false, note: `claude spawn failed: ${String(e)}` });
|
|
91099
91775
|
return;
|
|
91100
91776
|
}
|
|
91101
|
-
child3.on("error", (e) =>
|
|
91777
|
+
child3.on("error", (e) => resolve8({ ok: false, note: `claude not available: ${e.message}` }));
|
|
91102
91778
|
let out = "";
|
|
91103
91779
|
let err = "";
|
|
91104
91780
|
child3.stdout?.setEncoding("utf8");
|
|
@@ -91109,22 +91785,22 @@ function runClaude(prompt, cwd, opts) {
|
|
|
91109
91785
|
child3.on("close", (code) => {
|
|
91110
91786
|
clearTimeout(timer);
|
|
91111
91787
|
try {
|
|
91112
|
-
appendFileSync(
|
|
91788
|
+
appendFileSync(join22(cwd, "analyzer.log"), out + (err ? `
|
|
91113
91789
|
--- stderr ---
|
|
91114
91790
|
${err}` : ""));
|
|
91115
91791
|
} catch {}
|
|
91116
91792
|
try {
|
|
91117
91793
|
const result = JSON.parse(out);
|
|
91118
91794
|
if (result.is_error) {
|
|
91119
|
-
|
|
91795
|
+
resolve8({ ok: false, note: `analyzer errored: ${result.result?.slice(0, 200)}` });
|
|
91120
91796
|
return;
|
|
91121
91797
|
}
|
|
91122
|
-
|
|
91798
|
+
resolve8({
|
|
91123
91799
|
ok: true,
|
|
91124
91800
|
note: `${result.num_turns ?? "?"} turns, $${(result.total_cost_usd ?? 0).toFixed(4)}`
|
|
91125
91801
|
});
|
|
91126
91802
|
} catch {
|
|
91127
|
-
|
|
91803
|
+
resolve8({ ok: false, note: `claude exit ${code}, unparseable output` });
|
|
91128
91804
|
}
|
|
91129
91805
|
});
|
|
91130
91806
|
});
|
|
@@ -91159,9 +91835,9 @@ var init_settings = __esm(() => {
|
|
|
91159
91835
|
|
|
91160
91836
|
// src/telemetry/trigger.ts
|
|
91161
91837
|
import { existsSync as existsSync12, mkdirSync as mkdirSync2, readFileSync as readFileSync6, rmSync as rmSync2, unlinkSync, writeFileSync as writeFileSync3 } from "node:fs";
|
|
91162
|
-
import { join as
|
|
91838
|
+
import { join as join23 } from "node:path";
|
|
91163
91839
|
function lockPath() {
|
|
91164
|
-
return
|
|
91840
|
+
return join23(sessionsRoot(), ".analyzer.lock");
|
|
91165
91841
|
}
|
|
91166
91842
|
function releaseLock() {
|
|
91167
91843
|
try {
|
|
@@ -91244,7 +91920,7 @@ var exports_add2 = {};
|
|
|
91244
91920
|
__export(exports_add2, {
|
|
91245
91921
|
default: () => add_default2
|
|
91246
91922
|
});
|
|
91247
|
-
import { readFile as
|
|
91923
|
+
import { readFile as readFile23 } from "node:fs/promises";
|
|
91248
91924
|
function isString(value3) {
|
|
91249
91925
|
return typeof value3 === "string";
|
|
91250
91926
|
}
|
|
@@ -91306,7 +91982,7 @@ Security:
|
|
|
91306
91982
|
if (!opts.issuer && !opts.metadata && !opts.workosAuthkit) {
|
|
91307
91983
|
throw new Error("Either --issuer, --metadata, or --workos-authkit is required");
|
|
91308
91984
|
}
|
|
91309
|
-
let metadata = opts.workosAuthkit ? workosAuthKitMetadata(opts.workosApiHostname, opts.clientId) : opts.metadata ? OidcMetadataSchema.parse(JSON.parse(await
|
|
91985
|
+
let metadata = opts.workosAuthkit ? workosAuthKitMetadata(opts.workosApiHostname, opts.clientId) : opts.metadata ? OidcMetadataSchema.parse(JSON.parse(await readFile23(opts.metadata, "utf-8"))) : await fetchOidcMetadata(opts.issuer);
|
|
91310
91986
|
if (opts.issuer) {
|
|
91311
91987
|
validateUrl(opts.issuer);
|
|
91312
91988
|
if (normalizeIssuer2(metadata.issuer) !== normalizeIssuer2(opts.issuer)) {
|
|
@@ -91872,7 +92548,7 @@ async function buildProgram() {
|
|
|
91872
92548
|
(await Promise.resolve().then(() => (init_use4(), exports_use4))).default,
|
|
91873
92549
|
(await Promise.resolve().then(() => (init_whoami3(), exports_whoami))).default,
|
|
91874
92550
|
(await Promise.resolve().then(() => (init_delete2(), exports_delete2))).default,
|
|
91875
|
-
(await Promise.resolve().then(() => (
|
|
92551
|
+
(await Promise.resolve().then(() => (init_sync2(), exports_sync))).default,
|
|
91876
92552
|
(await Promise.resolve().then(() => (init_unsync(), exports_unsync))).default,
|
|
91877
92553
|
(await Promise.resolve().then(() => (init_export2(), exports_export))).default,
|
|
91878
92554
|
(await Promise.resolve().then(() => (init_import2(), exports_import))).default
|
|
@@ -91996,16 +92672,16 @@ function redactArgv(argv) {
|
|
|
91996
92672
|
|
|
91997
92673
|
// src/telemetry/session.ts
|
|
91998
92674
|
init_store();
|
|
91999
|
-
import { createHash as
|
|
92675
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
92000
92676
|
import { existsSync as existsSync13, mkdirSync as mkdirSync3, writeFileSync as writeFileSync4 } from "node:fs";
|
|
92001
|
-
import { dirname as
|
|
92677
|
+
import { dirname as dirname14, join as join24 } from "node:path";
|
|
92002
92678
|
var MAX_ID_LEN = 64;
|
|
92003
92679
|
function findGitRoot(start) {
|
|
92004
92680
|
let dir = start;
|
|
92005
92681
|
for (;; ) {
|
|
92006
|
-
if (existsSync13(
|
|
92682
|
+
if (existsSync13(join24(dir, ".git")))
|
|
92007
92683
|
return dir;
|
|
92008
|
-
const parent =
|
|
92684
|
+
const parent = dirname14(dir);
|
|
92009
92685
|
if (parent === dir)
|
|
92010
92686
|
return null;
|
|
92011
92687
|
dir = parent;
|
|
@@ -92027,7 +92703,7 @@ function findOpenAmbient(root) {
|
|
|
92027
92703
|
return null;
|
|
92028
92704
|
}
|
|
92029
92705
|
function mintAmbientId(root) {
|
|
92030
|
-
const hash8 =
|
|
92706
|
+
const hash8 = createHash4("sha256").update(root).digest("hex").slice(0, 8);
|
|
92031
92707
|
return `amb-${hash8}-${stamp()}`;
|
|
92032
92708
|
}
|
|
92033
92709
|
function resolveSession2(cwd) {
|
|
@@ -92112,7 +92788,7 @@ init_settings();
|
|
|
92112
92788
|
init_store();
|
|
92113
92789
|
import { spawn as spawn4 } from "node:child_process";
|
|
92114
92790
|
import { existsSync as existsSync14, mkdirSync as mkdirSync4, readFileSync as readFileSync7, rmSync as rmSync3, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "node:fs";
|
|
92115
|
-
import { join as
|
|
92791
|
+
import { join as join25 } from "node:path";
|
|
92116
92792
|
var LOCK_STALE_MS2 = 30 * 60 * 1000;
|
|
92117
92793
|
var GC_AGE_MS2 = 30 * 24 * 60 * 60 * 1000;
|
|
92118
92794
|
var GC_MAX_PER_RUN = 20;
|
|
@@ -92131,7 +92807,7 @@ function gcOldSessions(sessions) {
|
|
|
92131
92807
|
} catch {}
|
|
92132
92808
|
}
|
|
92133
92809
|
function lockPath2() {
|
|
92134
|
-
return
|
|
92810
|
+
return join25(sessionsRoot(), ".analyzer.lock");
|
|
92135
92811
|
}
|
|
92136
92812
|
function claimLock() {
|
|
92137
92813
|
const path8 = lockPath2();
|