bazilion 0.21.0-beta.1 → 0.21.0-beta.2

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/cli.js CHANGED
@@ -6,7 +6,7 @@ import { defineCommand as defineCommand39, runCommand, showUsage } from "citty";
6
6
  // package.json
7
7
  var package_default = {
8
8
  name: "bazilion",
9
- version: "0.21.0-beta.1",
9
+ version: "0.21.0-beta.2",
10
10
  description: "Multi-agent runtime CLI \u2014 spawn LLM agents, manage profiles/teams/skills, and run the local daemon.",
11
11
  license: "MIT",
12
12
  repository: {
@@ -375,12 +375,29 @@ function readAuthFile(authFile) {
375
375
  }
376
376
 
377
377
  // src/paths.ts
378
+ import { realpathSync } from "fs";
378
379
  import { homedir } from "os";
379
- import { join } from "path";
380
+ import { basename, dirname, join, resolve } from "path";
380
381
  function resolveCliPaths(home) {
381
- const root = home ?? process.env.BAZILION_HOME ?? join(homedir(), ".bazilion");
382
+ const root = canonicalHome(resolve(home ?? process.env.BAZILION_HOME ?? join(homedir(), ".bazilion")));
382
383
  return { home: root, authFile: join(root, "auth.json") };
383
384
  }
385
+ function canonicalHome(root) {
386
+ let resolved = root;
387
+ const unresolvedTail = [];
388
+ while (true) {
389
+ try {
390
+ resolved = realpathSync(resolved);
391
+ break;
392
+ } catch {
393
+ const parent = dirname(resolved);
394
+ if (parent === resolved) break;
395
+ unresolvedTail.unshift(basename(resolved));
396
+ resolved = parent;
397
+ }
398
+ }
399
+ return join(resolved, ...unresolvedTail);
400
+ }
384
401
 
385
402
  // src/client.ts
386
403
  function loadClientConfig() {
@@ -721,7 +738,7 @@ var questionCommand = defineCommand3({
721
738
  // src/commands/queue.ts
722
739
  import { randomUUID as randomUUID3 } from "crypto";
723
740
  import { readFileSync as readFileSync2, statSync } from "fs";
724
- import { basename, extname } from "path";
741
+ import { basename as basename2, extname } from "path";
725
742
  import { defineCommand as defineCommand4 } from "citty";
726
743
  var positional4 = { type: "positional", required: true };
727
744
  var output3 = (value) => console.log(JSON.stringify(value, null, 2));
@@ -796,7 +813,7 @@ async function submit(args2, replacement) {
796
813
  ".pdf": "application/pdf"
797
814
  };
798
815
  return {
799
- name: basename(path),
816
+ name: basename2(path),
800
817
  mimeType: mime[extname(path).toLowerCase()] ?? "application/octet-stream",
801
818
  data: readFileSync2(path).toString("base64")
802
819
  };
@@ -886,7 +903,7 @@ var queueCommand = defineCommand4({
886
903
  // src/commands/agent.ts
887
904
  import { randomUUID as randomUUID4 } from "crypto";
888
905
  import { readFileSync as readFileSync3, writeFileSync } from "fs";
889
- import { basename as basename2, extname as extname2 } from "path";
906
+ import { basename as basename3, extname as extname2 } from "path";
890
907
  import { stdin, stdout } from "process";
891
908
  import { createInterface } from "readline/promises";
892
909
  import { defineCommand as defineCommand5 } from "citty";
@@ -978,7 +995,7 @@ function loadImages(paths) {
978
995
  return paths.map((p) => {
979
996
  const mimeType = IMAGE_MIME[extname2(p).toLowerCase()];
980
997
  if (!mimeType) throw new Error(`unsupported image type: ${p} (png/jpg/gif/webp only)`);
981
- return { name: basename2(p), mimeType, data: readFileSync3(p).toString("base64") };
998
+ return { name: basename3(p), mimeType, data: readFileSync3(p).toString("base64") };
982
999
  });
983
1000
  }
984
1001
  var FILE_MIME = {
@@ -992,7 +1009,7 @@ var FILE_MIME = {
992
1009
  };
993
1010
  function loadFiles(paths) {
994
1011
  return paths.map((p) => ({
995
- name: basename2(p),
1012
+ name: basename3(p),
996
1013
  mimeType: FILE_MIME[extname2(p).toLowerCase()] ?? "application/octet-stream",
997
1014
  data: readFileSync3(p).toString("base64")
998
1015
  }));
@@ -1268,7 +1285,7 @@ function printEvent(e, state) {
1268
1285
  process.stdout.write("\n");
1269
1286
  state.inDeltaStream = false;
1270
1287
  }
1271
- const out = basename2(e.name).replace(/[^\w.-]/g, "_") || "file";
1288
+ const out = basename3(e.name).replace(/[^\w.-]/g, "_") || "file";
1272
1289
  writeFileSync(out, Buffer.from(e.data, "base64"));
1273
1290
  console.log(` [file received: saved to ./${out} (${e.mimeType})]`);
1274
1291
  break;
@@ -1558,8 +1575,8 @@ var chatCompactCmd = defineCommand5({
1558
1575
  process.stdout.write(
1559
1576
  `compact chat history for ${args2.id}? head turns become a summary; tail is preserved. [y/N] `
1560
1577
  );
1561
- const answer = await new Promise((resolve6) => {
1562
- process.stdin.once("data", (d) => resolve6(String(d).trim().toLowerCase()));
1578
+ const answer = await new Promise((resolve7) => {
1579
+ process.stdin.once("data", (d) => resolve7(String(d).trim().toLowerCase()));
1563
1580
  });
1564
1581
  if (answer !== "y" && answer !== "yes") {
1565
1582
  console.log("aborted");
@@ -2086,7 +2103,7 @@ function answerCliOpenAIPrompt(prompt, input = process.stdin, output4 = process.
2086
2103
  );
2087
2104
  }
2088
2105
  output4.write(`${prompt.message}: `);
2089
- return new Promise((resolve6, reject) => {
2106
+ return new Promise((resolve7, reject) => {
2090
2107
  let settled = false;
2091
2108
  const signal = prompt.signal;
2092
2109
  let readingInput = true;
@@ -2107,7 +2124,7 @@ function answerCliOpenAIPrompt(prompt, input = process.stdin, output4 = process.
2107
2124
  if (settled) return;
2108
2125
  settled = true;
2109
2126
  cleanup();
2110
- resolve6(String(data).trim());
2127
+ resolve7(String(data).trim());
2111
2128
  };
2112
2129
  const onAbort = () => {
2113
2130
  if (settled || !signal) return;
@@ -2286,12 +2303,13 @@ import {
2286
2303
  readdirSync as readdirSync2,
2287
2304
  readFileSync as readFileSync6,
2288
2305
  readSync,
2306
+ realpathSync as realpathSync3,
2289
2307
  renameSync as renameSync2,
2290
2308
  rmSync as rmSync2,
2291
2309
  writeFileSync as writeFileSync2
2292
2310
  } from "fs";
2293
2311
  import { tmpdir } from "os";
2294
- import { basename as basename4, dirname as dirname3, isAbsolute, parse, posix, relative, resolve as resolve3 } from "path";
2312
+ import { basename as basename5, dirname as dirname4, isAbsolute, join as join4, parse, posix, relative, resolve as resolve4 } from "path";
2295
2313
  import { DatabaseSync as DatabaseSync4, backup as sqliteBackup } from "node:sqlite";
2296
2314
  import { Readable } from "stream";
2297
2315
  import { pipeline } from "stream/promises";
@@ -2301,7 +2319,7 @@ import { extract, list as list5 } from "tar";
2301
2319
 
2302
2320
  // src/backup-coding-recovery.ts
2303
2321
  import { lstatSync } from "fs";
2304
- import { resolve } from "path";
2322
+ import { resolve as resolve2 } from "path";
2305
2323
  function invalidateRestoredCodingEvidence(db, payload, targetHome) {
2306
2324
  const rows = db.prepare("SELECT id, receipt_json FROM coding_commands").all();
2307
2325
  for (const row2 of rows) {
@@ -2364,8 +2382,8 @@ function invalidateRestoredCodingEvidence(db, payload, targetHome) {
2364
2382
  const teams = db.prepare("SELECT id FROM teams").all();
2365
2383
  const rebase = db.prepare("UPDATE workspace_writers SET root_path = ? WHERE team_id = ?");
2366
2384
  for (const team of teams) {
2367
- if (lstatSync(resolve(payload, "teams", team.id)).isDirectory())
2368
- rebase.run(resolve(targetHome, "teams", team.id), team.id);
2385
+ if (lstatSync(resolve2(payload, "teams", team.id)).isDirectory())
2386
+ rebase.run(resolve2(targetHome, "teams", team.id), team.id);
2369
2387
  }
2370
2388
  }
2371
2389
 
@@ -2443,7 +2461,7 @@ import { createHash } from "crypto";
2443
2461
 
2444
2462
  // ../daemon/src/core/db/migrate.ts
2445
2463
  import { readdirSync, readFileSync as readFileSync4 } from "fs";
2446
- import { dirname, join as join2 } from "path";
2464
+ import { dirname as dirname2, join as join2 } from "path";
2447
2465
  import { DatabaseSync as DatabaseSync3 } from "node:sqlite";
2448
2466
  import { fileURLToPath } from "url";
2449
2467
 
@@ -2535,7 +2553,7 @@ function openInMemoryDb() {
2535
2553
  }
2536
2554
 
2537
2555
  // ../daemon/src/core/db/migrate.ts
2538
- var migrationsDir = join2(dirname(fileURLToPath(import.meta.url)), "migrations");
2556
+ var migrationsDir = join2(dirname2(fileURLToPath(import.meta.url)), "migrations");
2539
2557
  var schemaMigrationsSql = `
2540
2558
  CREATE TABLE IF NOT EXISTS schema_migrations (
2541
2559
  version TEXT PRIMARY KEY,
@@ -2635,30 +2653,30 @@ import {
2635
2653
  mkdirSync,
2636
2654
  openSync,
2637
2655
  readFileSync as readFileSync5,
2638
- realpathSync,
2656
+ realpathSync as realpathSync2,
2639
2657
  renameSync,
2640
2658
  rmSync,
2641
2659
  writeSync
2642
2660
  } from "fs";
2643
- import { basename as basename3, dirname as dirname2, join as join3, resolve as resolve2 } from "path";
2661
+ import { basename as basename4, dirname as dirname3, join as join3, resolve as resolve3 } from "path";
2644
2662
  var DAEMON_LIVENESS_FILENAME = "daemon-runtime.json";
2645
2663
  var STALE_AFTER_MS = 6e4;
2646
2664
  var PROBE_TIMEOUT_MS = 750;
2647
2665
  function canonicalHomeIdentity(home) {
2648
- const absolute = resolve2(home);
2666
+ const absolute = resolve3(home);
2649
2667
  try {
2650
- return realpathSync.native(absolute);
2668
+ return realpathSync2.native(absolute);
2651
2669
  } catch (error) {
2652
2670
  if (errorCode(error) !== "ENOENT") throw error;
2653
- const parent = dirname2(absolute);
2671
+ const parent = dirname3(absolute);
2654
2672
  if (parent === absolute) throw error;
2655
- return join3(canonicalHomeIdentity(parent), basename3(absolute));
2673
+ return join3(canonicalHomeIdentity(parent), basename4(absolute));
2656
2674
  }
2657
2675
  }
2658
2676
  function daemonLivenessPath(home) {
2659
- const canonicalHome = canonicalHomeIdentity(home);
2660
- const identity = createHash2("sha256").update(canonicalHome).digest("hex").slice(0, 24);
2661
- return join3(dirname2(canonicalHome), `.bazilion-runtime-${identity}.json`);
2677
+ const canonicalHome3 = canonicalHomeIdentity(home);
2678
+ const identity = createHash2("sha256").update(canonicalHome3).digest("hex").slice(0, 24);
2679
+ return join3(dirname3(canonicalHome3), `.bazilion-runtime-${identity}.json`);
2662
2680
  }
2663
2681
  function errorCode(error) {
2664
2682
  return error instanceof Error && "code" in error && typeof error.code === "string" ? error.code : void 0;
@@ -2753,7 +2771,7 @@ function writeRecord(fd, record) {
2753
2771
  function fsyncParentDirectory(path) {
2754
2772
  let directoryFd = null;
2755
2773
  try {
2756
- directoryFd = openSync(dirname2(path), "r");
2774
+ directoryFd = openSync(dirname3(path), "r");
2757
2775
  fsyncSync(directoryFd);
2758
2776
  } catch (error) {
2759
2777
  if (process.platform !== "win32") throw error;
@@ -2783,10 +2801,10 @@ function reclaimRecord(path, existing) {
2783
2801
  }
2784
2802
  }
2785
2803
  async function acquireHomeRestoreLock(home, operation = "restoring") {
2786
- const targetHome = resolve2(home);
2787
- mkdirSync(dirname2(targetHome), { recursive: true });
2804
+ const targetHome = resolve3(home);
2805
+ mkdirSync(dirname3(targetHome), { recursive: true });
2788
2806
  const path = daemonLivenessPath(targetHome);
2789
- mkdirSync(dirname2(path), { recursive: true });
2807
+ mkdirSync(dirname3(path), { recursive: true });
2790
2808
  const instanceId = randomUUID6();
2791
2809
  let fd = null;
2792
2810
  let reclaimClaim = null;
@@ -2912,7 +2930,7 @@ async function acquireHomeRestoreLock(home, operation = "restoring") {
2912
2930
  markSwapping(recoveryPath, hadPrevious) {
2913
2931
  if (released || !stillOwnsPath()) throw new Error("restore ownership was lost");
2914
2932
  record.state = "swapping";
2915
- record.recoveryPath = resolve2(recoveryPath);
2933
+ record.recoveryPath = resolve3(recoveryPath);
2916
2934
  record.hadPrevious = hadPrevious;
2917
2935
  writeRecord(fd, record);
2918
2936
  fsyncParentDirectory(path);
@@ -2927,7 +2945,7 @@ async function acquireHomeRestoreLock(home, operation = "restoring") {
2927
2945
  markRecoveryRequired(recoveryPath, hadPrevious) {
2928
2946
  if (released || !stillOwnsPath()) throw new Error("restore ownership was lost");
2929
2947
  record.state = "recovery-required";
2930
- record.recoveryPath = resolve2(recoveryPath);
2948
+ record.recoveryPath = resolve3(recoveryPath);
2931
2949
  record.hadPrevious = hadPrevious;
2932
2950
  writeRecord(fd, record);
2933
2951
  },
@@ -2979,10 +2997,10 @@ var createCmd = defineCommand9({
2979
2997
  const cfg = loadClientConfig();
2980
2998
  const date = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
2981
2999
  const defaultSuffix = args2.recipient ? ".tar.gz.age" : ".tar.gz";
2982
- const outAbs = resolve3(args2.output ?? `bazilion-backup-${date}${defaultSuffix}`);
3000
+ const outAbs = resolve4(args2.output ?? `bazilion-backup-${date}${defaultSuffix}`);
2983
3001
  if (existsSync2(outAbs)) throw new Error(`refusing to overwrite existing backup: ${outAbs}`);
2984
- const configuredHome = resolve3(resolveCliPaths().home);
2985
- const outputFromHome = relative(configuredHome, outAbs);
3002
+ const configuredHome = canonicalHome2(resolveCliPaths().home);
3003
+ const outputFromHome = relative(configuredHome, canonicalHome2(outAbs));
2986
3004
  if (!outputFromHome || !outputFromHome.startsWith("..") && !isAbsolute(outputFromHome)) {
2987
3005
  throw new Error(
2988
3006
  `backup output must be outside BAZILION_HOME (${configuredHome}) to avoid nesting backups`
@@ -3004,8 +3022,8 @@ var createCmd = defineCommand9({
3004
3022
  }
3005
3023
  throw new Error(`backup failed: ${err}`);
3006
3024
  }
3007
- const downloadDir = mkdtempSync(resolve3(tmpdir(), "bazilion-download-"));
3008
- const partial = resolve3(downloadDir, "backup.tar.gz");
3025
+ const downloadDir = mkdtempSync(resolve4(tmpdir(), "bazilion-download-"));
3026
+ const partial = resolve4(downloadDir, "backup.tar.gz");
3009
3027
  try {
3010
3028
  if (args2.recipient) {
3011
3029
  const [encryptSource, validateSource] = res.body.tee();
@@ -3030,9 +3048,9 @@ var createCmd = defineCommand9({
3030
3048
  renameSync2(partial, outAbs);
3031
3049
  } catch (error) {
3032
3050
  if (!(error instanceof Error) || !("code" in error) || error.code !== "EXDEV") throw error;
3033
- const installPartial = resolve3(
3034
- dirname3(outAbs),
3035
- `.${basename4(outAbs)}.${randomUUID7()}.installing`
3051
+ const installPartial = resolve4(
3052
+ dirname4(outAbs),
3053
+ `.${basename5(outAbs)}.${randomUUID7()}.installing`
3036
3054
  );
3037
3055
  try {
3038
3056
  copyFileSync(partial, installPartial);
@@ -3261,6 +3279,22 @@ function validateDatabase(path, authToken) {
3261
3279
  db?.close();
3262
3280
  }
3263
3281
  }
3282
+ function canonicalHome2(root) {
3283
+ let resolved = resolve4(root);
3284
+ const unresolvedTail = [];
3285
+ while (true) {
3286
+ try {
3287
+ resolved = realpathSync3(resolved);
3288
+ break;
3289
+ } catch {
3290
+ const parent = dirname4(resolved);
3291
+ if (parent === resolved) break;
3292
+ unresolvedTail.unshift(basename5(resolved));
3293
+ resolved = parent;
3294
+ }
3295
+ }
3296
+ return join4(resolved, ...unresolvedTail);
3297
+ }
3264
3298
  var SLUG_ID = /^[a-z0-9][a-z0-9-]*$/;
3265
3299
  var AGENT_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
3266
3300
  function validateEntityId(id, pattern, entity) {
@@ -3270,7 +3304,7 @@ function validateEntityId(id, pattern, entity) {
3270
3304
  return id;
3271
3305
  }
3272
3306
  function containedChildDirectory(root, id, rowLabel) {
3273
- const child = resolve3(root, id);
3307
+ const child = resolve4(root, id);
3274
3308
  const fromRoot = relative(root, child);
3275
3309
  if (!fromRoot || fromRoot.startsWith("..") || isAbsolute(fromRoot)) {
3276
3310
  throw new Error(`${rowLabel} directory escapes its canonical root: ${JSON.stringify(id)}`);
@@ -3295,6 +3329,8 @@ function requireExtractedTeamSlot(path, rowLabel) {
3295
3329
  function rebaseRestoredHomeDirectories(database, payload, targetHome) {
3296
3330
  let db = null;
3297
3331
  try {
3332
+ const canonicalTarget = canonicalHome2(targetHome);
3333
+ const canonicalPayload = realpathSync3(payload);
3298
3334
  db = new DatabaseSync4(database);
3299
3335
  db.exec("PRAGMA foreign_keys = ON");
3300
3336
  const profiles = db.prepare("SELECT id FROM profiles ORDER BY id").all();
@@ -3306,8 +3342,8 @@ function rebaseRestoredHomeDirectories(database, payload, targetHome) {
3306
3342
  ["agents", agents, AGENT_ID]
3307
3343
  ]) {
3308
3344
  const collection = table;
3309
- const stagedRoot = resolve3(payload, collection);
3310
- const targetRoot = resolve3(targetHome, collection);
3345
+ const stagedRoot = resolve4(canonicalPayload, collection);
3346
+ const targetRoot = resolve4(canonicalTarget, collection);
3311
3347
  for (const row2 of rows) {
3312
3348
  const id = validateEntityId(row2.id, idPattern, `${table} row`);
3313
3349
  const rowLabel = `${table} row ${JSON.stringify(id)}`;
@@ -3320,7 +3356,7 @@ function rebaseRestoredHomeDirectories(database, payload, targetHome) {
3320
3356
  });
3321
3357
  }
3322
3358
  }
3323
- const stagedTeamsRoot = resolve3(payload, "teams");
3359
+ const stagedTeamsRoot = resolve4(canonicalPayload, "teams");
3324
3360
  for (const row2 of teams) {
3325
3361
  const id = validateEntityId(row2.id, SLUG_ID, "teams row");
3326
3362
  const rowLabel = `teams row ${JSON.stringify(id)}`;
@@ -3370,15 +3406,15 @@ function rebaseRestoredHomeDirectories(database, payload, targetHome) {
3370
3406
  }
3371
3407
  }
3372
3408
  function removeRebuildableQmdIndexes(payload) {
3373
- const teamsDir = resolve3(payload, "teams");
3409
+ const teamsDir = resolve4(payload, "teams");
3374
3410
  if (!existsSync2(teamsDir) || !lstatSync3(teamsDir).isDirectory()) return;
3375
3411
  for (const team of readdirSync2(teamsDir, { withFileTypes: true })) {
3376
3412
  if (!team.isDirectory() || team.isSymbolicLink()) continue;
3377
- const memoryDir = resolve3(teamsDir, team.name, "memory");
3413
+ const memoryDir = resolve4(teamsDir, team.name, "memory");
3378
3414
  if (!existsSync2(memoryDir) || !lstatSync3(memoryDir).isDirectory()) continue;
3379
3415
  for (const entry3 of readdirSync2(memoryDir, { withFileTypes: true })) {
3380
3416
  if (entry3.isFile() && entry3.name.startsWith(".qmd-index.sqlite")) {
3381
- rmSync2(resolve3(memoryDir, entry3.name), { force: true });
3417
+ rmSync2(resolve4(memoryDir, entry3.name), { force: true });
3382
3418
  }
3383
3419
  }
3384
3420
  }
@@ -3392,9 +3428,9 @@ function revokeRestoredBrowserSessions(database) {
3392
3428
  }
3393
3429
  }
3394
3430
  function installValidatedPayload(payload, targetHome, staging, lifecycle, operations = { rename: renameSync2 }) {
3395
- const previous = resolve3(staging, "previous-home");
3431
+ const previous = resolve4(staging, "previous-home");
3396
3432
  const hadPrevious = existsSync2(targetHome);
3397
- const targetParent = dirname3(targetHome);
3433
+ const targetParent = dirname4(targetHome);
3398
3434
  const syncDirectory = operations.fsyncDirectory ?? fsyncDirectory;
3399
3435
  const recoveryError = (message, recoveryPath, cause) => {
3400
3436
  let markerError;
@@ -3505,7 +3541,7 @@ function fsyncDirectory(path) {
3505
3541
  }
3506
3542
  }
3507
3543
  function fsyncFile(path) {
3508
- const fd = openSync2(path, "r");
3544
+ const fd = openSync2(path, "r+");
3509
3545
  try {
3510
3546
  fsyncSync2(fd);
3511
3547
  } finally {
@@ -3523,7 +3559,7 @@ function isAgeEncrypted(path) {
3523
3559
  }
3524
3560
  }
3525
3561
  function readAgeIdentity(rawPath) {
3526
- const path = resolve3(rawPath);
3562
+ const path = resolve4(rawPath);
3527
3563
  const entry3 = lstatSync3(path);
3528
3564
  if (!entry3.isFile()) throw new Error(`age identity is not a regular file: ${path}`);
3529
3565
  if (process.platform !== "win32" && (entry3.mode & 63) !== 0) {
@@ -3557,18 +3593,18 @@ var restoreCmd = defineCommand9({
3557
3593
  }
3558
3594
  },
3559
3595
  async run({ args: args2 }) {
3560
- const file = resolve3(args2.file);
3596
+ const file = resolve4(args2.file);
3561
3597
  if (!existsSync2(file)) throw new Error(`backup file not found: ${file}`);
3562
3598
  const paths = resolveCliPaths(args2.home);
3563
- const targetHome = resolve3(paths.home);
3599
+ const targetHome = resolve4(paths.home);
3564
3600
  if (targetHome === parse(targetHome).root) {
3565
3601
  throw new Error(`refusing to restore over filesystem root: ${targetHome}`);
3566
3602
  }
3567
- const targetParent = dirname3(targetHome);
3603
+ const targetParent = dirname4(targetHome);
3568
3604
  mkdirSync2(targetParent, { recursive: true });
3569
3605
  const restoreLock = await acquireHomeRestoreLock(targetHome);
3570
3606
  try {
3571
- const targetsConfiguredHome = targetHome === resolve3(resolveCliPaths().home);
3607
+ const targetsConfiguredHome = targetHome === resolve4(resolveCliPaths().home);
3572
3608
  if (targetsConfiguredHome) {
3573
3609
  for (const serverUrl of configuredLoopbackUrls()) {
3574
3610
  if (await probeServerRunning(serverUrl)) {
@@ -3589,9 +3625,9 @@ var restoreCmd = defineCommand9({
3589
3625
  );
3590
3626
  }
3591
3627
  }
3592
- const staging = mkdtempSync(resolve3(targetParent, ".bazilion-restore-"));
3593
- const stagedArchive = resolve3(staging, "backup.tar.gz");
3594
- const payload = resolve3(staging, "payload");
3628
+ const staging = mkdtempSync(resolve4(targetParent, ".bazilion-restore-"));
3629
+ const stagedArchive = resolve4(staging, "backup.tar.gz");
3630
+ const payload = resolve4(staging, "payload");
3595
3631
  let preserveStaging = false;
3596
3632
  try {
3597
3633
  if (isAgeEncrypted(file)) {
@@ -3637,8 +3673,8 @@ var restoreCmd = defineCommand9({
3637
3673
  // payload-relative path by npm-tar.
3638
3674
  preservePaths: true
3639
3675
  });
3640
- const database = resolve3(payload, "bazilion.db");
3641
- const authFile = resolve3(payload, "auth.json");
3676
+ const database = resolve4(payload, "bazilion.db");
3677
+ const authFile = resolve4(payload, "auth.json");
3642
3678
  if (!lstatSync3(database).isFile() || !lstatSync3(authFile).isFile()) {
3643
3679
  throw new Error("backup required files did not extract as regular files");
3644
3680
  }
@@ -3701,8 +3737,8 @@ function encryptSecretEnvelope(value, password) {
3701
3737
  });
3702
3738
  }
3703
3739
  function credentialInventory(home) {
3704
- const authFile = resolve3(home, "auth.json");
3705
- const database = resolve3(home, "bazilion.db");
3740
+ const authFile = resolve4(home, "auth.json");
3741
+ const database = resolve4(home, "bazilion.db");
3706
3742
  const token = validateAuthFile(authFile);
3707
3743
  validateDatabase(database, token);
3708
3744
  const db = new DatabaseSync4(database, { readOnly: true });
@@ -3720,7 +3756,7 @@ var inventoryCmd = defineCommand9({
3720
3756
  meta: { name: "inventory", description: "List credential classes captured by a backup/home" },
3721
3757
  args: { home: { type: "string", description: "Override BAZILION_HOME" } },
3722
3758
  run({ args: args2 }) {
3723
- const home = resolve3(resolveCliPaths(args2.home).home);
3759
+ const home = resolve4(resolveCliPaths(args2.home).home);
3724
3760
  const inventory = credentialInventory(home);
3725
3761
  console.log("credential classes present (values are never shown):");
3726
3762
  console.log(` bootstrap token: ${inventory.bootstrap ? "present" : "missing"}`);
@@ -3759,14 +3795,14 @@ var rotateBootstrapCmd = defineCommand9({
3759
3795
  async run({ args: args2 }) {
3760
3796
  if (!args2.yes) throw new Error("--yes is required");
3761
3797
  const paths = resolveCliPaths(args2.home);
3762
- const targetHome = resolve3(paths.home);
3798
+ const targetHome = resolve4(paths.home);
3763
3799
  if (targetHome === parse(targetHome).root) {
3764
3800
  throw new Error(`refusing to rotate filesystem root: ${targetHome}`);
3765
3801
  }
3766
3802
  const lock = await acquireHomeRestoreLock(targetHome);
3767
- const parent = dirname3(targetHome);
3768
- const staging = mkdtempSync(resolve3(parent, ".bazilion-rotate-"));
3769
- const payload = resolve3(staging, "payload");
3803
+ const parent = dirname4(targetHome);
3804
+ const staging = mkdtempSync(resolve4(parent, ".bazilion-rotate-"));
3805
+ const payload = resolve4(staging, "payload");
3770
3806
  let preserveStaging = false;
3771
3807
  try {
3772
3808
  for (const serverUrl of configuredLoopbackUrls()) {
@@ -3778,16 +3814,16 @@ var rotateBootstrapCmd = defineCommand9({
3778
3814
  if (typeof oldAuth.token !== "string" || !oldAuth.token) {
3779
3815
  throw new Error("auth.json is missing the bootstrap token");
3780
3816
  }
3781
- validateDatabase(resolve3(targetHome, "bazilion.db"), oldAuth.token);
3817
+ validateDatabase(resolve4(targetHome, "bazilion.db"), oldAuth.token);
3782
3818
  cpSync(targetHome, payload, {
3783
3819
  recursive: true,
3784
3820
  dereference: false,
3785
3821
  verbatimSymlinks: true,
3786
3822
  preserveTimestamps: true
3787
3823
  });
3788
- const stagedDb = resolve3(payload, "bazilion.db");
3824
+ const stagedDb = resolve4(payload, "bazilion.db");
3789
3825
  rmSync2(stagedDb, { force: true });
3790
- const sourceDb = new DatabaseSync4(resolve3(targetHome, "bazilion.db"), { readOnly: true });
3826
+ const sourceDb = new DatabaseSync4(resolve4(targetHome, "bazilion.db"), { readOnly: true });
3791
3827
  try {
3792
3828
  await sqliteBackup(sourceDb, stagedDb);
3793
3829
  } finally {
@@ -3834,8 +3870,8 @@ var rotateBootstrapCmd = defineCommand9({
3834
3870
  } finally {
3835
3871
  db.close();
3836
3872
  }
3837
- const stagedAuth = resolve3(payload, "auth.json");
3838
- const authPartial = resolve3(payload, `.auth.json.${randomUUID7()}.installing`);
3873
+ const stagedAuth = resolve4(payload, "auth.json");
3874
+ const authPartial = resolve4(payload, `.auth.json.${randomUUID7()}.installing`);
3839
3875
  writeFileSync2(authPartial, `${JSON.stringify({ ...oldAuth, token: newToken }, null, 2)}
3840
3876
  `, {
3841
3877
  mode: 384,
@@ -4093,16 +4129,16 @@ var configCommand = defineCommand11({
4093
4129
  import { spawn } from "child_process";
4094
4130
  import { existsSync as existsSync3 } from "fs";
4095
4131
  import { connect } from "net";
4096
- import { join as join4 } from "path";
4132
+ import { join as join5 } from "path";
4097
4133
  import { defineCommand as defineCommand12 } from "citty";
4098
- var bundledDaemonEntry = join4(import.meta.dirname, "daemon.js");
4099
- var sourceDaemonEntry = join4(import.meta.dirname, "..", "..", "..", "daemon", "src", "index.ts");
4134
+ var bundledDaemonEntry = join5(import.meta.dirname, "daemon.js");
4135
+ var sourceDaemonEntry = join5(import.meta.dirname, "..", "..", "..", "daemon", "src", "index.ts");
4100
4136
  var daemonEntry = existsSync3(bundledDaemonEntry) ? bundledDaemonEntry : sourceDaemonEntry;
4101
- var bundledWebServerEntry = join4(import.meta.dirname, "web-server.js");
4102
- var sourceWebServerEntry = join4(import.meta.dirname, "..", "web-server.ts");
4137
+ var bundledWebServerEntry = join5(import.meta.dirname, "web-server.js");
4138
+ var sourceWebServerEntry = join5(import.meta.dirname, "..", "web-server.ts");
4103
4139
  var webServerEntry = existsSync3(bundledWebServerEntry) ? bundledWebServerEntry : sourceWebServerEntry;
4104
- var bundledWebDist = join4(import.meta.dirname, "web");
4105
- var sourceWebDist = join4(import.meta.dirname, "..", "..", "..", "web", "dist");
4140
+ var bundledWebDist = join5(import.meta.dirname, "web");
4141
+ var sourceWebDist = join5(import.meta.dirname, "..", "..", "..", "web", "dist");
4106
4142
  var webDist = existsSync3(bundledWebDist) ? bundledWebDist : sourceWebDist;
4107
4143
  function nodeArgs(entry3) {
4108
4144
  return entry3.endsWith(".ts") ? ["--import", "tsx/esm", entry3] : [entry3];
@@ -4121,12 +4157,12 @@ function probeHost(host) {
4121
4157
  return host;
4122
4158
  }
4123
4159
  function isTcpPortOpen(host, port) {
4124
- return new Promise((resolve6) => {
4160
+ return new Promise((resolve7) => {
4125
4161
  const socket = connect({ host: probeHost(host), port: Number(port) });
4126
4162
  const done = (open) => {
4127
4163
  socket.removeAllListeners();
4128
4164
  socket.destroy();
4129
- resolve6(open);
4165
+ resolve7(open);
4130
4166
  };
4131
4167
  socket.setTimeout(600);
4132
4168
  socket.once("connect", () => done(true));
@@ -4265,7 +4301,7 @@ var dashboardCommand = defineCommand12({
4265
4301
  `web UI port ${webPort} is already in use. Re-run with --port <free-port>.`
4266
4302
  );
4267
4303
  }
4268
- if (!existsSync3(join4(webDist, "server", "server.js"))) {
4304
+ if (!existsSync3(join5(webDist, "server", "server.js"))) {
4269
4305
  throw new Error(
4270
4306
  `bazilion web UI bundle not found at ${webDist}. Run "pnpm --filter @bazilion/web build" from the repository root of a source checkout, or reinstall the published package.`
4271
4307
  );
@@ -4292,13 +4328,13 @@ var dashboardCommand = defineCommand12({
4292
4328
  if (children.length === 0) return;
4293
4329
  process.on("SIGINT", terminateChildren);
4294
4330
  process.on("SIGTERM", terminateChildren);
4295
- await new Promise((resolve6) => {
4331
+ await new Promise((resolve7) => {
4296
4332
  let remaining = children.length;
4297
4333
  for (const child of children) {
4298
4334
  child.on("close", (code) => {
4299
4335
  remaining--;
4300
4336
  if (!signalled && code && code !== 0) process.exitCode = code;
4301
- if (remaining === 0) resolve6();
4337
+ if (remaining === 0) resolve7();
4302
4338
  });
4303
4339
  }
4304
4340
  });
@@ -4965,7 +5001,7 @@ import { spawn as spawn2 } from "child_process";
4965
5001
  import { randomBytes as randomBytes2 } from "crypto";
4966
5002
  import { readFileSync as readFileSync8, rmSync as rmSync3, writeFileSync as writeFileSync4 } from "fs";
4967
5003
  import { tmpdir as tmpdir2 } from "os";
4968
- import { join as join5 } from "path";
5004
+ import { join as join6 } from "path";
4969
5005
 
4970
5006
  // ../../packages/api-types/src/git-review.ts
4971
5007
  var REVIEW_LIMITS = {
@@ -5117,14 +5153,14 @@ var editCmd2 = defineCommand19({
5117
5153
  const { content } = await client.get(
5118
5154
  `/api/profiles/${args2.id}/files/${file}`
5119
5155
  );
5120
- const tmpPath = join5(tmpdir2(), `bazilion-${args2.id}-${file}-${randomBytes2(4).toString("hex")}`);
5156
+ const tmpPath = join6(tmpdir2(), `bazilion-${args2.id}-${file}-${randomBytes2(4).toString("hex")}`);
5121
5157
  writeFileSync4(tmpPath, content);
5122
5158
  try {
5123
5159
  const editor = process.env.EDITOR ?? process.env.VISUAL ?? "vi";
5124
- const code = await new Promise((resolve6, reject) => {
5160
+ const code = await new Promise((resolve7, reject) => {
5125
5161
  const child = spawn2(editor, [tmpPath], { stdio: "inherit" });
5126
5162
  child.on("error", reject);
5127
- child.on("close", (c) => resolve6(c ?? 0));
5163
+ child.on("close", (c) => resolve7(c ?? 0));
5128
5164
  });
5129
5165
  if (code !== 0) throw new Error(`editor exited with code ${code}`);
5130
5166
  const updated = readFileSync8(tmpPath, "utf8");
@@ -5473,10 +5509,10 @@ var sendCommand = defineCommand22({
5473
5509
  // src/commands/serve.ts
5474
5510
  import { spawn as spawn3 } from "child_process";
5475
5511
  import { existsSync as existsSync5 } from "fs";
5476
- import { join as join6 } from "path";
5512
+ import { join as join7 } from "path";
5477
5513
  import { defineCommand as defineCommand23 } from "citty";
5478
- var bundledDaemonEntry2 = join6(import.meta.dirname, "daemon.js");
5479
- var sourceDaemonEntry2 = join6(import.meta.dirname, "..", "..", "..", "daemon", "src", "index.ts");
5514
+ var bundledDaemonEntry2 = join7(import.meta.dirname, "daemon.js");
5515
+ var sourceDaemonEntry2 = join7(import.meta.dirname, "..", "..", "..", "daemon", "src", "index.ts");
5480
5516
  var daemonEntry2 = existsSync5(bundledDaemonEntry2) ? bundledDaemonEntry2 : sourceDaemonEntry2;
5481
5517
  var serveCommand = defineCommand23({
5482
5518
  meta: {
@@ -5527,17 +5563,17 @@ var serveCommand = defineCommand23({
5527
5563
  signalled = true;
5528
5564
  });
5529
5565
  process.on("SIGTERM", onSigterm);
5530
- await new Promise((resolve6, reject) => {
5566
+ await new Promise((resolve7, reject) => {
5531
5567
  proc.on("error", (err) => reject(err));
5532
5568
  proc.on("close", (code) => {
5533
5569
  if (signalled) {
5534
5570
  process.exitCode = 0;
5535
- resolve6();
5571
+ resolve7();
5536
5572
  } else if (code === 0 || code === null) {
5537
- resolve6();
5573
+ resolve7();
5538
5574
  } else {
5539
5575
  process.exitCode = code;
5540
- resolve6();
5576
+ resolve7();
5541
5577
  }
5542
5578
  });
5543
5579
  });
@@ -5583,7 +5619,7 @@ var sessionCommand = defineCommand24({
5583
5619
 
5584
5620
  // src/commands/skill.ts
5585
5621
  import { existsSync as existsSync6, readFileSync as readFileSync9, statSync as statSync2 } from "fs";
5586
- import { basename as basename5, resolve as resolve4 } from "path";
5622
+ import { basename as basename6, resolve as resolve5 } from "path";
5587
5623
  import { defineCommand as defineCommand25 } from "citty";
5588
5624
  function printFindings(findings, prefix = " ") {
5589
5625
  for (const f of findings) {
@@ -5647,13 +5683,13 @@ var importCmd = defineCommand25({
5647
5683
  },
5648
5684
  async run({ args: args2 }) {
5649
5685
  const client = createClient2();
5650
- const absFrom = resolve4(args2.from);
5686
+ const absFrom = resolve5(args2.from);
5651
5687
  const isLocalZip = args2.from.toLowerCase().endsWith(".zip") && existsSync6(absFrom) && statSync2(absFrom).isFile();
5652
5688
  let result;
5653
5689
  try {
5654
5690
  if (isLocalZip) {
5655
5691
  const bytes = readFileSync9(absFrom);
5656
- const file = new File([bytes], basename5(absFrom), { type: "application/zip" });
5692
+ const file = new File([bytes], basename6(absFrom), { type: "application/zip" });
5657
5693
  const fd = new FormData();
5658
5694
  fd.set("file", file);
5659
5695
  if (args2.force) fd.set("force", "true");
@@ -8299,9 +8335,9 @@ var triggerCommand = defineCommand37({
8299
8335
  });
8300
8336
 
8301
8337
  // src/commands/uninstall.ts
8302
- import { existsSync as existsSync7, lstatSync as lstatSync4, readdirSync as readdirSync3, realpathSync as realpathSync2, rmSync as rmSync4 } from "fs";
8338
+ import { existsSync as existsSync7, lstatSync as lstatSync4, readdirSync as readdirSync3, realpathSync as realpathSync4, rmSync as rmSync4 } from "fs";
8303
8339
  import { homedir as homedir2 } from "os";
8304
- import { isAbsolute as isAbsolute2, join as join7, parse as parse2, relative as relative2, resolve as resolve5, sep } from "path";
8340
+ import { isAbsolute as isAbsolute2, join as join8, parse as parse2, relative as relative2, resolve as resolve6, sep } from "path";
8305
8341
  import { defineCommand as defineCommand38 } from "citty";
8306
8342
  function makeLineReader() {
8307
8343
  let buffer = "";
@@ -8312,8 +8348,8 @@ function makeLineReader() {
8312
8348
  const nlIdx = buffer.indexOf("\n");
8313
8349
  if (nlIdx === -1) {
8314
8350
  if (ended) {
8315
- const resolve6 = queue.shift();
8316
- resolve6?.(buffer);
8351
+ const resolve7 = queue.shift();
8352
+ resolve7?.(buffer);
8317
8353
  buffer = "";
8318
8354
  } else {
8319
8355
  return;
@@ -8321,8 +8357,8 @@ function makeLineReader() {
8321
8357
  } else {
8322
8358
  const line = buffer.slice(0, nlIdx);
8323
8359
  buffer = buffer.slice(nlIdx + 1);
8324
- const resolve6 = queue.shift();
8325
- resolve6?.(line);
8360
+ const resolve7 = queue.shift();
8361
+ resolve7?.(line);
8326
8362
  }
8327
8363
  }
8328
8364
  };
@@ -8335,8 +8371,8 @@ function makeLineReader() {
8335
8371
  ended = true;
8336
8372
  tryDeliver();
8337
8373
  });
8338
- return () => new Promise((resolve6) => {
8339
- queue.push(resolve6);
8374
+ return () => new Promise((resolve7) => {
8375
+ queue.push(resolve7);
8340
8376
  tryDeliver();
8341
8377
  });
8342
8378
  }
@@ -8357,10 +8393,10 @@ function removePath(p) {
8357
8393
  }
8358
8394
  function canonicalExistingPath(path) {
8359
8395
  try {
8360
- return realpathSync2.native(path);
8396
+ return realpathSync4.native(path);
8361
8397
  } catch (error) {
8362
8398
  if (!(error instanceof Error && "code" in error && error.code === "ENOENT")) throw error;
8363
- return resolve5(path);
8399
+ return resolve6(path);
8364
8400
  }
8365
8401
  }
8366
8402
  function containsPath(container, candidate) {
@@ -8368,7 +8404,7 @@ function containsPath(container, candidate) {
8368
8404
  return nested === "" || nested !== ".." && !nested.startsWith(`..${sep}`) && !isAbsolute2(nested);
8369
8405
  }
8370
8406
  function assertSafeUninstallHome(home) {
8371
- const target = resolve5(home);
8407
+ const target = resolve6(home);
8372
8408
  const canonical = canonicalExistingPath(target);
8373
8409
  const userHome = canonicalExistingPath(homedir2());
8374
8410
  const workingDirectory = canonicalExistingPath(process.cwd());
@@ -8408,15 +8444,22 @@ var uninstallCommand = defineCommand38({
8408
8444
  async run({ args: args2 }) {
8409
8445
  const paths = resolveCliPaths(args2.home);
8410
8446
  const targetHome = assertSafeUninstallHome(paths.home);
8411
- const dbFile = join7(targetHome, "bazilion.db");
8412
- const profilesDir = join7(targetHome, "profiles");
8413
- const agentsDir = join7(targetHome, "agents");
8414
- const teamsDir = join7(targetHome, "teams");
8415
- const legacyGroupsDir = join7(targetHome, "groups");
8416
- const skillsDir = join7(targetHome, "skills");
8417
- const logsDir = join7(targetHome, "logs");
8418
- const legacyConfigFile = join7(targetHome, "config.json");
8419
- const legacySecretsFile = join7(targetHome, "secrets.enc");
8447
+ const requestedHome = resolve6(args2.home ?? process.env.BAZILION_HOME ?? join8(homedir2(), ".bazilion"));
8448
+ let requestedIsSymlink = false;
8449
+ try {
8450
+ requestedIsSymlink = lstatSync4(requestedHome).isSymbolicLink();
8451
+ } catch {
8452
+ }
8453
+ const homeIsSymlink = requestedIsSymlink;
8454
+ const dbFile = join8(targetHome, "bazilion.db");
8455
+ const profilesDir = join8(targetHome, "profiles");
8456
+ const agentsDir = join8(targetHome, "agents");
8457
+ const teamsDir = join8(targetHome, "teams");
8458
+ const legacyGroupsDir = join8(targetHome, "groups");
8459
+ const skillsDir = join8(targetHome, "skills");
8460
+ const logsDir = join8(targetHome, "logs");
8461
+ const legacyConfigFile = join8(targetHome, "config.json");
8462
+ const legacySecretsFile = join8(targetHome, "secrets.enc");
8420
8463
  if (!existsSync7(targetHome)) {
8421
8464
  const uninstallLock2 = await acquireHomeRestoreLock(targetHome, "uninstalling");
8422
8465
  try {
@@ -8427,7 +8470,6 @@ var uninstallCommand = defineCommand38({
8427
8470
  }
8428
8471
  return;
8429
8472
  }
8430
- const homeIsSymlink = lstatSync4(targetHome).isSymbolicLink();
8431
8473
  console.log(`about to uninstall bazilion at ${targetHome}`);
8432
8474
  console.log("");
8433
8475
  const resetTargets = [
@@ -8435,7 +8477,7 @@ var uninstallCommand = defineCommand38({
8435
8477
  `${dbFile}-wal`,
8436
8478
  `${dbFile}-shm`,
8437
8479
  `${dbFile}-journal`,
8438
- join7(targetHome, "auth.json"),
8480
+ join8(targetHome, "auth.json"),
8439
8481
  legacyConfigFile,
8440
8482
  legacySecretsFile,
8441
8483
  profilesDir,