@astrale-os/cli 1.0.0-beta.3 → 1.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/astrale.js CHANGED
@@ -9738,7 +9738,7 @@ var package_default;
9738
9738
  var init_package = __esm(() => {
9739
9739
  package_default = {
9740
9740
  name: "@astrale-os/cli",
9741
- version: "1.0.0-beta.3",
9741
+ version: "1.0.0-beta.4",
9742
9742
  description: "Astrale CLI — connect to existing Astrale kernels",
9743
9743
  keywords: [
9744
9744
  "astrale",
@@ -67208,7 +67208,7 @@ function builtinIdpConfig(name, clientIdOverride, env2 = process.env) {
67208
67208
  };
67209
67209
  }
67210
67210
  function workosClientIdFromEnv(env2 = process.env) {
67211
- return WORKOS_CLIENT_ID_ENV_NAMES.map((name) => env2[name]?.trim()).find((value) => typeof value === "string" && value.length > 0);
67211
+ return WORKOS_CLIENT_ID_ENV_NAMES.map((name) => env2[name]?.trim()).find((value) => typeof value === "string" && value.length > 0) ?? DEFAULT_WORKOS_CLIENT_ID;
67212
67212
  }
67213
67213
  async function fetchOAuthAuthorizationServerMetadata(issuer) {
67214
67214
  const discoveryUrl = new URL("/.well-known/oauth-authorization-server", issuer);
@@ -67553,7 +67553,7 @@ async function fetchWorkosApplication(args) {
67553
67553
  function normalizeIssuer(value) {
67554
67554
  return value.replace(/\/+$/, "");
67555
67555
  }
67556
- var IdpAudienceMismatchError, OAuthTokenError, OidcMetadataSchema, IdpClientConfigSchema, IdpIndexEntrySchema, IdpStoreSchema, IdpSessionSchema, BUILTIN_WORKOS_IDP_NAME = "workos", DEFAULT_WORKOS_API_HOST = "https://api.workos.com", WORKOS_CLIENT_ID_ENV_NAMES;
67556
+ var IdpAudienceMismatchError, OAuthTokenError, OidcMetadataSchema, IdpClientConfigSchema, IdpIndexEntrySchema, IdpStoreSchema, IdpSessionSchema, BUILTIN_WORKOS_IDP_NAME = "workos", DEFAULT_WORKOS_API_HOST = "https://api.workos.com", DEFAULT_WORKOS_CLIENT_ID = "client_01KC29HET5F3QAQ8GNTPZ7F320", WORKOS_CLIENT_ID_ENV_NAMES;
67557
67557
  var init_idp = __esm(() => {
67558
67558
  init_webapi();
67559
67559
  init_zod2();
@@ -70394,7 +70394,257 @@ var init_instance2 = __esm(() => {
70394
70394
  });
70395
70395
  });
70396
70396
 
70397
+ // src/lib/proc.ts
70398
+ import { spawn } from "node:child_process";
70399
+ function run(file2, args = [], opts = {}) {
70400
+ return new Promise((resolve3, reject) => {
70401
+ const child3 = spawn(file2, args, { cwd: opts.cwd, stdio: ["ignore", "pipe", "pipe"] });
70402
+ let stdout = "";
70403
+ let stderr = "";
70404
+ child3.stdout?.setEncoding("utf8");
70405
+ child3.stderr?.setEncoding("utf8");
70406
+ child3.stdout?.on("data", (chunk) => {
70407
+ stdout += chunk;
70408
+ });
70409
+ child3.stderr?.on("data", (chunk) => {
70410
+ stderr += chunk;
70411
+ });
70412
+ child3.on("error", reject);
70413
+ child3.on("close", (code) => resolve3({ code: code ?? -1, stdout, stderr }));
70414
+ });
70415
+ }
70416
+ function runInherit(file2, args = [], opts = {}) {
70417
+ return new Promise((resolve3, reject) => {
70418
+ const child3 = spawn(file2, args, { cwd: opts.cwd, stdio: "inherit" });
70419
+ child3.on("error", reject);
70420
+ child3.on("close", (code) => resolve3(code ?? -1));
70421
+ });
70422
+ }
70423
+ function spawnHandle(file2, args = [], opts = {}) {
70424
+ return spawn(file2, args, {
70425
+ cwd: opts.cwd,
70426
+ env: opts.env,
70427
+ detached: opts.detached,
70428
+ stdio: opts.stdio ?? ["ignore", "inherit", "inherit"]
70429
+ });
70430
+ }
70431
+ var init_proc = () => {};
70432
+
70433
+ // src/lib/update.ts
70434
+ import { createHash } from "node:crypto";
70435
+ import { chmod as chmod2, copyFile, mkdir as mkdir6, mkdtemp, readFile as readFile7, rename as rename2, rm, writeFile as writeFile2 } from "node:fs/promises";
70436
+ import { tmpdir } from "node:os";
70437
+ import { dirname as dirname6, join as join4 } from "node:path";
70438
+ function detectPlatform() {
70439
+ const os2 = process.platform;
70440
+ const arch = process.arch;
70441
+ if (os2 !== "darwin" && os2 !== "linux") {
70442
+ throw new AstraleError("UNSUPPORTED_PLATFORM", `Unsupported OS "${os2}" — Astrale update supports macOS and Linux.`);
70443
+ }
70444
+ if (arch !== "arm64" && arch !== "x64") {
70445
+ throw new AstraleError("UNSUPPORTED_PLATFORM", `Unsupported CPU architecture "${arch}" — Astrale update supports arm64 and x64.`);
70446
+ }
70447
+ return { os: os2, arch };
70448
+ }
70449
+ function platformKey(platform) {
70450
+ return `${platform.os}-${platform.arch}`;
70451
+ }
70452
+ function isStandaloneBinary() {
70453
+ return Boolean(process.versions.bun);
70454
+ }
70455
+ async function readInstallMetadata(path3 = INSTALL_PATH) {
70456
+ let raw2;
70457
+ try {
70458
+ raw2 = await readFile7(path3, "utf8");
70459
+ } catch {
70460
+ throw isStandaloneBinary() ? new AstraleError("UPDATE_NOT_SCRIPT_INSTALLED", "Astrale was not installed by the official install script.", "Reinstall with: curl -fsSL https://raw.githubusercontent.com/astrale-os/cli/main/install.sh | sh") : new AstraleError("UPDATE_PACKAGE_MANAGED", "This Astrale build is managed by your package manager.", "Update with: npm install -g @astrale-os/cli@latest (or pnpm/bun)");
70461
+ }
70462
+ const parsed = InstallMetadataSchema.safeParse(JSON.parse(raw2));
70463
+ if (!parsed.success) {
70464
+ throw new AstraleError("UPDATE_BAD_INSTALL_METADATA", `Invalid install metadata at ${path3}.`, "Reinstall with: curl -fsSL https://raw.githubusercontent.com/astrale-os/cli/main/install.sh | sh");
70465
+ }
70466
+ return parsed.data;
70467
+ }
70468
+ async function writeInstallMetadata(meta3, path3 = INSTALL_PATH) {
70469
+ await mkdir6(dirname6(path3), { recursive: true });
70470
+ await writeFile2(path3, JSON.stringify(meta3, null, 2) + `
70471
+ `);
70472
+ }
70473
+ function releaseBase(meta3, req) {
70474
+ if (process.env.ASTRALE_UPDATE_BASE)
70475
+ return process.env.ASTRALE_UPDATE_BASE.replace(/\/+$/, "");
70476
+ const repo = meta3.repo || DEFAULT_REPO;
70477
+ if (req.version) {
70478
+ const version2 = req.version.replace(/^cli\/v/, "").replace(/^v/, "");
70479
+ return `https://github.com/${repo}/releases/download/cli/v${version2}`;
70480
+ }
70481
+ return `https://github.com/${repo}/releases/download/${req.channel ?? meta3.channel ?? DEFAULT_UPDATE_CHANNEL}`;
70482
+ }
70483
+ async function fetchManifest(base2) {
70484
+ const raw2 = await readUrlText(`${base2}/manifest.json`);
70485
+ return UpdateManifestSchema.parse(JSON.parse(raw2));
70486
+ }
70487
+ function shouldUpdate(currentVersion, manifestVersion) {
70488
+ return currentVersion !== manifestVersion;
70489
+ }
70490
+ async function updateAstrale(req) {
70491
+ const meta3 = await readInstallMetadata(req.installPath);
70492
+ const currentVersion = meta3.version ?? req.currentVersion;
70493
+ const channel = req.channel ?? meta3.channel ?? DEFAULT_UPDATE_CHANNEL;
70494
+ const platform = req.platform ?? detectPlatform();
70495
+ const key = platformKey(platform);
70496
+ const base2 = releaseBase(meta3, { channel, version: req.version });
70497
+ const manifest = await fetchManifest(base2);
70498
+ const asset = manifest.assets[key];
70499
+ if (!asset) {
70500
+ throw new AstraleError("UPDATE_ASSET_NOT_FOUND", `No Astrale CLI release asset for ${key}.`, `Available platforms: ${Object.keys(manifest.assets).join(", ")}`);
70501
+ }
70502
+ if (!shouldUpdate(currentVersion, manifest.version)) {
70503
+ return {
70504
+ status: "up-to-date",
70505
+ currentVersion,
70506
+ latestVersion: manifest.version,
70507
+ channel: manifest.channel
70508
+ };
70509
+ }
70510
+ if (req.check) {
70511
+ return {
70512
+ status: "available",
70513
+ currentVersion,
70514
+ latestVersion: manifest.version,
70515
+ channel: manifest.channel
70516
+ };
70517
+ }
70518
+ const tmp = await mkdtemp(join4(tmpdir(), "astrale-update-"));
70519
+ try {
70520
+ const archive = join4(tmp, asset.name);
70521
+ await downloadToFile(`${base2}/${asset.name}`, archive);
70522
+ const manifestChecksum = "sha256" in asset ? asset.sha256 : undefined;
70523
+ const expected = manifestChecksum ?? await fetchChecksum(base2, asset.name);
70524
+ const actual = await sha256File(archive);
70525
+ if (actual !== expected.toLowerCase()) {
70526
+ throw new AstraleError("UPDATE_CHECKSUM_MISMATCH", `Checksum mismatch for ${asset.name}.`, `Expected ${expected}; got ${actual}.`);
70527
+ }
70528
+ await extractTarGz(archive, tmp);
70529
+ const nextBin = join4(tmp, "astrale");
70530
+ await chmod2(nextBin, 493);
70531
+ await smokeVersion(nextBin, manifest.binaryVersion ?? manifest.version);
70532
+ const previous = `${meta3.bin}.previous`;
70533
+ const staged = `${meta3.bin}.next`;
70534
+ await copyFile(meta3.bin, previous).catch(() => {
70535
+ return;
70536
+ });
70537
+ await copyFile(nextBin, staged);
70538
+ await chmod2(staged, 493);
70539
+ await rename2(staged, meta3.bin);
70540
+ await writeInstallMetadata({
70541
+ ...meta3,
70542
+ channel: manifest.channel,
70543
+ version: manifest.version,
70544
+ installedAt: new Date().toISOString()
70545
+ }, req.installPath);
70546
+ return {
70547
+ status: "updated",
70548
+ previousVersion: currentVersion,
70549
+ currentVersion: manifest.version,
70550
+ channel: manifest.channel,
70551
+ bin: meta3.bin
70552
+ };
70553
+ } finally {
70554
+ await rm(tmp, { recursive: true, force: true });
70555
+ }
70556
+ }
70557
+ async function readUrlText(url3) {
70558
+ if (url3.startsWith("file://")) {
70559
+ return readFile7(new URL(url3), "utf8");
70560
+ }
70561
+ const res = await fetch(url3);
70562
+ if (!res.ok)
70563
+ throw new Error(`GET ${url3} failed: HTTP ${res.status}`);
70564
+ return res.text();
70565
+ }
70566
+ async function downloadToFile(url3, path3) {
70567
+ if (url3.startsWith("file://")) {
70568
+ await copyFile(new URL(url3), path3);
70569
+ return;
70570
+ }
70571
+ const res = await fetch(url3);
70572
+ if (!res.ok)
70573
+ throw new Error(`GET ${url3} failed: HTTP ${res.status}`);
70574
+ const bytes = new Uint8Array(await res.arrayBuffer());
70575
+ await writeFile2(path3, bytes);
70576
+ }
70577
+ async function fetchChecksum(base2, assetName) {
70578
+ const raw2 = await readUrlText(`${base2}/sha256sums.txt`);
70579
+ for (const line of raw2.split(/\r?\n/)) {
70580
+ const [sha, file2] = line.trim().split(/\s+/, 2);
70581
+ if (!sha || !file2)
70582
+ continue;
70583
+ if (file2.replace(/^\*/, "") === assetName && /^[a-fA-F0-9]{64}$/.test(sha))
70584
+ return sha;
70585
+ }
70586
+ throw new AstraleError("UPDATE_CHECKSUM_NOT_FOUND", `Checksum entry not found for ${assetName}.`, `Release base: ${base2}`);
70587
+ }
70588
+ async function sha256File(path3) {
70589
+ const hash2 = createHash("sha256");
70590
+ hash2.update(await readFile7(path3));
70591
+ return hash2.digest("hex");
70592
+ }
70593
+ async function extractTarGz(archive, cwd) {
70594
+ const { code, stderr } = await run("tar", ["-xzf", archive, "-C", cwd]);
70595
+ if (code !== 0) {
70596
+ throw new Error(`Could not extract update archive: ${stderr.trim()}`);
70597
+ }
70598
+ }
70599
+ async function smokeVersion(bin, expectedVersion) {
70600
+ const { code, stdout, stderr } = await run(bin, ["--version"]);
70601
+ if (code !== 0)
70602
+ throw new Error(`Updated binary failed --version: ${stderr.trim()}`);
70603
+ const actual = stdout.trim();
70604
+ if (actual !== expectedVersion) {
70605
+ throw new Error(`Updated binary reported version ${actual}, expected ${expectedVersion}`);
70606
+ }
70607
+ }
70608
+ var DEFAULT_REPO = "astrale-os/cli", DEFAULT_UPDATE_CHANNEL = "beta", InstallMetadataSchema, ManifestAssetSchema, UpdateManifestSchema;
70609
+ var init_update = __esm(() => {
70610
+ init_zod2();
70611
+ init_errors2();
70612
+ init_state();
70613
+ init_proc();
70614
+ InstallMetadataSchema = exports_external2.object({
70615
+ method: exports_external2.literal("script"),
70616
+ channel: exports_external2.string().min(1).default(DEFAULT_UPDATE_CHANNEL),
70617
+ version: exports_external2.string().min(1).optional(),
70618
+ repo: exports_external2.string().min(1).default(DEFAULT_REPO),
70619
+ bin: exports_external2.string().min(1),
70620
+ installedAt: exports_external2.string().optional()
70621
+ });
70622
+ ManifestAssetSchema = exports_external2.object({
70623
+ name: exports_external2.string().min(1),
70624
+ sha256: exports_external2.string().regex(/^[a-fA-F0-9]{64}$/).optional()
70625
+ });
70626
+ UpdateManifestSchema = exports_external2.object({
70627
+ version: exports_external2.string().min(1),
70628
+ binaryVersion: exports_external2.string().min(1).optional(),
70629
+ channel: exports_external2.string().min(1),
70630
+ repo: exports_external2.string().min(1).optional(),
70631
+ assets: exports_external2.record(exports_external2.string(), exports_external2.union([
70632
+ ManifestAssetSchema,
70633
+ exports_external2.string().min(1).transform((name) => ({ name }))
70634
+ ]))
70635
+ });
70636
+ });
70637
+
70397
70638
  // src/lib/admin-target.ts
70639
+ function defaultAdminTargetForChannel(channel) {
70640
+ return channel === "stable" ? {
70641
+ url: "https://admin.eu.astrale.ai/api",
70642
+ domainIssuer: "https://admin.astrale.ai"
70643
+ } : {
70644
+ url: "https://admin.eu.beta.astrale.ai/api",
70645
+ domainIssuer: "https://admin.beta.astrale.ai"
70646
+ };
70647
+ }
70398
70648
  async function resolveAdminTarget(opts, config2, store) {
70399
70649
  return resolveAdminTargetFromStore(opts, config2, store ?? await readInstances());
70400
70650
  }
@@ -70486,12 +70736,16 @@ function requireDomainIssuer(value, label) {
70486
70736
  return value;
70487
70737
  throw new AstraleError("ADMIN_DOMAIN_ISSUER_MISSING", `${label} has no Domain issuer for token exchange.`, "Configure domainIssuer or pass --domain-issuer <url>; there is no legacy token fallback.");
70488
70738
  }
70489
- var DEFAULT_ADMIN_TARGET_NAME = "admin", DEFAULT_ADMIN_TARGET_URL = "https://admin.eu.astrale.ai/api", DEFAULT_ADMIN_DOMAIN_ISSUER = "https://admin.beta.astrale.ai", DEFAULT_ADMIN_TARGET_CONFIG, HttpUrlSchema, AdminTargetConfigSchema, ADMIN_TARGET_OPTIONS;
70739
+ var DEFAULT_ADMIN_TARGET_NAME = "admin", DEFAULT_ADMIN_TARGET, DEFAULT_ADMIN_TARGET_URL, DEFAULT_ADMIN_DOMAIN_ISSUER, DEFAULT_ADMIN_TARGET_CONFIG, HttpUrlSchema, AdminTargetConfigSchema, ADMIN_TARGET_OPTIONS;
70490
70740
  var init_admin_target = __esm(() => {
70491
70741
  init_zod2();
70492
70742
  init_errors2();
70493
70743
  init_instance2();
70744
+ init_update();
70494
70745
  init_validation2();
70746
+ DEFAULT_ADMIN_TARGET = defaultAdminTargetForChannel(DEFAULT_UPDATE_CHANNEL);
70747
+ DEFAULT_ADMIN_TARGET_URL = DEFAULT_ADMIN_TARGET.url;
70748
+ DEFAULT_ADMIN_DOMAIN_ISSUER = DEFAULT_ADMIN_TARGET.domainIssuer;
70495
70749
  DEFAULT_ADMIN_TARGET_CONFIG = {
70496
70750
  name: DEFAULT_ADMIN_TARGET_NAME,
70497
70751
  url: DEFAULT_ADMIN_TARGET_URL,
@@ -70553,11 +70807,11 @@ var init_admin_target = __esm(() => {
70553
70807
  });
70554
70808
 
70555
70809
  // src/lib/config.ts
70556
- import { readFile as readFile7, writeFile as writeFile2, mkdir as mkdir6 } from "node:fs/promises";
70557
- import { dirname as dirname6 } from "node:path";
70810
+ import { readFile as readFile8, writeFile as writeFile3, mkdir as mkdir7 } from "node:fs/promises";
70811
+ import { dirname as dirname7 } from "node:path";
70558
70812
  async function readConfig() {
70559
70813
  try {
70560
- const raw2 = await readFile7(CONFIG_PATH, "utf-8");
70814
+ const raw2 = await readFile8(CONFIG_PATH, "utf-8");
70561
70815
  return AstraleConfigSchema.parse(JSON.parse(raw2));
70562
70816
  } catch (e) {
70563
70817
  if (e instanceof exports_external2.ZodError || e instanceof SyntaxError) {
@@ -70567,8 +70821,8 @@ async function readConfig() {
70567
70821
  }
70568
70822
  }
70569
70823
  async function writeConfig(config2) {
70570
- await mkdir6(dirname6(CONFIG_PATH), { recursive: true });
70571
- await writeFile2(CONFIG_PATH, JSON.stringify(config2, null, 2) + `
70824
+ await mkdir7(dirname7(CONFIG_PATH), { recursive: true });
70825
+ await writeFile3(CONFIG_PATH, JSON.stringify(config2, null, 2) + `
70572
70826
  `);
70573
70827
  }
70574
70828
  var AstraleConfigSchema, DEFAULT_CONFIG;
@@ -70754,13 +71008,13 @@ function readline() {
70754
71008
  function withUpdates(fn2) {
70755
71009
  const wrapped = (...args) => {
70756
71010
  const store = getStore();
70757
- let shouldUpdate = false;
71011
+ let shouldUpdate2 = false;
70758
71012
  const oldHandleChange = store.handleChange;
70759
71013
  store.handleChange = () => {
70760
- shouldUpdate = true;
71014
+ shouldUpdate2 = true;
70761
71015
  };
70762
71016
  const returnValue = fn2(...args);
70763
- if (shouldUpdate) {
71017
+ if (shouldUpdate2) {
70764
71018
  oldHandleChange();
70765
71019
  }
70766
71020
  store.handleChange = oldHandleChange;
@@ -82156,7 +82410,7 @@ function parseEditorCommand(editor) {
82156
82410
  }
82157
82411
 
82158
82412
  // node_modules/.pnpm/@inquirer+external-editor@3.0.3_@types+node@22.20.0/node_modules/@inquirer/external-editor/dist/index.js
82159
- import { spawn, spawnSync } from "node:child_process";
82413
+ import { spawn as spawn2, spawnSync } from "node:child_process";
82160
82414
  import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
82161
82415
  import path4 from "node:path";
82162
82416
  import os2 from "node:os";
@@ -82204,7 +82458,7 @@ class ExternalEditor {
82204
82458
  this.createTempFile();
82205
82459
  const promise2 = new Promise((resolve3, reject) => {
82206
82460
  try {
82207
- const editorProcess = spawn(this.editor.bin, this.editorArgs(), {
82461
+ const editorProcess = spawn2(this.editor.bin, this.editorArgs(), {
82208
82462
  shell: false,
82209
82463
  stdio: "inherit"
82210
82464
  });
@@ -83544,51 +83798,15 @@ var init_admin = __esm(() => {
83544
83798
  };
83545
83799
  });
83546
83800
 
83547
- // src/lib/proc.ts
83548
- import { spawn as spawn2 } from "node:child_process";
83549
- function run(file2, args = [], opts = {}) {
83550
- return new Promise((resolve3, reject) => {
83551
- const child3 = spawn2(file2, args, { cwd: opts.cwd, stdio: ["ignore", "pipe", "pipe"] });
83552
- let stdout = "";
83553
- let stderr = "";
83554
- child3.stdout?.setEncoding("utf8");
83555
- child3.stderr?.setEncoding("utf8");
83556
- child3.stdout?.on("data", (chunk) => {
83557
- stdout += chunk;
83558
- });
83559
- child3.stderr?.on("data", (chunk) => {
83560
- stderr += chunk;
83561
- });
83562
- child3.on("error", reject);
83563
- child3.on("close", (code) => resolve3({ code: code ?? -1, stdout, stderr }));
83564
- });
83565
- }
83566
- function runInherit(file2, args = [], opts = {}) {
83567
- return new Promise((resolve3, reject) => {
83568
- const child3 = spawn2(file2, args, { cwd: opts.cwd, stdio: "inherit" });
83569
- child3.on("error", reject);
83570
- child3.on("close", (code) => resolve3(code ?? -1));
83571
- });
83572
- }
83573
- function spawnHandle(file2, args = [], opts = {}) {
83574
- return spawn2(file2, args, {
83575
- cwd: opts.cwd,
83576
- env: opts.env,
83577
- detached: opts.detached,
83578
- stdio: opts.stdio ?? ["ignore", "inherit", "inherit"]
83579
- });
83580
- }
83581
- var init_proc = () => {};
83582
-
83583
83801
  // src/lib/browser.ts
83584
- import { mkdir as mkdir7, readFile as readFile8, writeFile as writeFile3 } from "node:fs/promises";
83585
- import { join as join4 } from "node:path";
83802
+ import { mkdir as mkdir8, readFile as readFile9, writeFile as writeFile4 } from "node:fs/promises";
83803
+ import { join as join5 } from "node:path";
83586
83804
  function profileDirFor(host) {
83587
- return join4(BROWSER_DIR, host);
83805
+ return join5(BROWSER_DIR, host);
83588
83806
  }
83589
83807
  async function saveSession(session) {
83590
- await mkdir7(paths3.home, { recursive: true });
83591
- await writeFile3(BROWSER_SESSION_PATH, `${JSON.stringify(session, null, 2)}
83808
+ await mkdir8(paths3.home, { recursive: true });
83809
+ await writeFile4(BROWSER_SESSION_PATH, `${JSON.stringify(session, null, 2)}
83592
83810
  `);
83593
83811
  }
83594
83812
  async function findAgentBrowser() {
@@ -83638,15 +83856,15 @@ var BROWSER_DIR, BROWSER_SESSION_PATH, AGENT_BROWSER_REPO = "vercel-labs/agent-b
83638
83856
  var init_browser = __esm(() => {
83639
83857
  init_state();
83640
83858
  init_proc();
83641
- BROWSER_DIR = join4(paths3.home, "browser");
83642
- BROWSER_SESSION_PATH = join4(paths3.home, "browser.json");
83859
+ BROWSER_DIR = join5(paths3.home, "browser");
83860
+ BROWSER_SESSION_PATH = join5(paths3.home, "browser.json");
83643
83861
  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}))";
83644
83862
  });
83645
83863
 
83646
83864
  // src/lib/skills.ts
83647
83865
  import { existsSync, lstatSync, mkdirSync, readlinkSync, symlinkSync } from "node:fs";
83648
83866
  import { homedir as homedir2 } from "node:os";
83649
- import { dirname as dirname7, join as join5 } from "node:path";
83867
+ import { dirname as dirname8, join as join6 } from "node:path";
83650
83868
  async function installSkills() {
83651
83869
  const { code, stdout, stderr } = await run("npx", [
83652
83870
  "skills",
@@ -83663,18 +83881,18 @@ function skillSearchDirs() {
83663
83881
  const dirs = [];
83664
83882
  let cur = process.cwd();
83665
83883
  for (;; ) {
83666
- dirs.push(join5(cur, ".claude", "skills"));
83667
- const parent = dirname7(cur);
83884
+ dirs.push(join6(cur, ".claude", "skills"));
83885
+ const parent = dirname8(cur);
83668
83886
  if (parent === cur)
83669
83887
  break;
83670
83888
  cur = parent;
83671
83889
  }
83672
- dirs.push(join5(homedir2(), ".claude", "skills"));
83890
+ dirs.push(join6(homedir2(), ".claude", "skills"));
83673
83891
  return dirs;
83674
83892
  }
83675
83893
  function detectSkill(name) {
83676
83894
  for (const dir of skillSearchDirs()) {
83677
- const file2 = join5(dir, name, "SKILL.md");
83895
+ const file2 = join6(dir, name, "SKILL.md");
83678
83896
  if (existsSync(file2))
83679
83897
  return { installed: true, location: file2 };
83680
83898
  }
@@ -83693,9 +83911,9 @@ function isSymlink(p) {
83693
83911
  function findAgentsSkillsRoot(fromDir) {
83694
83912
  let cur = fromDir;
83695
83913
  for (;; ) {
83696
- if (existsSync(join5(cur, ".agents", "skills")))
83914
+ if (existsSync(join6(cur, ".agents", "skills")))
83697
83915
  return cur;
83698
- const parent = dirname7(cur);
83916
+ const parent = dirname8(cur);
83699
83917
  if (parent === cur)
83700
83918
  return null;
83701
83919
  cur = parent;
@@ -83705,7 +83923,7 @@ function skillsBridgeStatus(fromDir = process.cwd()) {
83705
83923
  const root = findAgentsSkillsRoot(fromDir);
83706
83924
  if (!root)
83707
83925
  return { kind: "none" };
83708
- const link = join5(root, ".claude", "skills");
83926
+ const link = join6(root, ".claude", "skills");
83709
83927
  if (isSymlink(link)) {
83710
83928
  try {
83711
83929
  if (readlinkSync(link) === BRIDGE_TARGET)
@@ -83721,7 +83939,7 @@ function ensureSkillsBridge(fromDir = process.cwd()) {
83721
83939
  const status = skillsBridgeStatus(fromDir);
83722
83940
  if (status.kind !== "unbridged")
83723
83941
  return status;
83724
- mkdirSync(dirname7(status.link), { recursive: true });
83942
+ mkdirSync(dirname8(status.link), { recursive: true });
83725
83943
  symlinkSync(BRIDGE_TARGET, status.link);
83726
83944
  return { kind: "bridged", root: status.root };
83727
83945
  }
@@ -83730,7 +83948,7 @@ var init_skills = __esm(() => {
83730
83948
  init_browser();
83731
83949
  init_proc();
83732
83950
  SKILL_INSTALL_HINT = `npx skills add ${ASTRALE_CLI_SKILL_SOURCE} -g`;
83733
- BRIDGE_TARGET = join5("..", ".agents", "skills");
83951
+ BRIDGE_TARGET = join6("..", ".agents", "skills");
83734
83952
  });
83735
83953
 
83736
83954
  // src/setup/steps/agent-browser.ts
@@ -83973,9 +84191,9 @@ var init_auth3 = __esm(() => {
83973
84191
 
83974
84192
  // src/setup/steps/domain.ts
83975
84193
  import { existsSync as existsSync2 } from "node:fs";
83976
- import { join as join6 } from "node:path";
84194
+ import { join as join7 } from "node:path";
83977
84195
  function hasDomainProject() {
83978
- return existsSync2(join6(process.cwd(), "astrale.config.ts"));
84196
+ return existsSync2(join7(process.cwd(), "astrale.config.ts"));
83979
84197
  }
83980
84198
  var FIX4 = "npx create-astrale-domain <name> --instance <slug>", domainStep;
83981
84199
  var init_domain7 = __esm(() => {
@@ -85940,14 +86158,14 @@ async function boundedResponse(response2, maximum, signal) {
85940
86158
  signal.removeEventListener("abort", abort);
85941
86159
  reader.releaseLock();
85942
86160
  }
85943
- return join7(chunks, total);
86161
+ return join8(chunks, total);
85944
86162
  }
85945
86163
  function requireExactResponse(response2, expected, label) {
85946
86164
  if (response2.redirected || response2.url !== expected) {
85947
86165
  throw new ClientError(`${label} did not return the exact requested URL.`);
85948
86166
  }
85949
86167
  }
85950
- function join7(parts2, length) {
86168
+ function join8(parts2, length) {
85951
86169
  if (parts2.length === 1)
85952
86170
  return new Uint8Array(parts2[0]);
85953
86171
  const output3 = new Uint8Array(length);
@@ -86751,73 +86969,161 @@ var init_session2 = __esm(() => {
86751
86969
  init_session();
86752
86970
  });
86753
86971
 
86754
- // src/admin/binding.ts
86755
- async function bindAdmin(session) {
86756
- const snapshot2 = await session.snapshot();
86757
- if (snapshot2.publication.origin !== ADMIN_ORIGIN || snapshot2.bundle.root.origin !== ADMIN_ORIGIN) {
86758
- throw new TypeError("Configured Admin target does not serve the Admin Domain.");
86972
+ // node_modules/.pnpm/@astrale-os+kernel-client@0.6.0-beta.4_typescript@6.0.3/node_modules/@astrale-os/kernel-client/dist/domain/callable.js
86973
+ async function invokeRemote(session, target2, callable, input, options) {
86974
+ return dispatchCallable(session, target2, callable, undefined, input, options);
86975
+ }
86976
+ async function invokeRemoteMethod(session, target2, method, receiver, input, options) {
86977
+ return dispatchCallable(session, target2, method, receiver, input, options);
86978
+ }
86979
+ function bindRemoteMethod(session, target2) {
86980
+ return (method, receiver) => (input) => dispatchCallable(session, target2, method, Path.id(receiver.id), input);
86981
+ }
86982
+ function concreteRootCallables(domain3) {
86983
+ const result = new Map;
86984
+ for (const definition3 of domain3.$.definitions.values()) {
86985
+ if (definition3.kind === "function") {
86986
+ const callable = definition3;
86987
+ result.set(callable.key, callable);
86988
+ continue;
86989
+ }
86990
+ if (definition3.kind !== "class" && definition3.kind !== "interface" || definition3.family !== "node") {
86991
+ continue;
86992
+ }
86993
+ for (const method of definition3.methods.values()) {
86994
+ if (method.definition.inheritance !== "abstract") {
86995
+ const callable = method;
86996
+ result.set(callable.key, callable);
86997
+ }
86998
+ }
86759
86999
  }
86760
- const compatible = session;
86761
- const resolveInstallation = compatible.installation ?? compatible.installed;
86762
- if (resolveInstallation === undefined) {
86763
- throw new TypeError("Client Session cannot resolve an installed Admin Domain.");
86764
- }
86765
- const installation = await resolveInstallation.call(session, ADMIN_ORIGIN);
86766
- const domain3 = Domain.fromSchema(snapshot2.bundle.root);
86767
- const invoke = (callable, receiverOrInput, inputOrOptions, options) => {
86768
- const target2 = "on" in callable ? callable.on(Path.from(receiverOrInput)) : callable.path;
86769
- const reference3 = Object.freeze({
86770
- origin: ADMIN_ORIGIN,
86771
- revision: snapshot2.publication.schema.revision,
86772
- callable: callable.key,
86773
- target: target2,
86774
- outputMode: callable.definition.output.mode
86775
- });
86776
- return invokeCompatible(session, snapshot2, reference3, "on" in callable ? inputOrOptions : receiverOrInput, "on" in callable ? options : inputOrOptions);
86777
- };
86778
- return Object.freeze({
87000
+ return result;
87001
+ }
87002
+ async function dispatchCallable(session, target2, callable, receiver, input, controls = {}) {
87003
+ const bound = target2.callables.get(callable.key);
87004
+ if (bound === undefined) {
87005
+ throw new ClientError("Callable is not a concrete member of the bound Domain root.");
87006
+ }
87007
+ const path5 = receiver === undefined ? bound.path : bound.on(Path.from(receiver));
87008
+ const result = await dispatchBound(session, call(path5, input), target2.bound, controls);
87009
+ return requireOutput(bound, result);
87010
+ }
87011
+ function requireOutput(callable, result) {
87012
+ const mode = callable.definition.output.mode;
87013
+ switch (mode) {
87014
+ case "value":
87015
+ if (result.kind === "value")
87016
+ return result.value;
87017
+ break;
87018
+ case "stream":
87019
+ if (result.kind === "stream")
87020
+ return result.stream;
87021
+ break;
87022
+ case "binary":
87023
+ if (result.kind === "binary")
87024
+ return result.value;
87025
+ break;
87026
+ }
87027
+ return resultMismatch(mode, result);
87028
+ }
87029
+ function resultMismatch(expected, result) {
87030
+ if (result.kind === "stream") {
87031
+ result.stream.cancel(`Remote callable declared ${expected} output.`);
87032
+ }
87033
+ throw new ClientError(`Remote callable declared ${expected} output but returned ${result.kind}.`);
87034
+ }
87035
+ var init_callable4 = __esm(() => {
87036
+ init_path4();
87037
+ init_client3();
87038
+ init_errors7();
87039
+ init_session2();
87040
+ });
87041
+
87042
+ // node_modules/.pnpm/@astrale-os+kernel-client@0.6.0-beta.4_typescript@6.0.3/node_modules/@astrale-os/kernel-client/dist/domain/node.js
87043
+ function bindNode(domain3, methodBinder, definitionOrValue, value2) {
87044
+ return value2 === undefined ? domain3.$.wrap(definitionOrValue, methodBinder) : domain3.$.wrap(definitionOrValue, value2, methodBinder);
87045
+ }
87046
+
87047
+ // node_modules/.pnpm/@astrale-os+kernel-client@0.6.0-beta.4_typescript@6.0.3/node_modules/@astrale-os/kernel-client/dist/domain/binding.js
87048
+ function bind(session, schemaOrInstalled, maybeInstalled) {
87049
+ const installed = admitInstalled(maybeInstalled ?? schemaOrInstalled);
87050
+ const published = installed.source.kind === "remote" ? installed.source.publication : undefined;
87051
+ const root = maybeInstalled === undefined ? installed.bundle.root : schemaOrInstalled;
87052
+ if (published !== undefined)
87053
+ requireSchemaPublication(root, published);
87054
+ if (root.origin !== installed.bundle.root.origin || exports_schema.revision(root) !== exports_schema.revision(installed.bundle.root)) {
87055
+ throw new TypeError("Expected Domain schema does not match the installed schema Bundle.");
87056
+ }
87057
+ const domain3 = Domain.fromSchema(root);
87058
+ const invocationTarget = Object.freeze({
87059
+ callables: concreteRootCallables(domain3),
87060
+ bound: Object.freeze({
87061
+ schema: published === undefined ? Object.freeze({ target: installed.target }) : Object.freeze({ revision: exports_schema.revision(root) }),
87062
+ ...published === undefined ? {} : { publication: exports_publication.reference(published) }
87063
+ })
87064
+ });
87065
+ const methodBinder = bindRemoteMethod(session, invocationTarget);
87066
+ const invoke = (callable, receiverOrInput, inputOrOptions, options) => ("on" in callable) ? invokeRemoteMethod(session, invocationTarget, callable, receiverOrInput, inputOrOptions, options) : invokeRemote(session, invocationTarget, callable, receiverOrInput, inputOrOptions);
87067
+ const bind2 = (definitionOrValue, value2) => value2 === undefined ? bindNode(domain3, methodBinder, definitionOrValue) : bindNode(domain3, methodBinder, definitionOrValue, value2);
87068
+ const binding6 = {
86779
87069
  ...domain3,
86780
87070
  $: Object.freeze({
86781
87071
  ...domain3.$,
86782
- installation,
86783
- publication: snapshot2.publication,
86784
- invoke
87072
+ installed,
87073
+ ...published === undefined ? {} : { publication: published },
87074
+ invoke,
87075
+ bind: bind2
86785
87076
  })
86786
- });
87077
+ };
87078
+ return Object.freeze(binding6);
86787
87079
  }
86788
- async function invokeCompatible(session, snapshot2, reference3, input, options) {
86789
- const current = session;
86790
- if (current.invoke !== undefined)
86791
- return current.invoke(reference3, input, options);
86792
- const dispatchBound2 = dispatchBound;
86793
- if (dispatchBound2 === undefined) {
86794
- throw new TypeError("Client Session cannot invoke an exact Admin publication.");
87080
+ function admitInstalled(input) {
87081
+ if (input === null || typeof input !== "object" || Array.isArray(input)) {
87082
+ throw new TypeError("Installed Domain evidence is invalid.");
86795
87083
  }
86796
- const result = await dispatchBound2(session, call(reference3.target, input), {
86797
- schema: { revision: reference3.revision },
86798
- publication: {
86799
- origin: snapshot2.publication.origin,
86800
- identity: snapshot2.publication.identity,
86801
- revision: snapshot2.publication.schema.revision,
86802
- etag: snapshot2.publication.etag
86803
- }
86804
- }, options);
86805
- return requireOutput(reference3.outputMode, result);
87084
+ if (input.state !== "ready" || input.readiness === null) {
87085
+ throw new TypeError("Installed Domain is not ready.");
87086
+ }
87087
+ if (input.source.kind === "remote") {
87088
+ const published = exports_publication.accept(input.source.publication);
87089
+ const acceptedBundle = exports_publication.acceptBundle(published, input.bundle);
87090
+ return Object.freeze({
87091
+ ...input,
87092
+ source: Object.freeze({ kind: "remote", publication: published }),
87093
+ bundle: acceptedBundle
87094
+ });
87095
+ }
87096
+ return input;
86806
87097
  }
86807
- function requireOutput(expected, result) {
86808
- if (result.kind !== expected) {
86809
- if (result.kind === "stream")
86810
- result.stream.cancel(`Admin callable declared ${expected}.`);
86811
- throw new TypeError(`Admin callable declared ${expected} output but returned ${result.kind}.`);
87098
+ function requireSchemaPublication(domainSchema, published) {
87099
+ if (domainSchema.origin !== published.origin || exports_schema.revision(domainSchema) !== published.schema.revision) {
87100
+ throw new TypeError("Expected Domain schema does not match the target Publication revision.");
86812
87101
  }
86813
- return result.kind === "stream" ? result.stream : result.value;
86814
87102
  }
86815
- var ADMIN_ORIGIN = "admin.astrale.ai";
86816
87103
  var init_binding3 = __esm(() => {
86817
- init_dist4();
86818
- init_session2();
86819
- init_domain6();
86820
- init_path5();
87104
+ init_domain3();
87105
+ init_v1();
87106
+ init_dist2();
87107
+ init_callable4();
87108
+ });
87109
+
87110
+ // node_modules/.pnpm/@astrale-os+kernel-client@0.6.0-beta.4_typescript@6.0.3/node_modules/@astrale-os/kernel-client/dist/domain/index.js
87111
+ var init_domain8 = __esm(() => {
87112
+ init_binding3();
87113
+ });
87114
+
87115
+ // src/admin/binding.ts
87116
+ async function bindAdmin(session) {
87117
+ const installed = await session.installed(ADMIN_ORIGIN);
87118
+ const binding6 = bind(session, installed);
87119
+ if (binding6.$.publication?.origin !== ADMIN_ORIGIN || binding6.$.origin !== ADMIN_ORIGIN) {
87120
+ throw new TypeError("Configured Admin target does not serve the Admin Domain.");
87121
+ }
87122
+ return binding6;
87123
+ }
87124
+ var ADMIN_ORIGIN = "admin.astrale.ai";
87125
+ var init_binding4 = __esm(() => {
87126
+ init_domain8();
86821
87127
  });
86822
87128
 
86823
87129
  // src/admin/graph/nodes.ts
@@ -87040,7 +87346,7 @@ var ADMIN_ORIGIN2 = "admin.astrale.ai", PAGE_SIZE = 256, MAXIMUM_INSTANCES = 1e4
87040
87346
  var init_client4 = __esm(() => {
87041
87347
  init_path5();
87042
87348
  init_query4();
87043
- init_binding3();
87349
+ init_binding4();
87044
87350
  init_graph3();
87045
87351
  init_model6();
87046
87352
  MAXIMUM_PAGES2 = Math.ceil(MAXIMUM_INSTANCES / PAGE_SIZE) + 1;
@@ -89123,11 +89429,11 @@ var init_skills2 = __esm(() => {
89123
89429
 
89124
89430
  // src/setup/steps/skills-bridge.ts
89125
89431
  import { existsSync as existsSync3, readdirSync } from "node:fs";
89126
- import { join as join8 } from "node:path";
89432
+ import { join as join9 } from "node:path";
89127
89433
  function countStaged(root) {
89128
89434
  try {
89129
- const dir = join8(root, ".agents", "skills");
89130
- return readdirSync(dir).filter((e) => existsSync3(join8(dir, e, "SKILL.md"))).length;
89435
+ const dir = join9(root, ".agents", "skills");
89436
+ return readdirSync(dir).filter((e) => existsSync3(join9(dir, e, "SKILL.md"))).length;
89131
89437
  } catch {
89132
89438
  return 0;
89133
89439
  }
@@ -89165,7 +89471,7 @@ var init_skills_bridge = __esm(() => {
89165
89471
  }
89166
89472
  const after = ensureSkillsBridge();
89167
89473
  if (after.kind === "bridged") {
89168
- log.success(`Workspace skills bridged — ${join8(after.root, ".agents/skills")} → .claude/skills`);
89474
+ log.success(`Workspace skills bridged — ${join9(after.root, ".agents/skills")} → .claude/skills`);
89169
89475
  return "fixed";
89170
89476
  }
89171
89477
  log.warn("Could not create the skills bridge — create it manually: ln -s ../.agents/skills .claude/skills");
@@ -89627,18 +89933,18 @@ Examples:
89627
89933
 
89628
89934
  // src/lib/sdk-deps.ts
89629
89935
  import { existsSync as existsSync4 } from "node:fs";
89630
- import { join as join9 } from "node:path";
89936
+ import { join as join10 } from "node:path";
89631
89937
  function inDomainProject(cwd = process.cwd()) {
89632
- return existsSync4(join9(cwd, "astrale.config.ts"));
89938
+ return existsSync4(join10(cwd, "astrale.config.ts"));
89633
89939
  }
89634
89940
  function foreignPackageManager(cwd = process.cwd()) {
89635
- if (existsSync4(join9(cwd, "pnpm-lock.yaml")))
89941
+ if (existsSync4(join10(cwd, "pnpm-lock.yaml")))
89636
89942
  return null;
89637
- if (existsSync4(join9(cwd, "package-lock.json")))
89943
+ if (existsSync4(join10(cwd, "package-lock.json")))
89638
89944
  return "npm";
89639
- if (existsSync4(join9(cwd, "yarn.lock")))
89945
+ if (existsSync4(join10(cwd, "yarn.lock")))
89640
89946
  return "yarn";
89641
- if (existsSync4(join9(cwd, "bun.lockb")) || existsSync4(join9(cwd, "bun.lock")))
89947
+ if (existsSync4(join10(cwd, "bun.lockb")) || existsSync4(join10(cwd, "bun.lock")))
89642
89948
  return "bun";
89643
89949
  return null;
89644
89950
  }
@@ -89683,211 +89989,6 @@ var init_sdk_deps = __esm(() => {
89683
89989
  init_proc();
89684
89990
  });
89685
89991
 
89686
- // src/lib/update.ts
89687
- import { createHash } from "node:crypto";
89688
- import { chmod as chmod2, copyFile, mkdir as mkdir8, mkdtemp, readFile as readFile9, rename as rename2, rm, writeFile as writeFile4 } from "node:fs/promises";
89689
- import { tmpdir } from "node:os";
89690
- import { dirname as dirname8, join as join10 } from "node:path";
89691
- function detectPlatform() {
89692
- const os3 = process.platform;
89693
- const arch = process.arch;
89694
- if (os3 !== "darwin" && os3 !== "linux") {
89695
- throw new AstraleError("UNSUPPORTED_PLATFORM", `Unsupported OS "${os3}" — Astrale update supports macOS and Linux.`);
89696
- }
89697
- if (arch !== "arm64" && arch !== "x64") {
89698
- throw new AstraleError("UNSUPPORTED_PLATFORM", `Unsupported CPU architecture "${arch}" — Astrale update supports arm64 and x64.`);
89699
- }
89700
- return { os: os3, arch };
89701
- }
89702
- function platformKey(platform) {
89703
- return `${platform.os}-${platform.arch}`;
89704
- }
89705
- function isStandaloneBinary() {
89706
- return Boolean(process.versions.bun);
89707
- }
89708
- async function readInstallMetadata(path5 = INSTALL_PATH) {
89709
- let raw2;
89710
- try {
89711
- raw2 = await readFile9(path5, "utf8");
89712
- } catch {
89713
- throw isStandaloneBinary() ? new AstraleError("UPDATE_NOT_SCRIPT_INSTALLED", "Astrale was not installed by the official install script.", "Reinstall with: curl -fsSL https://raw.githubusercontent.com/astrale-os/cli/main/install.sh | sh") : new AstraleError("UPDATE_PACKAGE_MANAGED", "This Astrale build is managed by your package manager.", "Update with: npm install -g @astrale-os/cli@latest (or pnpm/bun)");
89714
- }
89715
- const parsed = InstallMetadataSchema.safeParse(JSON.parse(raw2));
89716
- if (!parsed.success) {
89717
- throw new AstraleError("UPDATE_BAD_INSTALL_METADATA", `Invalid install metadata at ${path5}.`, "Reinstall with: curl -fsSL https://raw.githubusercontent.com/astrale-os/cli/main/install.sh | sh");
89718
- }
89719
- return parsed.data;
89720
- }
89721
- async function writeInstallMetadata(meta3, path5 = INSTALL_PATH) {
89722
- await mkdir8(dirname8(path5), { recursive: true });
89723
- await writeFile4(path5, JSON.stringify(meta3, null, 2) + `
89724
- `);
89725
- }
89726
- function releaseBase(meta3, req) {
89727
- if (process.env.ASTRALE_UPDATE_BASE)
89728
- return process.env.ASTRALE_UPDATE_BASE.replace(/\/+$/, "");
89729
- const repo = meta3.repo || DEFAULT_REPO;
89730
- if (req.version) {
89731
- const version2 = req.version.replace(/^cli\/v/, "").replace(/^v/, "");
89732
- return `https://github.com/${repo}/releases/download/cli/v${version2}`;
89733
- }
89734
- return `https://github.com/${repo}/releases/download/${req.channel ?? meta3.channel ?? DEFAULT_UPDATE_CHANNEL}`;
89735
- }
89736
- async function fetchManifest(base2) {
89737
- const raw2 = await readUrlText(`${base2}/manifest.json`);
89738
- return UpdateManifestSchema.parse(JSON.parse(raw2));
89739
- }
89740
- function shouldUpdate(currentVersion, manifestVersion) {
89741
- return currentVersion !== manifestVersion;
89742
- }
89743
- async function updateAstrale(req) {
89744
- const meta3 = await readInstallMetadata(req.installPath);
89745
- const currentVersion = meta3.version ?? req.currentVersion;
89746
- const channel = req.channel ?? meta3.channel ?? DEFAULT_UPDATE_CHANNEL;
89747
- const platform = req.platform ?? detectPlatform();
89748
- const key = platformKey(platform);
89749
- const base2 = releaseBase(meta3, { channel, version: req.version });
89750
- const manifest = await fetchManifest(base2);
89751
- const asset = manifest.assets[key];
89752
- if (!asset) {
89753
- throw new AstraleError("UPDATE_ASSET_NOT_FOUND", `No Astrale CLI release asset for ${key}.`, `Available platforms: ${Object.keys(manifest.assets).join(", ")}`);
89754
- }
89755
- if (!shouldUpdate(currentVersion, manifest.version)) {
89756
- return {
89757
- status: "up-to-date",
89758
- currentVersion,
89759
- latestVersion: manifest.version,
89760
- channel: manifest.channel
89761
- };
89762
- }
89763
- if (req.check) {
89764
- return {
89765
- status: "available",
89766
- currentVersion,
89767
- latestVersion: manifest.version,
89768
- channel: manifest.channel
89769
- };
89770
- }
89771
- const tmp = await mkdtemp(join10(tmpdir(), "astrale-update-"));
89772
- try {
89773
- const archive = join10(tmp, asset.name);
89774
- await downloadToFile(`${base2}/${asset.name}`, archive);
89775
- const manifestChecksum = "sha256" in asset ? asset.sha256 : undefined;
89776
- const expected = manifestChecksum ?? await fetchChecksum(base2, asset.name);
89777
- const actual = await sha256File(archive);
89778
- if (actual !== expected.toLowerCase()) {
89779
- throw new AstraleError("UPDATE_CHECKSUM_MISMATCH", `Checksum mismatch for ${asset.name}.`, `Expected ${expected}; got ${actual}.`);
89780
- }
89781
- await extractTarGz(archive, tmp);
89782
- const nextBin = join10(tmp, "astrale");
89783
- await chmod2(nextBin, 493);
89784
- await smokeVersion(nextBin, manifest.binaryVersion ?? manifest.version);
89785
- const previous = `${meta3.bin}.previous`;
89786
- const staged = `${meta3.bin}.next`;
89787
- await copyFile(meta3.bin, previous).catch(() => {
89788
- return;
89789
- });
89790
- await copyFile(nextBin, staged);
89791
- await chmod2(staged, 493);
89792
- await rename2(staged, meta3.bin);
89793
- await writeInstallMetadata({
89794
- ...meta3,
89795
- channel: manifest.channel,
89796
- version: manifest.version,
89797
- installedAt: new Date().toISOString()
89798
- }, req.installPath);
89799
- return {
89800
- status: "updated",
89801
- previousVersion: currentVersion,
89802
- currentVersion: manifest.version,
89803
- channel: manifest.channel,
89804
- bin: meta3.bin
89805
- };
89806
- } finally {
89807
- await rm(tmp, { recursive: true, force: true });
89808
- }
89809
- }
89810
- async function readUrlText(url3) {
89811
- if (url3.startsWith("file://")) {
89812
- return readFile9(new URL(url3), "utf8");
89813
- }
89814
- const res = await fetch(url3);
89815
- if (!res.ok)
89816
- throw new Error(`GET ${url3} failed: HTTP ${res.status}`);
89817
- return res.text();
89818
- }
89819
- async function downloadToFile(url3, path5) {
89820
- if (url3.startsWith("file://")) {
89821
- await copyFile(new URL(url3), path5);
89822
- return;
89823
- }
89824
- const res = await fetch(url3);
89825
- if (!res.ok)
89826
- throw new Error(`GET ${url3} failed: HTTP ${res.status}`);
89827
- const bytes = new Uint8Array(await res.arrayBuffer());
89828
- await writeFile4(path5, bytes);
89829
- }
89830
- async function fetchChecksum(base2, assetName) {
89831
- const raw2 = await readUrlText(`${base2}/sha256sums.txt`);
89832
- for (const line of raw2.split(/\r?\n/)) {
89833
- const [sha, file2] = line.trim().split(/\s+/, 2);
89834
- if (!sha || !file2)
89835
- continue;
89836
- if (file2.replace(/^\*/, "") === assetName && /^[a-fA-F0-9]{64}$/.test(sha))
89837
- return sha;
89838
- }
89839
- throw new AstraleError("UPDATE_CHECKSUM_NOT_FOUND", `Checksum entry not found for ${assetName}.`, `Release base: ${base2}`);
89840
- }
89841
- async function sha256File(path5) {
89842
- const hash2 = createHash("sha256");
89843
- hash2.update(await readFile9(path5));
89844
- return hash2.digest("hex");
89845
- }
89846
- async function extractTarGz(archive, cwd) {
89847
- const { code, stderr } = await run("tar", ["-xzf", archive, "-C", cwd]);
89848
- if (code !== 0) {
89849
- throw new Error(`Could not extract update archive: ${stderr.trim()}`);
89850
- }
89851
- }
89852
- async function smokeVersion(bin, expectedVersion) {
89853
- const { code, stdout, stderr } = await run(bin, ["--version"]);
89854
- if (code !== 0)
89855
- throw new Error(`Updated binary failed --version: ${stderr.trim()}`);
89856
- const actual = stdout.trim();
89857
- if (actual !== expectedVersion) {
89858
- throw new Error(`Updated binary reported version ${actual}, expected ${expectedVersion}`);
89859
- }
89860
- }
89861
- var DEFAULT_REPO = "astrale-os/cli", DEFAULT_UPDATE_CHANNEL = "beta", InstallMetadataSchema, ManifestAssetSchema, UpdateManifestSchema;
89862
- var init_update = __esm(() => {
89863
- init_zod2();
89864
- init_errors2();
89865
- init_state();
89866
- init_proc();
89867
- InstallMetadataSchema = exports_external2.object({
89868
- method: exports_external2.literal("script"),
89869
- channel: exports_external2.string().min(1).default(DEFAULT_UPDATE_CHANNEL),
89870
- version: exports_external2.string().min(1).optional(),
89871
- repo: exports_external2.string().min(1).default(DEFAULT_REPO),
89872
- bin: exports_external2.string().min(1),
89873
- installedAt: exports_external2.string().optional()
89874
- });
89875
- ManifestAssetSchema = exports_external2.object({
89876
- name: exports_external2.string().min(1),
89877
- sha256: exports_external2.string().regex(/^[a-fA-F0-9]{64}$/).optional()
89878
- });
89879
- UpdateManifestSchema = exports_external2.object({
89880
- version: exports_external2.string().min(1),
89881
- binaryVersion: exports_external2.string().min(1).optional(),
89882
- channel: exports_external2.string().min(1),
89883
- repo: exports_external2.string().min(1).optional(),
89884
- assets: exports_external2.record(exports_external2.string(), exports_external2.union([
89885
- ManifestAssetSchema,
89886
- exports_external2.string().min(1).transform((name) => ({ name }))
89887
- ]))
89888
- });
89889
- });
89890
-
89891
89992
  // src/commands/update.ts
89892
89993
  var exports_update = {};
89893
89994
  __export(exports_update, {
@@ -93473,7 +93574,7 @@ var ADMIN_ORIGIN3 = "admin.astrale.ai", PAGE_SIZE2 = 256, MAXIMUM_DOMAINS = 1e4,
93473
93574
  var init_client5 = __esm(() => {
93474
93575
  init_path5();
93475
93576
  init_query4();
93476
- init_binding3();
93577
+ init_binding4();
93477
93578
  init_graph3();
93478
93579
  init_model7();
93479
93580
  MAXIMUM_PAGES3 = Math.ceil(MAXIMUM_DOMAINS / PAGE_SIZE2) + 1;