zam-core 0.10.1 → 0.10.3

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
@@ -5481,20 +5481,20 @@ import { homedir as homedir5 } from "os";
5481
5481
  import { join as join8 } from "path";
5482
5482
  import { fileURLToPath } from "url";
5483
5483
  function getPackageSkillPath(agent = "default") {
5484
- const packageRoot2 = [
5484
+ const packageRoot4 = [
5485
5485
  fileURLToPath(new URL("../../..", import.meta.url)),
5486
5486
  fileURLToPath(new URL("../..", import.meta.url)),
5487
5487
  fileURLToPath(new URL("..", import.meta.url))
5488
5488
  ].find((candidate) => existsSync7(join8(candidate, "package.json"))) ?? "";
5489
- if (!packageRoot2) return "";
5489
+ if (!packageRoot4) return "";
5490
5490
  if (agent === "codex") {
5491
- const codexPath = join8(packageRoot2, ".agents", "skills", "zam", "SKILL.md");
5491
+ const codexPath = join8(packageRoot4, ".agents", "skills", "zam", "SKILL.md");
5492
5492
  if (existsSync7(codexPath)) return codexPath;
5493
5493
  return "";
5494
5494
  }
5495
5495
  if (agent === "claude") {
5496
5496
  const claudePath = join8(
5497
- packageRoot2,
5497
+ packageRoot4,
5498
5498
  ".claude",
5499
5499
  "skills",
5500
5500
  "zam",
@@ -5503,9 +5503,9 @@ function getPackageSkillPath(agent = "default") {
5503
5503
  if (existsSync7(claudePath)) return claudePath;
5504
5504
  return "";
5505
5505
  }
5506
- let path = join8(packageRoot2, ".agent", "skills", "zam", "SKILL.md");
5506
+ let path = join8(packageRoot4, ".agent", "skills", "zam", "SKILL.md");
5507
5507
  if (existsSync7(path)) return path;
5508
- path = join8(packageRoot2, ".claude", "skills", "zam", "SKILL.md");
5508
+ path = join8(packageRoot4, ".claude", "skills", "zam", "SKILL.md");
5509
5509
  if (existsSync7(path)) return path;
5510
5510
  return "";
5511
5511
  }
@@ -6808,16 +6808,16 @@ var init_kernel = __esm({
6808
6808
  });
6809
6809
 
6810
6810
  // src/cli/app.ts
6811
- import { readFileSync as readFileSync18 } from "fs";
6812
- import { dirname as dirname12, join as join27 } from "path";
6813
- import { fileURLToPath as fileURLToPath6 } from "url";
6811
+ import { readFileSync as readFileSync20 } from "fs";
6812
+ import { dirname as dirname14, join as join29 } from "path";
6813
+ import { fileURLToPath as fileURLToPath8 } from "url";
6814
6814
  import { Command as Command27 } from "commander";
6815
6815
 
6816
6816
  // src/cli/commands/agent.ts
6817
6817
  init_kernel();
6818
- import { existsSync as existsSync13, mkdirSync as mkdirSync8, writeFileSync as writeFileSync7 } from "fs";
6819
- import { homedir as homedir9 } from "os";
6820
- import { dirname as dirname5, join as join13 } from "path";
6818
+ import { existsSync as existsSync15, mkdirSync as mkdirSync10, writeFileSync as writeFileSync9 } from "fs";
6819
+ import { homedir as homedir11 } from "os";
6820
+ import { dirname as dirname7, join as join15 } from "path";
6821
6821
  import { Command } from "commander";
6822
6822
 
6823
6823
  // src/cli/agent-harness.ts
@@ -7040,6 +7040,18 @@ function openTerminalWindow(opts) {
7040
7040
  }
7041
7041
 
7042
7042
  // src/cli/agent-harness.ts
7043
+ var ANTIGRAVITY_IDE_CANDIDATE_PATHS = {
7044
+ darwin: [
7045
+ join12(
7046
+ homedir8(),
7047
+ ".antigravity-ide",
7048
+ "antigravity-ide",
7049
+ "bin",
7050
+ "antigravity-ide"
7051
+ ),
7052
+ "/Applications/Antigravity IDE.app/Contents/Resources/app/bin/antigravity-ide"
7053
+ ]
7054
+ };
7043
7055
  var AGENT_HARNESSES = [
7044
7056
  { id: "claude-code", label: "Claude Code", kind: "cli", command: "claude" },
7045
7057
  { id: "codex", label: "Codex", kind: "cli", command: "codex" },
@@ -7061,19 +7073,41 @@ var AGENT_HARNESSES = [
7061
7073
  id: "antigravity",
7062
7074
  label: "Antigravity",
7063
7075
  kind: "app",
7064
- command: "antigravity"
7076
+ command: "antigravity",
7077
+ candidatePaths: {
7078
+ darwin: [
7079
+ ...ANTIGRAVITY_IDE_CANDIDATE_PATHS.darwin ?? [],
7080
+ "/Applications/Antigravity.app/Contents/MacOS/Antigravity"
7081
+ ]
7082
+ }
7065
7083
  },
7066
7084
  { id: "goose", label: "goose", kind: "cli", command: "goose" }
7067
7085
  ];
7068
7086
  function getHarness(id) {
7069
7087
  return AGENT_HARNESSES.find((h) => h.id === id);
7070
7088
  }
7089
+ function resolveAntigravityIdeExecutable(deps = {}) {
7090
+ const find = deps.find ?? findExecutable;
7091
+ const exists = deps.exists ?? existsSync12;
7092
+ const platform = deps.platform ?? process.platform;
7093
+ const found = find("antigravity-ide");
7094
+ if (found) return found;
7095
+ return ANTIGRAVITY_IDE_CANDIDATE_PATHS[platform]?.find((path) => exists(path)) ?? null;
7096
+ }
7071
7097
  function resolveHarnessExecutable(harness, overrideCommand, deps = {}) {
7072
7098
  const find = deps.find ?? findExecutable;
7073
7099
  const exists = deps.exists ?? existsSync12;
7074
7100
  const platform = deps.platform ?? process.platform;
7075
7101
  const found = find(overrideCommand || harness.command);
7076
7102
  if (found) return found;
7103
+ if (!overrideCommand && harness.id === "antigravity") {
7104
+ const foundIde = resolveAntigravityIdeExecutable({
7105
+ find,
7106
+ exists,
7107
+ platform
7108
+ });
7109
+ if (foundIde) return foundIde;
7110
+ }
7077
7111
  if (harness.kind === "app") {
7078
7112
  for (const candidate of harness.candidatePaths?.[platform] ?? []) {
7079
7113
  if (exists(candidate)) return candidate;
@@ -7118,6 +7152,76 @@ function launchHarness(harness, opts) {
7118
7152
  console.log(`Launched ${harness.label} in ${opts.workspace}`);
7119
7153
  }
7120
7154
  }
7155
+ function detectInstalledConnectHarnesses(options = {}) {
7156
+ const home = options.home ?? homedir8();
7157
+ const platform = options.platform ?? process.platform;
7158
+ const find = options.find ?? findExecutable;
7159
+ const exists = options.exists ?? existsSync12;
7160
+ const detected = [];
7161
+ const hasCommandOrPath = (command, paths = []) => Boolean(find(command)) || paths.some((path) => exists(path));
7162
+ if (hasCommandOrPath("codex", [
7163
+ join12(home, ".codex"),
7164
+ ...platform === "darwin" ? ["/Applications/Codex.app"] : platform === "win32" ? [join12(home, "AppData", "Local", "Programs", "Codex")] : []
7165
+ ])) {
7166
+ detected.push("codex");
7167
+ }
7168
+ const vscodePaths = platform === "darwin" ? [
7169
+ "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code",
7170
+ join12(
7171
+ home,
7172
+ "Applications",
7173
+ "Visual Studio Code.app",
7174
+ "Contents",
7175
+ "Resources",
7176
+ "app",
7177
+ "bin",
7178
+ "code"
7179
+ )
7180
+ ] : platform === "win32" ? [
7181
+ join12(
7182
+ home,
7183
+ "AppData",
7184
+ "Local",
7185
+ "Programs",
7186
+ "Microsoft VS Code",
7187
+ "bin",
7188
+ "code.cmd"
7189
+ )
7190
+ ] : ["/usr/bin/code", "/usr/local/bin/code", "/snap/bin/code"];
7191
+ if (hasCommandOrPath("code", vscodePaths)) detected.push("vscode");
7192
+ const copilotHome = options.copilotHome ?? join12(home, ".copilot");
7193
+ if (hasCommandOrPath("copilot", [
7194
+ copilotHome,
7195
+ ...platform === "darwin" ? ["/Applications/GitHub Copilot.app"] : []
7196
+ ])) {
7197
+ detected.push("copilot");
7198
+ }
7199
+ if (hasCommandOrPath("opencode", [join12(home, ".config", "opencode")])) {
7200
+ detected.push("opencode");
7201
+ }
7202
+ if (hasCommandOrPath("goose", [join12(home, ".config", "goose")])) {
7203
+ detected.push("goose");
7204
+ }
7205
+ if (hasCommandOrPath("antigravity", [
7206
+ join12(home, ".gemini", "config"),
7207
+ ...platform === "darwin" ? [
7208
+ join12(
7209
+ home,
7210
+ ".antigravity-ide",
7211
+ "antigravity-ide",
7212
+ "bin",
7213
+ "antigravity-ide"
7214
+ ),
7215
+ "/Applications/Antigravity.app",
7216
+ "/Applications/Antigravity IDE.app"
7217
+ ] : []
7218
+ ]) || find("antigravity-ide")) {
7219
+ detected.push("antigravity");
7220
+ }
7221
+ const claudeDesktopPath = platform === "darwin" ? "/Applications/Claude.app" : platform === "win32" ? join12(home, "AppData", "Local", "AnthropicClaude") : join12(home, ".config", "Claude");
7222
+ if (exists(claudeDesktopPath)) detected.push("claude-desktop");
7223
+ return detected;
7224
+ }
7121
7225
  function parseMcpJsonConfig(path, content) {
7122
7226
  let parsed;
7123
7227
  try {
@@ -7248,6 +7352,36 @@ approval_mode = "prompt"
7248
7352
  content = existingStr ? `${existingStr.trimEnd()}
7249
7353
  ${block}` : block;
7250
7354
  }
7355
+ } else if (harnessId === "vscode") {
7356
+ const platform = opts.platform ?? process.platform;
7357
+ targetPath = platform === "win32" ? join12(opts.home, "AppData", "Roaming", "Code", "User", "mcp.json") : platform === "darwin" ? join12(
7358
+ opts.home,
7359
+ "Library",
7360
+ "Application Support",
7361
+ "Code",
7362
+ "User",
7363
+ "mcp.json"
7364
+ ) : join12(opts.home, ".config", "Code", "User", "mcp.json");
7365
+ hint = "Reload VS Code after setup. ZAM Companion stays separate from the Codex chat and can be moved to any panel or sidebar.";
7366
+ let existing = {};
7367
+ if (exists(targetPath)) {
7368
+ existing = parseMcpJsonConfig(targetPath, read(targetPath));
7369
+ }
7370
+ if (existing.servers !== void 0 && (typeof existing.servers !== "object" || existing.servers === null || Array.isArray(existing.servers))) {
7371
+ throw new Error(
7372
+ `Cannot update ${targetPath}: servers must be a JSON object`
7373
+ );
7374
+ }
7375
+ if (existing.inputs !== void 0 && !Array.isArray(existing.inputs)) {
7376
+ throw new Error(`Cannot update ${targetPath}: inputs must be an array`);
7377
+ }
7378
+ if (!existing.servers) existing.servers = {};
7379
+ const expectedServer = { command: opts.zamPath, args: ["mcp"] };
7380
+ const currentServer = existing.servers.zam;
7381
+ alreadyConfigured = Array.isArray(existing.inputs) && typeof currentServer === "object" && currentServer !== null && !Array.isArray(currentServer) && JSON.stringify(currentServer) === JSON.stringify(expectedServer);
7382
+ existing.servers.zam = expectedServer;
7383
+ if (!existing.inputs) existing.inputs = [];
7384
+ content = JSON.stringify(existing, null, 2);
7251
7385
  } else if (harnessId === "goose") {
7252
7386
  targetPath = join12(opts.home, ".config", "goose", "config.yaml");
7253
7387
  hint = "goose will load the 'zam' extension on next session start. Run 'goose configure' to manage extensions.";
@@ -7286,8 +7420,11 @@ ${zamExtension}
7286
7420
  `;
7287
7421
  }
7288
7422
  } else if (harnessId === "copilot") {
7289
- targetPath = join12(opts.home, ".copilot", "mcp-config.json");
7290
- hint = "GitHub Copilot CLI will load the 'zam' MCP server on next session. Use '/mcp show' in Copilot CLI to verify.";
7423
+ targetPath = join12(
7424
+ opts.copilotHome ?? join12(opts.home, ".copilot"),
7425
+ "mcp-config.json"
7426
+ );
7427
+ hint = "Restart GitHub Copilot or start a new session to load the 'zam' MCP server and its focused Recall, Graph, and Settings canvases.";
7291
7428
  let existing = {};
7292
7429
  if (exists(targetPath)) {
7293
7430
  existing = parseMcpJsonConfig(targetPath, read(targetPath));
@@ -7311,6 +7448,231 @@ ${zamExtension}
7311
7448
  };
7312
7449
  }
7313
7450
 
7451
+ // src/cli/copilot-extension.ts
7452
+ import {
7453
+ existsSync as existsSync13,
7454
+ lstatSync,
7455
+ mkdirSync as mkdirSync8,
7456
+ readFileSync as readFileSync10,
7457
+ writeFileSync as writeFileSync7
7458
+ } from "fs";
7459
+ import { homedir as homedir9 } from "os";
7460
+ import { dirname as dirname5, join as join13, resolve as resolve3 } from "path";
7461
+ import { fileURLToPath as fileURLToPath2 } from "url";
7462
+ var EXTENSION_NAME = "zam-mcp-apps";
7463
+ var EXTENSION_FILES = [
7464
+ "extension.mjs",
7465
+ "host.bundle.js",
7466
+ "mcp-client.bundle.mjs",
7467
+ "manifest.json"
7468
+ ];
7469
+ var packageRoot = [
7470
+ fileURLToPath2(new URL("../..", import.meta.url)),
7471
+ fileURLToPath2(new URL("../../..", import.meta.url))
7472
+ ].find((candidate) => existsSync13(join13(candidate, "package.json"))) ?? fileURLToPath2(new URL("../..", import.meta.url));
7473
+ function defaultCliEntry() {
7474
+ return join13(dirname5(fileURLToPath2(import.meta.url)), "index.js");
7475
+ }
7476
+ function resolveCopilotHome(home = homedir9(), configuredHome = process.env.COPILOT_HOME) {
7477
+ return configuredHome?.trim() ? resolve3(configuredHome) : join13(home, ".copilot");
7478
+ }
7479
+ function resolveCopilotZamLaunch(zamPath, options = {}) {
7480
+ const cliEntry = options.cliEntry ?? defaultCliEntry();
7481
+ if (existsSync13(cliEntry)) {
7482
+ return {
7483
+ command: options.nodePath ?? process.execPath,
7484
+ args: [cliEntry, "mcp"]
7485
+ };
7486
+ }
7487
+ return {
7488
+ command: zamPath,
7489
+ args: ["mcp"]
7490
+ };
7491
+ }
7492
+ function planCopilotExtensionInstall(options) {
7493
+ const sourceDir = options.assetsDir ?? join13(packageRoot, "dist", "copilot-extension");
7494
+ for (const file of EXTENSION_FILES) {
7495
+ if (!existsSync13(join13(sourceDir, file))) {
7496
+ throw new Error(
7497
+ `Copilot MCP Apps asset is missing: ${join13(sourceDir, file)}. Run \`npm run build\` and retry.`
7498
+ );
7499
+ }
7500
+ }
7501
+ const manifest = JSON.parse(
7502
+ readFileSync10(join13(sourceDir, "manifest.json"), "utf8")
7503
+ );
7504
+ if (manifest.name !== EXTENSION_NAME || typeof manifest.version !== "string" || !manifest.version) {
7505
+ throw new Error(
7506
+ `Invalid Copilot MCP Apps manifest: ${join13(sourceDir, "manifest.json")}`
7507
+ );
7508
+ }
7509
+ const copilotHome = resolveCopilotHome(
7510
+ options.home,
7511
+ options.copilotHome ?? process.env.COPILOT_HOME
7512
+ );
7513
+ return {
7514
+ sourceDir,
7515
+ destinationDir: join13(copilotHome, "extensions", EXTENSION_NAME),
7516
+ launch: resolveCopilotZamLaunch(options.zamPath, options),
7517
+ files: EXTENSION_FILES
7518
+ };
7519
+ }
7520
+ function writeIfChanged(path, content) {
7521
+ const next = Buffer.isBuffer(content) ? content : Buffer.from(content);
7522
+ if (existsSync13(path) && readFileSync10(path).equals(next)) return false;
7523
+ writeFileSync7(path, next);
7524
+ return true;
7525
+ }
7526
+ function installCopilotExtension(options) {
7527
+ const plan = planCopilotExtensionInstall(options);
7528
+ if (options.dryRun) {
7529
+ return { ...plan, action: "planned", changedFiles: [] };
7530
+ }
7531
+ const destinationExisted = existsSync13(plan.destinationDir);
7532
+ if (destinationExisted && lstatSync(plan.destinationDir).isSymbolicLink()) {
7533
+ throw new Error(
7534
+ `Refusing to replace symlinked Copilot extension directory: ${plan.destinationDir}`
7535
+ );
7536
+ }
7537
+ mkdirSync8(plan.destinationDir, { recursive: true });
7538
+ const changedFiles = [];
7539
+ for (const file of plan.files) {
7540
+ const source = join13(plan.sourceDir, file);
7541
+ const destination = join13(plan.destinationDir, file);
7542
+ if (writeIfChanged(destination, readFileSync10(source))) {
7543
+ changedFiles.push(file);
7544
+ }
7545
+ }
7546
+ const launchContent = `${JSON.stringify(
7547
+ {
7548
+ schemaVersion: 1,
7549
+ command: plan.launch.command,
7550
+ args: plan.launch.args
7551
+ },
7552
+ null,
7553
+ 2
7554
+ )}
7555
+ `;
7556
+ if (writeIfChanged(join13(plan.destinationDir, "launch.json"), launchContent)) {
7557
+ changedFiles.push("launch.json");
7558
+ }
7559
+ return {
7560
+ ...plan,
7561
+ action: !destinationExisted ? "installed" : changedFiles.length > 0 ? "updated" : "unchanged",
7562
+ changedFiles
7563
+ };
7564
+ }
7565
+
7566
+ // src/cli/vscode-extension.ts
7567
+ import { execFileSync as execFileSync3 } from "child_process";
7568
+ import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync8 } from "fs";
7569
+ import { homedir as homedir10 } from "os";
7570
+ import { dirname as dirname6, join as join14 } from "path";
7571
+ import { fileURLToPath as fileURLToPath3 } from "url";
7572
+ var packageRoot2 = [
7573
+ fileURLToPath3(new URL("../..", import.meta.url)),
7574
+ fileURLToPath3(new URL("../../..", import.meta.url))
7575
+ ].find((candidate) => existsSync14(join14(candidate, "package.json"))) ?? fileURLToPath3(new URL("../..", import.meta.url));
7576
+ function resolveVscodeExecutable(options = {}) {
7577
+ const home = options.home ?? homedir10();
7578
+ const platform = options.platform ?? process.platform;
7579
+ const find = options.find ?? findExecutable;
7580
+ const exists = options.exists ?? existsSync14;
7581
+ const found = find("code");
7582
+ if (found) return found;
7583
+ const candidates = platform === "darwin" ? [
7584
+ "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code",
7585
+ join14(
7586
+ home,
7587
+ "Applications",
7588
+ "Visual Studio Code.app",
7589
+ "Contents",
7590
+ "Resources",
7591
+ "app",
7592
+ "bin",
7593
+ "code"
7594
+ )
7595
+ ] : platform === "win32" ? [
7596
+ join14(
7597
+ home,
7598
+ "AppData",
7599
+ "Local",
7600
+ "Programs",
7601
+ "Microsoft VS Code",
7602
+ "bin",
7603
+ "code.cmd"
7604
+ )
7605
+ ] : ["/usr/bin/code", "/usr/local/bin/code", "/snap/bin/code"];
7606
+ return candidates.find((candidate) => exists(candidate)) ?? null;
7607
+ }
7608
+ function packageVersion() {
7609
+ const parsed = JSON.parse(
7610
+ readFileSync11(join14(packageRoot2, "package.json"), "utf8")
7611
+ );
7612
+ if (typeof parsed.version !== "string" || !parsed.version) {
7613
+ throw new Error("Cannot determine the ZAM package version");
7614
+ }
7615
+ return parsed.version;
7616
+ }
7617
+ function planVscodeExtensionInstall(options) {
7618
+ const home = options.home ?? homedir10();
7619
+ const version = options.version ?? packageVersion();
7620
+ const assetsDir = options.assetsDir ?? join14(packageRoot2, "dist", "vscode-extension");
7621
+ const vsixPath = join14(assetsDir, `ZAM_Companion_${version}.vsix`);
7622
+ if (!existsSync14(vsixPath)) {
7623
+ throw new Error(
7624
+ `ZAM Companion VSIX asset is missing: ${vsixPath}. Run \`npm run build\` and retry.`
7625
+ );
7626
+ }
7627
+ const codePath = options.codePath ?? resolveVscodeExecutable({
7628
+ home,
7629
+ platform: options.platform,
7630
+ find: options.find,
7631
+ exists: options.exists
7632
+ });
7633
+ if (!codePath) {
7634
+ throw new Error(
7635
+ "Visual Studio Code was not detected. Install VS Code or add its 'code' command to PATH."
7636
+ );
7637
+ }
7638
+ return {
7639
+ version,
7640
+ vsixPath,
7641
+ codePath,
7642
+ launchConfigPath: join14(home, ".zam", "vscode-launch.json"),
7643
+ launch: { command: options.zamPath, args: ["mcp"] }
7644
+ };
7645
+ }
7646
+ function installVscodeExtension(options) {
7647
+ const plan = planVscodeExtensionInstall(options);
7648
+ if (options.dryRun) return { ...plan, action: "planned" };
7649
+ const launchContent = `${JSON.stringify(
7650
+ {
7651
+ schemaVersion: 1,
7652
+ version: plan.version,
7653
+ command: plan.launch.command,
7654
+ args: plan.launch.args
7655
+ },
7656
+ null,
7657
+ 2
7658
+ )}
7659
+ `;
7660
+ const existed = existsSync14(plan.launchConfigPath);
7661
+ const changed = !existed || readFileSync11(plan.launchConfigPath, "utf8") !== launchContent;
7662
+ const run = options.run ?? ((command, args) => {
7663
+ execFileSync3(command, args, { stdio: "pipe" });
7664
+ });
7665
+ run(plan.codePath, ["--install-extension", plan.vsixPath, "--force"]);
7666
+ if (changed) {
7667
+ mkdirSync9(dirname6(plan.launchConfigPath), { recursive: true });
7668
+ writeFileSync8(plan.launchConfigPath, launchContent, "utf8");
7669
+ }
7670
+ return {
7671
+ ...plan,
7672
+ action: !existed ? "installed" : changed ? "updated" : "unchanged"
7673
+ };
7674
+ }
7675
+
7314
7676
  // src/cli/commands/agent.ts
7315
7677
  var C = {
7316
7678
  reset: "\x1B[0m",
@@ -7326,6 +7688,7 @@ var CONNECT_HARNESSES = [
7326
7688
  "claude-desktop",
7327
7689
  "antigravity",
7328
7690
  "codex",
7691
+ "vscode",
7329
7692
  "opencode",
7330
7693
  "goose",
7331
7694
  "copilot"
@@ -7334,7 +7697,7 @@ function isConnectHarnessId(value) {
7334
7697
  return CONNECT_HARNESSES.includes(value);
7335
7698
  }
7336
7699
  function agentsMdPresent(cwd = process.cwd()) {
7337
- return existsSync13(join13(cwd, "AGENTS.md"));
7700
+ return existsSync15(join15(cwd, "AGENTS.md"));
7338
7701
  }
7339
7702
  function printStatus() {
7340
7703
  const installed = hasCommand("opencode");
@@ -7440,16 +7803,34 @@ var openCmd = new Command("open").description("Open an agent harness in the work
7440
7803
  const workspace = opts.dir ?? process.cwd();
7441
7804
  launchHarness(harness, { executable, workspace, shell });
7442
7805
  });
7443
- var connectCmd = new Command("connect").description("Configure the ZAM MCP server for an agent harness").argument(
7444
- "<harness>",
7445
- "Harness to connect: claude-code | claude-desktop | antigravity | codex | opencode | goose | copilot"
7806
+ var connectCmd = new Command("connect").description(
7807
+ "Configure ZAM for detected user agent harnesses, or one explicit harness"
7808
+ ).argument(
7809
+ "[harness]",
7810
+ "Optional harness: claude-code | claude-desktop | antigravity | codex | vscode | opencode | goose | copilot"
7446
7811
  ).option(
7447
7812
  "--print",
7448
7813
  "Print configuration changes instead of writing them to disk"
7449
7814
  ).action(async (harnessArg, opts) => {
7450
- if (!isConnectHarnessId(harnessArg)) {
7815
+ let explicitHarness;
7816
+ if (harnessArg) {
7817
+ if (!isConnectHarnessId(harnessArg)) {
7818
+ console.error(
7819
+ `Unsupported harness: ${harnessArg}. Supported: ${CONNECT_HARNESSES.join(", ")}.`
7820
+ );
7821
+ process.exit(1);
7822
+ } else {
7823
+ explicitHarness = harnessArg;
7824
+ }
7825
+ }
7826
+ const home = homedir11();
7827
+ const harnesses = explicitHarness ? [explicitHarness] : detectInstalledConnectHarnesses({
7828
+ home,
7829
+ copilotHome: process.env.COPILOT_HOME
7830
+ });
7831
+ if (harnesses.length === 0) {
7451
7832
  console.error(
7452
- `Unsupported harness: ${harnessArg}. Supported: ${CONNECT_HARNESSES.join(", ")}.`
7833
+ "No supported user-scoped agent harness was detected. Install Codex, VS Code, or another supported host, or pass a harness explicitly."
7453
7834
  );
7454
7835
  process.exit(1);
7455
7836
  }
@@ -7460,54 +7841,117 @@ var connectCmd = new Command("connect").description("Configure the ZAM MCP serve
7460
7841
  );
7461
7842
  zamPath = "zam";
7462
7843
  }
7463
- let result;
7464
- try {
7465
- result = connectHarnessMcp(harnessArg, {
7466
- zamPath,
7467
- cwd: process.cwd(),
7468
- home: homedir9()
7469
- });
7470
- } catch (error) {
7471
- console.error(
7472
- `Error preparing MCP configuration: ${error instanceof Error ? error.message : String(error)}`
7473
- );
7474
- process.exit(1);
7475
- }
7476
- if (opts.print) {
7477
- console.log(`Path: ${result.path}`);
7478
- console.log(`Content:
7844
+ for (const harness of harnesses) {
7845
+ let result;
7846
+ try {
7847
+ result = connectHarnessMcp(harness, {
7848
+ zamPath,
7849
+ cwd: process.cwd(),
7850
+ home,
7851
+ copilotHome: process.env.COPILOT_HOME
7852
+ });
7853
+ } catch (error) {
7854
+ console.error(
7855
+ `Error preparing ${harness} MCP configuration: ${error instanceof Error ? error.message : String(error)}`
7856
+ );
7857
+ process.exit(1);
7858
+ }
7859
+ let copilotExtension;
7860
+ let vscodeExtension;
7861
+ try {
7862
+ if (harness === "copilot") {
7863
+ copilotExtension = installCopilotExtension({
7864
+ home,
7865
+ zamPath,
7866
+ dryRun: Boolean(opts.print)
7867
+ });
7868
+ } else if (harness === "vscode") {
7869
+ vscodeExtension = installVscodeExtension({
7870
+ home,
7871
+ zamPath,
7872
+ dryRun: Boolean(opts.print)
7873
+ });
7874
+ } else if (harness === "antigravity") {
7875
+ const antigravityPath = resolveAntigravityIdeExecutable();
7876
+ if (antigravityPath) {
7877
+ vscodeExtension = installVscodeExtension({
7878
+ home,
7879
+ zamPath,
7880
+ codePath: antigravityPath,
7881
+ dryRun: Boolean(opts.print)
7882
+ });
7883
+ }
7884
+ }
7885
+ } catch (error) {
7886
+ console.error(
7887
+ `Error preparing ${harness} companion extension: ${error instanceof Error ? error.message : String(error)}`
7888
+ );
7889
+ process.exit(1);
7890
+ }
7891
+ if (opts.print) {
7892
+ if (harnesses.length > 1) console.log(`${C.bold}${harness}${C.reset}`);
7893
+ console.log(`Path: ${result.path}`);
7894
+ console.log(`Content:
7479
7895
  ${result.content}`);
7480
- return;
7481
- }
7482
- if (result.alreadyConfigured) {
7483
- console.log(
7484
- `${C.green}\u2713${C.reset} MCP server 'zam' already configured in ${result.path}`
7485
- );
7486
- return;
7896
+ if (copilotExtension) {
7897
+ console.log(`Extension: ${copilotExtension.destinationDir}`);
7898
+ console.log(
7899
+ `Launch: ${copilotExtension.launch.command} ${copilotExtension.launch.args.join(" ")}`
7900
+ );
7901
+ }
7902
+ if (vscodeExtension) {
7903
+ console.log(`Extension: ${vscodeExtension.vsixPath}`);
7904
+ console.log(`Launch config: ${vscodeExtension.launchConfigPath}`);
7905
+ }
7906
+ continue;
7907
+ }
7908
+ if (result.alreadyConfigured) {
7909
+ console.log(
7910
+ `${C.green}\u2713${C.reset} ${harness}: MCP server 'zam' already configured in ${result.path}`
7911
+ );
7912
+ } else {
7913
+ try {
7914
+ mkdirSync10(dirname7(result.path), { recursive: true });
7915
+ writeFileSync9(result.path, result.content, "utf-8");
7916
+ console.log(
7917
+ `${C.green}\u2713${C.reset} ${harness}: wrote MCP configuration to ${result.path}`
7918
+ );
7919
+ } catch (error) {
7920
+ console.error(
7921
+ `Error writing ${harness} MCP configuration: ${error instanceof Error ? error.message : String(error)}`
7922
+ );
7923
+ process.exit(1);
7924
+ }
7925
+ }
7926
+ if (copilotExtension) {
7927
+ console.log(
7928
+ `${C.green}\u2713${C.reset} Copilot MCP Apps extension ${copilotExtension.action} at ${copilotExtension.destinationDir}`
7929
+ );
7930
+ }
7931
+ if (vscodeExtension) {
7932
+ console.log(
7933
+ `${C.green}\u2713${C.reset} ZAM Companion ${vscodeExtension.action} from ${vscodeExtension.vsixPath}`
7934
+ );
7935
+ }
7936
+ console.log(` ${C.dim}${result.hint}${C.reset}`);
7487
7937
  }
7488
- try {
7489
- mkdirSync8(dirname5(result.path), { recursive: true });
7490
- writeFileSync7(result.path, result.content, "utf-8");
7938
+ if (!opts.print) {
7939
+ const skills = distributeGlobalSkills(home);
7940
+ const installed = skills.filter((result) => result.success).length;
7491
7941
  console.log(
7492
- `${C.green}\u2713${C.reset} Wrote MCP configuration to ${result.path}`
7942
+ `${C.green}\u2713${C.reset} Refreshed ${installed}/${skills.length} global ZAM skill installations`
7493
7943
  );
7494
- console.log(` ${C.dim}${result.hint}${C.reset}`);
7495
- } catch (error) {
7496
- console.error(
7497
- `Error writing MCP configuration: ${error instanceof Error ? error.message : String(error)}`
7498
- );
7499
- process.exit(1);
7500
7944
  }
7501
7945
  });
7502
7946
  var agentCommand = new Command("agent").description("Provision and inspect the agent that drives ZAM sessions").addCommand(installCmd).addCommand(statusCmd).addCommand(openCmd).addCommand(listCmd).addCommand(connectCmd).action(printStatus);
7503
7947
 
7504
7948
  // src/cli/commands/bridge.ts
7505
7949
  init_kernel();
7506
- import { execFileSync as execFileSync3 } from "child_process";
7950
+ import { execFileSync as execFileSync4 } from "child_process";
7507
7951
  import { randomBytes as randomBytes2 } from "crypto";
7508
- import { existsSync as existsSync17, readdirSync as readdirSync2, readFileSync as readFileSync14, rmSync as rmSync3 } from "fs";
7509
- import { homedir as homedir11, tmpdir as tmpdir3 } from "os";
7510
- import { join as join20, resolve as resolve4 } from "path";
7952
+ import { existsSync as existsSync19, readdirSync as readdirSync2, readFileSync as readFileSync16, rmSync as rmSync3 } from "fs";
7953
+ import { homedir as homedir13, tmpdir as tmpdir3 } from "os";
7954
+ import { join as join22, resolve as resolve5 } from "path";
7511
7955
  import { Command as Command2 } from "commander";
7512
7956
  import { ulid as ulid9 } from "ulid";
7513
7957
 
@@ -7518,7 +7962,7 @@ import fs from "fs";
7518
7962
  // src/cli/llm/client.ts
7519
7963
  init_kernel();
7520
7964
  import { spawn as spawn2 } from "child_process";
7521
- import { existsSync as existsSync14, readFileSync as readFileSync10, statSync as statSync2 } from "fs";
7965
+ import { existsSync as existsSync16, readFileSync as readFileSync12, statSync as statSync2 } from "fs";
7522
7966
  var DEFAULT_LLM_URL = "http://localhost:8000/v1";
7523
7967
  var DEFAULT_LLM_MAX_TOKENS = 1e4;
7524
7968
  var RECALL_QUESTION_MAX_OUTPUT_TOKENS = 400;
@@ -8234,7 +8678,7 @@ async function extractTextFromScanViaLLM(db, imagePath) {
8234
8678
  "Vision role is not enabled in settings (llm.vision.enabled)"
8235
8679
  );
8236
8680
  }
8237
- if (!existsSync14(imagePath)) {
8681
+ if (!existsSync16(imagePath)) {
8238
8682
  throw new Error(`Scan file not found: ${imagePath}`);
8239
8683
  }
8240
8684
  const stat = statSync2(imagePath);
@@ -8255,7 +8699,7 @@ async function extractTextFromScanViaLLM(db, imagePath) {
8255
8699
  if (!mime) {
8256
8700
  throw new Error("Unsupported scan format; use PNG, JPEG, or WebP");
8257
8701
  }
8258
- const imageBytes = readFileSync10(imagePath);
8702
+ const imageBytes = readFileSync12(imagePath);
8259
8703
  const dataUrl = `data:${mime};base64,${imageBytes.toString("base64")}`;
8260
8704
  const visionEndpoint = await getVisionConfig(db);
8261
8705
  const langName = LANGUAGE_NAMES[p.locale] || "English";
@@ -8472,7 +8916,7 @@ async function prepareRecallChain(db, opts) {
8472
8916
  } else {
8473
8917
  spawnLocalRunner(endpoint.url, endpoint.model, endpoint.runner);
8474
8918
  while (Date.now() < deadline) {
8475
- await new Promise((resolve10) => setTimeout(resolve10, 1e3));
8919
+ await new Promise((resolve11) => setTimeout(resolve11, 1e3));
8476
8920
  if (await isLlmOnline(endpoint.url)) {
8477
8921
  online = true;
8478
8922
  break;
@@ -8687,7 +9131,7 @@ function spawnLocalRunner(url, model, hint) {
8687
9131
  const { runner, port } = detectRunner(url, model, hint);
8688
9132
  try {
8689
9133
  if (runner === "fastflowlm") {
8690
- const flmExe = existsSync14("C:\\Program Files\\flm\\flm.exe") ? "C:\\Program Files\\flm\\flm.exe" : "flm";
9134
+ const flmExe = existsSync16("C:\\Program Files\\flm\\flm.exe") ? "C:\\Program Files\\flm\\flm.exe" : "flm";
8691
9135
  if (!hasCommand("flm") && flmExe === "flm") return;
8692
9136
  spawn2(flmExe, ["serve", model, "--port", port], {
8693
9137
  detached: true,
@@ -8708,7 +9152,7 @@ function spawnLocalRunner(url, model, hint) {
8708
9152
  async function startLocalRunner(url, model, locale, hint) {
8709
9153
  const { runner, port } = detectRunner(url, model, hint);
8710
9154
  if (runner === "fastflowlm") {
8711
- const flmExe = existsSync14("C:\\Program Files\\flm\\flm.exe") ? "C:\\Program Files\\flm\\flm.exe" : "flm";
9155
+ const flmExe = existsSync16("C:\\Program Files\\flm\\flm.exe") ? "C:\\Program Files\\flm\\flm.exe" : "flm";
8712
9156
  if (!hasCommand("flm") && flmExe === "flm") {
8713
9157
  console.warn(
8714
9158
  "\x1B[31m\u2717 FastFlowLM is configured but could not be found on the system.\x1B[0m"
@@ -8765,7 +9209,7 @@ async function startLocalRunner(url, model, locale, hint) {
8765
9209
  let attempts = 0;
8766
9210
  const dotsPerLine = 30;
8767
9211
  while (true) {
8768
- await new Promise((resolve10) => setTimeout(resolve10, 500));
9212
+ await new Promise((resolve11) => setTimeout(resolve11, 500));
8769
9213
  if (await isLlmOnline(url)) {
8770
9214
  if (attempts > 0) process.stdout.write("\n");
8771
9215
  return true;
@@ -8854,8 +9298,8 @@ async function fetchWithInteractiveTimeout(url, options = {}) {
8854
9298
  const dotsPerLine = 30;
8855
9299
  while (true) {
8856
9300
  let timeoutId;
8857
- const timeoutPromise = new Promise((resolve10) => {
8858
- timeoutId = setTimeout(() => resolve10("timeout"), timeoutMs);
9301
+ const timeoutPromise = new Promise((resolve11) => {
9302
+ timeoutId = setTimeout(() => resolve11("timeout"), timeoutMs);
8859
9303
  });
8860
9304
  const dotsInterval = setInterval(() => {
8861
9305
  process.stdout.write(".");
@@ -9187,8 +9631,8 @@ async function readImageOCR(db, imagePath) {
9187
9631
 
9188
9632
  // src/cli/bridge-handlers.ts
9189
9633
  init_kernel();
9190
- import { mkdirSync as mkdirSync10, writeFileSync as writeFileSync8 } from "fs";
9191
- import { join as join16 } from "path";
9634
+ import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync10 } from "fs";
9635
+ import { join as join18 } from "path";
9192
9636
 
9193
9637
  // src/cli/knowledge-contexts.ts
9194
9638
  init_kernel();
@@ -9435,16 +9879,16 @@ async function resolveSuggestMinSimilarity(db) {
9435
9879
  }
9436
9880
 
9437
9881
  // 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";
9882
+ import { readFileSync as readFileSync13 } from "fs";
9883
+ import { dirname as dirname8, join as join16 } from "path";
9884
+ import { fileURLToPath as fileURLToPath4 } from "url";
9441
9885
  var GITHUB_REPO = "zam-os/zam";
9442
9886
  function currentVersion() {
9443
- const here = dirname6(fileURLToPath2(import.meta.url));
9887
+ const here = dirname8(fileURLToPath4(import.meta.url));
9444
9888
  for (const up of ["..", "../..", "../../.."]) {
9445
9889
  try {
9446
9890
  const pkg2 = JSON.parse(
9447
- readFileSync11(join14(here, up, "package.json"), "utf-8")
9891
+ readFileSync13(join16(here, up, "package.json"), "utf-8")
9448
9892
  );
9449
9893
  if (pkg2.version) return pkg2.version;
9450
9894
  } catch {
@@ -9474,16 +9918,16 @@ async function fetchLatestVersion(repo) {
9474
9918
 
9475
9919
  // src/cli/workspaces/active.ts
9476
9920
  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";
9921
+ import { existsSync as existsSync17, mkdirSync as mkdirSync11 } from "fs";
9922
+ import { homedir as homedir12 } from "os";
9923
+ import { basename as basename3, join as join17, resolve as resolve4 } from "path";
9480
9924
  var LEGACY_WORKSPACE_DIR_KEY = "personal.workspace_dir";
9481
9925
  var DEFAULT_WORKSPACE_ID = "personal";
9482
9926
  function defaultWorkspaceDir() {
9483
- return join15(homedir10(), "Documents", "zam");
9927
+ return join17(homedir12(), "Documents", "zam");
9484
9928
  }
9485
9929
  function normalizeWorkspacePath(path) {
9486
- const resolved = resolve3(path);
9930
+ const resolved = resolve4(path);
9487
9931
  return process.platform === "win32" ? resolved.toLowerCase() : resolved;
9488
9932
  }
9489
9933
  function sameWorkspacePath(left, right) {
@@ -9512,7 +9956,7 @@ async function clearLegacyWorkspaceDir(db) {
9512
9956
  async function migrateLegacyWorkspaceDir(db) {
9513
9957
  const legacyDir = await getSetting(db, LEGACY_WORKSPACE_DIR_KEY);
9514
9958
  if (!legacyDir) return void 0;
9515
- const path = resolve3(legacyDir);
9959
+ const path = resolve4(legacyDir);
9516
9960
  const existing = findWorkspaceByPath(path);
9517
9961
  const migrated = existing ?? {
9518
9962
  id: getConfiguredWorkspaces().some(
@@ -9535,13 +9979,13 @@ async function ensureActiveWorkspace(db) {
9535
9979
  await migrateLegacyWorkspaceDir(db);
9536
9980
  const active = getActiveWorkspace();
9537
9981
  if (active) {
9538
- mkdirSync9(active.path, { recursive: true });
9982
+ mkdirSync11(active.path, { recursive: true });
9539
9983
  return active;
9540
9984
  }
9541
9985
  const configured = getConfiguredWorkspaces()[0];
9542
9986
  if (configured) {
9543
9987
  setActiveWorkspaceId(configured.id);
9544
- mkdirSync9(configured.path, { recursive: true });
9988
+ mkdirSync11(configured.path, { recursive: true });
9545
9989
  return configured;
9546
9990
  }
9547
9991
  const workspace = {
@@ -9550,7 +9994,7 @@ async function ensureActiveWorkspace(db) {
9550
9994
  kind: "personal",
9551
9995
  path: defaultWorkspaceDir()
9552
9996
  };
9553
- mkdirSync9(workspace.path, { recursive: true });
9997
+ mkdirSync11(workspace.path, { recursive: true });
9554
9998
  upsertConfiguredWorkspace(workspace);
9555
9999
  setActiveWorkspaceId(workspace.id);
9556
10000
  await clearLegacyWorkspaceDir(db);
@@ -9564,7 +10008,7 @@ async function activateWorkspace(db, workspace) {
9564
10008
  }
9565
10009
  async function activateWorkspacePath(db, dir, opts = {}) {
9566
10010
  await migrateLegacyWorkspaceDir(db);
9567
- const path = resolve3(dir);
10011
+ const path = resolve4(dir);
9568
10012
  const existing = opts.id ? void 0 : findWorkspaceByPath(path);
9569
10013
  if (existing) {
9570
10014
  setActiveWorkspaceId(existing.id);
@@ -9589,7 +10033,7 @@ async function removeWorkspaceAndResolveActive(db, id) {
9589
10033
  };
9590
10034
  }
9591
10035
  function existingWorkspaceDirOrHome(workspace) {
9592
- return existsSync15(workspace.path) ? workspace.path : homedir10();
10036
+ return existsSync17(workspace.path) ? workspace.path : homedir12();
9593
10037
  }
9594
10038
 
9595
10039
  // src/cli/bridge-handlers.ts
@@ -10361,11 +10805,11 @@ async function backupCreate(db, params) {
10361
10805
  const targetDir = params.dir || (await ensureActiveWorkspace(db)).path;
10362
10806
  const snapshot = await exportSnapshot(db);
10363
10807
  const manifest = verifySnapshot(snapshot);
10364
- const backupDir = join16(targetDir, "zam-backups");
10365
- mkdirSync10(backupDir, { recursive: true });
10808
+ const backupDir = join18(targetDir, "zam-backups");
10809
+ mkdirSync12(backupDir, { recursive: true });
10366
10810
  const stamp = manifest.createdAt.replace(/[:.]/g, "-");
10367
- const path = join16(backupDir, `zam-snapshot-${stamp}.sql`);
10368
- writeFileSync8(path, snapshot, "utf-8");
10811
+ const path = join18(backupDir, `zam-snapshot-${stamp}.sql`);
10812
+ writeFileSync10(path, snapshot, "utf-8");
10369
10813
  return {
10370
10814
  ok: true,
10371
10815
  path,
@@ -13050,9 +13494,9 @@ function getCurriculumProvider(id) {
13050
13494
  // src/cli/llm/vision.ts
13051
13495
  init_kernel();
13052
13496
  import { randomBytes } from "crypto";
13053
- import { readFileSync as readFileSync12 } from "fs";
13497
+ import { readFileSync as readFileSync14 } from "fs";
13054
13498
  import { tmpdir as tmpdir2 } from "os";
13055
- import { basename as basename4, join as join17 } from "path";
13499
+ import { basename as basename4, join as join19 } from "path";
13056
13500
  var LANGUAGE_NAMES2 = {
13057
13501
  en: "English",
13058
13502
  de: "German",
@@ -13088,13 +13532,13 @@ async function observeUiSnapshotViaLLM(db, input8) {
13088
13532
  const imageUrls = [];
13089
13533
  const isVideo = /\.(mp4|mov|m4v|avi|mkv|webm)$/i.test(input8.imagePath);
13090
13534
  if (isVideo) {
13091
- const { mkdirSync: mkdirSync16, readdirSync: readdirSync3, rmSync: rmSync4 } = await import("fs");
13535
+ const { mkdirSync: mkdirSync18, readdirSync: readdirSync3, rmSync: rmSync4 } = await import("fs");
13092
13536
  const { execSync: execSync6 } = await import("child_process");
13093
- const tempDir = join17(
13537
+ const tempDir = join19(
13094
13538
  tmpdir2(),
13095
13539
  `zam-frames-${randomBytes(4).toString("hex")}`
13096
13540
  );
13097
- mkdirSync16(tempDir, { recursive: true });
13541
+ mkdirSync18(tempDir, { recursive: true });
13098
13542
  try {
13099
13543
  execSync6(
13100
13544
  `ffmpeg -i "${input8.imagePath}" -vf "fps=1/3,scale=1280:-1" -vsync vfr "${tempDir}/frame_%03d.png"`,
@@ -13123,7 +13567,7 @@ async function observeUiSnapshotViaLLM(db, input8) {
13123
13567
  }
13124
13568
  }
13125
13569
  for (const file of sampledFiles) {
13126
- const bytes = readFileSync12(join17(tempDir, file));
13570
+ const bytes = readFileSync14(join19(tempDir, file));
13127
13571
  imageUrls.push(`data:image/png;base64,${bytes.toString("base64")}`);
13128
13572
  }
13129
13573
  } finally {
@@ -13133,7 +13577,7 @@ async function observeUiSnapshotViaLLM(db, input8) {
13133
13577
  }
13134
13578
  }
13135
13579
  } else {
13136
- const imageBytes = readFileSync12(input8.imagePath);
13580
+ const imageBytes = readFileSync14(input8.imagePath);
13137
13581
  const ext = input8.imagePath.split(".").pop()?.toLowerCase();
13138
13582
  const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : "image/png";
13139
13583
  imageUrls.push(`data:${mime};base64,${imageBytes.toString("base64")}`);
@@ -13602,36 +14046,36 @@ async function withProviderScope(machine, action) {
13602
14046
 
13603
14047
  // src/cli/provisioning/index.ts
13604
14048
  import {
13605
- existsSync as existsSync16,
13606
- lstatSync,
13607
- mkdirSync as mkdirSync11,
13608
- readFileSync as readFileSync13,
14049
+ existsSync as existsSync18,
14050
+ lstatSync as lstatSync2,
14051
+ mkdirSync as mkdirSync13,
14052
+ readFileSync as readFileSync15,
13609
14053
  realpathSync,
13610
14054
  rmSync as rmSync2,
13611
14055
  symlinkSync,
13612
- writeFileSync as writeFileSync9
14056
+ writeFileSync as writeFileSync11
13613
14057
  } from "fs";
13614
- import { basename as basename5, dirname as dirname7, join as join18 } from "path";
13615
- import { fileURLToPath as fileURLToPath3 } from "url";
13616
- var packageRoot = [
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));
14058
+ import { basename as basename5, dirname as dirname9, join as join20 } from "path";
14059
+ import { fileURLToPath as fileURLToPath5 } from "url";
14060
+ var packageRoot3 = [
14061
+ fileURLToPath5(new URL("../..", import.meta.url)),
14062
+ fileURLToPath5(new URL("../../..", import.meta.url))
14063
+ ].find((candidate) => existsSync18(join20(candidate, "package.json"))) ?? fileURLToPath5(new URL("../..", import.meta.url));
13620
14064
  var ALL_SETUP_AGENTS = ["claude", "copilot", "codex", "agent"];
13621
14065
  var SKILL_PAIRS = [
13622
14066
  {
13623
- from: join18(packageRoot, ".claude", "skills", "zam", "SKILL.md"),
13624
- to: join18(".claude", "skills", "zam", "SKILL.md"),
14067
+ from: join20(packageRoot3, ".claude", "skills", "zam", "SKILL.md"),
14068
+ to: join20(".claude", "skills", "zam", "SKILL.md"),
13625
14069
  agents: ["claude", "copilot"]
13626
14070
  },
13627
14071
  {
13628
- from: join18(packageRoot, ".agent", "skills", "zam", "SKILL.md"),
13629
- to: join18(".agent", "skills", "zam", "SKILL.md"),
14072
+ from: join20(packageRoot3, ".agent", "skills", "zam", "SKILL.md"),
14073
+ to: join20(".agent", "skills", "zam", "SKILL.md"),
13630
14074
  agents: ["agent"]
13631
14075
  },
13632
14076
  {
13633
- from: join18(packageRoot, ".agents", "skills", "zam", "SKILL.md"),
13634
- to: join18(".agents", "skills", "zam", "SKILL.md"),
14077
+ from: join20(packageRoot3, ".agents", "skills", "zam", "SKILL.md"),
14078
+ to: join20(".agents", "skills", "zam", "SKILL.md"),
13635
14079
  agents: ["codex"]
13636
14080
  }
13637
14081
  ];
@@ -13661,7 +14105,7 @@ function parseSetupAgents(value) {
13661
14105
  }
13662
14106
  function pathExists(path) {
13663
14107
  try {
13664
- lstatSync(path);
14108
+ lstatSync2(path);
13665
14109
  return true;
13666
14110
  } catch {
13667
14111
  return false;
@@ -13669,7 +14113,7 @@ function pathExists(path) {
13669
14113
  }
13670
14114
  function isSymbolicLink(path) {
13671
14115
  try {
13672
- return lstatSync(path).isSymbolicLink();
14116
+ return lstatSync2(path).isSymbolicLink();
13673
14117
  } catch {
13674
14118
  return false;
13675
14119
  }
@@ -13690,16 +14134,16 @@ function linkPointsTo(sourceDir, destinationDir) {
13690
14134
  }
13691
14135
  function isZamSkillCopy(destinationDir) {
13692
14136
  try {
13693
- if (!lstatSync(destinationDir).isDirectory()) return false;
13694
- const skillFile = join18(destinationDir, "SKILL.md");
13695
- if (!existsSync16(skillFile)) return false;
13696
- return /^name:\s*zam\s*$/m.test(readFileSync13(skillFile, "utf8"));
14137
+ if (!lstatSync2(destinationDir).isDirectory()) return false;
14138
+ const skillFile = join20(destinationDir, "SKILL.md");
14139
+ if (!existsSync18(skillFile)) return false;
14140
+ return /^name:\s*zam\s*$/m.test(readFileSync15(skillFile, "utf8"));
13697
14141
  } catch {
13698
14142
  return false;
13699
14143
  }
13700
14144
  }
13701
14145
  function classifySkillDestination(sourceDir, destinationDir) {
13702
- if (!existsSync16(sourceDir)) return "source-missing";
14146
+ if (!existsSync18(sourceDir)) return "source-missing";
13703
14147
  if (!isSymbolicLink(destinationDir) && pathsResolveToSameDirectory(sourceDir, destinationDir)) {
13704
14148
  return "source-directory";
13705
14149
  }
@@ -13716,9 +14160,9 @@ function wireSkills(cwd = process.cwd(), agents = parseSetupAgents(), opts = {})
13716
14160
  };
13717
14161
  for (const { from, to, agents: pairAgents } of SKILL_PAIRS) {
13718
14162
  if (!pairAgents.some((agent) => agents.has(agent))) continue;
13719
- const sourceDir = dirname7(from);
13720
- const destinationDir = dirname7(join18(cwd, to));
13721
- const label = dirname7(to);
14163
+ const sourceDir = dirname9(from);
14164
+ const destinationDir = dirname9(join20(cwd, to));
14165
+ const label = dirname9(to);
13722
14166
  const state = classifySkillDestination(sourceDir, destinationDir);
13723
14167
  if (state === "source-missing") {
13724
14168
  if (!opts.quiet) {
@@ -13775,7 +14219,7 @@ function wireSkills(cwd = process.cwd(), agents = parseSetupAgents(), opts = {})
13775
14219
  if (destinationExists) {
13776
14220
  rmSync2(destinationDir, { recursive: true, force: true });
13777
14221
  }
13778
- mkdirSync11(dirname7(destinationDir), { recursive: true });
14222
+ mkdirSync13(dirname9(destinationDir), { recursive: true });
13779
14223
  symlinkSync(
13780
14224
  sourceDir,
13781
14225
  destinationDir,
@@ -13791,8 +14235,8 @@ function inspectSkillLinks(cwd = process.cwd(), agents = parseSetupAgents()) {
13791
14235
  const results = [];
13792
14236
  for (const { from, to, agents: pairAgents } of SKILL_PAIRS) {
13793
14237
  if (!pairAgents.some((agent) => agents.has(agent))) continue;
13794
- const sourceDir = dirname7(from);
13795
- const destinationDir = dirname7(join18(cwd, to));
14238
+ const sourceDir = dirname9(from);
14239
+ const destinationDir = dirname9(join20(cwd, to));
13796
14240
  results.push({
13797
14241
  agents: pairAgents,
13798
14242
  source: sourceDir,
@@ -13818,15 +14262,15 @@ function upsertMarkedBlock(dest, blockBody, dryRun) {
13818
14262
  const block = `${ZAM_BLOCK_START}
13819
14263
  ${blockBody.trim()}
13820
14264
  ${ZAM_BLOCK_END}`;
13821
- if (!existsSync16(dest)) {
14265
+ if (!existsSync18(dest)) {
13822
14266
  if (!dryRun) {
13823
- mkdirSync11(dirname7(dest), { recursive: true });
13824
- writeFileSync9(dest, `${block}
14267
+ mkdirSync13(dirname9(dest), { recursive: true });
14268
+ writeFileSync11(dest, `${block}
13825
14269
  `, "utf8");
13826
14270
  }
13827
14271
  return "write";
13828
14272
  }
13829
- const existing = readFileSync13(dest, "utf8");
14273
+ const existing = readFileSync15(dest, "utf8");
13830
14274
  if (existing.includes(block)) return "skip";
13831
14275
  const start = existing.indexOf(ZAM_BLOCK_START);
13832
14276
  const end = existing.indexOf(ZAM_BLOCK_END);
@@ -13834,7 +14278,7 @@ ${ZAM_BLOCK_END}`;
13834
14278
 
13835
14279
  ${block}
13836
14280
  `;
13837
- if (!dryRun) writeFileSync9(dest, next, "utf8");
14281
+ if (!dryRun) writeFileSync11(dest, next, "utf8");
13838
14282
  return start >= 0 && end > start ? "update" : "write";
13839
14283
  }
13840
14284
  function logInstructionAction(action, label, dryRun) {
@@ -13846,8 +14290,8 @@ function logInstructionAction(action, label, dryRun) {
13846
14290
  }
13847
14291
  function writeClaudeMd(skipClaudeMd, cwd = process.cwd(), opts = {}) {
13848
14292
  if (skipClaudeMd) return;
13849
- const dest = join18(cwd, "CLAUDE.md");
13850
- if (existsSync16(dest)) {
14293
+ const dest = join20(cwd, "CLAUDE.md");
14294
+ if (existsSync18(dest)) {
13851
14295
  if (!opts.updateExisting) {
13852
14296
  console.log(` skip CLAUDE.md (already present)`);
13853
14297
  return;
@@ -13890,14 +14334,14 @@ Use \`zam connector setup turso\` to store cloud credentials in
13890
14334
  if (opts.dryRun) {
13891
14335
  console.log(` would write CLAUDE.md`);
13892
14336
  } else {
13893
- writeFileSync9(dest, content, "utf8");
14337
+ writeFileSync11(dest, content, "utf8");
13894
14338
  console.log(` write CLAUDE.md`);
13895
14339
  }
13896
14340
  }
13897
14341
  function writeAgentsMd(skipAgentsMd, cwd = process.cwd(), opts = {}) {
13898
14342
  if (skipAgentsMd) return;
13899
- const dest = join18(cwd, "AGENTS.md");
13900
- if (existsSync16(dest)) {
14343
+ const dest = join20(cwd, "AGENTS.md");
14344
+ if (existsSync18(dest)) {
13901
14345
  if (!opts.updateExisting) {
13902
14346
  console.log(` skip AGENTS.md (already present)`);
13903
14347
  return;
@@ -13947,12 +14391,12 @@ Codex discovers repository skills under \`.agents/skills/\`. Run
13947
14391
  if (opts.dryRun) {
13948
14392
  console.log(` would write AGENTS.md`);
13949
14393
  } else {
13950
- writeFileSync9(dest, content, "utf8");
14394
+ writeFileSync11(dest, content, "utf8");
13951
14395
  console.log(` write AGENTS.md`);
13952
14396
  }
13953
14397
  }
13954
14398
  function writeCopilotInstructions(cwd = process.cwd(), opts = {}) {
13955
- const dest = join18(cwd, ".github", "copilot-instructions.md");
14399
+ const dest = join20(cwd, ".github", "copilot-instructions.md");
13956
14400
  const action = upsertMarkedBlock(
13957
14401
  dest,
13958
14402
  `## ZAM learning sessions
@@ -13993,13 +14437,13 @@ async function resolveUser(opts, db, resolveOpts) {
13993
14437
  }
13994
14438
 
13995
14439
  // src/cli/workspaces/backup.ts
13996
- import { mkdirSync as mkdirSync12 } from "fs";
13997
- import { join as join19 } from "path";
14440
+ import { mkdirSync as mkdirSync14 } from "fs";
14441
+ import { join as join21 } from "path";
13998
14442
  async function backupDatabaseTo(db, targetDir) {
13999
- const backupDir = join19(targetDir, "zam-backups");
14000
- mkdirSync12(backupDir, { recursive: true });
14443
+ const backupDir = join21(targetDir, "zam-backups");
14444
+ mkdirSync14(backupDir, { recursive: true });
14001
14445
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
14002
- const dest = join19(backupDir, `zam-${stamp}.db`);
14446
+ const dest = join21(backupDir, `zam-${stamp}.db`);
14003
14447
  await db.exec(`VACUUM INTO '${dest.replace(/'/g, "''")}'`);
14004
14448
  return dest;
14005
14449
  }
@@ -14130,20 +14574,20 @@ bridgeCommand.command("workspace-info").description("Report the workspace dir, i
14130
14574
  activeWorkspace,
14131
14575
  workspaceDir: activeWorkspace.path,
14132
14576
  defaultWorkspaceDir: defaultWorkspaceDir(),
14133
- dataDir: join20(homedir11(), ".zam")
14577
+ dataDir: join22(homedir13(), ".zam")
14134
14578
  });
14135
14579
  });
14136
14580
  });
14137
14581
  function provisionConfiguredWorkspaces() {
14138
14582
  return getConfiguredWorkspaces().flatMap(
14139
- (workspace) => existsSync17(workspace.path) ? wireSkills(workspace.path, parseSetupAgents(), { quiet: true }) : []
14583
+ (workspace) => existsSync19(workspace.path) ? wireSkills(workspace.path, parseSetupAgents(), { quiet: true }) : []
14140
14584
  );
14141
14585
  }
14142
14586
  function buildWorkspaceLinkHealth(workspaces) {
14143
14587
  const agents = parseSetupAgents();
14144
14588
  const map = {};
14145
14589
  for (const workspace of workspaces) {
14146
- if (!existsSync17(workspace.path)) continue;
14590
+ if (!existsSync19(workspace.path)) continue;
14147
14591
  const links = inspectSkillLinks(workspace.path, agents);
14148
14592
  map[workspace.id] = {
14149
14593
  health: summarizeSkillLinkHealth(links),
@@ -14173,7 +14617,7 @@ bridgeCommand.command("workspace-list").description("List configured ZAM workspa
14173
14617
  activeWorkspace,
14174
14618
  workspaceDir: activeWorkspace.path,
14175
14619
  defaultWorkspaceDir: defaultWorkspaceDir(),
14176
- dataDir: join20(homedir11(), ".zam"),
14620
+ dataDir: join22(homedir13(), ".zam"),
14177
14621
  linkHealth: buildWorkspaceLinkHealth(workspaces)
14178
14622
  });
14179
14623
  });
@@ -14188,7 +14632,7 @@ bridgeCommand.command("workspace-repair-links").description(
14188
14632
  if (!id) jsonError("A non-empty --id is required");
14189
14633
  const workspace = getConfiguredWorkspaces().find((item) => item.id === id);
14190
14634
  if (!workspace) jsonError(`Workspace "${id}" is not configured`);
14191
- if (!existsSync17(workspace.path)) {
14635
+ if (!existsSync19(workspace.path)) {
14192
14636
  jsonError(`Workspace path does not exist: ${workspace.path}`);
14193
14637
  }
14194
14638
  const agents = parseSetupAgents(opts.agents);
@@ -14219,8 +14663,8 @@ function parseBridgeWorkspaceKind(value) {
14219
14663
  bridgeCommand.command("workspace-add").description("Register an existing directory as a ZAM workspace (JSON)").requiredOption("--path <dir>", "Existing workspace/repository directory").option("--id <id>", "Workspace id").option("--label <label>", "Human-readable label").option("--kind <kind>", "Workspace kind", "custom").action(async (opts) => {
14220
14664
  const raw = String(opts.path ?? "").trim();
14221
14665
  if (!raw) jsonError("A non-empty --path is required");
14222
- const path = resolve4(raw);
14223
- if (!existsSync17(path)) jsonError(`Workspace path does not exist: ${path}`);
14666
+ const path = resolve5(raw);
14667
+ if (!existsSync19(path)) jsonError(`Workspace path does not exist: ${path}`);
14224
14668
  const id = opts.id ? String(opts.id).trim() : void 0;
14225
14669
  if (opts.id && !id) jsonError("A non-empty --id is required");
14226
14670
  const kind = parseBridgeWorkspaceKind(opts.kind);
@@ -14264,8 +14708,8 @@ bridgeCommand.command("workspace-remove").description("Unregister a ZAM workspac
14264
14708
  bridgeCommand.command("set-workspace-dir").description("Set the personal workspace directory (JSON)").requiredOption("--dir <path>", "Path to the workspace directory").action(async (opts) => {
14265
14709
  const raw = String(opts.dir ?? "").trim();
14266
14710
  if (!raw) jsonError("A non-empty --dir is required");
14267
- const dir = resolve4(raw);
14268
- if (!existsSync17(dir)) jsonError(`Workspace path does not exist: ${dir}`);
14711
+ const dir = resolve5(raw);
14712
+ if (!existsSync19(dir)) jsonError(`Workspace path does not exist: ${dir}`);
14269
14713
  const skillLinks = wireSkills(dir, parseSetupAgents(), { quiet: true });
14270
14714
  await withDb2(async (db) => {
14271
14715
  const workspace = await activateWorkspacePath(db, dir);
@@ -14328,7 +14772,7 @@ bridgeCommand.command("agent-open").description("Launch an agent harness in the
14328
14772
  jsonError(`Workspace is not configured: ${opts.workspace}`);
14329
14773
  }
14330
14774
  const activeWorkspace = await ensureActiveWorkspace(db);
14331
- const workspace = opts.dir ? existsSync17(opts.dir) ? opts.dir : homedir11() : existingWorkspaceDirOrHome(configuredWorkspace ?? activeWorkspace);
14775
+ const workspace = opts.dir ? existsSync19(opts.dir) ? opts.dir : homedir13() : existingWorkspaceDirOrHome(configuredWorkspace ?? activeWorkspace);
14332
14776
  launchHarness(harness, {
14333
14777
  executable,
14334
14778
  workspace,
@@ -14700,7 +15144,7 @@ bridgeCommand.command("discover-skills").description(
14700
15144
  "20"
14701
15145
  ).action(async (opts) => {
14702
15146
  try {
14703
- const monitorDir = join20(homedir11(), ".zam", "monitor");
15147
+ const monitorDir = join22(homedir13(), ".zam", "monitor");
14704
15148
  let files;
14705
15149
  try {
14706
15150
  files = readdirSync2(monitorDir).filter((f) => f.endsWith(".jsonl"));
@@ -14713,7 +15157,7 @@ bridgeCommand.command("discover-skills").description(
14713
15157
  return;
14714
15158
  }
14715
15159
  const limit = Number(opts.limit);
14716
- const sorted = files.map((f) => ({ name: f, path: join20(monitorDir, f) })).sort((a, b) => b.name.localeCompare(a.name)).slice(0, limit);
15160
+ const sorted = files.map((f) => ({ name: f, path: join22(monitorDir, f) })).sort((a, b) => b.name.localeCompare(a.name)).slice(0, limit);
14717
15161
  const sessionCommands = /* @__PURE__ */ new Map();
14718
15162
  for (const file of sorted) {
14719
15163
  const sessionId = file.name.replace(".jsonl", "");
@@ -14825,7 +15269,7 @@ bridgeCommand.command("observe-ui-snapshot").description(
14825
15269
  });
14826
15270
  function resolveWindowsPowerShell() {
14827
15271
  try {
14828
- execFileSync3("where.exe", ["pwsh.exe"], { stdio: "ignore" });
15272
+ execFileSync4("where.exe", ["pwsh.exe"], { stdio: "ignore" });
14829
15273
  return "pwsh";
14830
15274
  } catch {
14831
15275
  return "powershell";
@@ -14840,7 +15284,7 @@ function captureScreenshot(outputPath, hwnd, processName) {
14840
15284
  throw new Error(`Invalid process name format: ${processName}`);
14841
15285
  }
14842
15286
  if (platform === "win32") {
14843
- const stdout = execFileSync3(
15287
+ const stdout = execFileSync4(
14844
15288
  resolveWindowsPowerShell(),
14845
15289
  [
14846
15290
  "-NoProfile",
@@ -15153,13 +15597,13 @@ Write-CaptureResult "fullscreen" $hwndVal $matchedBy
15153
15597
  } else if (platform === "darwin") {
15154
15598
  if (hwnd) {
15155
15599
  const parsedHwnd = hwnd.startsWith("0x") ? parseInt(hwnd, 16) : parseInt(hwnd, 10);
15156
- execFileSync3("screencapture", ["-l", String(parsedHwnd), outputPath], {
15600
+ execFileSync4("screencapture", ["-l", String(parsedHwnd), outputPath], {
15157
15601
  stdio: "pipe"
15158
15602
  });
15159
15603
  return { method: "screencapture-window", target: null };
15160
15604
  } else if (processName) {
15161
15605
  try {
15162
- const windowId = execFileSync3(
15606
+ const windowId = execFileSync4(
15163
15607
  "osascript",
15164
15608
  [
15165
15609
  "-e",
@@ -15168,17 +15612,17 @@ Write-CaptureResult "fullscreen" $hwndVal $matchedBy
15168
15612
  { encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] }
15169
15613
  ).trim();
15170
15614
  if (windowId && /^\d+$/.test(windowId)) {
15171
- execFileSync3("screencapture", ["-l", windowId, outputPath], {
15615
+ execFileSync4("screencapture", ["-l", windowId, outputPath], {
15172
15616
  stdio: "pipe"
15173
15617
  });
15174
15618
  return { method: "screencapture-window", target: null };
15175
15619
  }
15176
15620
  } catch {
15177
15621
  }
15178
- execFileSync3("screencapture", ["-x", outputPath], { stdio: "pipe" });
15622
+ execFileSync4("screencapture", ["-x", outputPath], { stdio: "pipe" });
15179
15623
  return { method: "screencapture-full", target: null };
15180
15624
  } else {
15181
- execFileSync3("screencapture", ["-x", outputPath], { stdio: "pipe" });
15625
+ execFileSync4("screencapture", ["-x", outputPath], { stdio: "pipe" });
15182
15626
  return { method: "screencapture-full", target: null };
15183
15627
  }
15184
15628
  } else {
@@ -15215,7 +15659,7 @@ bridgeCommand.command("capture-ui").description("Capture a screenshot for agent-
15215
15659
  return;
15216
15660
  }
15217
15661
  }
15218
- const outputPath = opts.image ?? opts.output ?? join20(tmpdir3(), `zam-capture-${randomBytes2(4).toString("hex")}.png`);
15662
+ const outputPath = opts.image ?? opts.output ?? join22(tmpdir3(), `zam-capture-${randomBytes2(4).toString("hex")}.png`);
15219
15663
  const captureResult = isProvided ? { method: "provided", target: null } : captureScreenshot(outputPath, opts.hwnd, opts.processName);
15220
15664
  if (!isProvided) {
15221
15665
  const post = decidePostCapture(policy, {
@@ -15243,7 +15687,7 @@ bridgeCommand.command("capture-ui").description("Capture a screenshot for agent-
15243
15687
  return;
15244
15688
  }
15245
15689
  }
15246
- const imageBytes = readFileSync14(outputPath);
15690
+ const imageBytes = readFileSync16(outputPath);
15247
15691
  const base64 = imageBytes.toString("base64");
15248
15692
  jsonOut2({
15249
15693
  sessionId: opts.session ?? null,
@@ -15270,11 +15714,11 @@ bridgeCommand.command("start-recording").description("Start screen recording in
15270
15714
  return;
15271
15715
  }
15272
15716
  const sessionId = opts.session;
15273
- const statePath = join20(tmpdir3(), `zam-recording-${sessionId}.json`);
15717
+ const statePath = join22(tmpdir3(), `zam-recording-${sessionId}.json`);
15274
15718
  const defaultExt = platform === "win32" ? ".mkv" : ".mov";
15275
- const outputPath = opts.output ?? join20(tmpdir3(), `zam-recording-${sessionId}${defaultExt}`);
15276
- const { existsSync: existsSync26, writeFileSync: writeFileSync14, openSync, closeSync } = await import("fs");
15277
- if (existsSync26(statePath)) {
15719
+ const outputPath = opts.output ?? join22(tmpdir3(), `zam-recording-${sessionId}${defaultExt}`);
15720
+ const { existsSync: existsSync28, writeFileSync: writeFileSync16, openSync, closeSync } = await import("fs");
15721
+ if (existsSync28(statePath)) {
15278
15722
  jsonOut2({
15279
15723
  sessionId,
15280
15724
  started: false,
@@ -15282,7 +15726,7 @@ bridgeCommand.command("start-recording").description("Start screen recording in
15282
15726
  });
15283
15727
  return;
15284
15728
  }
15285
- const logPath = join20(tmpdir3(), `zam-recording-${sessionId}.log`);
15729
+ const logPath = join22(tmpdir3(), `zam-recording-${sessionId}.log`);
15286
15730
  let logFd;
15287
15731
  try {
15288
15732
  logFd = openSync(logPath, "w");
@@ -15328,7 +15772,7 @@ bridgeCommand.command("start-recording").description("Start screen recording in
15328
15772
  }
15329
15773
  child.unref();
15330
15774
  if (child.pid) {
15331
- writeFileSync14(
15775
+ writeFileSync16(
15332
15776
  statePath,
15333
15777
  JSON.stringify({
15334
15778
  pid: child.pid,
@@ -15364,9 +15808,9 @@ bridgeCommand.command("stop-recording").description(
15364
15808
  return;
15365
15809
  }
15366
15810
  const sessionId = opts.session;
15367
- const statePath = join20(tmpdir3(), `zam-recording-${sessionId}.json`);
15368
- const { existsSync: existsSync26, readFileSync: readFileSync19, rmSync: rmSync4 } = await import("fs");
15369
- if (!existsSync26(statePath)) {
15811
+ const statePath = join22(tmpdir3(), `zam-recording-${sessionId}.json`);
15812
+ const { existsSync: existsSync28, readFileSync: readFileSync21, rmSync: rmSync4 } = await import("fs");
15813
+ if (!existsSync28(statePath)) {
15370
15814
  jsonOut2({
15371
15815
  sessionId,
15372
15816
  stopped: false,
@@ -15374,7 +15818,7 @@ bridgeCommand.command("stop-recording").description(
15374
15818
  });
15375
15819
  return;
15376
15820
  }
15377
- const state = JSON.parse(readFileSync19(statePath, "utf8"));
15821
+ const state = JSON.parse(readFileSync21(statePath, "utf8"));
15378
15822
  const { pid, outputPath } = state;
15379
15823
  try {
15380
15824
  process.kill(pid, "SIGINT");
@@ -15390,7 +15834,7 @@ bridgeCommand.command("stop-recording").description(
15390
15834
  };
15391
15835
  let attempts = 0;
15392
15836
  while (isProcessRunning(pid) && attempts < 20) {
15393
- await new Promise((resolve10) => setTimeout(resolve10, 250));
15837
+ await new Promise((resolve11) => setTimeout(resolve11, 250));
15394
15838
  attempts++;
15395
15839
  }
15396
15840
  if (isProcessRunning(pid)) {
@@ -15403,7 +15847,7 @@ bridgeCommand.command("stop-recording").description(
15403
15847
  rmSync4(statePath, { force: true });
15404
15848
  } catch {
15405
15849
  }
15406
- if (!existsSync26(outputPath)) {
15850
+ if (!existsSync28(outputPath)) {
15407
15851
  jsonOut2({
15408
15852
  sessionId,
15409
15853
  stopped: false,
@@ -15640,7 +16084,7 @@ bridgeCommand.command("cloud-model-hint").description("Suggest a cloud model for
15640
16084
  });
15641
16085
  bridgeCommand.command("local-llm-hints").description("Detect installed local LLM servers and suggest defaults (JSON)").action(() => {
15642
16086
  const profile = getSystemProfile();
15643
- const flmInstalled = hasCommand("flm") || existsSync17("C:\\Program Files\\flm\\flm.exe");
16087
+ const flmInstalled = hasCommand("flm") || existsSync19("C:\\Program Files\\flm\\flm.exe");
15644
16088
  const ollamaInstalled = isOllamaInstalled();
15645
16089
  const runners = [
15646
16090
  { id: "flm", label: "FastFlowLM", installed: flmInstalled },
@@ -18190,26 +18634,26 @@ var doctorCommand = new Command5("doctor").description(
18190
18634
  // src/cli/commands/git-sync.ts
18191
18635
  init_kernel();
18192
18636
  import { execSync as execSync5 } from "child_process";
18193
- import { chmodSync as chmodSync2, existsSync as existsSync18, writeFileSync as writeFileSync10 } from "fs";
18194
- import { join as join21 } from "path";
18637
+ import { chmodSync as chmodSync2, existsSync as existsSync20, writeFileSync as writeFileSync12 } from "fs";
18638
+ import { join as join23 } from "path";
18195
18639
  import { Command as Command6 } from "commander";
18196
18640
  function installHook2() {
18197
- const gitDir = join21(process.cwd(), ".git");
18198
- if (!existsSync18(gitDir)) {
18641
+ const gitDir = join23(process.cwd(), ".git");
18642
+ if (!existsSync20(gitDir)) {
18199
18643
  console.error(
18200
18644
  "Error: Current directory is not the root of a Git repository."
18201
18645
  );
18202
18646
  process.exit(1);
18203
18647
  }
18204
- const hooksDir = join21(gitDir, "hooks");
18205
- const hookPath = join21(hooksDir, "post-commit");
18648
+ const hooksDir = join23(gitDir, "hooks");
18649
+ const hookPath = join23(hooksDir, "post-commit");
18206
18650
  const hookContent = `#!/bin/sh
18207
18651
  # ZAM Spaced Repetition Auto-Stale Hook
18208
18652
  # Triggered automatically on git commits to decay modified concept cards.
18209
18653
  zam git-sync --commit HEAD --quiet
18210
18654
  `;
18211
18655
  try {
18212
- writeFileSync10(hookPath, hookContent, { encoding: "utf-8", flag: "w" });
18656
+ writeFileSync12(hookPath, hookContent, { encoding: "utf-8", flag: "w" });
18213
18657
  try {
18214
18658
  chmodSync2(hookPath, "755");
18215
18659
  } catch (_e) {
@@ -18312,8 +18756,8 @@ ZAM Auto-Stale Complete: Scanned ${changedFiles.length} file(s).`
18312
18756
 
18313
18757
  // src/cli/commands/goal.ts
18314
18758
  init_kernel();
18315
- import { existsSync as existsSync19, mkdirSync as mkdirSync13 } from "fs";
18316
- import { resolve as resolve5 } from "path";
18759
+ import { existsSync as existsSync21, mkdirSync as mkdirSync15 } from "fs";
18760
+ import { resolve as resolve6 } from "path";
18317
18761
  import { input as input2 } from "@inquirer/prompts";
18318
18762
  import { Command as Command7 } from "commander";
18319
18763
  async function resolveGoalsDir() {
@@ -18326,7 +18770,7 @@ async function resolveGoalsDir() {
18326
18770
  } finally {
18327
18771
  await db?.close();
18328
18772
  }
18329
- return goalsDir ? resolve5(goalsDir) : resolve5("goals");
18773
+ return goalsDir ? resolve6(goalsDir) : resolve6("goals");
18330
18774
  }
18331
18775
  var goalCommand = new Command7("goal").description(
18332
18776
  "Manage learning goals (markdown files)"
@@ -18336,7 +18780,7 @@ goalCommand.command("list").description("List all goals").option(
18336
18780
  "Filter by status (active, completed, paused, abandoned)"
18337
18781
  ).option("--tree", "Show goals as a tree with parent/child relationships").option("--json", "Output as JSON").action(async (opts) => {
18338
18782
  const goalsDir = await resolveGoalsDir();
18339
- if (!existsSync19(goalsDir)) {
18783
+ if (!existsSync21(goalsDir)) {
18340
18784
  console.error(`Goals directory not found: ${goalsDir}`);
18341
18785
  console.error(
18342
18786
  "Set it with: zam settings set personal.goals_dir /path/to/goals"
@@ -18437,8 +18881,8 @@ ${"\u2500".repeat(50)}`);
18437
18881
  });
18438
18882
  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) => {
18439
18883
  const goalsDir = await resolveGoalsDir();
18440
- if (!existsSync19(goalsDir)) {
18441
- mkdirSync13(goalsDir, { recursive: true });
18884
+ if (!existsSync21(goalsDir)) {
18885
+ mkdirSync15(goalsDir, { recursive: true });
18442
18886
  }
18443
18887
  let slug = opts.slug;
18444
18888
  let title = opts.title;
@@ -18498,22 +18942,22 @@ goalCommand.command("status <slug> <status>").description("Update a goal's statu
18498
18942
 
18499
18943
  // src/cli/commands/init.ts
18500
18944
  init_kernel();
18501
- import { existsSync as existsSync20, mkdirSync as mkdirSync14, writeFileSync as writeFileSync11 } from "fs";
18502
- import { homedir as homedir12 } from "os";
18503
- import { join as join22, resolve as resolve6 } from "path";
18945
+ import { existsSync as existsSync22, mkdirSync as mkdirSync16, writeFileSync as writeFileSync13 } from "fs";
18946
+ import { homedir as homedir14 } from "os";
18947
+ import { join as join24, resolve as resolve7 } from "path";
18504
18948
  import { confirm, input as input3 } from "@inquirer/prompts";
18505
18949
  import { Command as Command8 } from "commander";
18506
- var HOME2 = homedir12();
18950
+ var HOME2 = homedir14();
18507
18951
  function printLine(char = "\u2550", len = 60, color = "\x1B[36m") {
18508
18952
  console.log(`${color}${char.repeat(len)}\x1B[0m`);
18509
18953
  }
18510
18954
  function bootstrapSandboxWorkspace(workspaceDir) {
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");
18515
- if (!existsSync20(worldviewFile)) {
18516
- writeFileSync11(
18955
+ mkdirSync16(join24(workspaceDir, "beliefs"), { recursive: true });
18956
+ mkdirSync16(join24(workspaceDir, "goals"), { recursive: true });
18957
+ mkdirSync16(join24(workspaceDir, "skills"), { recursive: true });
18958
+ const worldviewFile = join24(workspaceDir, "beliefs", "worldview.md");
18959
+ if (!existsSync22(worldviewFile)) {
18960
+ writeFileSync13(
18517
18961
  worldviewFile,
18518
18962
  `# Personal Worldview
18519
18963
 
@@ -18525,9 +18969,9 @@ Here, I declare the core concepts and principles I want to master.
18525
18969
  "utf8"
18526
18970
  );
18527
18971
  }
18528
- const goalsFile = join22(workspaceDir, "goals", "goals.md");
18529
- if (!existsSync20(goalsFile)) {
18530
- writeFileSync11(
18972
+ const goalsFile = join24(workspaceDir, "goals", "goals.md");
18973
+ if (!existsSync22(goalsFile)) {
18974
+ writeFileSync13(
18531
18975
  goalsFile,
18532
18976
  `# Personal Goals
18533
18977
 
@@ -18549,8 +18993,8 @@ var initCommand = new Command8("init").description("Launch the guided interactiv
18549
18993
  );
18550
18994
  printLine();
18551
18995
  console.log("\n\x1B[1m[1/5] Setting up Local Workspace Sandbox\x1B[0m");
18552
- const defaultWorkspace = join22(HOME2, "Documents", "zam");
18553
- const workspacePath = resolve6(
18996
+ const defaultWorkspace = join24(HOME2, "Documents", "zam");
18997
+ const workspacePath = resolve7(
18554
18998
  await input3({
18555
18999
  message: "Choose your ZAM workspace directory:",
18556
19000
  default: defaultWorkspace
@@ -19751,7 +20195,7 @@ observerCommand.command("revoke <process>").description("Remove a process from o
19751
20195
 
19752
20196
  // src/cli/commands/profile.ts
19753
20197
  init_kernel();
19754
- import { dirname as dirname8, resolve as resolve7 } from "path";
20198
+ import { dirname as dirname10, resolve as resolve8 } from "path";
19755
20199
  import { Command as Command13 } from "commander";
19756
20200
  var C2 = {
19757
20201
  reset: "\x1B[0m",
@@ -19779,7 +20223,7 @@ var profileCommand = new Command13("profile").description("Show or change this m
19779
20223
  if (opts.mode) setInstallMode(opts.mode);
19780
20224
  db = await openDatabaseWithSync({ initialize: true });
19781
20225
  if (opts.dir) {
19782
- await activateWorkspacePath(db, resolve7(opts.dir), {
20226
+ await activateWorkspacePath(db, resolve8(opts.dir), {
19783
20227
  kind: "personal",
19784
20228
  label: "Personal"
19785
20229
  });
@@ -19792,7 +20236,7 @@ var profileCommand = new Command13("profile").description("Show or change this m
19792
20236
  mode: getInstallMode(),
19793
20237
  personalDir,
19794
20238
  syncProvider: detectSyncProvider(personalDir),
19795
- dataDir: dirname8(dbPath),
20239
+ dataDir: dirname10(dbPath),
19796
20240
  dbPath
19797
20241
  };
19798
20242
  if (opts.json) {
@@ -20181,7 +20625,7 @@ ${"\u2550".repeat(50)}`);
20181
20625
 
20182
20626
  // src/cli/commands/session.ts
20183
20627
  init_kernel();
20184
- import { readFileSync as readFileSync15 } from "fs";
20628
+ import { readFileSync as readFileSync17 } from "fs";
20185
20629
  import { input as input6, select as select2 } from "@inquirer/prompts";
20186
20630
  import { Command as Command16 } from "commander";
20187
20631
  var sessionCommand = new Command16("session").description(
@@ -20372,7 +20816,7 @@ function loadPatternFile(path) {
20372
20816
  if (!path) return [];
20373
20817
  let parsed;
20374
20818
  try {
20375
- parsed = JSON.parse(readFileSync15(path, "utf-8"));
20819
+ parsed = JSON.parse(readFileSync17(path, "utf-8"));
20376
20820
  } catch (err) {
20377
20821
  throw new Error(
20378
20822
  `Cannot read synthesis patterns from ${path}: ${err.message}`
@@ -20563,7 +21007,7 @@ sessionCommand.command("end").description("End a session and show summary").requ
20563
21007
 
20564
21008
  // src/cli/commands/settings.ts
20565
21009
  init_kernel();
20566
- import { existsSync as existsSync21 } from "fs";
21010
+ import { existsSync as existsSync23 } from "fs";
20567
21011
  import { Command as Command17 } from "commander";
20568
21012
  var settingsCommand = new Command17("settings").description(
20569
21013
  "Manage user settings"
@@ -20728,7 +21172,7 @@ settingsCommand.command("repos").description("Show or set Personal, Team, and Or
20728
21172
  console.log("\nValidation:");
20729
21173
  for (const [name, path] of Object.entries(paths)) {
20730
21174
  if (path) {
20731
- const exists = existsSync21(path);
21175
+ const exists = existsSync23(path);
20732
21176
  console.log(
20733
21177
  ` ${name.padEnd(9)}: ${exists ? "\x1B[32m\u2713 Valid folder\x1B[0m" : "\x1B[31m\u2717 Directory does not exist\x1B[0m"}`
20734
21178
  );
@@ -20741,7 +21185,7 @@ settingsCommand.command("repos").description("Show or set Personal, Team, and Or
20741
21185
 
20742
21186
  // src/cli/commands/setup.ts
20743
21187
  init_kernel();
20744
- import { resolve as resolve8 } from "path";
21188
+ import { resolve as resolve9 } from "path";
20745
21189
  import { Command as Command18 } from "commander";
20746
21190
  function formatDatabaseInitTarget(target) {
20747
21191
  switch (target.kind) {
@@ -20801,7 +21245,7 @@ var setupCommand = new Command18("setup").description(
20801
21245
  console.error(`Error: ${err.message}`);
20802
21246
  process.exit(1);
20803
21247
  }
20804
- const target = resolve8(opts.target ?? process.cwd());
21248
+ const target = resolve9(opts.target ?? process.cwd());
20805
21249
  const updateExistingInstructions = Boolean(opts.target) || opts.force;
20806
21250
  console.log(
20807
21251
  `Setting up ZAM in ${target}${opts.dryRun ? " (dry run)" : ""}
@@ -20925,8 +21369,8 @@ skillCommand.command("add").description("Register a new agent skill").requiredOp
20925
21369
 
20926
21370
  // src/cli/commands/snapshot.ts
20927
21371
  init_kernel();
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";
21372
+ import { existsSync as existsSync24, mkdirSync as mkdirSync17, readFileSync as readFileSync18, writeFileSync as writeFileSync14 } from "fs";
21373
+ import { dirname as dirname11, join as join25 } from "path";
20930
21374
  import { Command as Command20 } from "commander";
20931
21375
  function defaultOutName() {
20932
21376
  const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d+Z$/, "").replace(/:/g, "-");
@@ -20955,12 +21399,12 @@ var exportCmd = new Command20("export").description("Write a portable SQL-text s
20955
21399
  process.stdout.write(snapshot);
20956
21400
  return;
20957
21401
  }
20958
- const out = opts.out ?? join23(personalDir, "snapshots", defaultOutName());
20959
- const dir = dirname9(out);
20960
- if (dir && dir !== "." && !existsSync22(dir)) {
20961
- mkdirSync15(dir, { recursive: true });
21402
+ const out = opts.out ?? join25(personalDir, "snapshots", defaultOutName());
21403
+ const dir = dirname11(out);
21404
+ if (dir && dir !== "." && !existsSync24(dir)) {
21405
+ mkdirSync17(dir, { recursive: true });
20962
21406
  }
20963
- writeFileSync12(out, snapshot, "utf-8");
21407
+ writeFileSync14(out, snapshot, "utf-8");
20964
21408
  console.log(`Snapshot written: ${out}`);
20965
21409
  console.log(
20966
21410
  ` ${total} row(s)${nonEmpty.length ? ` \u2014 ${nonEmpty.join(", ")}` : ""}`
@@ -20974,11 +21418,11 @@ var exportCmd = new Command20("export").description("Write a portable SQL-text s
20974
21418
  var importCmd = new Command20("import").description("Restore a snapshot into the database").argument("<file>", "Snapshot file to restore").option("--force", "Overwrite a non-empty database", false).action(async (file, opts) => {
20975
21419
  let db;
20976
21420
  try {
20977
- if (!existsSync22(file)) {
21421
+ if (!existsSync24(file)) {
20978
21422
  console.error(`Error: Snapshot file not found: ${file}`);
20979
21423
  process.exit(1);
20980
21424
  }
20981
- const snapshot = readFileSync16(file, "utf-8");
21425
+ const snapshot = readFileSync18(file, "utf-8");
20982
21426
  db = await openDatabaseWithSync({ initialize: true });
20983
21427
  const result = await importSnapshot(db, snapshot, { force: opts.force });
20984
21428
  await db.close();
@@ -20996,11 +21440,11 @@ var importCmd = new Command20("import").description("Restore a snapshot into the
20996
21440
  });
20997
21441
  var verifyCmd = new Command20("verify").description("Check a snapshot's manifest and checksum without importing").argument("<file>", "Snapshot file to verify").action((file) => {
20998
21442
  try {
20999
- if (!existsSync22(file)) {
21443
+ if (!existsSync24(file)) {
21000
21444
  console.error(`Error: Snapshot file not found: ${file}`);
21001
21445
  process.exit(1);
21002
21446
  }
21003
- const manifest = verifySnapshot(readFileSync16(file, "utf-8"));
21447
+ const manifest = verifySnapshot(readFileSync18(file, "utf-8"));
21004
21448
  const { total, nonEmpty } = summarize(manifest.tables);
21005
21449
  console.log(`Valid snapshot (format v${manifest.version})`);
21006
21450
  console.log(` created: ${manifest.createdAt}`);
@@ -21549,10 +21993,10 @@ tokenCommand.command("reembed").description("Backfill or refresh semantic-search
21549
21993
  // src/cli/commands/ui.ts
21550
21994
  init_kernel();
21551
21995
  import { spawn as spawn3, spawnSync } from "child_process";
21552
- import { existsSync as existsSync23 } from "fs";
21553
- import { homedir as homedir13 } from "os";
21554
- import { dirname as dirname10, join as join24 } from "path";
21555
- import { fileURLToPath as fileURLToPath4 } from "url";
21996
+ import { existsSync as existsSync25 } from "fs";
21997
+ import { homedir as homedir15 } from "os";
21998
+ import { dirname as dirname12, join as join26 } from "path";
21999
+ import { fileURLToPath as fileURLToPath6 } from "url";
21556
22000
  import { Command as Command23 } from "commander";
21557
22001
  var C3 = {
21558
22002
  reset: "\x1B[0m",
@@ -21563,14 +22007,14 @@ var C3 = {
21563
22007
  dim: "\x1B[2m"
21564
22008
  };
21565
22009
  function findDesktopDir() {
21566
- const starts = [process.cwd(), dirname10(fileURLToPath4(import.meta.url))];
22010
+ const starts = [process.cwd(), dirname12(fileURLToPath6(import.meta.url))];
21567
22011
  for (const start of starts) {
21568
22012
  let dir = start;
21569
22013
  for (let i = 0; i < 10; i++) {
21570
- if (existsSync23(join24(dir, "desktop", "src-tauri", "tauri.conf.json"))) {
21571
- return join24(dir, "desktop");
22014
+ if (existsSync25(join26(dir, "desktop", "src-tauri", "tauri.conf.json"))) {
22015
+ return join26(dir, "desktop");
21572
22016
  }
21573
- const parent = dirname10(dir);
22017
+ const parent = dirname12(dir);
21574
22018
  if (parent === dir) break;
21575
22019
  dir = parent;
21576
22020
  }
@@ -21578,30 +22022,30 @@ function findDesktopDir() {
21578
22022
  return null;
21579
22023
  }
21580
22024
  function findBuiltApp(desktopDir) {
21581
- const releaseDir = join24(desktopDir, "src-tauri", "target", "release");
22025
+ const releaseDir = join26(desktopDir, "src-tauri", "target", "release");
21582
22026
  if (process.platform === "win32") {
21583
22027
  for (const name of ["ZAM.exe", "zam.exe", "zam-desktop.exe"]) {
21584
- const p = join24(releaseDir, name);
21585
- if (existsSync23(p)) return p;
22028
+ const p = join26(releaseDir, name);
22029
+ if (existsSync25(p)) return p;
21586
22030
  }
21587
22031
  } else if (process.platform === "darwin") {
21588
- const app = join24(releaseDir, "bundle", "macos", "ZAM.app");
21589
- if (existsSync23(app)) return app;
22032
+ const app = join26(releaseDir, "bundle", "macos", "ZAM.app");
22033
+ if (existsSync25(app)) return app;
21590
22034
  } else {
21591
22035
  for (const name of ["zam", "ZAM", "zam-desktop"]) {
21592
- const p = join24(releaseDir, name);
21593
- if (existsSync23(p)) return p;
22036
+ const p = join26(releaseDir, name);
22037
+ if (existsSync25(p)) return p;
21594
22038
  }
21595
22039
  }
21596
22040
  return null;
21597
22041
  }
21598
22042
  function findInstalledApp() {
21599
22043
  const candidates = process.platform === "win32" ? [
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"];
21604
- return candidates.find((candidate) => candidate && existsSync23(candidate)) || null;
22044
+ process.env.LOCALAPPDATA && join26(process.env.LOCALAPPDATA, "Programs", "ZAM", "ZAM.exe"),
22045
+ process.env.ProgramFiles && join26(process.env.ProgramFiles, "ZAM", "ZAM.exe"),
22046
+ process.env["ProgramFiles(x86)"] && join26(process.env["ProgramFiles(x86)"], "ZAM", "ZAM.exe")
22047
+ ] : process.platform === "darwin" ? ["/Applications/ZAM.app", join26(homedir15(), "Applications", "ZAM.app")] : ["/opt/ZAM/zam", "/usr/bin/zam-desktop"];
22048
+ return candidates.find((candidate) => candidate && existsSync25(candidate)) || null;
21605
22049
  }
21606
22050
  function runNpm(args, opts) {
21607
22051
  const res = spawnSync("npm", args, {
@@ -21612,7 +22056,7 @@ function runNpm(args, opts) {
21612
22056
  return res.status ?? 1;
21613
22057
  }
21614
22058
  function ensureDesktopDeps(desktopDir) {
21615
- if (existsSync23(join24(desktopDir, "node_modules"))) return true;
22059
+ if (existsSync25(join26(desktopDir, "node_modules"))) return true;
21616
22060
  console.log(
21617
22061
  `${C3.cyan}Installing desktop dependencies (one-time)...${C3.reset}`
21618
22062
  );
@@ -21638,13 +22082,13 @@ function requireRust() {
21638
22082
  function hasMsvcBuildTools() {
21639
22083
  if (process.platform !== "win32") return true;
21640
22084
  const pf86 = process.env["ProgramFiles(x86)"] || "C:\\Program Files (x86)";
21641
- const vswhere = join24(
22085
+ const vswhere = join26(
21642
22086
  pf86,
21643
22087
  "Microsoft Visual Studio",
21644
22088
  "Installer",
21645
22089
  "vswhere.exe"
21646
22090
  );
21647
- if (!existsSync23(vswhere)) return false;
22091
+ if (!existsSync25(vswhere)) return false;
21648
22092
  const res = spawnSync(
21649
22093
  vswhere,
21650
22094
  [
@@ -21676,7 +22120,7 @@ function requireMsvcOnWindows() {
21676
22120
  return false;
21677
22121
  }
21678
22122
  function warnIfCliMissing(repoRoot) {
21679
- if (!existsSync23(join24(repoRoot, "dist", "cli", "index.js"))) {
22123
+ if (!existsSync25(join26(repoRoot, "dist", "cli", "index.js"))) {
21680
22124
  console.warn(
21681
22125
  `${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}`
21682
22126
  );
@@ -21739,7 +22183,7 @@ var uiCommand = new Command23("ui").description("Launch the ZAM Desktop GUI (Act
21739
22183
  ).option("--shortcut", "Create Desktop + Start-menu shortcuts to the GUI").action((opts) => {
21740
22184
  const installedApp = findInstalledApp();
21741
22185
  if (!opts.dev && !opts.build && !opts.shortcut && installedApp) {
21742
- launchApp(installedApp, homedir13());
22186
+ launchApp(installedApp, homedir15());
21743
22187
  return;
21744
22188
  }
21745
22189
  const desktopDir = findDesktopDir();
@@ -21749,7 +22193,7 @@ var uiCommand = new Command23("ui").description("Launch the ZAM Desktop GUI (Act
21749
22193
  );
21750
22194
  process.exit(1);
21751
22195
  }
21752
- const repoRoot = dirname10(desktopDir);
22196
+ const repoRoot = dirname12(desktopDir);
21753
22197
  if (opts.build) {
21754
22198
  if (!requireRust()) process.exit(1);
21755
22199
  if (!requireMsvcOnWindows()) process.exit(1);
@@ -21760,7 +22204,7 @@ var uiCommand = new Command23("ui").description("Launch the ZAM Desktop GUI (Act
21760
22204
  );
21761
22205
  const code = runNpm(["run", "tauri", "build"], { cwd: desktopDir });
21762
22206
  if (code === 0) {
21763
- const bundle = join24(
22207
+ const bundle = join26(
21764
22208
  desktopDir,
21765
22209
  "src-tauri",
21766
22210
  "target",
@@ -21800,7 +22244,7 @@ ${C3.green}\u2713 Done. Installer is in:${C3.reset}
21800
22244
  );
21801
22245
  process.exit(1);
21802
22246
  }
21803
- createShortcuts(shortcutTarget, dirname10(shortcutTarget));
22247
+ createShortcuts(shortcutTarget, dirname12(shortcutTarget));
21804
22248
  return;
21805
22249
  }
21806
22250
  if (builtApp) {
@@ -21838,9 +22282,9 @@ ${C3.dim}After that, 'zam ui' launches it directly.${C3.reset}`
21838
22282
  // src/cli/commands/update.ts
21839
22283
  init_kernel();
21840
22284
  import { spawnSync as spawnSync2 } from "child_process";
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";
22285
+ import { existsSync as existsSync26, readFileSync as readFileSync19, realpathSync as realpathSync2 } from "fs";
22286
+ import { dirname as dirname13, join as join27 } from "path";
22287
+ import { fileURLToPath as fileURLToPath7 } from "url";
21844
22288
  import { confirm as confirm3 } from "@inquirer/prompts";
21845
22289
  import { Command as Command24 } from "commander";
21846
22290
  var CHANNELS = [
@@ -21861,7 +22305,7 @@ var C4 = {
21861
22305
  function versionAt(dir) {
21862
22306
  try {
21863
22307
  const pkg2 = JSON.parse(
21864
- readFileSync17(join25(dir, "package.json"), "utf-8")
22308
+ readFileSync19(join27(dir, "package.json"), "utf-8")
21865
22309
  );
21866
22310
  return pkg2.version ?? "unknown";
21867
22311
  } catch {
@@ -21919,14 +22363,14 @@ var checkCmd = new Command24("check").description("Check whether a newer ZAM has
21919
22363
  }
21920
22364
  );
21921
22365
  function findSourceRepo() {
21922
- let dir = realpathSync2(dirname11(fileURLToPath5(import.meta.url)));
21923
- let parent = dirname11(dir);
22366
+ let dir = realpathSync2(dirname13(fileURLToPath7(import.meta.url)));
22367
+ let parent = dirname13(dir);
21924
22368
  while (parent !== dir) {
21925
- if (existsSync24(join25(dir, ".git"))) return dir;
22369
+ if (existsSync26(join27(dir, ".git"))) return dir;
21926
22370
  dir = parent;
21927
- parent = dirname11(dir);
22371
+ parent = dirname13(dir);
21928
22372
  }
21929
- return existsSync24(join25(dir, ".git")) ? dir : null;
22373
+ return existsSync26(join27(dir, ".git")) ? dir : null;
21930
22374
  }
21931
22375
  function runGit(cwd, args, capture) {
21932
22376
  const res = spawnSync2("git", args, {
@@ -21947,7 +22391,7 @@ function runNpm2(args, cwd) {
21947
22391
  function smokeTestBuild(src) {
21948
22392
  const res = spawnSync2(
21949
22393
  process.execPath,
21950
- [join25(src, "dist", "cli", "index.js"), "--version"],
22394
+ [join27(src, "dist", "cli", "index.js"), "--version"],
21951
22395
  {
21952
22396
  cwd: src,
21953
22397
  encoding: "utf8",
@@ -22027,7 +22471,7 @@ Fix it manually in ${src} (try \`npm ci && npm run build\`, and check your Node
22027
22471
  console.log(`${C4.dim}\u2192 zam setup --force${C4.reset}`);
22028
22472
  const setup = spawnSync2(
22029
22473
  process.execPath,
22030
- [join25(src, "dist", "cli", "index.js"), "setup", "--force"],
22474
+ [join27(src, "dist", "cli", "index.js"), "setup", "--force"],
22031
22475
  { cwd: process.cwd(), stdio: "inherit" }
22032
22476
  );
22033
22477
  if (setup.status !== 0) {
@@ -22139,15 +22583,15 @@ var whoamiCommand = new Command25("whoami").description("Show or set the default
22139
22583
 
22140
22584
  // src/cli/commands/workspace.ts
22141
22585
  init_kernel();
22142
- import { execFileSync as execFileSync4 } from "child_process";
22143
- import { existsSync as existsSync25, writeFileSync as writeFileSync13 } from "fs";
22144
- import { homedir as homedir14 } from "os";
22145
- import { join as join26, resolve as resolve9 } from "path";
22586
+ import { execFileSync as execFileSync5 } from "child_process";
22587
+ import { existsSync as existsSync27, writeFileSync as writeFileSync15 } from "fs";
22588
+ import { homedir as homedir16 } from "os";
22589
+ import { join as join28, resolve as resolve10 } from "path";
22146
22590
  import { confirm as confirm4, input as input7 } from "@inquirer/prompts";
22147
22591
  import { Command as Command26 } from "commander";
22148
22592
  function runGit2(cwd, args) {
22149
22593
  try {
22150
- return execFileSync4("git", args, {
22594
+ return execFileSync5("git", args, {
22151
22595
  cwd,
22152
22596
  stdio: "pipe",
22153
22597
  encoding: "utf8"
@@ -22226,7 +22670,7 @@ workspaceCommand.command("list").description("List configured ZAM workspaces").o
22226
22670
  const workspaces = getConfiguredWorkspaces();
22227
22671
  const agents = parseSetupAgents();
22228
22672
  const linkHealth = Object.fromEntries(
22229
- workspaces.filter((workspace) => existsSync25(workspace.path)).map((workspace) => [
22673
+ workspaces.filter((workspace) => existsSync27(workspace.path)).map((workspace) => [
22230
22674
  workspace.id,
22231
22675
  summarizeSkillLinkHealth(inspectSkillLinks(workspace.path, agents))
22232
22676
  ])
@@ -22268,8 +22712,8 @@ workspaceCommand.command("add <id>").description("Register an existing directory
22268
22712
  `Source-control provider (${WORKSPACE_SOURCE_CONTROLS.join(" | ")})`
22269
22713
  ).option("--scopes <list>", "Comma-separated knowledge scopes").option("--default-agent <id>", "Default agent harness for this workspace").action((id, opts) => {
22270
22714
  try {
22271
- const path = resolve9(String(opts.path));
22272
- if (!existsSync25(path)) {
22715
+ const path = resolve10(String(opts.path));
22716
+ if (!existsSync27(path)) {
22273
22717
  console.error(`Workspace path does not exist: ${path}`);
22274
22718
  process.exit(1);
22275
22719
  }
@@ -22363,7 +22807,7 @@ workspaceCommand.command("publish").description("Publish your local workspace sa
22363
22807
  );
22364
22808
  process.exit(1);
22365
22809
  }
22366
- if (!existsSync25(workspaceDir)) {
22810
+ if (!existsSync27(workspaceDir)) {
22367
22811
  console.error(
22368
22812
  `\x1B[31m\u2717 Workspace directory does not exist: ${workspaceDir}\x1B[0m`
22369
22813
  );
@@ -22377,15 +22821,15 @@ Active workspace: \x1B[36m${workspaceDir}\x1B[0m`);
22377
22821
  );
22378
22822
  process.exit(1);
22379
22823
  }
22380
- const gitignorePath = join26(workspaceDir, ".gitignore");
22381
- if (!existsSync25(gitignorePath)) {
22382
- writeFileSync13(
22824
+ const gitignorePath = join28(workspaceDir, ".gitignore");
22825
+ if (!existsSync27(gitignorePath)) {
22826
+ writeFileSync15(
22383
22827
  gitignorePath,
22384
22828
  "node_modules/\n.agent/\n.agents/\n.claude/\n.gemini/\n.goose/\n*.log\n",
22385
22829
  "utf8"
22386
22830
  );
22387
22831
  }
22388
- const hasGitRepo = existsSync25(join26(workspaceDir, ".git"));
22832
+ const hasGitRepo = existsSync27(join28(workspaceDir, ".git"));
22389
22833
  if (!hasGitRepo) {
22390
22834
  console.log("Initializing local Git repository...");
22391
22835
  runGit2(workspaceDir, ["init", "-b", "main"]);
@@ -22417,7 +22861,7 @@ Active workspace: \x1B[36m${workspaceDir}\x1B[0m`);
22417
22861
  if (proceedGh) {
22418
22862
  try {
22419
22863
  console.log(`Creating GitHub repository ${repoName}...`);
22420
- execFileSync4("gh", ghRepoCreateArgs(repoName, repoVisibility), {
22864
+ execFileSync5("gh", ghRepoCreateArgs(repoName, repoVisibility), {
22421
22865
  cwd: workspaceDir,
22422
22866
  stdio: "inherit"
22423
22867
  });
@@ -22472,7 +22916,7 @@ Active workspace: \x1B[36m${workspaceDir}\x1B[0m`);
22472
22916
  }
22473
22917
  });
22474
22918
  workspaceCommand.command("data-dir").description("Print the ZAM data directory (database, credentials, config)").option("--json", "Output as JSON").action((opts) => {
22475
- const dir = join26(homedir14(), ".zam");
22919
+ const dir = join28(homedir16(), ".zam");
22476
22920
  console.log(opts.json ? JSON.stringify({ dataDir: dir }) : dir);
22477
22921
  });
22478
22922
  workspaceCommand.command("backup").description("Back up the local ZAM database into your workspace").option(
@@ -22513,9 +22957,9 @@ workspaceCommand.command("backup").description("Back up the local ZAM database i
22513
22957
  });
22514
22958
 
22515
22959
  // src/cli/app.ts
22516
- var __dirname = dirname12(fileURLToPath6(import.meta.url));
22960
+ var __dirname = dirname14(fileURLToPath8(import.meta.url));
22517
22961
  var pkg = JSON.parse(
22518
- readFileSync18(join27(__dirname, "..", "..", "package.json"), "utf-8")
22962
+ readFileSync20(join29(__dirname, "..", "..", "package.json"), "utf-8")
22519
22963
  );
22520
22964
  var program = new Command27();
22521
22965
  program.name("zam").description(