zam-core 0.9.4 → 0.10.0

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/app.js CHANGED
@@ -6808,9 +6808,9 @@ var init_kernel = __esm({
6808
6808
  });
6809
6809
 
6810
6810
  // src/cli/app.ts
6811
- import { readFileSync as readFileSync17 } from "fs";
6812
- import { dirname as dirname11, join as join25 } from "path";
6813
- import { fileURLToPath as fileURLToPath5 } from "url";
6811
+ import { readFileSync as readFileSync18 } from "fs";
6812
+ import { dirname as dirname12, join as join27 } from "path";
6813
+ import { fileURLToPath as fileURLToPath6 } from "url";
6814
6814
  import { Command as Command27 } from "commander";
6815
6815
 
6816
6816
  // src/cli/commands/agent.ts
@@ -7156,12 +7156,10 @@ function connectHarnessMcp(harnessId, opts) {
7156
7156
  let content = "";
7157
7157
  let alreadyConfigured = false;
7158
7158
  let hint = "";
7159
- if (harnessId === "claude-code") {
7160
- targetPath = join12(opts.cwd, ".mcp.json");
7161
- hint = "Claude Code will prompt you to approve the 'zam' MCP server on next launch.";
7159
+ const mergeMcpServersJson = (path) => {
7162
7160
  let existing = {};
7163
- if (exists(targetPath)) {
7164
- existing = parseMcpJsonConfig(targetPath, read(targetPath));
7161
+ if (exists(path)) {
7162
+ existing = parseMcpJsonConfig(path, read(path));
7165
7163
  }
7166
7164
  if (!existing.mcpServers) {
7167
7165
  existing.mcpServers = {};
@@ -7170,7 +7168,29 @@ function connectHarnessMcp(harnessId, opts) {
7170
7168
  command: opts.zamPath,
7171
7169
  args: ["mcp"]
7172
7170
  };
7173
- content = JSON.stringify(existing, null, 2);
7171
+ return JSON.stringify(existing, null, 2);
7172
+ };
7173
+ if (harnessId === "claude-code") {
7174
+ targetPath = join12(opts.cwd, ".mcp.json");
7175
+ hint = "Claude Code will prompt you to approve the 'zam' MCP server on next launch.";
7176
+ content = mergeMcpServersJson(targetPath);
7177
+ } else if (harnessId === "claude-desktop") {
7178
+ const platform = opts.platform ?? process.platform;
7179
+ targetPath = platform === "win32" ? join12(
7180
+ opts.home,
7181
+ "AppData",
7182
+ "Roaming",
7183
+ "Claude",
7184
+ "claude_desktop_config.json"
7185
+ ) : platform === "darwin" ? join12(
7186
+ opts.home,
7187
+ "Library",
7188
+ "Application Support",
7189
+ "Claude",
7190
+ "claude_desktop_config.json"
7191
+ ) : join12(opts.home, ".config", "Claude", "claude_desktop_config.json");
7192
+ hint = "Restart Claude Desktop to load the 'zam' MCP server; MCP Apps panels render inline in the chat.";
7193
+ content = mergeMcpServersJson(targetPath);
7174
7194
  } else if (harnessId === "antigravity") {
7175
7195
  targetPath = join12(opts.home, ".gemini", "config", "mcp_config.json");
7176
7196
  hint = "Shared config read by Antigravity CLI and IDE (2.0+); older IDE builds read ~/.gemini/antigravity/mcp_config.json instead. Refresh Installed MCP Servers; the first tool call may still require approval.";
@@ -7303,6 +7323,7 @@ var C = {
7303
7323
  var SUPPORTED_AGENTS = ["opencode"];
7304
7324
  var CONNECT_HARNESSES = [
7305
7325
  "claude-code",
7326
+ "claude-desktop",
7306
7327
  "antigravity",
7307
7328
  "codex",
7308
7329
  "opencode",
@@ -7421,7 +7442,7 @@ var openCmd = new Command("open").description("Open an agent harness in the work
7421
7442
  });
7422
7443
  var connectCmd = new Command("connect").description("Configure the ZAM MCP server for an agent harness").argument(
7423
7444
  "<harness>",
7424
- "Harness to connect: claude-code | antigravity | codex | opencode | goose | copilot"
7445
+ "Harness to connect: claude-code | claude-desktop | antigravity | codex | opencode | goose | copilot"
7425
7446
  ).option(
7426
7447
  "--print",
7427
7448
  "Print configuration changes instead of writing them to disk"
@@ -7484,9 +7505,9 @@ var agentCommand = new Command("agent").description("Provision and inspect the a
7484
7505
  init_kernel();
7485
7506
  import { execFileSync as execFileSync3 } from "child_process";
7486
7507
  import { randomBytes as randomBytes2 } from "crypto";
7487
- import { existsSync as existsSync17, readdirSync as readdirSync2, readFileSync as readFileSync13, rmSync as rmSync3 } from "fs";
7508
+ import { existsSync as existsSync17, readdirSync as readdirSync2, readFileSync as readFileSync14, rmSync as rmSync3 } from "fs";
7488
7509
  import { homedir as homedir11, tmpdir as tmpdir3 } from "os";
7489
- import { join as join18, resolve as resolve4 } from "path";
7510
+ import { join as join20, resolve as resolve4 } from "path";
7490
7511
  import { Command as Command2 } from "commander";
7491
7512
  import { ulid as ulid9 } from "ulid";
7492
7513
 
@@ -9101,7 +9122,7 @@ async function readWebLink(url) {
9101
9122
  redirect: "manual",
9102
9123
  signal: controller.signal,
9103
9124
  headers: {
9104
- "User-Agent": "ZAM-Content-Studio/0.9.4"
9125
+ "User-Agent": "ZAM-Content-Studio/0.10.0"
9105
9126
  }
9106
9127
  });
9107
9128
  if (res.status >= 300 && res.status < 400) {
@@ -9166,6 +9187,8 @@ async function readImageOCR(db, imagePath) {
9166
9187
 
9167
9188
  // src/cli/bridge-handlers.ts
9168
9189
  init_kernel();
9190
+ import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync8 } from "fs";
9191
+ import { join as join16 } from "path";
9169
9192
 
9170
9193
  // src/cli/knowledge-contexts.ts
9171
9194
  init_kernel();
@@ -9411,6 +9434,164 @@ async function resolveSuggestMinSimilarity(db) {
9411
9434
  return Number.isFinite(parsed) && parsed > 0 && parsed <= 1 ? parsed : 0.45;
9412
9435
  }
9413
9436
 
9437
+ // src/cli/update/latest-version.ts
9438
+ import { readFileSync as readFileSync11 } from "fs";
9439
+ import { dirname as dirname6, join as join14 } from "path";
9440
+ import { fileURLToPath as fileURLToPath2 } from "url";
9441
+ var GITHUB_REPO = "zam-os/zam";
9442
+ function currentVersion() {
9443
+ const here = dirname6(fileURLToPath2(import.meta.url));
9444
+ for (const up of ["..", "../..", "../../.."]) {
9445
+ try {
9446
+ const pkg2 = JSON.parse(
9447
+ readFileSync11(join14(here, up, "package.json"), "utf-8")
9448
+ );
9449
+ if (pkg2.version) return pkg2.version;
9450
+ } catch {
9451
+ }
9452
+ }
9453
+ return "0.0.0";
9454
+ }
9455
+ async function fetchLatestVersion(repo) {
9456
+ const res = await fetch(
9457
+ `https://api.github.com/repos/${repo}/releases/latest`,
9458
+ {
9459
+ headers: {
9460
+ Accept: "application/vnd.github+json",
9461
+ "User-Agent": "zam-cli"
9462
+ }
9463
+ }
9464
+ );
9465
+ if (!res.ok) {
9466
+ throw new Error(
9467
+ `Could not reach the release server (HTTP ${res.status}). Pass --latest <version> to check offline.`
9468
+ );
9469
+ }
9470
+ const data = await res.json();
9471
+ if (!data.tag_name) throw new Error("No published release found yet.");
9472
+ return data.tag_name;
9473
+ }
9474
+
9475
+ // src/cli/workspaces/active.ts
9476
+ init_kernel();
9477
+ import { existsSync as existsSync15, mkdirSync as mkdirSync9 } from "fs";
9478
+ import { homedir as homedir10 } from "os";
9479
+ import { basename as basename3, join as join15, resolve as resolve3 } from "path";
9480
+ var LEGACY_WORKSPACE_DIR_KEY = "personal.workspace_dir";
9481
+ var DEFAULT_WORKSPACE_ID = "personal";
9482
+ function defaultWorkspaceDir() {
9483
+ return join15(homedir10(), "Documents", "zam");
9484
+ }
9485
+ function normalizeWorkspacePath(path) {
9486
+ const resolved = resolve3(path);
9487
+ return process.platform === "win32" ? resolved.toLowerCase() : resolved;
9488
+ }
9489
+ function sameWorkspacePath(left, right) {
9490
+ return normalizeWorkspacePath(left) === normalizeWorkspacePath(right);
9491
+ }
9492
+ function labelFromPath(path) {
9493
+ return basename3(path) || "ZAM";
9494
+ }
9495
+ function workspaceIdFromPath(dir) {
9496
+ const base = basename3(dir).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
9497
+ const prefix = base || "workspace";
9498
+ const existing = new Set(getConfiguredWorkspaces().map((item) => item.id));
9499
+ if (!existing.has(prefix)) return prefix;
9500
+ let index = 2;
9501
+ while (existing.has(`${prefix}-${index}`)) index++;
9502
+ return `${prefix}-${index}`;
9503
+ }
9504
+ function findWorkspaceByPath(dir) {
9505
+ return getConfiguredWorkspaces().find(
9506
+ (workspace) => sameWorkspacePath(workspace.path, dir)
9507
+ );
9508
+ }
9509
+ async function clearLegacyWorkspaceDir(db) {
9510
+ await deleteSetting(db, LEGACY_WORKSPACE_DIR_KEY);
9511
+ }
9512
+ async function migrateLegacyWorkspaceDir(db) {
9513
+ const legacyDir = await getSetting(db, LEGACY_WORKSPACE_DIR_KEY);
9514
+ if (!legacyDir) return void 0;
9515
+ const path = resolve3(legacyDir);
9516
+ const existing = findWorkspaceByPath(path);
9517
+ const migrated = existing ?? {
9518
+ id: getConfiguredWorkspaces().some(
9519
+ (workspace) => workspace.id === DEFAULT_WORKSPACE_ID
9520
+ ) ? workspaceIdFromPath(path) : DEFAULT_WORKSPACE_ID,
9521
+ label: labelFromPath(path),
9522
+ kind: "personal",
9523
+ path
9524
+ };
9525
+ if (!existing) {
9526
+ upsertConfiguredWorkspace(migrated);
9527
+ }
9528
+ if (!getActiveWorkspace()) {
9529
+ setActiveWorkspaceId(migrated.id);
9530
+ }
9531
+ await clearLegacyWorkspaceDir(db);
9532
+ return migrated;
9533
+ }
9534
+ async function ensureActiveWorkspace(db) {
9535
+ await migrateLegacyWorkspaceDir(db);
9536
+ const active = getActiveWorkspace();
9537
+ if (active) {
9538
+ mkdirSync9(active.path, { recursive: true });
9539
+ return active;
9540
+ }
9541
+ const configured = getConfiguredWorkspaces()[0];
9542
+ if (configured) {
9543
+ setActiveWorkspaceId(configured.id);
9544
+ mkdirSync9(configured.path, { recursive: true });
9545
+ return configured;
9546
+ }
9547
+ const workspace = {
9548
+ id: DEFAULT_WORKSPACE_ID,
9549
+ label: "Personal",
9550
+ kind: "personal",
9551
+ path: defaultWorkspaceDir()
9552
+ };
9553
+ mkdirSync9(workspace.path, { recursive: true });
9554
+ upsertConfiguredWorkspace(workspace);
9555
+ setActiveWorkspaceId(workspace.id);
9556
+ await clearLegacyWorkspaceDir(db);
9557
+ return workspace;
9558
+ }
9559
+ async function activateWorkspace(db, workspace) {
9560
+ upsertConfiguredWorkspace(workspace);
9561
+ setActiveWorkspaceId(workspace.id);
9562
+ await clearLegacyWorkspaceDir(db);
9563
+ return workspace;
9564
+ }
9565
+ async function activateWorkspacePath(db, dir, opts = {}) {
9566
+ await migrateLegacyWorkspaceDir(db);
9567
+ const path = resolve3(dir);
9568
+ const existing = opts.id ? void 0 : findWorkspaceByPath(path);
9569
+ if (existing) {
9570
+ setActiveWorkspaceId(existing.id);
9571
+ await clearLegacyWorkspaceDir(db);
9572
+ return existing;
9573
+ }
9574
+ const workspace = {
9575
+ id: opts.id || workspaceIdFromPath(path),
9576
+ label: opts.label || labelFromPath(path),
9577
+ kind: opts.kind || "personal",
9578
+ path
9579
+ };
9580
+ return activateWorkspace(db, workspace);
9581
+ }
9582
+ async function removeWorkspaceAndResolveActive(db, id) {
9583
+ removeConfiguredWorkspace(id);
9584
+ await clearLegacyWorkspaceDir(db);
9585
+ const activeWorkspace = await ensureActiveWorkspace(db);
9586
+ return {
9587
+ activeWorkspace,
9588
+ workspaces: getConfiguredWorkspaces()
9589
+ };
9590
+ }
9591
+ function existingWorkspaceDirOrHome(workspace) {
9592
+ return existsSync15(workspace.path) ? workspace.path : homedir10();
9593
+ }
9594
+
9414
9595
  // src/cli/bridge-handlers.ts
9415
9596
  var BLOOM_VERBS3 = {
9416
9597
  1: "Remember",
@@ -10176,6 +10357,33 @@ async function sessionOpen(db, params) {
10176
10357
  relevant: findTokensResult
10177
10358
  };
10178
10359
  }
10360
+ async function backupCreate(db, params) {
10361
+ const targetDir = params.dir || (await ensureActiveWorkspace(db)).path;
10362
+ const snapshot = await exportSnapshot(db);
10363
+ const manifest = verifySnapshot(snapshot);
10364
+ const backupDir = join16(targetDir, "zam-backups");
10365
+ mkdirSync10(backupDir, { recursive: true });
10366
+ const stamp = manifest.createdAt.replace(/[:.]/g, "-");
10367
+ const path = join16(backupDir, `zam-snapshot-${stamp}.sql`);
10368
+ writeFileSync8(path, snapshot, "utf-8");
10369
+ return {
10370
+ ok: true,
10371
+ path,
10372
+ createdAt: manifest.createdAt,
10373
+ checksum: manifest.checksum,
10374
+ tables: manifest.tables
10375
+ };
10376
+ }
10377
+ async function updateCheck(params) {
10378
+ const current = currentVersion();
10379
+ const latest = params.latest ?? await fetchLatestVersion(GITHUB_REPO);
10380
+ const channel = params.channel ?? getInstallChannel();
10381
+ return decideUpdate({
10382
+ currentVersion: current,
10383
+ latestVersion: latest,
10384
+ channel
10385
+ });
10386
+ }
10179
10387
 
10180
10388
  // src/cli/curriculum/breadcrumb.ts
10181
10389
  init_kernel();
@@ -12842,9 +13050,9 @@ function getCurriculumProvider(id) {
12842
13050
  // src/cli/llm/vision.ts
12843
13051
  init_kernel();
12844
13052
  import { randomBytes } from "crypto";
12845
- import { readFileSync as readFileSync11 } from "fs";
13053
+ import { readFileSync as readFileSync12 } from "fs";
12846
13054
  import { tmpdir as tmpdir2 } from "os";
12847
- import { basename as basename3, join as join14 } from "path";
13055
+ import { basename as basename4, join as join17 } from "path";
12848
13056
  var LANGUAGE_NAMES2 = {
12849
13057
  en: "English",
12850
13058
  de: "German",
@@ -12880,13 +13088,13 @@ async function observeUiSnapshotViaLLM(db, input8) {
12880
13088
  const imageUrls = [];
12881
13089
  const isVideo = /\.(mp4|mov|m4v|avi|mkv|webm)$/i.test(input8.imagePath);
12882
13090
  if (isVideo) {
12883
- const { mkdirSync: mkdirSync15, readdirSync: readdirSync3, rmSync: rmSync4 } = await import("fs");
13091
+ const { mkdirSync: mkdirSync16, readdirSync: readdirSync3, rmSync: rmSync4 } = await import("fs");
12884
13092
  const { execSync: execSync6 } = await import("child_process");
12885
- const tempDir = join14(
13093
+ const tempDir = join17(
12886
13094
  tmpdir2(),
12887
13095
  `zam-frames-${randomBytes(4).toString("hex")}`
12888
13096
  );
12889
- mkdirSync15(tempDir, { recursive: true });
13097
+ mkdirSync16(tempDir, { recursive: true });
12890
13098
  try {
12891
13099
  execSync6(
12892
13100
  `ffmpeg -i "${input8.imagePath}" -vf "fps=1/3,scale=1280:-1" -vsync vfr "${tempDir}/frame_%03d.png"`,
@@ -12915,7 +13123,7 @@ async function observeUiSnapshotViaLLM(db, input8) {
12915
13123
  }
12916
13124
  }
12917
13125
  for (const file of sampledFiles) {
12918
- const bytes = readFileSync11(join14(tempDir, file));
13126
+ const bytes = readFileSync12(join17(tempDir, file));
12919
13127
  imageUrls.push(`data:image/png;base64,${bytes.toString("base64")}`);
12920
13128
  }
12921
13129
  } finally {
@@ -12925,7 +13133,7 @@ async function observeUiSnapshotViaLLM(db, input8) {
12925
13133
  }
12926
13134
  }
12927
13135
  } else {
12928
- const imageBytes = readFileSync11(input8.imagePath);
13136
+ const imageBytes = readFileSync12(input8.imagePath);
12929
13137
  const ext = input8.imagePath.split(".").pop()?.toLowerCase();
12930
13138
  const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : "image/png";
12931
13139
  imageUrls.push(`data:${mime};base64,${imageBytes.toString("base64")}`);
@@ -13163,7 +13371,7 @@ function buildReport(input8, draft) {
13163
13371
  evidence: [
13164
13372
  {
13165
13373
  type: "keyframe",
13166
- ref: input8.evidenceRef ?? basename3(input8.imagePath),
13374
+ ref: input8.evidenceRef ?? basename4(input8.imagePath),
13167
13375
  redacted: input8.redacted ?? false
13168
13376
  }
13169
13377
  ],
@@ -13185,7 +13393,7 @@ function uncertainReport(input8, summary) {
13185
13393
  evidence: [
13186
13394
  {
13187
13395
  type: "keyframe",
13188
- ref: input8.evidenceRef ?? basename3(input8.imagePath),
13396
+ ref: input8.evidenceRef ?? basename4(input8.imagePath),
13189
13397
  redacted: input8.redacted ?? false
13190
13398
  }
13191
13399
  ],
@@ -13394,36 +13602,36 @@ async function withProviderScope(machine, action) {
13394
13602
 
13395
13603
  // src/cli/provisioning/index.ts
13396
13604
  import {
13397
- existsSync as existsSync15,
13605
+ existsSync as existsSync16,
13398
13606
  lstatSync,
13399
- mkdirSync as mkdirSync9,
13400
- readFileSync as readFileSync12,
13607
+ mkdirSync as mkdirSync11,
13608
+ readFileSync as readFileSync13,
13401
13609
  realpathSync,
13402
13610
  rmSync as rmSync2,
13403
13611
  symlinkSync,
13404
- writeFileSync as writeFileSync8
13612
+ writeFileSync as writeFileSync9
13405
13613
  } from "fs";
13406
- import { basename as basename4, dirname as dirname6, join as join15 } from "path";
13407
- import { fileURLToPath as fileURLToPath2 } from "url";
13614
+ import { basename as basename5, dirname as dirname7, join as join18 } from "path";
13615
+ import { fileURLToPath as fileURLToPath3 } from "url";
13408
13616
  var packageRoot = [
13409
- fileURLToPath2(new URL("../..", import.meta.url)),
13410
- fileURLToPath2(new URL("../../..", import.meta.url))
13411
- ].find((candidate) => existsSync15(join15(candidate, "package.json"))) ?? fileURLToPath2(new URL("../..", import.meta.url));
13617
+ fileURLToPath3(new URL("../..", import.meta.url)),
13618
+ fileURLToPath3(new URL("../../..", import.meta.url))
13619
+ ].find((candidate) => existsSync16(join18(candidate, "package.json"))) ?? fileURLToPath3(new URL("../..", import.meta.url));
13412
13620
  var ALL_SETUP_AGENTS = ["claude", "copilot", "codex", "agent"];
13413
13621
  var SKILL_PAIRS = [
13414
13622
  {
13415
- from: join15(packageRoot, ".claude", "skills", "zam", "SKILL.md"),
13416
- to: join15(".claude", "skills", "zam", "SKILL.md"),
13623
+ from: join18(packageRoot, ".claude", "skills", "zam", "SKILL.md"),
13624
+ to: join18(".claude", "skills", "zam", "SKILL.md"),
13417
13625
  agents: ["claude", "copilot"]
13418
13626
  },
13419
13627
  {
13420
- from: join15(packageRoot, ".agent", "skills", "zam", "SKILL.md"),
13421
- to: join15(".agent", "skills", "zam", "SKILL.md"),
13628
+ from: join18(packageRoot, ".agent", "skills", "zam", "SKILL.md"),
13629
+ to: join18(".agent", "skills", "zam", "SKILL.md"),
13422
13630
  agents: ["agent"]
13423
13631
  },
13424
13632
  {
13425
- from: join15(packageRoot, ".agents", "skills", "zam", "SKILL.md"),
13426
- to: join15(".agents", "skills", "zam", "SKILL.md"),
13633
+ from: join18(packageRoot, ".agents", "skills", "zam", "SKILL.md"),
13634
+ to: join18(".agents", "skills", "zam", "SKILL.md"),
13427
13635
  agents: ["codex"]
13428
13636
  }
13429
13637
  ];
@@ -13483,15 +13691,15 @@ function linkPointsTo(sourceDir, destinationDir) {
13483
13691
  function isZamSkillCopy(destinationDir) {
13484
13692
  try {
13485
13693
  if (!lstatSync(destinationDir).isDirectory()) return false;
13486
- const skillFile = join15(destinationDir, "SKILL.md");
13487
- if (!existsSync15(skillFile)) return false;
13488
- return /^name:\s*zam\s*$/m.test(readFileSync12(skillFile, "utf8"));
13694
+ const skillFile = join18(destinationDir, "SKILL.md");
13695
+ if (!existsSync16(skillFile)) return false;
13696
+ return /^name:\s*zam\s*$/m.test(readFileSync13(skillFile, "utf8"));
13489
13697
  } catch {
13490
13698
  return false;
13491
13699
  }
13492
13700
  }
13493
13701
  function classifySkillDestination(sourceDir, destinationDir) {
13494
- if (!existsSync15(sourceDir)) return "source-missing";
13702
+ if (!existsSync16(sourceDir)) return "source-missing";
13495
13703
  if (!isSymbolicLink(destinationDir) && pathsResolveToSameDirectory(sourceDir, destinationDir)) {
13496
13704
  return "source-directory";
13497
13705
  }
@@ -13508,9 +13716,9 @@ function wireSkills(cwd = process.cwd(), agents = parseSetupAgents(), opts = {})
13508
13716
  };
13509
13717
  for (const { from, to, agents: pairAgents } of SKILL_PAIRS) {
13510
13718
  if (!pairAgents.some((agent) => agents.has(agent))) continue;
13511
- const sourceDir = dirname6(from);
13512
- const destinationDir = dirname6(join15(cwd, to));
13513
- const label = dirname6(to);
13719
+ const sourceDir = dirname7(from);
13720
+ const destinationDir = dirname7(join18(cwd, to));
13721
+ const label = dirname7(to);
13514
13722
  const state = classifySkillDestination(sourceDir, destinationDir);
13515
13723
  if (state === "source-missing") {
13516
13724
  if (!opts.quiet) {
@@ -13567,7 +13775,7 @@ function wireSkills(cwd = process.cwd(), agents = parseSetupAgents(), opts = {})
13567
13775
  if (destinationExists) {
13568
13776
  rmSync2(destinationDir, { recursive: true, force: true });
13569
13777
  }
13570
- mkdirSync9(dirname6(destinationDir), { recursive: true });
13778
+ mkdirSync11(dirname7(destinationDir), { recursive: true });
13571
13779
  symlinkSync(
13572
13780
  sourceDir,
13573
13781
  destinationDir,
@@ -13583,8 +13791,8 @@ function inspectSkillLinks(cwd = process.cwd(), agents = parseSetupAgents()) {
13583
13791
  const results = [];
13584
13792
  for (const { from, to, agents: pairAgents } of SKILL_PAIRS) {
13585
13793
  if (!pairAgents.some((agent) => agents.has(agent))) continue;
13586
- const sourceDir = dirname6(from);
13587
- const destinationDir = dirname6(join15(cwd, to));
13794
+ const sourceDir = dirname7(from);
13795
+ const destinationDir = dirname7(join18(cwd, to));
13588
13796
  results.push({
13589
13797
  agents: pairAgents,
13590
13798
  source: sourceDir,
@@ -13610,15 +13818,15 @@ function upsertMarkedBlock(dest, blockBody, dryRun) {
13610
13818
  const block = `${ZAM_BLOCK_START}
13611
13819
  ${blockBody.trim()}
13612
13820
  ${ZAM_BLOCK_END}`;
13613
- if (!existsSync15(dest)) {
13821
+ if (!existsSync16(dest)) {
13614
13822
  if (!dryRun) {
13615
- mkdirSync9(dirname6(dest), { recursive: true });
13616
- writeFileSync8(dest, `${block}
13823
+ mkdirSync11(dirname7(dest), { recursive: true });
13824
+ writeFileSync9(dest, `${block}
13617
13825
  `, "utf8");
13618
13826
  }
13619
13827
  return "write";
13620
13828
  }
13621
- const existing = readFileSync12(dest, "utf8");
13829
+ const existing = readFileSync13(dest, "utf8");
13622
13830
  if (existing.includes(block)) return "skip";
13623
13831
  const start = existing.indexOf(ZAM_BLOCK_START);
13624
13832
  const end = existing.indexOf(ZAM_BLOCK_END);
@@ -13626,7 +13834,7 @@ ${ZAM_BLOCK_END}`;
13626
13834
 
13627
13835
  ${block}
13628
13836
  `;
13629
- if (!dryRun) writeFileSync8(dest, next, "utf8");
13837
+ if (!dryRun) writeFileSync9(dest, next, "utf8");
13630
13838
  return start >= 0 && end > start ? "update" : "write";
13631
13839
  }
13632
13840
  function logInstructionAction(action, label, dryRun) {
@@ -13638,8 +13846,8 @@ function logInstructionAction(action, label, dryRun) {
13638
13846
  }
13639
13847
  function writeClaudeMd(skipClaudeMd, cwd = process.cwd(), opts = {}) {
13640
13848
  if (skipClaudeMd) return;
13641
- const dest = join15(cwd, "CLAUDE.md");
13642
- if (existsSync15(dest)) {
13849
+ const dest = join18(cwd, "CLAUDE.md");
13850
+ if (existsSync16(dest)) {
13643
13851
  if (!opts.updateExisting) {
13644
13852
  console.log(` skip CLAUDE.md (already present)`);
13645
13853
  return;
@@ -13658,7 +13866,7 @@ ZAM is available in this repository. Use the \`zam\` skill in Claude Code to tur
13658
13866
  logInstructionAction(action, "CLAUDE.md", Boolean(opts.dryRun));
13659
13867
  return;
13660
13868
  }
13661
- const name = basename4(cwd);
13869
+ const name = basename5(cwd);
13662
13870
  const content = `# ZAM Personal Kernel \u2014 ${name}
13663
13871
 
13664
13872
  This is a ZAM personal instance. ZAM builds lasting skills through spaced
@@ -13682,14 +13890,14 @@ Use \`zam connector setup turso\` to store cloud credentials in
13682
13890
  if (opts.dryRun) {
13683
13891
  console.log(` would write CLAUDE.md`);
13684
13892
  } else {
13685
- writeFileSync8(dest, content, "utf8");
13893
+ writeFileSync9(dest, content, "utf8");
13686
13894
  console.log(` write CLAUDE.md`);
13687
13895
  }
13688
13896
  }
13689
13897
  function writeAgentsMd(skipAgentsMd, cwd = process.cwd(), opts = {}) {
13690
13898
  if (skipAgentsMd) return;
13691
- const dest = join15(cwd, "AGENTS.md");
13692
- if (existsSync15(dest)) {
13899
+ const dest = join18(cwd, "AGENTS.md");
13900
+ if (existsSync16(dest)) {
13693
13901
  if (!opts.updateExisting) {
13694
13902
  console.log(` skip AGENTS.md (already present)`);
13695
13903
  return;
@@ -13708,7 +13916,7 @@ ZAM is available in this repository. Select the \`zam\` skill through \`/skills\
13708
13916
  logInstructionAction(action, "AGENTS.md", Boolean(opts.dryRun));
13709
13917
  return;
13710
13918
  }
13711
- const name = basename4(cwd);
13919
+ const name = basename5(cwd);
13712
13920
  const content = `# ZAM Personal Kernel - ${name}
13713
13921
 
13714
13922
  This is a ZAM personal instance. ZAM builds lasting skills through spaced
@@ -13739,12 +13947,12 @@ Codex discovers repository skills under \`.agents/skills/\`. Run
13739
13947
  if (opts.dryRun) {
13740
13948
  console.log(` would write AGENTS.md`);
13741
13949
  } else {
13742
- writeFileSync8(dest, content, "utf8");
13950
+ writeFileSync9(dest, content, "utf8");
13743
13951
  console.log(` write AGENTS.md`);
13744
13952
  }
13745
13953
  }
13746
13954
  function writeCopilotInstructions(cwd = process.cwd(), opts = {}) {
13747
- const dest = join15(cwd, ".github", "copilot-instructions.md");
13955
+ const dest = join18(cwd, ".github", "copilot-instructions.md");
13748
13956
  const action = upsertMarkedBlock(
13749
13957
  dest,
13750
13958
  `## ZAM learning sessions
@@ -13784,134 +13992,14 @@ async function resolveUser(opts, db, resolveOpts) {
13784
13992
  process.exit(1);
13785
13993
  }
13786
13994
 
13787
- // src/cli/workspaces/active.ts
13788
- init_kernel();
13789
- import { existsSync as existsSync16, mkdirSync as mkdirSync10 } from "fs";
13790
- import { homedir as homedir10 } from "os";
13791
- import { basename as basename5, join as join16, resolve as resolve3 } from "path";
13792
- var LEGACY_WORKSPACE_DIR_KEY = "personal.workspace_dir";
13793
- var DEFAULT_WORKSPACE_ID = "personal";
13794
- function defaultWorkspaceDir() {
13795
- return join16(homedir10(), "Documents", "zam");
13796
- }
13797
- function normalizeWorkspacePath(path) {
13798
- const resolved = resolve3(path);
13799
- return process.platform === "win32" ? resolved.toLowerCase() : resolved;
13800
- }
13801
- function sameWorkspacePath(left, right) {
13802
- return normalizeWorkspacePath(left) === normalizeWorkspacePath(right);
13803
- }
13804
- function labelFromPath(path) {
13805
- return basename5(path) || "ZAM";
13806
- }
13807
- function workspaceIdFromPath(dir) {
13808
- const base = basename5(dir).toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "");
13809
- const prefix = base || "workspace";
13810
- const existing = new Set(getConfiguredWorkspaces().map((item) => item.id));
13811
- if (!existing.has(prefix)) return prefix;
13812
- let index = 2;
13813
- while (existing.has(`${prefix}-${index}`)) index++;
13814
- return `${prefix}-${index}`;
13815
- }
13816
- function findWorkspaceByPath(dir) {
13817
- return getConfiguredWorkspaces().find(
13818
- (workspace) => sameWorkspacePath(workspace.path, dir)
13819
- );
13820
- }
13821
- async function clearLegacyWorkspaceDir(db) {
13822
- await deleteSetting(db, LEGACY_WORKSPACE_DIR_KEY);
13823
- }
13824
- async function migrateLegacyWorkspaceDir(db) {
13825
- const legacyDir = await getSetting(db, LEGACY_WORKSPACE_DIR_KEY);
13826
- if (!legacyDir) return void 0;
13827
- const path = resolve3(legacyDir);
13828
- const existing = findWorkspaceByPath(path);
13829
- const migrated = existing ?? {
13830
- id: getConfiguredWorkspaces().some(
13831
- (workspace) => workspace.id === DEFAULT_WORKSPACE_ID
13832
- ) ? workspaceIdFromPath(path) : DEFAULT_WORKSPACE_ID,
13833
- label: labelFromPath(path),
13834
- kind: "personal",
13835
- path
13836
- };
13837
- if (!existing) {
13838
- upsertConfiguredWorkspace(migrated);
13839
- }
13840
- if (!getActiveWorkspace()) {
13841
- setActiveWorkspaceId(migrated.id);
13842
- }
13843
- await clearLegacyWorkspaceDir(db);
13844
- return migrated;
13845
- }
13846
- async function ensureActiveWorkspace(db) {
13847
- await migrateLegacyWorkspaceDir(db);
13848
- const active = getActiveWorkspace();
13849
- if (active) {
13850
- mkdirSync10(active.path, { recursive: true });
13851
- return active;
13852
- }
13853
- const configured = getConfiguredWorkspaces()[0];
13854
- if (configured) {
13855
- setActiveWorkspaceId(configured.id);
13856
- mkdirSync10(configured.path, { recursive: true });
13857
- return configured;
13858
- }
13859
- const workspace = {
13860
- id: DEFAULT_WORKSPACE_ID,
13861
- label: "Personal",
13862
- kind: "personal",
13863
- path: defaultWorkspaceDir()
13864
- };
13865
- mkdirSync10(workspace.path, { recursive: true });
13866
- upsertConfiguredWorkspace(workspace);
13867
- setActiveWorkspaceId(workspace.id);
13868
- await clearLegacyWorkspaceDir(db);
13869
- return workspace;
13870
- }
13871
- async function activateWorkspace(db, workspace) {
13872
- upsertConfiguredWorkspace(workspace);
13873
- setActiveWorkspaceId(workspace.id);
13874
- await clearLegacyWorkspaceDir(db);
13875
- return workspace;
13876
- }
13877
- async function activateWorkspacePath(db, dir, opts = {}) {
13878
- await migrateLegacyWorkspaceDir(db);
13879
- const path = resolve3(dir);
13880
- const existing = opts.id ? void 0 : findWorkspaceByPath(path);
13881
- if (existing) {
13882
- setActiveWorkspaceId(existing.id);
13883
- await clearLegacyWorkspaceDir(db);
13884
- return existing;
13885
- }
13886
- const workspace = {
13887
- id: opts.id || workspaceIdFromPath(path),
13888
- label: opts.label || labelFromPath(path),
13889
- kind: opts.kind || "personal",
13890
- path
13891
- };
13892
- return activateWorkspace(db, workspace);
13893
- }
13894
- async function removeWorkspaceAndResolveActive(db, id) {
13895
- removeConfiguredWorkspace(id);
13896
- await clearLegacyWorkspaceDir(db);
13897
- const activeWorkspace = await ensureActiveWorkspace(db);
13898
- return {
13899
- activeWorkspace,
13900
- workspaces: getConfiguredWorkspaces()
13901
- };
13902
- }
13903
- function existingWorkspaceDirOrHome(workspace) {
13904
- return existsSync16(workspace.path) ? workspace.path : homedir10();
13905
- }
13906
-
13907
13995
  // src/cli/workspaces/backup.ts
13908
- import { mkdirSync as mkdirSync11 } from "fs";
13909
- import { join as join17 } from "path";
13996
+ import { mkdirSync as mkdirSync12 } from "fs";
13997
+ import { join as join19 } from "path";
13910
13998
  async function backupDatabaseTo(db, targetDir) {
13911
- const backupDir = join17(targetDir, "zam-backups");
13912
- mkdirSync11(backupDir, { recursive: true });
13999
+ const backupDir = join19(targetDir, "zam-backups");
14000
+ mkdirSync12(backupDir, { recursive: true });
13913
14001
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
13914
- const dest = join17(backupDir, `zam-${stamp}.db`);
14002
+ const dest = join19(backupDir, `zam-${stamp}.db`);
13915
14003
  await db.exec(`VACUUM INTO '${dest.replace(/'/g, "''")}'`);
13916
14004
  return dest;
13917
14005
  }
@@ -14005,6 +14093,35 @@ bridgeCommand.command("backup-db").description("Back up the local database into
14005
14093
  jsonOut2({ ok: true, path });
14006
14094
  });
14007
14095
  });
14096
+ bridgeCommand.command("backup-create").description(
14097
+ "Create a portable SQL snapshot backup (kernel exportSnapshot), distinct from backup-db's VACUUM copy (JSON)"
14098
+ ).option(
14099
+ "--dir <path>",
14100
+ "Target directory (default: workspace dir, else ~/Documents/zam)"
14101
+ ).action(async (opts) => {
14102
+ await withDb2(async (db) => {
14103
+ try {
14104
+ const result = await backupCreate(db, { dir: opts.dir });
14105
+ jsonOut2(result);
14106
+ } catch (err) {
14107
+ jsonError(err.message);
14108
+ }
14109
+ });
14110
+ });
14111
+ bridgeCommand.command("update-check").description("Check whether a newer ZAM release is available (JSON)").option(
14112
+ "--latest <version>",
14113
+ "Compare against this version instead of fetching (offline/deterministic checks)"
14114
+ ).option("--channel <channel>", "Override the detected install channel").action(async (opts) => {
14115
+ try {
14116
+ const result = await updateCheck({
14117
+ latest: opts.latest,
14118
+ channel: opts.channel
14119
+ });
14120
+ jsonOut2(result);
14121
+ } catch (err) {
14122
+ jsonError(err.message);
14123
+ }
14124
+ });
14008
14125
  bridgeCommand.command("workspace-info").description("Report the workspace dir, its default, and the data dir (JSON)").action(async () => {
14009
14126
  await withDb2(async (db) => {
14010
14127
  const activeWorkspace = await ensureActiveWorkspace(db);
@@ -14013,7 +14130,7 @@ bridgeCommand.command("workspace-info").description("Report the workspace dir, i
14013
14130
  activeWorkspace,
14014
14131
  workspaceDir: activeWorkspace.path,
14015
14132
  defaultWorkspaceDir: defaultWorkspaceDir(),
14016
- dataDir: join18(homedir11(), ".zam")
14133
+ dataDir: join20(homedir11(), ".zam")
14017
14134
  });
14018
14135
  });
14019
14136
  });
@@ -14056,7 +14173,7 @@ bridgeCommand.command("workspace-list").description("List configured ZAM workspa
14056
14173
  activeWorkspace,
14057
14174
  workspaceDir: activeWorkspace.path,
14058
14175
  defaultWorkspaceDir: defaultWorkspaceDir(),
14059
- dataDir: join18(homedir11(), ".zam"),
14176
+ dataDir: join20(homedir11(), ".zam"),
14060
14177
  linkHealth: buildWorkspaceLinkHealth(workspaces)
14061
14178
  });
14062
14179
  });
@@ -14583,7 +14700,7 @@ bridgeCommand.command("discover-skills").description(
14583
14700
  "20"
14584
14701
  ).action(async (opts) => {
14585
14702
  try {
14586
- const monitorDir = join18(homedir11(), ".zam", "monitor");
14703
+ const monitorDir = join20(homedir11(), ".zam", "monitor");
14587
14704
  let files;
14588
14705
  try {
14589
14706
  files = readdirSync2(monitorDir).filter((f) => f.endsWith(".jsonl"));
@@ -14596,7 +14713,7 @@ bridgeCommand.command("discover-skills").description(
14596
14713
  return;
14597
14714
  }
14598
14715
  const limit = Number(opts.limit);
14599
- const sorted = files.map((f) => ({ name: f, path: join18(monitorDir, f) })).sort((a, b) => b.name.localeCompare(a.name)).slice(0, limit);
14716
+ const sorted = files.map((f) => ({ name: f, path: join20(monitorDir, f) })).sort((a, b) => b.name.localeCompare(a.name)).slice(0, limit);
14600
14717
  const sessionCommands = /* @__PURE__ */ new Map();
14601
14718
  for (const file of sorted) {
14602
14719
  const sessionId = file.name.replace(".jsonl", "");
@@ -15098,7 +15215,7 @@ bridgeCommand.command("capture-ui").description("Capture a screenshot for agent-
15098
15215
  return;
15099
15216
  }
15100
15217
  }
15101
- const outputPath = opts.image ?? opts.output ?? join18(tmpdir3(), `zam-capture-${randomBytes2(4).toString("hex")}.png`);
15218
+ const outputPath = opts.image ?? opts.output ?? join20(tmpdir3(), `zam-capture-${randomBytes2(4).toString("hex")}.png`);
15102
15219
  const captureResult = isProvided ? { method: "provided", target: null } : captureScreenshot(outputPath, opts.hwnd, opts.processName);
15103
15220
  if (!isProvided) {
15104
15221
  const post = decidePostCapture(policy, {
@@ -15126,7 +15243,7 @@ bridgeCommand.command("capture-ui").description("Capture a screenshot for agent-
15126
15243
  return;
15127
15244
  }
15128
15245
  }
15129
- const imageBytes = readFileSync13(outputPath);
15246
+ const imageBytes = readFileSync14(outputPath);
15130
15247
  const base64 = imageBytes.toString("base64");
15131
15248
  jsonOut2({
15132
15249
  sessionId: opts.session ?? null,
@@ -15153,10 +15270,10 @@ bridgeCommand.command("start-recording").description("Start screen recording in
15153
15270
  return;
15154
15271
  }
15155
15272
  const sessionId = opts.session;
15156
- const statePath = join18(tmpdir3(), `zam-recording-${sessionId}.json`);
15273
+ const statePath = join20(tmpdir3(), `zam-recording-${sessionId}.json`);
15157
15274
  const defaultExt = platform === "win32" ? ".mkv" : ".mov";
15158
- const outputPath = opts.output ?? join18(tmpdir3(), `zam-recording-${sessionId}${defaultExt}`);
15159
- const { existsSync: existsSync26, writeFileSync: writeFileSync13, openSync, closeSync } = await import("fs");
15275
+ const outputPath = opts.output ?? join20(tmpdir3(), `zam-recording-${sessionId}${defaultExt}`);
15276
+ const { existsSync: existsSync26, writeFileSync: writeFileSync14, openSync, closeSync } = await import("fs");
15160
15277
  if (existsSync26(statePath)) {
15161
15278
  jsonOut2({
15162
15279
  sessionId,
@@ -15165,7 +15282,7 @@ bridgeCommand.command("start-recording").description("Start screen recording in
15165
15282
  });
15166
15283
  return;
15167
15284
  }
15168
- const logPath = join18(tmpdir3(), `zam-recording-${sessionId}.log`);
15285
+ const logPath = join20(tmpdir3(), `zam-recording-${sessionId}.log`);
15169
15286
  let logFd;
15170
15287
  try {
15171
15288
  logFd = openSync(logPath, "w");
@@ -15211,7 +15328,7 @@ bridgeCommand.command("start-recording").description("Start screen recording in
15211
15328
  }
15212
15329
  child.unref();
15213
15330
  if (child.pid) {
15214
- writeFileSync13(
15331
+ writeFileSync14(
15215
15332
  statePath,
15216
15333
  JSON.stringify({
15217
15334
  pid: child.pid,
@@ -15247,8 +15364,8 @@ bridgeCommand.command("stop-recording").description(
15247
15364
  return;
15248
15365
  }
15249
15366
  const sessionId = opts.session;
15250
- const statePath = join18(tmpdir3(), `zam-recording-${sessionId}.json`);
15251
- const { existsSync: existsSync26, readFileSync: readFileSync18, rmSync: rmSync4 } = await import("fs");
15367
+ const statePath = join20(tmpdir3(), `zam-recording-${sessionId}.json`);
15368
+ const { existsSync: existsSync26, readFileSync: readFileSync19, rmSync: rmSync4 } = await import("fs");
15252
15369
  if (!existsSync26(statePath)) {
15253
15370
  jsonOut2({
15254
15371
  sessionId,
@@ -15257,7 +15374,7 @@ bridgeCommand.command("stop-recording").description(
15257
15374
  });
15258
15375
  return;
15259
15376
  }
15260
- const state = JSON.parse(readFileSync18(statePath, "utf8"));
15377
+ const state = JSON.parse(readFileSync19(statePath, "utf8"));
15261
15378
  const { pid, outputPath } = state;
15262
15379
  try {
15263
15380
  process.kill(pid, "SIGINT");
@@ -16645,6 +16762,79 @@ bridgeCommand.command("set-active-knowledge-context").description("Set the activ
16645
16762
  jsonOut2({ success: true, activeContext: context.name });
16646
16763
  });
16647
16764
  });
16765
+ var commanderConfiguredForJsonExecution = false;
16766
+ function ensureCommanderThrowsInsteadOfExiting() {
16767
+ if (commanderConfiguredForJsonExecution) return;
16768
+ bridgeCommand.exitOverride();
16769
+ for (const sub of bridgeCommand.commands) {
16770
+ sub.exitOverride();
16771
+ }
16772
+ commanderConfiguredForJsonExecution = true;
16773
+ }
16774
+ async function runBridgeCommandOnce(cmd, args) {
16775
+ ensureCommanderThrowsInsteadOfExiting();
16776
+ let outputBuffer = "";
16777
+ const captureOutput = (str) => {
16778
+ outputBuffer += str;
16779
+ };
16780
+ bridgeCommand.configureOutput({
16781
+ writeOut: captureOutput,
16782
+ writeErr: captureOutput
16783
+ });
16784
+ for (const sub of bridgeCommand.commands) {
16785
+ sub.configureOutput({ writeOut: captureOutput, writeErr: captureOutput });
16786
+ }
16787
+ const originalLog = console.log;
16788
+ const originalError = console.error;
16789
+ console.log = (...logArgs) => {
16790
+ outputBuffer += `${logArgs.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")}
16791
+ `;
16792
+ };
16793
+ console.error = (...logArgs) => {
16794
+ outputBuffer += `${logArgs.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")}
16795
+ `;
16796
+ };
16797
+ const wasServeMode = isServeMode;
16798
+ isServeMode = true;
16799
+ try {
16800
+ try {
16801
+ await bridgeCommand.parseAsync(["node", "bridge", cmd, ...args]);
16802
+ } catch (err) {
16803
+ let message;
16804
+ if (err instanceof Error && err.message.startsWith('{"error":')) {
16805
+ try {
16806
+ message = JSON.parse(err.message).error;
16807
+ } catch {
16808
+ message = err.message;
16809
+ }
16810
+ } else if (err?.code?.startsWith("commander.")) {
16811
+ message = outputBuffer.trim() || err.message;
16812
+ } else {
16813
+ message = err.message || String(err);
16814
+ }
16815
+ throw new Error(message);
16816
+ }
16817
+ } finally {
16818
+ console.log = originalLog;
16819
+ console.error = originalError;
16820
+ isServeMode = wasServeMode;
16821
+ }
16822
+ const trimmed = outputBuffer.trim();
16823
+ try {
16824
+ return JSON.parse(trimmed);
16825
+ } catch {
16826
+ return trimmed;
16827
+ }
16828
+ }
16829
+ var bridgeExecutionQueue = Promise.resolve();
16830
+ function executeBridgeCommandJson(cmd, args) {
16831
+ const run = bridgeExecutionQueue.then(() => runBridgeCommandOnce(cmd, args));
16832
+ bridgeExecutionQueue = run.then(
16833
+ () => void 0,
16834
+ () => void 0
16835
+ );
16836
+ return run;
16837
+ }
16648
16838
  bridgeCommand.command("serve").description("Start the persistent JSON-RPC stdin/stdout server").option("--stdin", "Use stdin/stdout for communication").action(async (_opts) => {
16649
16839
  isServeMode = true;
16650
16840
  const {
@@ -16667,25 +16857,7 @@ bridgeCommand.command("serve").description("Start the persistent JSON-RPC stdin/
16667
16857
  logDiag(
16668
16858
  `serve start | homedir=${nodeOs.homedir()} | USERPROFILE=${process.env.USERPROFILE ?? ""} | HOME=${process.env.HOME ?? ""} | cwd=${process.cwd()}`
16669
16859
  );
16670
- bridgeCommand.exitOverride();
16671
- for (const cmd of bridgeCommand.commands) {
16672
- cmd.exitOverride();
16673
- }
16674
- let outputBuffer = "";
16675
- const outputOpts = {
16676
- writeOut: (str) => {
16677
- outputBuffer += str;
16678
- },
16679
- writeErr: (str) => {
16680
- outputBuffer += str;
16681
- }
16682
- };
16683
- bridgeCommand.configureOutput(outputOpts);
16684
- for (const cmd of bridgeCommand.commands) {
16685
- cmd.configureOutput(outputOpts);
16686
- }
16687
16860
  const processRequest = async (line) => {
16688
- outputBuffer = "";
16689
16861
  let requestId = null;
16690
16862
  try {
16691
16863
  const req = JSON.parse(line);
@@ -16705,49 +16877,15 @@ bridgeCommand.command("serve").description("Start the persistent JSON-RPC stdin/
16705
16877
  error: "Missing 'cmd' field"
16706
16878
  });
16707
16879
  }
16708
- const originalLog = console.log;
16709
- const originalError = console.error;
16710
- console.log = (...logArgs) => {
16711
- outputBuffer += `${logArgs.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")}
16712
- `;
16713
- };
16714
- console.error = (...logArgs) => {
16715
- outputBuffer += `${logArgs.map((a) => typeof a === "object" ? JSON.stringify(a) : String(a)).join(" ")}
16716
- `;
16717
- };
16718
16880
  try {
16719
- await bridgeCommand.parseAsync(["node", "bridge", cmd, ...args]);
16881
+ const result = await executeBridgeCommandJson(cmd, args);
16882
+ return JSON.stringify({ id: requestId, result });
16720
16883
  } catch (err) {
16721
- if (err instanceof Error && err.message.startsWith('{"error":')) {
16722
- try {
16723
- const parsed = JSON.parse(err.message);
16724
- return JSON.stringify({ id: requestId, error: parsed.error });
16725
- } catch {
16726
- return JSON.stringify({ id: requestId, error: err.message });
16727
- }
16728
- }
16729
- if (err.code?.startsWith("commander.")) {
16730
- return JSON.stringify({
16731
- id: requestId,
16732
- error: outputBuffer.trim() || err.message
16733
- });
16734
- }
16735
16884
  return JSON.stringify({
16736
16885
  id: requestId,
16737
16886
  error: err.message || String(err)
16738
16887
  });
16739
- } finally {
16740
- console.log = originalLog;
16741
- console.error = originalError;
16742
- }
16743
- let result;
16744
- const trimmed = outputBuffer.trim();
16745
- try {
16746
- result = JSON.parse(trimmed);
16747
- } catch {
16748
- result = trimmed;
16749
16888
  }
16750
- return JSON.stringify({ id: requestId, result });
16751
16889
  } catch (err) {
16752
16890
  return JSON.stringify({
16753
16891
  id: requestId,
@@ -18052,26 +18190,26 @@ var doctorCommand = new Command5("doctor").description(
18052
18190
  // src/cli/commands/git-sync.ts
18053
18191
  init_kernel();
18054
18192
  import { execSync as execSync5 } from "child_process";
18055
- import { chmodSync as chmodSync2, existsSync as existsSync18, writeFileSync as writeFileSync9 } from "fs";
18056
- import { join as join19 } from "path";
18193
+ import { chmodSync as chmodSync2, existsSync as existsSync18, writeFileSync as writeFileSync10 } from "fs";
18194
+ import { join as join21 } from "path";
18057
18195
  import { Command as Command6 } from "commander";
18058
18196
  function installHook2() {
18059
- const gitDir = join19(process.cwd(), ".git");
18197
+ const gitDir = join21(process.cwd(), ".git");
18060
18198
  if (!existsSync18(gitDir)) {
18061
18199
  console.error(
18062
18200
  "Error: Current directory is not the root of a Git repository."
18063
18201
  );
18064
18202
  process.exit(1);
18065
18203
  }
18066
- const hooksDir = join19(gitDir, "hooks");
18067
- const hookPath = join19(hooksDir, "post-commit");
18204
+ const hooksDir = join21(gitDir, "hooks");
18205
+ const hookPath = join21(hooksDir, "post-commit");
18068
18206
  const hookContent = `#!/bin/sh
18069
18207
  # ZAM Spaced Repetition Auto-Stale Hook
18070
18208
  # Triggered automatically on git commits to decay modified concept cards.
18071
18209
  zam git-sync --commit HEAD --quiet
18072
18210
  `;
18073
18211
  try {
18074
- writeFileSync9(hookPath, hookContent, { encoding: "utf-8", flag: "w" });
18212
+ writeFileSync10(hookPath, hookContent, { encoding: "utf-8", flag: "w" });
18075
18213
  try {
18076
18214
  chmodSync2(hookPath, "755");
18077
18215
  } catch (_e) {
@@ -18174,7 +18312,7 @@ ZAM Auto-Stale Complete: Scanned ${changedFiles.length} file(s).`
18174
18312
 
18175
18313
  // src/cli/commands/goal.ts
18176
18314
  init_kernel();
18177
- import { existsSync as existsSync19, mkdirSync as mkdirSync12 } from "fs";
18315
+ import { existsSync as existsSync19, mkdirSync as mkdirSync13 } from "fs";
18178
18316
  import { resolve as resolve5 } from "path";
18179
18317
  import { input as input2 } from "@inquirer/prompts";
18180
18318
  import { Command as Command7 } from "commander";
@@ -18300,7 +18438,7 @@ ${"\u2500".repeat(50)}`);
18300
18438
  goalCommand.command("create").description("Create a new goal").option("--slug <slug>", "Goal slug (used as filename)").option("--title <title>", "Goal title").option("--parent <slug>", "Parent goal slug").option("--description <text>", "Goal description").option("--json", "Output as JSON").action(async (opts) => {
18301
18439
  const goalsDir = await resolveGoalsDir();
18302
18440
  if (!existsSync19(goalsDir)) {
18303
- mkdirSync12(goalsDir, { recursive: true });
18441
+ mkdirSync13(goalsDir, { recursive: true });
18304
18442
  }
18305
18443
  let slug = opts.slug;
18306
18444
  let title = opts.title;
@@ -18360,9 +18498,9 @@ goalCommand.command("status <slug> <status>").description("Update a goal's statu
18360
18498
 
18361
18499
  // src/cli/commands/init.ts
18362
18500
  init_kernel();
18363
- import { existsSync as existsSync20, mkdirSync as mkdirSync13, writeFileSync as writeFileSync10 } from "fs";
18501
+ import { existsSync as existsSync20, mkdirSync as mkdirSync14, writeFileSync as writeFileSync11 } from "fs";
18364
18502
  import { homedir as homedir12 } from "os";
18365
- import { join as join20, resolve as resolve6 } from "path";
18503
+ import { join as join22, resolve as resolve6 } from "path";
18366
18504
  import { confirm, input as input3 } from "@inquirer/prompts";
18367
18505
  import { Command as Command8 } from "commander";
18368
18506
  var HOME2 = homedir12();
@@ -18370,12 +18508,12 @@ function printLine(char = "\u2550", len = 60, color = "\x1B[36m") {
18370
18508
  console.log(`${color}${char.repeat(len)}\x1B[0m`);
18371
18509
  }
18372
18510
  function bootstrapSandboxWorkspace(workspaceDir) {
18373
- mkdirSync13(join20(workspaceDir, "beliefs"), { recursive: true });
18374
- mkdirSync13(join20(workspaceDir, "goals"), { recursive: true });
18375
- mkdirSync13(join20(workspaceDir, "skills"), { recursive: true });
18376
- const worldviewFile = join20(workspaceDir, "beliefs", "worldview.md");
18511
+ mkdirSync14(join22(workspaceDir, "beliefs"), { recursive: true });
18512
+ mkdirSync14(join22(workspaceDir, "goals"), { recursive: true });
18513
+ mkdirSync14(join22(workspaceDir, "skills"), { recursive: true });
18514
+ const worldviewFile = join22(workspaceDir, "beliefs", "worldview.md");
18377
18515
  if (!existsSync20(worldviewFile)) {
18378
- writeFileSync10(
18516
+ writeFileSync11(
18379
18517
  worldviewFile,
18380
18518
  `# Personal Worldview
18381
18519
 
@@ -18387,9 +18525,9 @@ Here, I declare the core concepts and principles I want to master.
18387
18525
  "utf8"
18388
18526
  );
18389
18527
  }
18390
- const goalsFile = join20(workspaceDir, "goals", "goals.md");
18528
+ const goalsFile = join22(workspaceDir, "goals", "goals.md");
18391
18529
  if (!existsSync20(goalsFile)) {
18392
- writeFileSync10(
18530
+ writeFileSync11(
18393
18531
  goalsFile,
18394
18532
  `# Personal Goals
18395
18533
 
@@ -18411,7 +18549,7 @@ var initCommand = new Command8("init").description("Launch the guided interactiv
18411
18549
  );
18412
18550
  printLine();
18413
18551
  console.log("\n\x1B[1m[1/5] Setting up Local Workspace Sandbox\x1B[0m");
18414
- const defaultWorkspace = join20(HOME2, "Documents", "zam");
18552
+ const defaultWorkspace = join22(HOME2, "Documents", "zam");
18415
18553
  const workspacePath = resolve6(
18416
18554
  await input3({
18417
18555
  message: "Choose your ZAM workspace directory:",
@@ -19613,7 +19751,7 @@ observerCommand.command("revoke <process>").description("Remove a process from o
19613
19751
 
19614
19752
  // src/cli/commands/profile.ts
19615
19753
  init_kernel();
19616
- import { dirname as dirname7, resolve as resolve7 } from "path";
19754
+ import { dirname as dirname8, resolve as resolve7 } from "path";
19617
19755
  import { Command as Command13 } from "commander";
19618
19756
  var C2 = {
19619
19757
  reset: "\x1B[0m",
@@ -19654,7 +19792,7 @@ var profileCommand = new Command13("profile").description("Show or change this m
19654
19792
  mode: getInstallMode(),
19655
19793
  personalDir,
19656
19794
  syncProvider: detectSyncProvider(personalDir),
19657
- dataDir: dirname7(dbPath),
19795
+ dataDir: dirname8(dbPath),
19658
19796
  dbPath
19659
19797
  };
19660
19798
  if (opts.json) {
@@ -20043,7 +20181,7 @@ ${"\u2550".repeat(50)}`);
20043
20181
 
20044
20182
  // src/cli/commands/session.ts
20045
20183
  init_kernel();
20046
- import { readFileSync as readFileSync14 } from "fs";
20184
+ import { readFileSync as readFileSync15 } from "fs";
20047
20185
  import { input as input6, select as select2 } from "@inquirer/prompts";
20048
20186
  import { Command as Command16 } from "commander";
20049
20187
  var sessionCommand = new Command16("session").description(
@@ -20234,7 +20372,7 @@ function loadPatternFile(path) {
20234
20372
  if (!path) return [];
20235
20373
  let parsed;
20236
20374
  try {
20237
- parsed = JSON.parse(readFileSync14(path, "utf-8"));
20375
+ parsed = JSON.parse(readFileSync15(path, "utf-8"));
20238
20376
  } catch (err) {
20239
20377
  throw new Error(
20240
20378
  `Cannot read synthesis patterns from ${path}: ${err.message}`
@@ -20787,8 +20925,8 @@ skillCommand.command("add").description("Register a new agent skill").requiredOp
20787
20925
 
20788
20926
  // src/cli/commands/snapshot.ts
20789
20927
  init_kernel();
20790
- import { existsSync as existsSync22, mkdirSync as mkdirSync14, readFileSync as readFileSync15, writeFileSync as writeFileSync11 } from "fs";
20791
- import { dirname as dirname8, join as join21 } from "path";
20928
+ import { existsSync as existsSync22, mkdirSync as mkdirSync15, readFileSync as readFileSync16, writeFileSync as writeFileSync12 } from "fs";
20929
+ import { dirname as dirname9, join as join23 } from "path";
20792
20930
  import { Command as Command20 } from "commander";
20793
20931
  function defaultOutName() {
20794
20932
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d+Z$/, "").replace(/:/g, "-");
@@ -20817,12 +20955,12 @@ var exportCmd = new Command20("export").description("Write a portable SQL-text s
20817
20955
  process.stdout.write(snapshot);
20818
20956
  return;
20819
20957
  }
20820
- const out = opts.out ?? join21(personalDir, "snapshots", defaultOutName());
20821
- const dir = dirname8(out);
20958
+ const out = opts.out ?? join23(personalDir, "snapshots", defaultOutName());
20959
+ const dir = dirname9(out);
20822
20960
  if (dir && dir !== "." && !existsSync22(dir)) {
20823
- mkdirSync14(dir, { recursive: true });
20961
+ mkdirSync15(dir, { recursive: true });
20824
20962
  }
20825
- writeFileSync11(out, snapshot, "utf-8");
20963
+ writeFileSync12(out, snapshot, "utf-8");
20826
20964
  console.log(`Snapshot written: ${out}`);
20827
20965
  console.log(
20828
20966
  ` ${total} row(s)${nonEmpty.length ? ` \u2014 ${nonEmpty.join(", ")}` : ""}`
@@ -20840,7 +20978,7 @@ var importCmd = new Command20("import").description("Restore a snapshot into the
20840
20978
  console.error(`Error: Snapshot file not found: ${file}`);
20841
20979
  process.exit(1);
20842
20980
  }
20843
- const snapshot = readFileSync15(file, "utf-8");
20981
+ const snapshot = readFileSync16(file, "utf-8");
20844
20982
  db = await openDatabaseWithSync({ initialize: true });
20845
20983
  const result = await importSnapshot(db, snapshot, { force: opts.force });
20846
20984
  await db.close();
@@ -20862,7 +21000,7 @@ var verifyCmd = new Command20("verify").description("Check a snapshot's manifest
20862
21000
  console.error(`Error: Snapshot file not found: ${file}`);
20863
21001
  process.exit(1);
20864
21002
  }
20865
- const manifest = verifySnapshot(readFileSync15(file, "utf-8"));
21003
+ const manifest = verifySnapshot(readFileSync16(file, "utf-8"));
20866
21004
  const { total, nonEmpty } = summarize(manifest.tables);
20867
21005
  console.log(`Valid snapshot (format v${manifest.version})`);
20868
21006
  console.log(` created: ${manifest.createdAt}`);
@@ -21413,8 +21551,8 @@ init_kernel();
21413
21551
  import { spawn as spawn3, spawnSync } from "child_process";
21414
21552
  import { existsSync as existsSync23 } from "fs";
21415
21553
  import { homedir as homedir13 } from "os";
21416
- import { dirname as dirname9, join as join22 } from "path";
21417
- import { fileURLToPath as fileURLToPath3 } from "url";
21554
+ import { dirname as dirname10, join as join24 } from "path";
21555
+ import { fileURLToPath as fileURLToPath4 } from "url";
21418
21556
  import { Command as Command23 } from "commander";
21419
21557
  var C3 = {
21420
21558
  reset: "\x1B[0m",
@@ -21425,14 +21563,14 @@ var C3 = {
21425
21563
  dim: "\x1B[2m"
21426
21564
  };
21427
21565
  function findDesktopDir() {
21428
- const starts = [process.cwd(), dirname9(fileURLToPath3(import.meta.url))];
21566
+ const starts = [process.cwd(), dirname10(fileURLToPath4(import.meta.url))];
21429
21567
  for (const start of starts) {
21430
21568
  let dir = start;
21431
21569
  for (let i = 0; i < 10; i++) {
21432
- if (existsSync23(join22(dir, "desktop", "src-tauri", "tauri.conf.json"))) {
21433
- return join22(dir, "desktop");
21570
+ if (existsSync23(join24(dir, "desktop", "src-tauri", "tauri.conf.json"))) {
21571
+ return join24(dir, "desktop");
21434
21572
  }
21435
- const parent = dirname9(dir);
21573
+ const parent = dirname10(dir);
21436
21574
  if (parent === dir) break;
21437
21575
  dir = parent;
21438
21576
  }
@@ -21440,18 +21578,18 @@ function findDesktopDir() {
21440
21578
  return null;
21441
21579
  }
21442
21580
  function findBuiltApp(desktopDir) {
21443
- const releaseDir = join22(desktopDir, "src-tauri", "target", "release");
21581
+ const releaseDir = join24(desktopDir, "src-tauri", "target", "release");
21444
21582
  if (process.platform === "win32") {
21445
21583
  for (const name of ["ZAM.exe", "zam.exe", "zam-desktop.exe"]) {
21446
- const p = join22(releaseDir, name);
21584
+ const p = join24(releaseDir, name);
21447
21585
  if (existsSync23(p)) return p;
21448
21586
  }
21449
21587
  } else if (process.platform === "darwin") {
21450
- const app = join22(releaseDir, "bundle", "macos", "ZAM.app");
21588
+ const app = join24(releaseDir, "bundle", "macos", "ZAM.app");
21451
21589
  if (existsSync23(app)) return app;
21452
21590
  } else {
21453
21591
  for (const name of ["zam", "ZAM", "zam-desktop"]) {
21454
- const p = join22(releaseDir, name);
21592
+ const p = join24(releaseDir, name);
21455
21593
  if (existsSync23(p)) return p;
21456
21594
  }
21457
21595
  }
@@ -21459,10 +21597,10 @@ function findBuiltApp(desktopDir) {
21459
21597
  }
21460
21598
  function findInstalledApp() {
21461
21599
  const candidates = process.platform === "win32" ? [
21462
- process.env.LOCALAPPDATA && join22(process.env.LOCALAPPDATA, "Programs", "ZAM", "ZAM.exe"),
21463
- process.env.ProgramFiles && join22(process.env.ProgramFiles, "ZAM", "ZAM.exe"),
21464
- process.env["ProgramFiles(x86)"] && join22(process.env["ProgramFiles(x86)"], "ZAM", "ZAM.exe")
21465
- ] : process.platform === "darwin" ? ["/Applications/ZAM.app", join22(homedir13(), "Applications", "ZAM.app")] : ["/opt/ZAM/zam", "/usr/bin/zam-desktop"];
21600
+ process.env.LOCALAPPDATA && join24(process.env.LOCALAPPDATA, "Programs", "ZAM", "ZAM.exe"),
21601
+ process.env.ProgramFiles && join24(process.env.ProgramFiles, "ZAM", "ZAM.exe"),
21602
+ process.env["ProgramFiles(x86)"] && join24(process.env["ProgramFiles(x86)"], "ZAM", "ZAM.exe")
21603
+ ] : process.platform === "darwin" ? ["/Applications/ZAM.app", join24(homedir13(), "Applications", "ZAM.app")] : ["/opt/ZAM/zam", "/usr/bin/zam-desktop"];
21466
21604
  return candidates.find((candidate) => candidate && existsSync23(candidate)) || null;
21467
21605
  }
21468
21606
  function runNpm(args, opts) {
@@ -21474,7 +21612,7 @@ function runNpm(args, opts) {
21474
21612
  return res.status ?? 1;
21475
21613
  }
21476
21614
  function ensureDesktopDeps(desktopDir) {
21477
- if (existsSync23(join22(desktopDir, "node_modules"))) return true;
21615
+ if (existsSync23(join24(desktopDir, "node_modules"))) return true;
21478
21616
  console.log(
21479
21617
  `${C3.cyan}Installing desktop dependencies (one-time)...${C3.reset}`
21480
21618
  );
@@ -21500,7 +21638,7 @@ function requireRust() {
21500
21638
  function hasMsvcBuildTools() {
21501
21639
  if (process.platform !== "win32") return true;
21502
21640
  const pf86 = process.env["ProgramFiles(x86)"] || "C:\\Program Files (x86)";
21503
- const vswhere = join22(
21641
+ const vswhere = join24(
21504
21642
  pf86,
21505
21643
  "Microsoft Visual Studio",
21506
21644
  "Installer",
@@ -21538,7 +21676,7 @@ function requireMsvcOnWindows() {
21538
21676
  return false;
21539
21677
  }
21540
21678
  function warnIfCliMissing(repoRoot) {
21541
- if (!existsSync23(join22(repoRoot, "dist", "cli", "index.js"))) {
21679
+ if (!existsSync23(join24(repoRoot, "dist", "cli", "index.js"))) {
21542
21680
  console.warn(
21543
21681
  `${C3.yellow}\u26A0 CLI build not found (dist/cli/index.js). The GUI bridge needs it \u2014 run 'npm run build' at the repo root.${C3.reset}`
21544
21682
  );
@@ -21611,7 +21749,7 @@ var uiCommand = new Command23("ui").description("Launch the ZAM Desktop GUI (Act
21611
21749
  );
21612
21750
  process.exit(1);
21613
21751
  }
21614
- const repoRoot = dirname9(desktopDir);
21752
+ const repoRoot = dirname10(desktopDir);
21615
21753
  if (opts.build) {
21616
21754
  if (!requireRust()) process.exit(1);
21617
21755
  if (!requireMsvcOnWindows()) process.exit(1);
@@ -21622,7 +21760,7 @@ var uiCommand = new Command23("ui").description("Launch the ZAM Desktop GUI (Act
21622
21760
  );
21623
21761
  const code = runNpm(["run", "tauri", "build"], { cwd: desktopDir });
21624
21762
  if (code === 0) {
21625
- const bundle = join22(
21763
+ const bundle = join24(
21626
21764
  desktopDir,
21627
21765
  "src-tauri",
21628
21766
  "target",
@@ -21662,7 +21800,7 @@ ${C3.green}\u2713 Done. Installer is in:${C3.reset}
21662
21800
  );
21663
21801
  process.exit(1);
21664
21802
  }
21665
- createShortcuts(shortcutTarget, dirname9(shortcutTarget));
21803
+ createShortcuts(shortcutTarget, dirname10(shortcutTarget));
21666
21804
  return;
21667
21805
  }
21668
21806
  if (builtApp) {
@@ -21700,12 +21838,11 @@ ${C3.dim}After that, 'zam ui' launches it directly.${C3.reset}`
21700
21838
  // src/cli/commands/update.ts
21701
21839
  init_kernel();
21702
21840
  import { spawnSync as spawnSync2 } from "child_process";
21703
- import { existsSync as existsSync24, readFileSync as readFileSync16, realpathSync as realpathSync2 } from "fs";
21704
- import { dirname as dirname10, join as join23 } from "path";
21705
- import { fileURLToPath as fileURLToPath4 } from "url";
21841
+ import { existsSync as existsSync24, readFileSync as readFileSync17, realpathSync as realpathSync2 } from "fs";
21842
+ import { dirname as dirname11, join as join25 } from "path";
21843
+ import { fileURLToPath as fileURLToPath5 } from "url";
21706
21844
  import { confirm as confirm3 } from "@inquirer/prompts";
21707
21845
  import { Command as Command24 } from "commander";
21708
- var GITHUB_REPO = "zam-os/zam";
21709
21846
  var CHANNELS = [
21710
21847
  "developer",
21711
21848
  "direct",
@@ -21721,48 +21858,16 @@ var C4 = {
21721
21858
  red: "\x1B[31m",
21722
21859
  yellow: "\x1B[33m"
21723
21860
  };
21724
- function currentVersion() {
21725
- const here = dirname10(fileURLToPath4(import.meta.url));
21726
- for (const up of ["..", "../..", "../../.."]) {
21727
- try {
21728
- const pkg2 = JSON.parse(
21729
- readFileSync16(join23(here, up, "package.json"), "utf-8")
21730
- );
21731
- if (pkg2.version) return pkg2.version;
21732
- } catch {
21733
- }
21734
- }
21735
- return "0.0.0";
21736
- }
21737
21861
  function versionAt(dir) {
21738
21862
  try {
21739
21863
  const pkg2 = JSON.parse(
21740
- readFileSync16(join23(dir, "package.json"), "utf-8")
21864
+ readFileSync17(join25(dir, "package.json"), "utf-8")
21741
21865
  );
21742
21866
  return pkg2.version ?? "unknown";
21743
21867
  } catch {
21744
21868
  return "unknown";
21745
21869
  }
21746
21870
  }
21747
- async function fetchLatestVersion(repo) {
21748
- const res = await fetch(
21749
- `https://api.github.com/repos/${repo}/releases/latest`,
21750
- {
21751
- headers: {
21752
- Accept: "application/vnd.github+json",
21753
- "User-Agent": "zam-cli"
21754
- }
21755
- }
21756
- );
21757
- if (!res.ok) {
21758
- throw new Error(
21759
- `Could not reach the release server (HTTP ${res.status}). Pass --latest <version> to check offline.`
21760
- );
21761
- }
21762
- const data = await res.json();
21763
- if (!data.tag_name) throw new Error("No published release found yet.");
21764
- return data.tag_name;
21765
- }
21766
21871
  function render2(decision) {
21767
21872
  if (!decision.updateAvailable) {
21768
21873
  console.log(
@@ -21814,14 +21919,14 @@ var checkCmd = new Command24("check").description("Check whether a newer ZAM has
21814
21919
  }
21815
21920
  );
21816
21921
  function findSourceRepo() {
21817
- let dir = realpathSync2(dirname10(fileURLToPath4(import.meta.url)));
21818
- let parent = dirname10(dir);
21922
+ let dir = realpathSync2(dirname11(fileURLToPath5(import.meta.url)));
21923
+ let parent = dirname11(dir);
21819
21924
  while (parent !== dir) {
21820
- if (existsSync24(join23(dir, ".git"))) return dir;
21925
+ if (existsSync24(join25(dir, ".git"))) return dir;
21821
21926
  dir = parent;
21822
- parent = dirname10(dir);
21927
+ parent = dirname11(dir);
21823
21928
  }
21824
- return existsSync24(join23(dir, ".git")) ? dir : null;
21929
+ return existsSync24(join25(dir, ".git")) ? dir : null;
21825
21930
  }
21826
21931
  function runGit(cwd, args, capture) {
21827
21932
  const res = spawnSync2("git", args, {
@@ -21842,7 +21947,7 @@ function runNpm2(args, cwd) {
21842
21947
  function smokeTestBuild(src) {
21843
21948
  const res = spawnSync2(
21844
21949
  process.execPath,
21845
- [join23(src, "dist", "cli", "index.js"), "--version"],
21950
+ [join25(src, "dist", "cli", "index.js"), "--version"],
21846
21951
  {
21847
21952
  cwd: src,
21848
21953
  encoding: "utf8",
@@ -21922,7 +22027,7 @@ Fix it manually in ${src} (try \`npm ci && npm run build\`, and check your Node
21922
22027
  console.log(`${C4.dim}\u2192 zam setup --force${C4.reset}`);
21923
22028
  const setup = spawnSync2(
21924
22029
  process.execPath,
21925
- [join23(src, "dist", "cli", "index.js"), "setup", "--force"],
22030
+ [join25(src, "dist", "cli", "index.js"), "setup", "--force"],
21926
22031
  { cwd: process.cwd(), stdio: "inherit" }
21927
22032
  );
21928
22033
  if (setup.status !== 0) {
@@ -22035,9 +22140,9 @@ var whoamiCommand = new Command25("whoami").description("Show or set the default
22035
22140
  // src/cli/commands/workspace.ts
22036
22141
  init_kernel();
22037
22142
  import { execFileSync as execFileSync4 } from "child_process";
22038
- import { existsSync as existsSync25, writeFileSync as writeFileSync12 } from "fs";
22143
+ import { existsSync as existsSync25, writeFileSync as writeFileSync13 } from "fs";
22039
22144
  import { homedir as homedir14 } from "os";
22040
- import { join as join24, resolve as resolve9 } from "path";
22145
+ import { join as join26, resolve as resolve9 } from "path";
22041
22146
  import { confirm as confirm4, input as input7 } from "@inquirer/prompts";
22042
22147
  import { Command as Command26 } from "commander";
22043
22148
  function runGit2(cwd, args) {
@@ -22272,15 +22377,15 @@ Active workspace: \x1B[36m${workspaceDir}\x1B[0m`);
22272
22377
  );
22273
22378
  process.exit(1);
22274
22379
  }
22275
- const gitignorePath = join24(workspaceDir, ".gitignore");
22380
+ const gitignorePath = join26(workspaceDir, ".gitignore");
22276
22381
  if (!existsSync25(gitignorePath)) {
22277
- writeFileSync12(
22382
+ writeFileSync13(
22278
22383
  gitignorePath,
22279
22384
  "node_modules/\n.agent/\n.agents/\n.claude/\n.gemini/\n.goose/\n*.log\n",
22280
22385
  "utf8"
22281
22386
  );
22282
22387
  }
22283
- const hasGitRepo = existsSync25(join24(workspaceDir, ".git"));
22388
+ const hasGitRepo = existsSync25(join26(workspaceDir, ".git"));
22284
22389
  if (!hasGitRepo) {
22285
22390
  console.log("Initializing local Git repository...");
22286
22391
  runGit2(workspaceDir, ["init", "-b", "main"]);
@@ -22367,7 +22472,7 @@ Active workspace: \x1B[36m${workspaceDir}\x1B[0m`);
22367
22472
  }
22368
22473
  });
22369
22474
  workspaceCommand.command("data-dir").description("Print the ZAM data directory (database, credentials, config)").option("--json", "Output as JSON").action((opts) => {
22370
- const dir = join24(homedir14(), ".zam");
22475
+ const dir = join26(homedir14(), ".zam");
22371
22476
  console.log(opts.json ? JSON.stringify({ dataDir: dir }) : dir);
22372
22477
  });
22373
22478
  workspaceCommand.command("backup").description("Back up the local ZAM database into your workspace").option(
@@ -22408,9 +22513,9 @@ workspaceCommand.command("backup").description("Back up the local ZAM database i
22408
22513
  });
22409
22514
 
22410
22515
  // src/cli/app.ts
22411
- var __dirname = dirname11(fileURLToPath5(import.meta.url));
22516
+ var __dirname = dirname12(fileURLToPath6(import.meta.url));
22412
22517
  var pkg = JSON.parse(
22413
- readFileSync17(join25(__dirname, "..", "..", "package.json"), "utf-8")
22518
+ readFileSync18(join27(__dirname, "..", "..", "package.json"), "utf-8")
22414
22519
  );
22415
22520
  var program = new Command27();
22416
22521
  program.name("zam").description(