zam-core 0.10.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -3
- package/dist/cli/app.js +385 -234
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/commands/mcp.js +14 -10
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/copilot-extension/extension.mjs +520 -0
- package/dist/copilot-extension/host.bundle.js +5317 -0
- package/dist/copilot-extension/manifest.json +9 -0
- package/dist/copilot-extension/mcp-client.bundle.mjs +74 -0
- package/dist/ui/graph-panel.html +21 -18
- package/dist/ui/recall-panel.html +50 -7
- package/dist/ui/studio-panel.html +1 -1
- package/package.json +3 -2
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
|
|
5484
|
+
const packageRoot3 = [
|
|
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 (!
|
|
5489
|
+
if (!packageRoot3) return "";
|
|
5490
5490
|
if (agent === "codex") {
|
|
5491
|
-
const codexPath = join8(
|
|
5491
|
+
const codexPath = join8(packageRoot3, ".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
|
-
|
|
5497
|
+
packageRoot3,
|
|
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(
|
|
5506
|
+
let path = join8(packageRoot3, ".agent", "skills", "zam", "SKILL.md");
|
|
5507
5507
|
if (existsSync7(path)) return path;
|
|
5508
|
-
path = join8(
|
|
5508
|
+
path = join8(packageRoot3, ".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
|
|
6812
|
-
import { dirname as
|
|
6813
|
-
import { fileURLToPath as
|
|
6811
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
6812
|
+
import { dirname as dirname13, join as join28 } from "path";
|
|
6813
|
+
import { fileURLToPath as fileURLToPath7 } 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
|
|
6819
|
-
import { homedir as
|
|
6820
|
-
import { dirname as
|
|
6818
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync9, writeFileSync as writeFileSync8 } from "fs";
|
|
6819
|
+
import { homedir as homedir10 } from "os";
|
|
6820
|
+
import { dirname as dirname6, join as join14 } from "path";
|
|
6821
6821
|
import { Command } from "commander";
|
|
6822
6822
|
|
|
6823
6823
|
// src/cli/agent-harness.ts
|
|
@@ -7286,8 +7286,11 @@ ${zamExtension}
|
|
|
7286
7286
|
`;
|
|
7287
7287
|
}
|
|
7288
7288
|
} else if (harnessId === "copilot") {
|
|
7289
|
-
targetPath = join12(
|
|
7290
|
-
|
|
7289
|
+
targetPath = join12(
|
|
7290
|
+
opts.copilotHome ?? join12(opts.home, ".copilot"),
|
|
7291
|
+
"mcp-config.json"
|
|
7292
|
+
);
|
|
7293
|
+
hint = "Restart GitHub Copilot or start a new session to load the 'zam' MCP server and its Studio, Recall, Graph, and Settings canvases.";
|
|
7291
7294
|
let existing = {};
|
|
7292
7295
|
if (exists(targetPath)) {
|
|
7293
7296
|
existing = parseMcpJsonConfig(targetPath, read(targetPath));
|
|
@@ -7311,6 +7314,121 @@ ${zamExtension}
|
|
|
7311
7314
|
};
|
|
7312
7315
|
}
|
|
7313
7316
|
|
|
7317
|
+
// src/cli/copilot-extension.ts
|
|
7318
|
+
import {
|
|
7319
|
+
existsSync as existsSync13,
|
|
7320
|
+
lstatSync,
|
|
7321
|
+
mkdirSync as mkdirSync8,
|
|
7322
|
+
readFileSync as readFileSync10,
|
|
7323
|
+
writeFileSync as writeFileSync7
|
|
7324
|
+
} from "fs";
|
|
7325
|
+
import { homedir as homedir9 } from "os";
|
|
7326
|
+
import { dirname as dirname5, join as join13, resolve as resolve3 } from "path";
|
|
7327
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
7328
|
+
var EXTENSION_NAME = "zam-mcp-apps";
|
|
7329
|
+
var EXTENSION_FILES = [
|
|
7330
|
+
"extension.mjs",
|
|
7331
|
+
"host.bundle.js",
|
|
7332
|
+
"mcp-client.bundle.mjs",
|
|
7333
|
+
"manifest.json"
|
|
7334
|
+
];
|
|
7335
|
+
var packageRoot = [
|
|
7336
|
+
fileURLToPath2(new URL("../..", import.meta.url)),
|
|
7337
|
+
fileURLToPath2(new URL("../../..", import.meta.url))
|
|
7338
|
+
].find((candidate) => existsSync13(join13(candidate, "package.json"))) ?? fileURLToPath2(new URL("../..", import.meta.url));
|
|
7339
|
+
function defaultCliEntry() {
|
|
7340
|
+
return join13(dirname5(fileURLToPath2(import.meta.url)), "index.js");
|
|
7341
|
+
}
|
|
7342
|
+
function resolveCopilotHome(home = homedir9(), configuredHome = process.env.COPILOT_HOME) {
|
|
7343
|
+
return configuredHome?.trim() ? resolve3(configuredHome) : join13(home, ".copilot");
|
|
7344
|
+
}
|
|
7345
|
+
function resolveCopilotZamLaunch(zamPath, options = {}) {
|
|
7346
|
+
const cliEntry = options.cliEntry ?? defaultCliEntry();
|
|
7347
|
+
if (existsSync13(cliEntry)) {
|
|
7348
|
+
return {
|
|
7349
|
+
command: options.nodePath ?? process.execPath,
|
|
7350
|
+
args: [cliEntry, "mcp"]
|
|
7351
|
+
};
|
|
7352
|
+
}
|
|
7353
|
+
return {
|
|
7354
|
+
command: zamPath,
|
|
7355
|
+
args: ["mcp"]
|
|
7356
|
+
};
|
|
7357
|
+
}
|
|
7358
|
+
function planCopilotExtensionInstall(options) {
|
|
7359
|
+
const sourceDir = options.assetsDir ?? join13(packageRoot, "dist", "copilot-extension");
|
|
7360
|
+
for (const file of EXTENSION_FILES) {
|
|
7361
|
+
if (!existsSync13(join13(sourceDir, file))) {
|
|
7362
|
+
throw new Error(
|
|
7363
|
+
`Copilot MCP Apps asset is missing: ${join13(sourceDir, file)}. Run \`npm run build\` and retry.`
|
|
7364
|
+
);
|
|
7365
|
+
}
|
|
7366
|
+
}
|
|
7367
|
+
const manifest = JSON.parse(
|
|
7368
|
+
readFileSync10(join13(sourceDir, "manifest.json"), "utf8")
|
|
7369
|
+
);
|
|
7370
|
+
if (manifest.name !== EXTENSION_NAME || typeof manifest.version !== "string" || !manifest.version) {
|
|
7371
|
+
throw new Error(
|
|
7372
|
+
`Invalid Copilot MCP Apps manifest: ${join13(sourceDir, "manifest.json")}`
|
|
7373
|
+
);
|
|
7374
|
+
}
|
|
7375
|
+
const copilotHome = resolveCopilotHome(
|
|
7376
|
+
options.home,
|
|
7377
|
+
options.copilotHome ?? process.env.COPILOT_HOME
|
|
7378
|
+
);
|
|
7379
|
+
return {
|
|
7380
|
+
sourceDir,
|
|
7381
|
+
destinationDir: join13(copilotHome, "extensions", EXTENSION_NAME),
|
|
7382
|
+
launch: resolveCopilotZamLaunch(options.zamPath, options),
|
|
7383
|
+
files: EXTENSION_FILES
|
|
7384
|
+
};
|
|
7385
|
+
}
|
|
7386
|
+
function writeIfChanged(path, content) {
|
|
7387
|
+
const next = Buffer.isBuffer(content) ? content : Buffer.from(content);
|
|
7388
|
+
if (existsSync13(path) && readFileSync10(path).equals(next)) return false;
|
|
7389
|
+
writeFileSync7(path, next);
|
|
7390
|
+
return true;
|
|
7391
|
+
}
|
|
7392
|
+
function installCopilotExtension(options) {
|
|
7393
|
+
const plan = planCopilotExtensionInstall(options);
|
|
7394
|
+
if (options.dryRun) {
|
|
7395
|
+
return { ...plan, action: "planned", changedFiles: [] };
|
|
7396
|
+
}
|
|
7397
|
+
const destinationExisted = existsSync13(plan.destinationDir);
|
|
7398
|
+
if (destinationExisted && lstatSync(plan.destinationDir).isSymbolicLink()) {
|
|
7399
|
+
throw new Error(
|
|
7400
|
+
`Refusing to replace symlinked Copilot extension directory: ${plan.destinationDir}`
|
|
7401
|
+
);
|
|
7402
|
+
}
|
|
7403
|
+
mkdirSync8(plan.destinationDir, { recursive: true });
|
|
7404
|
+
const changedFiles = [];
|
|
7405
|
+
for (const file of plan.files) {
|
|
7406
|
+
const source = join13(plan.sourceDir, file);
|
|
7407
|
+
const destination = join13(plan.destinationDir, file);
|
|
7408
|
+
if (writeIfChanged(destination, readFileSync10(source))) {
|
|
7409
|
+
changedFiles.push(file);
|
|
7410
|
+
}
|
|
7411
|
+
}
|
|
7412
|
+
const launchContent = `${JSON.stringify(
|
|
7413
|
+
{
|
|
7414
|
+
schemaVersion: 1,
|
|
7415
|
+
command: plan.launch.command,
|
|
7416
|
+
args: plan.launch.args
|
|
7417
|
+
},
|
|
7418
|
+
null,
|
|
7419
|
+
2
|
|
7420
|
+
)}
|
|
7421
|
+
`;
|
|
7422
|
+
if (writeIfChanged(join13(plan.destinationDir, "launch.json"), launchContent)) {
|
|
7423
|
+
changedFiles.push("launch.json");
|
|
7424
|
+
}
|
|
7425
|
+
return {
|
|
7426
|
+
...plan,
|
|
7427
|
+
action: !destinationExisted ? "installed" : changedFiles.length > 0 ? "updated" : "unchanged",
|
|
7428
|
+
changedFiles
|
|
7429
|
+
};
|
|
7430
|
+
}
|
|
7431
|
+
|
|
7314
7432
|
// src/cli/commands/agent.ts
|
|
7315
7433
|
var C = {
|
|
7316
7434
|
reset: "\x1B[0m",
|
|
@@ -7334,7 +7452,7 @@ function isConnectHarnessId(value) {
|
|
|
7334
7452
|
return CONNECT_HARNESSES.includes(value);
|
|
7335
7453
|
}
|
|
7336
7454
|
function agentsMdPresent(cwd = process.cwd()) {
|
|
7337
|
-
return
|
|
7455
|
+
return existsSync14(join14(cwd, "AGENTS.md"));
|
|
7338
7456
|
}
|
|
7339
7457
|
function printStatus() {
|
|
7340
7458
|
const installed = hasCommand("opencode");
|
|
@@ -7465,7 +7583,8 @@ var connectCmd = new Command("connect").description("Configure the ZAM MCP serve
|
|
|
7465
7583
|
result = connectHarnessMcp(harnessArg, {
|
|
7466
7584
|
zamPath,
|
|
7467
7585
|
cwd: process.cwd(),
|
|
7468
|
-
home:
|
|
7586
|
+
home: homedir10(),
|
|
7587
|
+
copilotHome: process.env.COPILOT_HOME
|
|
7469
7588
|
});
|
|
7470
7589
|
} catch (error) {
|
|
7471
7590
|
console.error(
|
|
@@ -7473,24 +7592,56 @@ var connectCmd = new Command("connect").description("Configure the ZAM MCP serve
|
|
|
7473
7592
|
);
|
|
7474
7593
|
process.exit(1);
|
|
7475
7594
|
}
|
|
7595
|
+
let copilotExtension;
|
|
7596
|
+
if (harnessArg === "copilot") {
|
|
7597
|
+
try {
|
|
7598
|
+
copilotExtension = installCopilotExtension({
|
|
7599
|
+
home: homedir10(),
|
|
7600
|
+
zamPath,
|
|
7601
|
+
dryRun: Boolean(opts.print)
|
|
7602
|
+
});
|
|
7603
|
+
} catch (error) {
|
|
7604
|
+
console.error(
|
|
7605
|
+
`Error preparing Copilot MCP Apps extension: ${error instanceof Error ? error.message : String(error)}`
|
|
7606
|
+
);
|
|
7607
|
+
process.exit(1);
|
|
7608
|
+
}
|
|
7609
|
+
}
|
|
7476
7610
|
if (opts.print) {
|
|
7477
7611
|
console.log(`Path: ${result.path}`);
|
|
7478
7612
|
console.log(`Content:
|
|
7479
7613
|
${result.content}`);
|
|
7614
|
+
if (copilotExtension) {
|
|
7615
|
+
console.log(`Extension: ${copilotExtension.destinationDir}`);
|
|
7616
|
+
console.log(
|
|
7617
|
+
`Launch: ${copilotExtension.launch.command} ${copilotExtension.launch.args.join(" ")}`
|
|
7618
|
+
);
|
|
7619
|
+
}
|
|
7480
7620
|
return;
|
|
7481
7621
|
}
|
|
7482
7622
|
if (result.alreadyConfigured) {
|
|
7483
7623
|
console.log(
|
|
7484
7624
|
`${C.green}\u2713${C.reset} MCP server 'zam' already configured in ${result.path}`
|
|
7485
7625
|
);
|
|
7626
|
+
if (copilotExtension) {
|
|
7627
|
+
console.log(
|
|
7628
|
+
`${C.green}\u2713${C.reset} MCP Apps extension ${copilotExtension.action} at ${copilotExtension.destinationDir}`
|
|
7629
|
+
);
|
|
7630
|
+
}
|
|
7631
|
+
console.log(` ${C.dim}${result.hint}${C.reset}`);
|
|
7486
7632
|
return;
|
|
7487
7633
|
}
|
|
7488
7634
|
try {
|
|
7489
|
-
|
|
7490
|
-
|
|
7635
|
+
mkdirSync9(dirname6(result.path), { recursive: true });
|
|
7636
|
+
writeFileSync8(result.path, result.content, "utf-8");
|
|
7491
7637
|
console.log(
|
|
7492
7638
|
`${C.green}\u2713${C.reset} Wrote MCP configuration to ${result.path}`
|
|
7493
7639
|
);
|
|
7640
|
+
if (copilotExtension) {
|
|
7641
|
+
console.log(
|
|
7642
|
+
`${C.green}\u2713${C.reset} MCP Apps extension ${copilotExtension.action} at ${copilotExtension.destinationDir}`
|
|
7643
|
+
);
|
|
7644
|
+
}
|
|
7494
7645
|
console.log(` ${C.dim}${result.hint}${C.reset}`);
|
|
7495
7646
|
} catch (error) {
|
|
7496
7647
|
console.error(
|
|
@@ -7505,9 +7656,9 @@ var agentCommand = new Command("agent").description("Provision and inspect the a
|
|
|
7505
7656
|
init_kernel();
|
|
7506
7657
|
import { execFileSync as execFileSync3 } from "child_process";
|
|
7507
7658
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
7508
|
-
import { existsSync as
|
|
7509
|
-
import { homedir as
|
|
7510
|
-
import { join as
|
|
7659
|
+
import { existsSync as existsSync18, readdirSync as readdirSync2, readFileSync as readFileSync15, rmSync as rmSync3 } from "fs";
|
|
7660
|
+
import { homedir as homedir12, tmpdir as tmpdir3 } from "os";
|
|
7661
|
+
import { join as join21, resolve as resolve5 } from "path";
|
|
7511
7662
|
import { Command as Command2 } from "commander";
|
|
7512
7663
|
import { ulid as ulid9 } from "ulid";
|
|
7513
7664
|
|
|
@@ -7518,7 +7669,7 @@ import fs from "fs";
|
|
|
7518
7669
|
// src/cli/llm/client.ts
|
|
7519
7670
|
init_kernel();
|
|
7520
7671
|
import { spawn as spawn2 } from "child_process";
|
|
7521
|
-
import { existsSync as
|
|
7672
|
+
import { existsSync as existsSync15, readFileSync as readFileSync11, statSync as statSync2 } from "fs";
|
|
7522
7673
|
var DEFAULT_LLM_URL = "http://localhost:8000/v1";
|
|
7523
7674
|
var DEFAULT_LLM_MAX_TOKENS = 1e4;
|
|
7524
7675
|
var RECALL_QUESTION_MAX_OUTPUT_TOKENS = 400;
|
|
@@ -8234,7 +8385,7 @@ async function extractTextFromScanViaLLM(db, imagePath) {
|
|
|
8234
8385
|
"Vision role is not enabled in settings (llm.vision.enabled)"
|
|
8235
8386
|
);
|
|
8236
8387
|
}
|
|
8237
|
-
if (!
|
|
8388
|
+
if (!existsSync15(imagePath)) {
|
|
8238
8389
|
throw new Error(`Scan file not found: ${imagePath}`);
|
|
8239
8390
|
}
|
|
8240
8391
|
const stat = statSync2(imagePath);
|
|
@@ -8255,7 +8406,7 @@ async function extractTextFromScanViaLLM(db, imagePath) {
|
|
|
8255
8406
|
if (!mime) {
|
|
8256
8407
|
throw new Error("Unsupported scan format; use PNG, JPEG, or WebP");
|
|
8257
8408
|
}
|
|
8258
|
-
const imageBytes =
|
|
8409
|
+
const imageBytes = readFileSync11(imagePath);
|
|
8259
8410
|
const dataUrl = `data:${mime};base64,${imageBytes.toString("base64")}`;
|
|
8260
8411
|
const visionEndpoint = await getVisionConfig(db);
|
|
8261
8412
|
const langName = LANGUAGE_NAMES[p.locale] || "English";
|
|
@@ -8472,7 +8623,7 @@ async function prepareRecallChain(db, opts) {
|
|
|
8472
8623
|
} else {
|
|
8473
8624
|
spawnLocalRunner(endpoint.url, endpoint.model, endpoint.runner);
|
|
8474
8625
|
while (Date.now() < deadline) {
|
|
8475
|
-
await new Promise((
|
|
8626
|
+
await new Promise((resolve11) => setTimeout(resolve11, 1e3));
|
|
8476
8627
|
if (await isLlmOnline(endpoint.url)) {
|
|
8477
8628
|
online = true;
|
|
8478
8629
|
break;
|
|
@@ -8687,7 +8838,7 @@ function spawnLocalRunner(url, model, hint) {
|
|
|
8687
8838
|
const { runner, port } = detectRunner(url, model, hint);
|
|
8688
8839
|
try {
|
|
8689
8840
|
if (runner === "fastflowlm") {
|
|
8690
|
-
const flmExe =
|
|
8841
|
+
const flmExe = existsSync15("C:\\Program Files\\flm\\flm.exe") ? "C:\\Program Files\\flm\\flm.exe" : "flm";
|
|
8691
8842
|
if (!hasCommand("flm") && flmExe === "flm") return;
|
|
8692
8843
|
spawn2(flmExe, ["serve", model, "--port", port], {
|
|
8693
8844
|
detached: true,
|
|
@@ -8708,7 +8859,7 @@ function spawnLocalRunner(url, model, hint) {
|
|
|
8708
8859
|
async function startLocalRunner(url, model, locale, hint) {
|
|
8709
8860
|
const { runner, port } = detectRunner(url, model, hint);
|
|
8710
8861
|
if (runner === "fastflowlm") {
|
|
8711
|
-
const flmExe =
|
|
8862
|
+
const flmExe = existsSync15("C:\\Program Files\\flm\\flm.exe") ? "C:\\Program Files\\flm\\flm.exe" : "flm";
|
|
8712
8863
|
if (!hasCommand("flm") && flmExe === "flm") {
|
|
8713
8864
|
console.warn(
|
|
8714
8865
|
"\x1B[31m\u2717 FastFlowLM is configured but could not be found on the system.\x1B[0m"
|
|
@@ -8765,7 +8916,7 @@ async function startLocalRunner(url, model, locale, hint) {
|
|
|
8765
8916
|
let attempts = 0;
|
|
8766
8917
|
const dotsPerLine = 30;
|
|
8767
8918
|
while (true) {
|
|
8768
|
-
await new Promise((
|
|
8919
|
+
await new Promise((resolve11) => setTimeout(resolve11, 500));
|
|
8769
8920
|
if (await isLlmOnline(url)) {
|
|
8770
8921
|
if (attempts > 0) process.stdout.write("\n");
|
|
8771
8922
|
return true;
|
|
@@ -8854,8 +9005,8 @@ async function fetchWithInteractiveTimeout(url, options = {}) {
|
|
|
8854
9005
|
const dotsPerLine = 30;
|
|
8855
9006
|
while (true) {
|
|
8856
9007
|
let timeoutId;
|
|
8857
|
-
const timeoutPromise = new Promise((
|
|
8858
|
-
timeoutId = setTimeout(() =>
|
|
9008
|
+
const timeoutPromise = new Promise((resolve11) => {
|
|
9009
|
+
timeoutId = setTimeout(() => resolve11("timeout"), timeoutMs);
|
|
8859
9010
|
});
|
|
8860
9011
|
const dotsInterval = setInterval(() => {
|
|
8861
9012
|
process.stdout.write(".");
|
|
@@ -9187,8 +9338,8 @@ async function readImageOCR(db, imagePath) {
|
|
|
9187
9338
|
|
|
9188
9339
|
// src/cli/bridge-handlers.ts
|
|
9189
9340
|
init_kernel();
|
|
9190
|
-
import { mkdirSync as
|
|
9191
|
-
import { join as
|
|
9341
|
+
import { mkdirSync as mkdirSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
9342
|
+
import { join as join17 } from "path";
|
|
9192
9343
|
|
|
9193
9344
|
// src/cli/knowledge-contexts.ts
|
|
9194
9345
|
init_kernel();
|
|
@@ -9435,16 +9586,16 @@ async function resolveSuggestMinSimilarity(db) {
|
|
|
9435
9586
|
}
|
|
9436
9587
|
|
|
9437
9588
|
// src/cli/update/latest-version.ts
|
|
9438
|
-
import { readFileSync as
|
|
9439
|
-
import { dirname as
|
|
9440
|
-
import { fileURLToPath as
|
|
9589
|
+
import { readFileSync as readFileSync12 } from "fs";
|
|
9590
|
+
import { dirname as dirname7, join as join15 } from "path";
|
|
9591
|
+
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
9441
9592
|
var GITHUB_REPO = "zam-os/zam";
|
|
9442
9593
|
function currentVersion() {
|
|
9443
|
-
const here =
|
|
9594
|
+
const here = dirname7(fileURLToPath3(import.meta.url));
|
|
9444
9595
|
for (const up of ["..", "../..", "../../.."]) {
|
|
9445
9596
|
try {
|
|
9446
9597
|
const pkg2 = JSON.parse(
|
|
9447
|
-
|
|
9598
|
+
readFileSync12(join15(here, up, "package.json"), "utf-8")
|
|
9448
9599
|
);
|
|
9449
9600
|
if (pkg2.version) return pkg2.version;
|
|
9450
9601
|
} catch {
|
|
@@ -9474,16 +9625,16 @@ async function fetchLatestVersion(repo) {
|
|
|
9474
9625
|
|
|
9475
9626
|
// src/cli/workspaces/active.ts
|
|
9476
9627
|
init_kernel();
|
|
9477
|
-
import { existsSync as
|
|
9478
|
-
import { homedir as
|
|
9479
|
-
import { basename as basename3, join as
|
|
9628
|
+
import { existsSync as existsSync16, mkdirSync as mkdirSync10 } from "fs";
|
|
9629
|
+
import { homedir as homedir11 } from "os";
|
|
9630
|
+
import { basename as basename3, join as join16, resolve as resolve4 } from "path";
|
|
9480
9631
|
var LEGACY_WORKSPACE_DIR_KEY = "personal.workspace_dir";
|
|
9481
9632
|
var DEFAULT_WORKSPACE_ID = "personal";
|
|
9482
9633
|
function defaultWorkspaceDir() {
|
|
9483
|
-
return
|
|
9634
|
+
return join16(homedir11(), "Documents", "zam");
|
|
9484
9635
|
}
|
|
9485
9636
|
function normalizeWorkspacePath(path) {
|
|
9486
|
-
const resolved =
|
|
9637
|
+
const resolved = resolve4(path);
|
|
9487
9638
|
return process.platform === "win32" ? resolved.toLowerCase() : resolved;
|
|
9488
9639
|
}
|
|
9489
9640
|
function sameWorkspacePath(left, right) {
|
|
@@ -9512,7 +9663,7 @@ async function clearLegacyWorkspaceDir(db) {
|
|
|
9512
9663
|
async function migrateLegacyWorkspaceDir(db) {
|
|
9513
9664
|
const legacyDir = await getSetting(db, LEGACY_WORKSPACE_DIR_KEY);
|
|
9514
9665
|
if (!legacyDir) return void 0;
|
|
9515
|
-
const path =
|
|
9666
|
+
const path = resolve4(legacyDir);
|
|
9516
9667
|
const existing = findWorkspaceByPath(path);
|
|
9517
9668
|
const migrated = existing ?? {
|
|
9518
9669
|
id: getConfiguredWorkspaces().some(
|
|
@@ -9535,13 +9686,13 @@ async function ensureActiveWorkspace(db) {
|
|
|
9535
9686
|
await migrateLegacyWorkspaceDir(db);
|
|
9536
9687
|
const active = getActiveWorkspace();
|
|
9537
9688
|
if (active) {
|
|
9538
|
-
|
|
9689
|
+
mkdirSync10(active.path, { recursive: true });
|
|
9539
9690
|
return active;
|
|
9540
9691
|
}
|
|
9541
9692
|
const configured = getConfiguredWorkspaces()[0];
|
|
9542
9693
|
if (configured) {
|
|
9543
9694
|
setActiveWorkspaceId(configured.id);
|
|
9544
|
-
|
|
9695
|
+
mkdirSync10(configured.path, { recursive: true });
|
|
9545
9696
|
return configured;
|
|
9546
9697
|
}
|
|
9547
9698
|
const workspace = {
|
|
@@ -9550,7 +9701,7 @@ async function ensureActiveWorkspace(db) {
|
|
|
9550
9701
|
kind: "personal",
|
|
9551
9702
|
path: defaultWorkspaceDir()
|
|
9552
9703
|
};
|
|
9553
|
-
|
|
9704
|
+
mkdirSync10(workspace.path, { recursive: true });
|
|
9554
9705
|
upsertConfiguredWorkspace(workspace);
|
|
9555
9706
|
setActiveWorkspaceId(workspace.id);
|
|
9556
9707
|
await clearLegacyWorkspaceDir(db);
|
|
@@ -9564,7 +9715,7 @@ async function activateWorkspace(db, workspace) {
|
|
|
9564
9715
|
}
|
|
9565
9716
|
async function activateWorkspacePath(db, dir, opts = {}) {
|
|
9566
9717
|
await migrateLegacyWorkspaceDir(db);
|
|
9567
|
-
const path =
|
|
9718
|
+
const path = resolve4(dir);
|
|
9568
9719
|
const existing = opts.id ? void 0 : findWorkspaceByPath(path);
|
|
9569
9720
|
if (existing) {
|
|
9570
9721
|
setActiveWorkspaceId(existing.id);
|
|
@@ -9589,7 +9740,7 @@ async function removeWorkspaceAndResolveActive(db, id) {
|
|
|
9589
9740
|
};
|
|
9590
9741
|
}
|
|
9591
9742
|
function existingWorkspaceDirOrHome(workspace) {
|
|
9592
|
-
return
|
|
9743
|
+
return existsSync16(workspace.path) ? workspace.path : homedir11();
|
|
9593
9744
|
}
|
|
9594
9745
|
|
|
9595
9746
|
// src/cli/bridge-handlers.ts
|
|
@@ -10361,11 +10512,11 @@ async function backupCreate(db, params) {
|
|
|
10361
10512
|
const targetDir = params.dir || (await ensureActiveWorkspace(db)).path;
|
|
10362
10513
|
const snapshot = await exportSnapshot(db);
|
|
10363
10514
|
const manifest = verifySnapshot(snapshot);
|
|
10364
|
-
const backupDir =
|
|
10365
|
-
|
|
10515
|
+
const backupDir = join17(targetDir, "zam-backups");
|
|
10516
|
+
mkdirSync11(backupDir, { recursive: true });
|
|
10366
10517
|
const stamp = manifest.createdAt.replace(/[:.]/g, "-");
|
|
10367
|
-
const path =
|
|
10368
|
-
|
|
10518
|
+
const path = join17(backupDir, `zam-snapshot-${stamp}.sql`);
|
|
10519
|
+
writeFileSync9(path, snapshot, "utf-8");
|
|
10369
10520
|
return {
|
|
10370
10521
|
ok: true,
|
|
10371
10522
|
path,
|
|
@@ -13050,9 +13201,9 @@ function getCurriculumProvider(id) {
|
|
|
13050
13201
|
// src/cli/llm/vision.ts
|
|
13051
13202
|
init_kernel();
|
|
13052
13203
|
import { randomBytes } from "crypto";
|
|
13053
|
-
import { readFileSync as
|
|
13204
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
13054
13205
|
import { tmpdir as tmpdir2 } from "os";
|
|
13055
|
-
import { basename as basename4, join as
|
|
13206
|
+
import { basename as basename4, join as join18 } from "path";
|
|
13056
13207
|
var LANGUAGE_NAMES2 = {
|
|
13057
13208
|
en: "English",
|
|
13058
13209
|
de: "German",
|
|
@@ -13088,13 +13239,13 @@ async function observeUiSnapshotViaLLM(db, input8) {
|
|
|
13088
13239
|
const imageUrls = [];
|
|
13089
13240
|
const isVideo = /\.(mp4|mov|m4v|avi|mkv|webm)$/i.test(input8.imagePath);
|
|
13090
13241
|
if (isVideo) {
|
|
13091
|
-
const { mkdirSync:
|
|
13242
|
+
const { mkdirSync: mkdirSync17, readdirSync: readdirSync3, rmSync: rmSync4 } = await import("fs");
|
|
13092
13243
|
const { execSync: execSync6 } = await import("child_process");
|
|
13093
|
-
const tempDir =
|
|
13244
|
+
const tempDir = join18(
|
|
13094
13245
|
tmpdir2(),
|
|
13095
13246
|
`zam-frames-${randomBytes(4).toString("hex")}`
|
|
13096
13247
|
);
|
|
13097
|
-
|
|
13248
|
+
mkdirSync17(tempDir, { recursive: true });
|
|
13098
13249
|
try {
|
|
13099
13250
|
execSync6(
|
|
13100
13251
|
`ffmpeg -i "${input8.imagePath}" -vf "fps=1/3,scale=1280:-1" -vsync vfr "${tempDir}/frame_%03d.png"`,
|
|
@@ -13123,7 +13274,7 @@ async function observeUiSnapshotViaLLM(db, input8) {
|
|
|
13123
13274
|
}
|
|
13124
13275
|
}
|
|
13125
13276
|
for (const file of sampledFiles) {
|
|
13126
|
-
const bytes =
|
|
13277
|
+
const bytes = readFileSync13(join18(tempDir, file));
|
|
13127
13278
|
imageUrls.push(`data:image/png;base64,${bytes.toString("base64")}`);
|
|
13128
13279
|
}
|
|
13129
13280
|
} finally {
|
|
@@ -13133,7 +13284,7 @@ async function observeUiSnapshotViaLLM(db, input8) {
|
|
|
13133
13284
|
}
|
|
13134
13285
|
}
|
|
13135
13286
|
} else {
|
|
13136
|
-
const imageBytes =
|
|
13287
|
+
const imageBytes = readFileSync13(input8.imagePath);
|
|
13137
13288
|
const ext = input8.imagePath.split(".").pop()?.toLowerCase();
|
|
13138
13289
|
const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : "image/png";
|
|
13139
13290
|
imageUrls.push(`data:${mime};base64,${imageBytes.toString("base64")}`);
|
|
@@ -13602,36 +13753,36 @@ async function withProviderScope(machine, action) {
|
|
|
13602
13753
|
|
|
13603
13754
|
// src/cli/provisioning/index.ts
|
|
13604
13755
|
import {
|
|
13605
|
-
existsSync as
|
|
13606
|
-
lstatSync,
|
|
13607
|
-
mkdirSync as
|
|
13608
|
-
readFileSync as
|
|
13756
|
+
existsSync as existsSync17,
|
|
13757
|
+
lstatSync as lstatSync2,
|
|
13758
|
+
mkdirSync as mkdirSync12,
|
|
13759
|
+
readFileSync as readFileSync14,
|
|
13609
13760
|
realpathSync,
|
|
13610
13761
|
rmSync as rmSync2,
|
|
13611
13762
|
symlinkSync,
|
|
13612
|
-
writeFileSync as
|
|
13763
|
+
writeFileSync as writeFileSync10
|
|
13613
13764
|
} from "fs";
|
|
13614
|
-
import { basename as basename5, dirname as
|
|
13615
|
-
import { fileURLToPath as
|
|
13616
|
-
var
|
|
13617
|
-
|
|
13618
|
-
|
|
13619
|
-
].find((candidate) =>
|
|
13765
|
+
import { basename as basename5, dirname as dirname8, join as join19 } from "path";
|
|
13766
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
13767
|
+
var packageRoot2 = [
|
|
13768
|
+
fileURLToPath4(new URL("../..", import.meta.url)),
|
|
13769
|
+
fileURLToPath4(new URL("../../..", import.meta.url))
|
|
13770
|
+
].find((candidate) => existsSync17(join19(candidate, "package.json"))) ?? fileURLToPath4(new URL("../..", import.meta.url));
|
|
13620
13771
|
var ALL_SETUP_AGENTS = ["claude", "copilot", "codex", "agent"];
|
|
13621
13772
|
var SKILL_PAIRS = [
|
|
13622
13773
|
{
|
|
13623
|
-
from:
|
|
13624
|
-
to:
|
|
13774
|
+
from: join19(packageRoot2, ".claude", "skills", "zam", "SKILL.md"),
|
|
13775
|
+
to: join19(".claude", "skills", "zam", "SKILL.md"),
|
|
13625
13776
|
agents: ["claude", "copilot"]
|
|
13626
13777
|
},
|
|
13627
13778
|
{
|
|
13628
|
-
from:
|
|
13629
|
-
to:
|
|
13779
|
+
from: join19(packageRoot2, ".agent", "skills", "zam", "SKILL.md"),
|
|
13780
|
+
to: join19(".agent", "skills", "zam", "SKILL.md"),
|
|
13630
13781
|
agents: ["agent"]
|
|
13631
13782
|
},
|
|
13632
13783
|
{
|
|
13633
|
-
from:
|
|
13634
|
-
to:
|
|
13784
|
+
from: join19(packageRoot2, ".agents", "skills", "zam", "SKILL.md"),
|
|
13785
|
+
to: join19(".agents", "skills", "zam", "SKILL.md"),
|
|
13635
13786
|
agents: ["codex"]
|
|
13636
13787
|
}
|
|
13637
13788
|
];
|
|
@@ -13661,7 +13812,7 @@ function parseSetupAgents(value) {
|
|
|
13661
13812
|
}
|
|
13662
13813
|
function pathExists(path) {
|
|
13663
13814
|
try {
|
|
13664
|
-
|
|
13815
|
+
lstatSync2(path);
|
|
13665
13816
|
return true;
|
|
13666
13817
|
} catch {
|
|
13667
13818
|
return false;
|
|
@@ -13669,7 +13820,7 @@ function pathExists(path) {
|
|
|
13669
13820
|
}
|
|
13670
13821
|
function isSymbolicLink(path) {
|
|
13671
13822
|
try {
|
|
13672
|
-
return
|
|
13823
|
+
return lstatSync2(path).isSymbolicLink();
|
|
13673
13824
|
} catch {
|
|
13674
13825
|
return false;
|
|
13675
13826
|
}
|
|
@@ -13690,16 +13841,16 @@ function linkPointsTo(sourceDir, destinationDir) {
|
|
|
13690
13841
|
}
|
|
13691
13842
|
function isZamSkillCopy(destinationDir) {
|
|
13692
13843
|
try {
|
|
13693
|
-
if (!
|
|
13694
|
-
const skillFile =
|
|
13695
|
-
if (!
|
|
13696
|
-
return /^name:\s*zam\s*$/m.test(
|
|
13844
|
+
if (!lstatSync2(destinationDir).isDirectory()) return false;
|
|
13845
|
+
const skillFile = join19(destinationDir, "SKILL.md");
|
|
13846
|
+
if (!existsSync17(skillFile)) return false;
|
|
13847
|
+
return /^name:\s*zam\s*$/m.test(readFileSync14(skillFile, "utf8"));
|
|
13697
13848
|
} catch {
|
|
13698
13849
|
return false;
|
|
13699
13850
|
}
|
|
13700
13851
|
}
|
|
13701
13852
|
function classifySkillDestination(sourceDir, destinationDir) {
|
|
13702
|
-
if (!
|
|
13853
|
+
if (!existsSync17(sourceDir)) return "source-missing";
|
|
13703
13854
|
if (!isSymbolicLink(destinationDir) && pathsResolveToSameDirectory(sourceDir, destinationDir)) {
|
|
13704
13855
|
return "source-directory";
|
|
13705
13856
|
}
|
|
@@ -13716,9 +13867,9 @@ function wireSkills(cwd = process.cwd(), agents = parseSetupAgents(), opts = {})
|
|
|
13716
13867
|
};
|
|
13717
13868
|
for (const { from, to, agents: pairAgents } of SKILL_PAIRS) {
|
|
13718
13869
|
if (!pairAgents.some((agent) => agents.has(agent))) continue;
|
|
13719
|
-
const sourceDir =
|
|
13720
|
-
const destinationDir =
|
|
13721
|
-
const label =
|
|
13870
|
+
const sourceDir = dirname8(from);
|
|
13871
|
+
const destinationDir = dirname8(join19(cwd, to));
|
|
13872
|
+
const label = dirname8(to);
|
|
13722
13873
|
const state = classifySkillDestination(sourceDir, destinationDir);
|
|
13723
13874
|
if (state === "source-missing") {
|
|
13724
13875
|
if (!opts.quiet) {
|
|
@@ -13775,7 +13926,7 @@ function wireSkills(cwd = process.cwd(), agents = parseSetupAgents(), opts = {})
|
|
|
13775
13926
|
if (destinationExists) {
|
|
13776
13927
|
rmSync2(destinationDir, { recursive: true, force: true });
|
|
13777
13928
|
}
|
|
13778
|
-
|
|
13929
|
+
mkdirSync12(dirname8(destinationDir), { recursive: true });
|
|
13779
13930
|
symlinkSync(
|
|
13780
13931
|
sourceDir,
|
|
13781
13932
|
destinationDir,
|
|
@@ -13791,8 +13942,8 @@ function inspectSkillLinks(cwd = process.cwd(), agents = parseSetupAgents()) {
|
|
|
13791
13942
|
const results = [];
|
|
13792
13943
|
for (const { from, to, agents: pairAgents } of SKILL_PAIRS) {
|
|
13793
13944
|
if (!pairAgents.some((agent) => agents.has(agent))) continue;
|
|
13794
|
-
const sourceDir =
|
|
13795
|
-
const destinationDir =
|
|
13945
|
+
const sourceDir = dirname8(from);
|
|
13946
|
+
const destinationDir = dirname8(join19(cwd, to));
|
|
13796
13947
|
results.push({
|
|
13797
13948
|
agents: pairAgents,
|
|
13798
13949
|
source: sourceDir,
|
|
@@ -13818,15 +13969,15 @@ function upsertMarkedBlock(dest, blockBody, dryRun) {
|
|
|
13818
13969
|
const block = `${ZAM_BLOCK_START}
|
|
13819
13970
|
${blockBody.trim()}
|
|
13820
13971
|
${ZAM_BLOCK_END}`;
|
|
13821
|
-
if (!
|
|
13972
|
+
if (!existsSync17(dest)) {
|
|
13822
13973
|
if (!dryRun) {
|
|
13823
|
-
|
|
13824
|
-
|
|
13974
|
+
mkdirSync12(dirname8(dest), { recursive: true });
|
|
13975
|
+
writeFileSync10(dest, `${block}
|
|
13825
13976
|
`, "utf8");
|
|
13826
13977
|
}
|
|
13827
13978
|
return "write";
|
|
13828
13979
|
}
|
|
13829
|
-
const existing =
|
|
13980
|
+
const existing = readFileSync14(dest, "utf8");
|
|
13830
13981
|
if (existing.includes(block)) return "skip";
|
|
13831
13982
|
const start = existing.indexOf(ZAM_BLOCK_START);
|
|
13832
13983
|
const end = existing.indexOf(ZAM_BLOCK_END);
|
|
@@ -13834,7 +13985,7 @@ ${ZAM_BLOCK_END}`;
|
|
|
13834
13985
|
|
|
13835
13986
|
${block}
|
|
13836
13987
|
`;
|
|
13837
|
-
if (!dryRun)
|
|
13988
|
+
if (!dryRun) writeFileSync10(dest, next, "utf8");
|
|
13838
13989
|
return start >= 0 && end > start ? "update" : "write";
|
|
13839
13990
|
}
|
|
13840
13991
|
function logInstructionAction(action, label, dryRun) {
|
|
@@ -13846,8 +13997,8 @@ function logInstructionAction(action, label, dryRun) {
|
|
|
13846
13997
|
}
|
|
13847
13998
|
function writeClaudeMd(skipClaudeMd, cwd = process.cwd(), opts = {}) {
|
|
13848
13999
|
if (skipClaudeMd) return;
|
|
13849
|
-
const dest =
|
|
13850
|
-
if (
|
|
14000
|
+
const dest = join19(cwd, "CLAUDE.md");
|
|
14001
|
+
if (existsSync17(dest)) {
|
|
13851
14002
|
if (!opts.updateExisting) {
|
|
13852
14003
|
console.log(` skip CLAUDE.md (already present)`);
|
|
13853
14004
|
return;
|
|
@@ -13890,14 +14041,14 @@ Use \`zam connector setup turso\` to store cloud credentials in
|
|
|
13890
14041
|
if (opts.dryRun) {
|
|
13891
14042
|
console.log(` would write CLAUDE.md`);
|
|
13892
14043
|
} else {
|
|
13893
|
-
|
|
14044
|
+
writeFileSync10(dest, content, "utf8");
|
|
13894
14045
|
console.log(` write CLAUDE.md`);
|
|
13895
14046
|
}
|
|
13896
14047
|
}
|
|
13897
14048
|
function writeAgentsMd(skipAgentsMd, cwd = process.cwd(), opts = {}) {
|
|
13898
14049
|
if (skipAgentsMd) return;
|
|
13899
|
-
const dest =
|
|
13900
|
-
if (
|
|
14050
|
+
const dest = join19(cwd, "AGENTS.md");
|
|
14051
|
+
if (existsSync17(dest)) {
|
|
13901
14052
|
if (!opts.updateExisting) {
|
|
13902
14053
|
console.log(` skip AGENTS.md (already present)`);
|
|
13903
14054
|
return;
|
|
@@ -13947,12 +14098,12 @@ Codex discovers repository skills under \`.agents/skills/\`. Run
|
|
|
13947
14098
|
if (opts.dryRun) {
|
|
13948
14099
|
console.log(` would write AGENTS.md`);
|
|
13949
14100
|
} else {
|
|
13950
|
-
|
|
14101
|
+
writeFileSync10(dest, content, "utf8");
|
|
13951
14102
|
console.log(` write AGENTS.md`);
|
|
13952
14103
|
}
|
|
13953
14104
|
}
|
|
13954
14105
|
function writeCopilotInstructions(cwd = process.cwd(), opts = {}) {
|
|
13955
|
-
const dest =
|
|
14106
|
+
const dest = join19(cwd, ".github", "copilot-instructions.md");
|
|
13956
14107
|
const action = upsertMarkedBlock(
|
|
13957
14108
|
dest,
|
|
13958
14109
|
`## ZAM learning sessions
|
|
@@ -13993,13 +14144,13 @@ async function resolveUser(opts, db, resolveOpts) {
|
|
|
13993
14144
|
}
|
|
13994
14145
|
|
|
13995
14146
|
// src/cli/workspaces/backup.ts
|
|
13996
|
-
import { mkdirSync as
|
|
13997
|
-
import { join as
|
|
14147
|
+
import { mkdirSync as mkdirSync13 } from "fs";
|
|
14148
|
+
import { join as join20 } from "path";
|
|
13998
14149
|
async function backupDatabaseTo(db, targetDir) {
|
|
13999
|
-
const backupDir =
|
|
14000
|
-
|
|
14150
|
+
const backupDir = join20(targetDir, "zam-backups");
|
|
14151
|
+
mkdirSync13(backupDir, { recursive: true });
|
|
14001
14152
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
14002
|
-
const dest =
|
|
14153
|
+
const dest = join20(backupDir, `zam-${stamp}.db`);
|
|
14003
14154
|
await db.exec(`VACUUM INTO '${dest.replace(/'/g, "''")}'`);
|
|
14004
14155
|
return dest;
|
|
14005
14156
|
}
|
|
@@ -14130,20 +14281,20 @@ bridgeCommand.command("workspace-info").description("Report the workspace dir, i
|
|
|
14130
14281
|
activeWorkspace,
|
|
14131
14282
|
workspaceDir: activeWorkspace.path,
|
|
14132
14283
|
defaultWorkspaceDir: defaultWorkspaceDir(),
|
|
14133
|
-
dataDir:
|
|
14284
|
+
dataDir: join21(homedir12(), ".zam")
|
|
14134
14285
|
});
|
|
14135
14286
|
});
|
|
14136
14287
|
});
|
|
14137
14288
|
function provisionConfiguredWorkspaces() {
|
|
14138
14289
|
return getConfiguredWorkspaces().flatMap(
|
|
14139
|
-
(workspace) =>
|
|
14290
|
+
(workspace) => existsSync18(workspace.path) ? wireSkills(workspace.path, parseSetupAgents(), { quiet: true }) : []
|
|
14140
14291
|
);
|
|
14141
14292
|
}
|
|
14142
14293
|
function buildWorkspaceLinkHealth(workspaces) {
|
|
14143
14294
|
const agents = parseSetupAgents();
|
|
14144
14295
|
const map = {};
|
|
14145
14296
|
for (const workspace of workspaces) {
|
|
14146
|
-
if (!
|
|
14297
|
+
if (!existsSync18(workspace.path)) continue;
|
|
14147
14298
|
const links = inspectSkillLinks(workspace.path, agents);
|
|
14148
14299
|
map[workspace.id] = {
|
|
14149
14300
|
health: summarizeSkillLinkHealth(links),
|
|
@@ -14173,7 +14324,7 @@ bridgeCommand.command("workspace-list").description("List configured ZAM workspa
|
|
|
14173
14324
|
activeWorkspace,
|
|
14174
14325
|
workspaceDir: activeWorkspace.path,
|
|
14175
14326
|
defaultWorkspaceDir: defaultWorkspaceDir(),
|
|
14176
|
-
dataDir:
|
|
14327
|
+
dataDir: join21(homedir12(), ".zam"),
|
|
14177
14328
|
linkHealth: buildWorkspaceLinkHealth(workspaces)
|
|
14178
14329
|
});
|
|
14179
14330
|
});
|
|
@@ -14188,7 +14339,7 @@ bridgeCommand.command("workspace-repair-links").description(
|
|
|
14188
14339
|
if (!id) jsonError("A non-empty --id is required");
|
|
14189
14340
|
const workspace = getConfiguredWorkspaces().find((item) => item.id === id);
|
|
14190
14341
|
if (!workspace) jsonError(`Workspace "${id}" is not configured`);
|
|
14191
|
-
if (!
|
|
14342
|
+
if (!existsSync18(workspace.path)) {
|
|
14192
14343
|
jsonError(`Workspace path does not exist: ${workspace.path}`);
|
|
14193
14344
|
}
|
|
14194
14345
|
const agents = parseSetupAgents(opts.agents);
|
|
@@ -14219,8 +14370,8 @@ function parseBridgeWorkspaceKind(value) {
|
|
|
14219
14370
|
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
14371
|
const raw = String(opts.path ?? "").trim();
|
|
14221
14372
|
if (!raw) jsonError("A non-empty --path is required");
|
|
14222
|
-
const path =
|
|
14223
|
-
if (!
|
|
14373
|
+
const path = resolve5(raw);
|
|
14374
|
+
if (!existsSync18(path)) jsonError(`Workspace path does not exist: ${path}`);
|
|
14224
14375
|
const id = opts.id ? String(opts.id).trim() : void 0;
|
|
14225
14376
|
if (opts.id && !id) jsonError("A non-empty --id is required");
|
|
14226
14377
|
const kind = parseBridgeWorkspaceKind(opts.kind);
|
|
@@ -14264,8 +14415,8 @@ bridgeCommand.command("workspace-remove").description("Unregister a ZAM workspac
|
|
|
14264
14415
|
bridgeCommand.command("set-workspace-dir").description("Set the personal workspace directory (JSON)").requiredOption("--dir <path>", "Path to the workspace directory").action(async (opts) => {
|
|
14265
14416
|
const raw = String(opts.dir ?? "").trim();
|
|
14266
14417
|
if (!raw) jsonError("A non-empty --dir is required");
|
|
14267
|
-
const dir =
|
|
14268
|
-
if (!
|
|
14418
|
+
const dir = resolve5(raw);
|
|
14419
|
+
if (!existsSync18(dir)) jsonError(`Workspace path does not exist: ${dir}`);
|
|
14269
14420
|
const skillLinks = wireSkills(dir, parseSetupAgents(), { quiet: true });
|
|
14270
14421
|
await withDb2(async (db) => {
|
|
14271
14422
|
const workspace = await activateWorkspacePath(db, dir);
|
|
@@ -14328,7 +14479,7 @@ bridgeCommand.command("agent-open").description("Launch an agent harness in the
|
|
|
14328
14479
|
jsonError(`Workspace is not configured: ${opts.workspace}`);
|
|
14329
14480
|
}
|
|
14330
14481
|
const activeWorkspace = await ensureActiveWorkspace(db);
|
|
14331
|
-
const workspace = opts.dir ?
|
|
14482
|
+
const workspace = opts.dir ? existsSync18(opts.dir) ? opts.dir : homedir12() : existingWorkspaceDirOrHome(configuredWorkspace ?? activeWorkspace);
|
|
14332
14483
|
launchHarness(harness, {
|
|
14333
14484
|
executable,
|
|
14334
14485
|
workspace,
|
|
@@ -14700,7 +14851,7 @@ bridgeCommand.command("discover-skills").description(
|
|
|
14700
14851
|
"20"
|
|
14701
14852
|
).action(async (opts) => {
|
|
14702
14853
|
try {
|
|
14703
|
-
const monitorDir =
|
|
14854
|
+
const monitorDir = join21(homedir12(), ".zam", "monitor");
|
|
14704
14855
|
let files;
|
|
14705
14856
|
try {
|
|
14706
14857
|
files = readdirSync2(monitorDir).filter((f) => f.endsWith(".jsonl"));
|
|
@@ -14713,7 +14864,7 @@ bridgeCommand.command("discover-skills").description(
|
|
|
14713
14864
|
return;
|
|
14714
14865
|
}
|
|
14715
14866
|
const limit = Number(opts.limit);
|
|
14716
|
-
const sorted = files.map((f) => ({ name: f, path:
|
|
14867
|
+
const sorted = files.map((f) => ({ name: f, path: join21(monitorDir, f) })).sort((a, b) => b.name.localeCompare(a.name)).slice(0, limit);
|
|
14717
14868
|
const sessionCommands = /* @__PURE__ */ new Map();
|
|
14718
14869
|
for (const file of sorted) {
|
|
14719
14870
|
const sessionId = file.name.replace(".jsonl", "");
|
|
@@ -15215,7 +15366,7 @@ bridgeCommand.command("capture-ui").description("Capture a screenshot for agent-
|
|
|
15215
15366
|
return;
|
|
15216
15367
|
}
|
|
15217
15368
|
}
|
|
15218
|
-
const outputPath = opts.image ?? opts.output ??
|
|
15369
|
+
const outputPath = opts.image ?? opts.output ?? join21(tmpdir3(), `zam-capture-${randomBytes2(4).toString("hex")}.png`);
|
|
15219
15370
|
const captureResult = isProvided ? { method: "provided", target: null } : captureScreenshot(outputPath, opts.hwnd, opts.processName);
|
|
15220
15371
|
if (!isProvided) {
|
|
15221
15372
|
const post = decidePostCapture(policy, {
|
|
@@ -15243,7 +15394,7 @@ bridgeCommand.command("capture-ui").description("Capture a screenshot for agent-
|
|
|
15243
15394
|
return;
|
|
15244
15395
|
}
|
|
15245
15396
|
}
|
|
15246
|
-
const imageBytes =
|
|
15397
|
+
const imageBytes = readFileSync15(outputPath);
|
|
15247
15398
|
const base64 = imageBytes.toString("base64");
|
|
15248
15399
|
jsonOut2({
|
|
15249
15400
|
sessionId: opts.session ?? null,
|
|
@@ -15270,11 +15421,11 @@ bridgeCommand.command("start-recording").description("Start screen recording in
|
|
|
15270
15421
|
return;
|
|
15271
15422
|
}
|
|
15272
15423
|
const sessionId = opts.session;
|
|
15273
|
-
const statePath =
|
|
15424
|
+
const statePath = join21(tmpdir3(), `zam-recording-${sessionId}.json`);
|
|
15274
15425
|
const defaultExt = platform === "win32" ? ".mkv" : ".mov";
|
|
15275
|
-
const outputPath = opts.output ??
|
|
15276
|
-
const { existsSync:
|
|
15277
|
-
if (
|
|
15426
|
+
const outputPath = opts.output ?? join21(tmpdir3(), `zam-recording-${sessionId}${defaultExt}`);
|
|
15427
|
+
const { existsSync: existsSync27, writeFileSync: writeFileSync15, openSync, closeSync } = await import("fs");
|
|
15428
|
+
if (existsSync27(statePath)) {
|
|
15278
15429
|
jsonOut2({
|
|
15279
15430
|
sessionId,
|
|
15280
15431
|
started: false,
|
|
@@ -15282,7 +15433,7 @@ bridgeCommand.command("start-recording").description("Start screen recording in
|
|
|
15282
15433
|
});
|
|
15283
15434
|
return;
|
|
15284
15435
|
}
|
|
15285
|
-
const logPath =
|
|
15436
|
+
const logPath = join21(tmpdir3(), `zam-recording-${sessionId}.log`);
|
|
15286
15437
|
let logFd;
|
|
15287
15438
|
try {
|
|
15288
15439
|
logFd = openSync(logPath, "w");
|
|
@@ -15328,7 +15479,7 @@ bridgeCommand.command("start-recording").description("Start screen recording in
|
|
|
15328
15479
|
}
|
|
15329
15480
|
child.unref();
|
|
15330
15481
|
if (child.pid) {
|
|
15331
|
-
|
|
15482
|
+
writeFileSync15(
|
|
15332
15483
|
statePath,
|
|
15333
15484
|
JSON.stringify({
|
|
15334
15485
|
pid: child.pid,
|
|
@@ -15364,9 +15515,9 @@ bridgeCommand.command("stop-recording").description(
|
|
|
15364
15515
|
return;
|
|
15365
15516
|
}
|
|
15366
15517
|
const sessionId = opts.session;
|
|
15367
|
-
const statePath =
|
|
15368
|
-
const { existsSync:
|
|
15369
|
-
if (!
|
|
15518
|
+
const statePath = join21(tmpdir3(), `zam-recording-${sessionId}.json`);
|
|
15519
|
+
const { existsSync: existsSync27, readFileSync: readFileSync20, rmSync: rmSync4 } = await import("fs");
|
|
15520
|
+
if (!existsSync27(statePath)) {
|
|
15370
15521
|
jsonOut2({
|
|
15371
15522
|
sessionId,
|
|
15372
15523
|
stopped: false,
|
|
@@ -15374,7 +15525,7 @@ bridgeCommand.command("stop-recording").description(
|
|
|
15374
15525
|
});
|
|
15375
15526
|
return;
|
|
15376
15527
|
}
|
|
15377
|
-
const state = JSON.parse(
|
|
15528
|
+
const state = JSON.parse(readFileSync20(statePath, "utf8"));
|
|
15378
15529
|
const { pid, outputPath } = state;
|
|
15379
15530
|
try {
|
|
15380
15531
|
process.kill(pid, "SIGINT");
|
|
@@ -15390,7 +15541,7 @@ bridgeCommand.command("stop-recording").description(
|
|
|
15390
15541
|
};
|
|
15391
15542
|
let attempts = 0;
|
|
15392
15543
|
while (isProcessRunning(pid) && attempts < 20) {
|
|
15393
|
-
await new Promise((
|
|
15544
|
+
await new Promise((resolve11) => setTimeout(resolve11, 250));
|
|
15394
15545
|
attempts++;
|
|
15395
15546
|
}
|
|
15396
15547
|
if (isProcessRunning(pid)) {
|
|
@@ -15403,7 +15554,7 @@ bridgeCommand.command("stop-recording").description(
|
|
|
15403
15554
|
rmSync4(statePath, { force: true });
|
|
15404
15555
|
} catch {
|
|
15405
15556
|
}
|
|
15406
|
-
if (!
|
|
15557
|
+
if (!existsSync27(outputPath)) {
|
|
15407
15558
|
jsonOut2({
|
|
15408
15559
|
sessionId,
|
|
15409
15560
|
stopped: false,
|
|
@@ -15640,7 +15791,7 @@ bridgeCommand.command("cloud-model-hint").description("Suggest a cloud model for
|
|
|
15640
15791
|
});
|
|
15641
15792
|
bridgeCommand.command("local-llm-hints").description("Detect installed local LLM servers and suggest defaults (JSON)").action(() => {
|
|
15642
15793
|
const profile = getSystemProfile();
|
|
15643
|
-
const flmInstalled = hasCommand("flm") ||
|
|
15794
|
+
const flmInstalled = hasCommand("flm") || existsSync18("C:\\Program Files\\flm\\flm.exe");
|
|
15644
15795
|
const ollamaInstalled = isOllamaInstalled();
|
|
15645
15796
|
const runners = [
|
|
15646
15797
|
{ id: "flm", label: "FastFlowLM", installed: flmInstalled },
|
|
@@ -18190,26 +18341,26 @@ var doctorCommand = new Command5("doctor").description(
|
|
|
18190
18341
|
// src/cli/commands/git-sync.ts
|
|
18191
18342
|
init_kernel();
|
|
18192
18343
|
import { execSync as execSync5 } from "child_process";
|
|
18193
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
18194
|
-
import { join as
|
|
18344
|
+
import { chmodSync as chmodSync2, existsSync as existsSync19, writeFileSync as writeFileSync11 } from "fs";
|
|
18345
|
+
import { join as join22 } from "path";
|
|
18195
18346
|
import { Command as Command6 } from "commander";
|
|
18196
18347
|
function installHook2() {
|
|
18197
|
-
const gitDir =
|
|
18198
|
-
if (!
|
|
18348
|
+
const gitDir = join22(process.cwd(), ".git");
|
|
18349
|
+
if (!existsSync19(gitDir)) {
|
|
18199
18350
|
console.error(
|
|
18200
18351
|
"Error: Current directory is not the root of a Git repository."
|
|
18201
18352
|
);
|
|
18202
18353
|
process.exit(1);
|
|
18203
18354
|
}
|
|
18204
|
-
const hooksDir =
|
|
18205
|
-
const hookPath =
|
|
18355
|
+
const hooksDir = join22(gitDir, "hooks");
|
|
18356
|
+
const hookPath = join22(hooksDir, "post-commit");
|
|
18206
18357
|
const hookContent = `#!/bin/sh
|
|
18207
18358
|
# ZAM Spaced Repetition Auto-Stale Hook
|
|
18208
18359
|
# Triggered automatically on git commits to decay modified concept cards.
|
|
18209
18360
|
zam git-sync --commit HEAD --quiet
|
|
18210
18361
|
`;
|
|
18211
18362
|
try {
|
|
18212
|
-
|
|
18363
|
+
writeFileSync11(hookPath, hookContent, { encoding: "utf-8", flag: "w" });
|
|
18213
18364
|
try {
|
|
18214
18365
|
chmodSync2(hookPath, "755");
|
|
18215
18366
|
} catch (_e) {
|
|
@@ -18312,8 +18463,8 @@ ZAM Auto-Stale Complete: Scanned ${changedFiles.length} file(s).`
|
|
|
18312
18463
|
|
|
18313
18464
|
// src/cli/commands/goal.ts
|
|
18314
18465
|
init_kernel();
|
|
18315
|
-
import { existsSync as
|
|
18316
|
-
import { resolve as
|
|
18466
|
+
import { existsSync as existsSync20, mkdirSync as mkdirSync14 } from "fs";
|
|
18467
|
+
import { resolve as resolve6 } from "path";
|
|
18317
18468
|
import { input as input2 } from "@inquirer/prompts";
|
|
18318
18469
|
import { Command as Command7 } from "commander";
|
|
18319
18470
|
async function resolveGoalsDir() {
|
|
@@ -18326,7 +18477,7 @@ async function resolveGoalsDir() {
|
|
|
18326
18477
|
} finally {
|
|
18327
18478
|
await db?.close();
|
|
18328
18479
|
}
|
|
18329
|
-
return goalsDir ?
|
|
18480
|
+
return goalsDir ? resolve6(goalsDir) : resolve6("goals");
|
|
18330
18481
|
}
|
|
18331
18482
|
var goalCommand = new Command7("goal").description(
|
|
18332
18483
|
"Manage learning goals (markdown files)"
|
|
@@ -18336,7 +18487,7 @@ goalCommand.command("list").description("List all goals").option(
|
|
|
18336
18487
|
"Filter by status (active, completed, paused, abandoned)"
|
|
18337
18488
|
).option("--tree", "Show goals as a tree with parent/child relationships").option("--json", "Output as JSON").action(async (opts) => {
|
|
18338
18489
|
const goalsDir = await resolveGoalsDir();
|
|
18339
|
-
if (!
|
|
18490
|
+
if (!existsSync20(goalsDir)) {
|
|
18340
18491
|
console.error(`Goals directory not found: ${goalsDir}`);
|
|
18341
18492
|
console.error(
|
|
18342
18493
|
"Set it with: zam settings set personal.goals_dir /path/to/goals"
|
|
@@ -18437,8 +18588,8 @@ ${"\u2500".repeat(50)}`);
|
|
|
18437
18588
|
});
|
|
18438
18589
|
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
18590
|
const goalsDir = await resolveGoalsDir();
|
|
18440
|
-
if (!
|
|
18441
|
-
|
|
18591
|
+
if (!existsSync20(goalsDir)) {
|
|
18592
|
+
mkdirSync14(goalsDir, { recursive: true });
|
|
18442
18593
|
}
|
|
18443
18594
|
let slug = opts.slug;
|
|
18444
18595
|
let title = opts.title;
|
|
@@ -18498,22 +18649,22 @@ goalCommand.command("status <slug> <status>").description("Update a goal's statu
|
|
|
18498
18649
|
|
|
18499
18650
|
// src/cli/commands/init.ts
|
|
18500
18651
|
init_kernel();
|
|
18501
|
-
import { existsSync as
|
|
18502
|
-
import { homedir as
|
|
18503
|
-
import { join as
|
|
18652
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync15, writeFileSync as writeFileSync12 } from "fs";
|
|
18653
|
+
import { homedir as homedir13 } from "os";
|
|
18654
|
+
import { join as join23, resolve as resolve7 } from "path";
|
|
18504
18655
|
import { confirm, input as input3 } from "@inquirer/prompts";
|
|
18505
18656
|
import { Command as Command8 } from "commander";
|
|
18506
|
-
var HOME2 =
|
|
18657
|
+
var HOME2 = homedir13();
|
|
18507
18658
|
function printLine(char = "\u2550", len = 60, color = "\x1B[36m") {
|
|
18508
18659
|
console.log(`${color}${char.repeat(len)}\x1B[0m`);
|
|
18509
18660
|
}
|
|
18510
18661
|
function bootstrapSandboxWorkspace(workspaceDir) {
|
|
18511
|
-
|
|
18512
|
-
|
|
18513
|
-
|
|
18514
|
-
const worldviewFile =
|
|
18515
|
-
if (!
|
|
18516
|
-
|
|
18662
|
+
mkdirSync15(join23(workspaceDir, "beliefs"), { recursive: true });
|
|
18663
|
+
mkdirSync15(join23(workspaceDir, "goals"), { recursive: true });
|
|
18664
|
+
mkdirSync15(join23(workspaceDir, "skills"), { recursive: true });
|
|
18665
|
+
const worldviewFile = join23(workspaceDir, "beliefs", "worldview.md");
|
|
18666
|
+
if (!existsSync21(worldviewFile)) {
|
|
18667
|
+
writeFileSync12(
|
|
18517
18668
|
worldviewFile,
|
|
18518
18669
|
`# Personal Worldview
|
|
18519
18670
|
|
|
@@ -18525,9 +18676,9 @@ Here, I declare the core concepts and principles I want to master.
|
|
|
18525
18676
|
"utf8"
|
|
18526
18677
|
);
|
|
18527
18678
|
}
|
|
18528
|
-
const goalsFile =
|
|
18529
|
-
if (!
|
|
18530
|
-
|
|
18679
|
+
const goalsFile = join23(workspaceDir, "goals", "goals.md");
|
|
18680
|
+
if (!existsSync21(goalsFile)) {
|
|
18681
|
+
writeFileSync12(
|
|
18531
18682
|
goalsFile,
|
|
18532
18683
|
`# Personal Goals
|
|
18533
18684
|
|
|
@@ -18549,8 +18700,8 @@ var initCommand = new Command8("init").description("Launch the guided interactiv
|
|
|
18549
18700
|
);
|
|
18550
18701
|
printLine();
|
|
18551
18702
|
console.log("\n\x1B[1m[1/5] Setting up Local Workspace Sandbox\x1B[0m");
|
|
18552
|
-
const defaultWorkspace =
|
|
18553
|
-
const workspacePath =
|
|
18703
|
+
const defaultWorkspace = join23(HOME2, "Documents", "zam");
|
|
18704
|
+
const workspacePath = resolve7(
|
|
18554
18705
|
await input3({
|
|
18555
18706
|
message: "Choose your ZAM workspace directory:",
|
|
18556
18707
|
default: defaultWorkspace
|
|
@@ -19751,7 +19902,7 @@ observerCommand.command("revoke <process>").description("Remove a process from o
|
|
|
19751
19902
|
|
|
19752
19903
|
// src/cli/commands/profile.ts
|
|
19753
19904
|
init_kernel();
|
|
19754
|
-
import { dirname as
|
|
19905
|
+
import { dirname as dirname9, resolve as resolve8 } from "path";
|
|
19755
19906
|
import { Command as Command13 } from "commander";
|
|
19756
19907
|
var C2 = {
|
|
19757
19908
|
reset: "\x1B[0m",
|
|
@@ -19779,7 +19930,7 @@ var profileCommand = new Command13("profile").description("Show or change this m
|
|
|
19779
19930
|
if (opts.mode) setInstallMode(opts.mode);
|
|
19780
19931
|
db = await openDatabaseWithSync({ initialize: true });
|
|
19781
19932
|
if (opts.dir) {
|
|
19782
|
-
await activateWorkspacePath(db,
|
|
19933
|
+
await activateWorkspacePath(db, resolve8(opts.dir), {
|
|
19783
19934
|
kind: "personal",
|
|
19784
19935
|
label: "Personal"
|
|
19785
19936
|
});
|
|
@@ -19792,7 +19943,7 @@ var profileCommand = new Command13("profile").description("Show or change this m
|
|
|
19792
19943
|
mode: getInstallMode(),
|
|
19793
19944
|
personalDir,
|
|
19794
19945
|
syncProvider: detectSyncProvider(personalDir),
|
|
19795
|
-
dataDir:
|
|
19946
|
+
dataDir: dirname9(dbPath),
|
|
19796
19947
|
dbPath
|
|
19797
19948
|
};
|
|
19798
19949
|
if (opts.json) {
|
|
@@ -20181,7 +20332,7 @@ ${"\u2550".repeat(50)}`);
|
|
|
20181
20332
|
|
|
20182
20333
|
// src/cli/commands/session.ts
|
|
20183
20334
|
init_kernel();
|
|
20184
|
-
import { readFileSync as
|
|
20335
|
+
import { readFileSync as readFileSync16 } from "fs";
|
|
20185
20336
|
import { input as input6, select as select2 } from "@inquirer/prompts";
|
|
20186
20337
|
import { Command as Command16 } from "commander";
|
|
20187
20338
|
var sessionCommand = new Command16("session").description(
|
|
@@ -20372,7 +20523,7 @@ function loadPatternFile(path) {
|
|
|
20372
20523
|
if (!path) return [];
|
|
20373
20524
|
let parsed;
|
|
20374
20525
|
try {
|
|
20375
|
-
parsed = JSON.parse(
|
|
20526
|
+
parsed = JSON.parse(readFileSync16(path, "utf-8"));
|
|
20376
20527
|
} catch (err) {
|
|
20377
20528
|
throw new Error(
|
|
20378
20529
|
`Cannot read synthesis patterns from ${path}: ${err.message}`
|
|
@@ -20563,7 +20714,7 @@ sessionCommand.command("end").description("End a session and show summary").requ
|
|
|
20563
20714
|
|
|
20564
20715
|
// src/cli/commands/settings.ts
|
|
20565
20716
|
init_kernel();
|
|
20566
|
-
import { existsSync as
|
|
20717
|
+
import { existsSync as existsSync22 } from "fs";
|
|
20567
20718
|
import { Command as Command17 } from "commander";
|
|
20568
20719
|
var settingsCommand = new Command17("settings").description(
|
|
20569
20720
|
"Manage user settings"
|
|
@@ -20728,7 +20879,7 @@ settingsCommand.command("repos").description("Show or set Personal, Team, and Or
|
|
|
20728
20879
|
console.log("\nValidation:");
|
|
20729
20880
|
for (const [name, path] of Object.entries(paths)) {
|
|
20730
20881
|
if (path) {
|
|
20731
|
-
const exists =
|
|
20882
|
+
const exists = existsSync22(path);
|
|
20732
20883
|
console.log(
|
|
20733
20884
|
` ${name.padEnd(9)}: ${exists ? "\x1B[32m\u2713 Valid folder\x1B[0m" : "\x1B[31m\u2717 Directory does not exist\x1B[0m"}`
|
|
20734
20885
|
);
|
|
@@ -20741,7 +20892,7 @@ settingsCommand.command("repos").description("Show or set Personal, Team, and Or
|
|
|
20741
20892
|
|
|
20742
20893
|
// src/cli/commands/setup.ts
|
|
20743
20894
|
init_kernel();
|
|
20744
|
-
import { resolve as
|
|
20895
|
+
import { resolve as resolve9 } from "path";
|
|
20745
20896
|
import { Command as Command18 } from "commander";
|
|
20746
20897
|
function formatDatabaseInitTarget(target) {
|
|
20747
20898
|
switch (target.kind) {
|
|
@@ -20801,7 +20952,7 @@ var setupCommand = new Command18("setup").description(
|
|
|
20801
20952
|
console.error(`Error: ${err.message}`);
|
|
20802
20953
|
process.exit(1);
|
|
20803
20954
|
}
|
|
20804
|
-
const target =
|
|
20955
|
+
const target = resolve9(opts.target ?? process.cwd());
|
|
20805
20956
|
const updateExistingInstructions = Boolean(opts.target) || opts.force;
|
|
20806
20957
|
console.log(
|
|
20807
20958
|
`Setting up ZAM in ${target}${opts.dryRun ? " (dry run)" : ""}
|
|
@@ -20925,8 +21076,8 @@ skillCommand.command("add").description("Register a new agent skill").requiredOp
|
|
|
20925
21076
|
|
|
20926
21077
|
// src/cli/commands/snapshot.ts
|
|
20927
21078
|
init_kernel();
|
|
20928
|
-
import { existsSync as
|
|
20929
|
-
import { dirname as
|
|
21079
|
+
import { existsSync as existsSync23, mkdirSync as mkdirSync16, readFileSync as readFileSync17, writeFileSync as writeFileSync13 } from "fs";
|
|
21080
|
+
import { dirname as dirname10, join as join24 } from "path";
|
|
20930
21081
|
import { Command as Command20 } from "commander";
|
|
20931
21082
|
function defaultOutName() {
|
|
20932
21083
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d+Z$/, "").replace(/:/g, "-");
|
|
@@ -20955,12 +21106,12 @@ var exportCmd = new Command20("export").description("Write a portable SQL-text s
|
|
|
20955
21106
|
process.stdout.write(snapshot);
|
|
20956
21107
|
return;
|
|
20957
21108
|
}
|
|
20958
|
-
const out = opts.out ??
|
|
20959
|
-
const dir =
|
|
20960
|
-
if (dir && dir !== "." && !
|
|
20961
|
-
|
|
21109
|
+
const out = opts.out ?? join24(personalDir, "snapshots", defaultOutName());
|
|
21110
|
+
const dir = dirname10(out);
|
|
21111
|
+
if (dir && dir !== "." && !existsSync23(dir)) {
|
|
21112
|
+
mkdirSync16(dir, { recursive: true });
|
|
20962
21113
|
}
|
|
20963
|
-
|
|
21114
|
+
writeFileSync13(out, snapshot, "utf-8");
|
|
20964
21115
|
console.log(`Snapshot written: ${out}`);
|
|
20965
21116
|
console.log(
|
|
20966
21117
|
` ${total} row(s)${nonEmpty.length ? ` \u2014 ${nonEmpty.join(", ")}` : ""}`
|
|
@@ -20974,11 +21125,11 @@ var exportCmd = new Command20("export").description("Write a portable SQL-text s
|
|
|
20974
21125
|
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
21126
|
let db;
|
|
20976
21127
|
try {
|
|
20977
|
-
if (!
|
|
21128
|
+
if (!existsSync23(file)) {
|
|
20978
21129
|
console.error(`Error: Snapshot file not found: ${file}`);
|
|
20979
21130
|
process.exit(1);
|
|
20980
21131
|
}
|
|
20981
|
-
const snapshot =
|
|
21132
|
+
const snapshot = readFileSync17(file, "utf-8");
|
|
20982
21133
|
db = await openDatabaseWithSync({ initialize: true });
|
|
20983
21134
|
const result = await importSnapshot(db, snapshot, { force: opts.force });
|
|
20984
21135
|
await db.close();
|
|
@@ -20996,11 +21147,11 @@ var importCmd = new Command20("import").description("Restore a snapshot into the
|
|
|
20996
21147
|
});
|
|
20997
21148
|
var verifyCmd = new Command20("verify").description("Check a snapshot's manifest and checksum without importing").argument("<file>", "Snapshot file to verify").action((file) => {
|
|
20998
21149
|
try {
|
|
20999
|
-
if (!
|
|
21150
|
+
if (!existsSync23(file)) {
|
|
21000
21151
|
console.error(`Error: Snapshot file not found: ${file}`);
|
|
21001
21152
|
process.exit(1);
|
|
21002
21153
|
}
|
|
21003
|
-
const manifest = verifySnapshot(
|
|
21154
|
+
const manifest = verifySnapshot(readFileSync17(file, "utf-8"));
|
|
21004
21155
|
const { total, nonEmpty } = summarize(manifest.tables);
|
|
21005
21156
|
console.log(`Valid snapshot (format v${manifest.version})`);
|
|
21006
21157
|
console.log(` created: ${manifest.createdAt}`);
|
|
@@ -21549,10 +21700,10 @@ tokenCommand.command("reembed").description("Backfill or refresh semantic-search
|
|
|
21549
21700
|
// src/cli/commands/ui.ts
|
|
21550
21701
|
init_kernel();
|
|
21551
21702
|
import { spawn as spawn3, spawnSync } from "child_process";
|
|
21552
|
-
import { existsSync as
|
|
21553
|
-
import { homedir as
|
|
21554
|
-
import { dirname as
|
|
21555
|
-
import { fileURLToPath as
|
|
21703
|
+
import { existsSync as existsSync24 } from "fs";
|
|
21704
|
+
import { homedir as homedir14 } from "os";
|
|
21705
|
+
import { dirname as dirname11, join as join25 } from "path";
|
|
21706
|
+
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
21556
21707
|
import { Command as Command23 } from "commander";
|
|
21557
21708
|
var C3 = {
|
|
21558
21709
|
reset: "\x1B[0m",
|
|
@@ -21563,14 +21714,14 @@ var C3 = {
|
|
|
21563
21714
|
dim: "\x1B[2m"
|
|
21564
21715
|
};
|
|
21565
21716
|
function findDesktopDir() {
|
|
21566
|
-
const starts = [process.cwd(),
|
|
21717
|
+
const starts = [process.cwd(), dirname11(fileURLToPath5(import.meta.url))];
|
|
21567
21718
|
for (const start of starts) {
|
|
21568
21719
|
let dir = start;
|
|
21569
21720
|
for (let i = 0; i < 10; i++) {
|
|
21570
|
-
if (
|
|
21571
|
-
return
|
|
21721
|
+
if (existsSync24(join25(dir, "desktop", "src-tauri", "tauri.conf.json"))) {
|
|
21722
|
+
return join25(dir, "desktop");
|
|
21572
21723
|
}
|
|
21573
|
-
const parent =
|
|
21724
|
+
const parent = dirname11(dir);
|
|
21574
21725
|
if (parent === dir) break;
|
|
21575
21726
|
dir = parent;
|
|
21576
21727
|
}
|
|
@@ -21578,30 +21729,30 @@ function findDesktopDir() {
|
|
|
21578
21729
|
return null;
|
|
21579
21730
|
}
|
|
21580
21731
|
function findBuiltApp(desktopDir) {
|
|
21581
|
-
const releaseDir =
|
|
21732
|
+
const releaseDir = join25(desktopDir, "src-tauri", "target", "release");
|
|
21582
21733
|
if (process.platform === "win32") {
|
|
21583
21734
|
for (const name of ["ZAM.exe", "zam.exe", "zam-desktop.exe"]) {
|
|
21584
|
-
const p =
|
|
21585
|
-
if (
|
|
21735
|
+
const p = join25(releaseDir, name);
|
|
21736
|
+
if (existsSync24(p)) return p;
|
|
21586
21737
|
}
|
|
21587
21738
|
} else if (process.platform === "darwin") {
|
|
21588
|
-
const app =
|
|
21589
|
-
if (
|
|
21739
|
+
const app = join25(releaseDir, "bundle", "macos", "ZAM.app");
|
|
21740
|
+
if (existsSync24(app)) return app;
|
|
21590
21741
|
} else {
|
|
21591
21742
|
for (const name of ["zam", "ZAM", "zam-desktop"]) {
|
|
21592
|
-
const p =
|
|
21593
|
-
if (
|
|
21743
|
+
const p = join25(releaseDir, name);
|
|
21744
|
+
if (existsSync24(p)) return p;
|
|
21594
21745
|
}
|
|
21595
21746
|
}
|
|
21596
21747
|
return null;
|
|
21597
21748
|
}
|
|
21598
21749
|
function findInstalledApp() {
|
|
21599
21750
|
const candidates = process.platform === "win32" ? [
|
|
21600
|
-
process.env.LOCALAPPDATA &&
|
|
21601
|
-
process.env.ProgramFiles &&
|
|
21602
|
-
process.env["ProgramFiles(x86)"] &&
|
|
21603
|
-
] : process.platform === "darwin" ? ["/Applications/ZAM.app",
|
|
21604
|
-
return candidates.find((candidate) => candidate &&
|
|
21751
|
+
process.env.LOCALAPPDATA && join25(process.env.LOCALAPPDATA, "Programs", "ZAM", "ZAM.exe"),
|
|
21752
|
+
process.env.ProgramFiles && join25(process.env.ProgramFiles, "ZAM", "ZAM.exe"),
|
|
21753
|
+
process.env["ProgramFiles(x86)"] && join25(process.env["ProgramFiles(x86)"], "ZAM", "ZAM.exe")
|
|
21754
|
+
] : process.platform === "darwin" ? ["/Applications/ZAM.app", join25(homedir14(), "Applications", "ZAM.app")] : ["/opt/ZAM/zam", "/usr/bin/zam-desktop"];
|
|
21755
|
+
return candidates.find((candidate) => candidate && existsSync24(candidate)) || null;
|
|
21605
21756
|
}
|
|
21606
21757
|
function runNpm(args, opts) {
|
|
21607
21758
|
const res = spawnSync("npm", args, {
|
|
@@ -21612,7 +21763,7 @@ function runNpm(args, opts) {
|
|
|
21612
21763
|
return res.status ?? 1;
|
|
21613
21764
|
}
|
|
21614
21765
|
function ensureDesktopDeps(desktopDir) {
|
|
21615
|
-
if (
|
|
21766
|
+
if (existsSync24(join25(desktopDir, "node_modules"))) return true;
|
|
21616
21767
|
console.log(
|
|
21617
21768
|
`${C3.cyan}Installing desktop dependencies (one-time)...${C3.reset}`
|
|
21618
21769
|
);
|
|
@@ -21638,13 +21789,13 @@ function requireRust() {
|
|
|
21638
21789
|
function hasMsvcBuildTools() {
|
|
21639
21790
|
if (process.platform !== "win32") return true;
|
|
21640
21791
|
const pf86 = process.env["ProgramFiles(x86)"] || "C:\\Program Files (x86)";
|
|
21641
|
-
const vswhere =
|
|
21792
|
+
const vswhere = join25(
|
|
21642
21793
|
pf86,
|
|
21643
21794
|
"Microsoft Visual Studio",
|
|
21644
21795
|
"Installer",
|
|
21645
21796
|
"vswhere.exe"
|
|
21646
21797
|
);
|
|
21647
|
-
if (!
|
|
21798
|
+
if (!existsSync24(vswhere)) return false;
|
|
21648
21799
|
const res = spawnSync(
|
|
21649
21800
|
vswhere,
|
|
21650
21801
|
[
|
|
@@ -21676,7 +21827,7 @@ function requireMsvcOnWindows() {
|
|
|
21676
21827
|
return false;
|
|
21677
21828
|
}
|
|
21678
21829
|
function warnIfCliMissing(repoRoot) {
|
|
21679
|
-
if (!
|
|
21830
|
+
if (!existsSync24(join25(repoRoot, "dist", "cli", "index.js"))) {
|
|
21680
21831
|
console.warn(
|
|
21681
21832
|
`${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
21833
|
);
|
|
@@ -21739,7 +21890,7 @@ var uiCommand = new Command23("ui").description("Launch the ZAM Desktop GUI (Act
|
|
|
21739
21890
|
).option("--shortcut", "Create Desktop + Start-menu shortcuts to the GUI").action((opts) => {
|
|
21740
21891
|
const installedApp = findInstalledApp();
|
|
21741
21892
|
if (!opts.dev && !opts.build && !opts.shortcut && installedApp) {
|
|
21742
|
-
launchApp(installedApp,
|
|
21893
|
+
launchApp(installedApp, homedir14());
|
|
21743
21894
|
return;
|
|
21744
21895
|
}
|
|
21745
21896
|
const desktopDir = findDesktopDir();
|
|
@@ -21749,7 +21900,7 @@ var uiCommand = new Command23("ui").description("Launch the ZAM Desktop GUI (Act
|
|
|
21749
21900
|
);
|
|
21750
21901
|
process.exit(1);
|
|
21751
21902
|
}
|
|
21752
|
-
const repoRoot =
|
|
21903
|
+
const repoRoot = dirname11(desktopDir);
|
|
21753
21904
|
if (opts.build) {
|
|
21754
21905
|
if (!requireRust()) process.exit(1);
|
|
21755
21906
|
if (!requireMsvcOnWindows()) process.exit(1);
|
|
@@ -21760,7 +21911,7 @@ var uiCommand = new Command23("ui").description("Launch the ZAM Desktop GUI (Act
|
|
|
21760
21911
|
);
|
|
21761
21912
|
const code = runNpm(["run", "tauri", "build"], { cwd: desktopDir });
|
|
21762
21913
|
if (code === 0) {
|
|
21763
|
-
const bundle =
|
|
21914
|
+
const bundle = join25(
|
|
21764
21915
|
desktopDir,
|
|
21765
21916
|
"src-tauri",
|
|
21766
21917
|
"target",
|
|
@@ -21800,7 +21951,7 @@ ${C3.green}\u2713 Done. Installer is in:${C3.reset}
|
|
|
21800
21951
|
);
|
|
21801
21952
|
process.exit(1);
|
|
21802
21953
|
}
|
|
21803
|
-
createShortcuts(shortcutTarget,
|
|
21954
|
+
createShortcuts(shortcutTarget, dirname11(shortcutTarget));
|
|
21804
21955
|
return;
|
|
21805
21956
|
}
|
|
21806
21957
|
if (builtApp) {
|
|
@@ -21838,9 +21989,9 @@ ${C3.dim}After that, 'zam ui' launches it directly.${C3.reset}`
|
|
|
21838
21989
|
// src/cli/commands/update.ts
|
|
21839
21990
|
init_kernel();
|
|
21840
21991
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
21841
|
-
import { existsSync as
|
|
21842
|
-
import { dirname as
|
|
21843
|
-
import { fileURLToPath as
|
|
21992
|
+
import { existsSync as existsSync25, readFileSync as readFileSync18, realpathSync as realpathSync2 } from "fs";
|
|
21993
|
+
import { dirname as dirname12, join as join26 } from "path";
|
|
21994
|
+
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
21844
21995
|
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
21845
21996
|
import { Command as Command24 } from "commander";
|
|
21846
21997
|
var CHANNELS = [
|
|
@@ -21861,7 +22012,7 @@ var C4 = {
|
|
|
21861
22012
|
function versionAt(dir) {
|
|
21862
22013
|
try {
|
|
21863
22014
|
const pkg2 = JSON.parse(
|
|
21864
|
-
|
|
22015
|
+
readFileSync18(join26(dir, "package.json"), "utf-8")
|
|
21865
22016
|
);
|
|
21866
22017
|
return pkg2.version ?? "unknown";
|
|
21867
22018
|
} catch {
|
|
@@ -21919,14 +22070,14 @@ var checkCmd = new Command24("check").description("Check whether a newer ZAM has
|
|
|
21919
22070
|
}
|
|
21920
22071
|
);
|
|
21921
22072
|
function findSourceRepo() {
|
|
21922
|
-
let dir = realpathSync2(
|
|
21923
|
-
let parent =
|
|
22073
|
+
let dir = realpathSync2(dirname12(fileURLToPath6(import.meta.url)));
|
|
22074
|
+
let parent = dirname12(dir);
|
|
21924
22075
|
while (parent !== dir) {
|
|
21925
|
-
if (
|
|
22076
|
+
if (existsSync25(join26(dir, ".git"))) return dir;
|
|
21926
22077
|
dir = parent;
|
|
21927
|
-
parent =
|
|
22078
|
+
parent = dirname12(dir);
|
|
21928
22079
|
}
|
|
21929
|
-
return
|
|
22080
|
+
return existsSync25(join26(dir, ".git")) ? dir : null;
|
|
21930
22081
|
}
|
|
21931
22082
|
function runGit(cwd, args, capture) {
|
|
21932
22083
|
const res = spawnSync2("git", args, {
|
|
@@ -21947,7 +22098,7 @@ function runNpm2(args, cwd) {
|
|
|
21947
22098
|
function smokeTestBuild(src) {
|
|
21948
22099
|
const res = spawnSync2(
|
|
21949
22100
|
process.execPath,
|
|
21950
|
-
[
|
|
22101
|
+
[join26(src, "dist", "cli", "index.js"), "--version"],
|
|
21951
22102
|
{
|
|
21952
22103
|
cwd: src,
|
|
21953
22104
|
encoding: "utf8",
|
|
@@ -22027,7 +22178,7 @@ Fix it manually in ${src} (try \`npm ci && npm run build\`, and check your Node
|
|
|
22027
22178
|
console.log(`${C4.dim}\u2192 zam setup --force${C4.reset}`);
|
|
22028
22179
|
const setup = spawnSync2(
|
|
22029
22180
|
process.execPath,
|
|
22030
|
-
[
|
|
22181
|
+
[join26(src, "dist", "cli", "index.js"), "setup", "--force"],
|
|
22031
22182
|
{ cwd: process.cwd(), stdio: "inherit" }
|
|
22032
22183
|
);
|
|
22033
22184
|
if (setup.status !== 0) {
|
|
@@ -22140,9 +22291,9 @@ var whoamiCommand = new Command25("whoami").description("Show or set the default
|
|
|
22140
22291
|
// src/cli/commands/workspace.ts
|
|
22141
22292
|
init_kernel();
|
|
22142
22293
|
import { execFileSync as execFileSync4 } from "child_process";
|
|
22143
|
-
import { existsSync as
|
|
22144
|
-
import { homedir as
|
|
22145
|
-
import { join as
|
|
22294
|
+
import { existsSync as existsSync26, writeFileSync as writeFileSync14 } from "fs";
|
|
22295
|
+
import { homedir as homedir15 } from "os";
|
|
22296
|
+
import { join as join27, resolve as resolve10 } from "path";
|
|
22146
22297
|
import { confirm as confirm4, input as input7 } from "@inquirer/prompts";
|
|
22147
22298
|
import { Command as Command26 } from "commander";
|
|
22148
22299
|
function runGit2(cwd, args) {
|
|
@@ -22226,7 +22377,7 @@ workspaceCommand.command("list").description("List configured ZAM workspaces").o
|
|
|
22226
22377
|
const workspaces = getConfiguredWorkspaces();
|
|
22227
22378
|
const agents = parseSetupAgents();
|
|
22228
22379
|
const linkHealth = Object.fromEntries(
|
|
22229
|
-
workspaces.filter((workspace) =>
|
|
22380
|
+
workspaces.filter((workspace) => existsSync26(workspace.path)).map((workspace) => [
|
|
22230
22381
|
workspace.id,
|
|
22231
22382
|
summarizeSkillLinkHealth(inspectSkillLinks(workspace.path, agents))
|
|
22232
22383
|
])
|
|
@@ -22268,8 +22419,8 @@ workspaceCommand.command("add <id>").description("Register an existing directory
|
|
|
22268
22419
|
`Source-control provider (${WORKSPACE_SOURCE_CONTROLS.join(" | ")})`
|
|
22269
22420
|
).option("--scopes <list>", "Comma-separated knowledge scopes").option("--default-agent <id>", "Default agent harness for this workspace").action((id, opts) => {
|
|
22270
22421
|
try {
|
|
22271
|
-
const path =
|
|
22272
|
-
if (!
|
|
22422
|
+
const path = resolve10(String(opts.path));
|
|
22423
|
+
if (!existsSync26(path)) {
|
|
22273
22424
|
console.error(`Workspace path does not exist: ${path}`);
|
|
22274
22425
|
process.exit(1);
|
|
22275
22426
|
}
|
|
@@ -22363,7 +22514,7 @@ workspaceCommand.command("publish").description("Publish your local workspace sa
|
|
|
22363
22514
|
);
|
|
22364
22515
|
process.exit(1);
|
|
22365
22516
|
}
|
|
22366
|
-
if (!
|
|
22517
|
+
if (!existsSync26(workspaceDir)) {
|
|
22367
22518
|
console.error(
|
|
22368
22519
|
`\x1B[31m\u2717 Workspace directory does not exist: ${workspaceDir}\x1B[0m`
|
|
22369
22520
|
);
|
|
@@ -22377,15 +22528,15 @@ Active workspace: \x1B[36m${workspaceDir}\x1B[0m`);
|
|
|
22377
22528
|
);
|
|
22378
22529
|
process.exit(1);
|
|
22379
22530
|
}
|
|
22380
|
-
const gitignorePath =
|
|
22381
|
-
if (!
|
|
22382
|
-
|
|
22531
|
+
const gitignorePath = join27(workspaceDir, ".gitignore");
|
|
22532
|
+
if (!existsSync26(gitignorePath)) {
|
|
22533
|
+
writeFileSync14(
|
|
22383
22534
|
gitignorePath,
|
|
22384
22535
|
"node_modules/\n.agent/\n.agents/\n.claude/\n.gemini/\n.goose/\n*.log\n",
|
|
22385
22536
|
"utf8"
|
|
22386
22537
|
);
|
|
22387
22538
|
}
|
|
22388
|
-
const hasGitRepo =
|
|
22539
|
+
const hasGitRepo = existsSync26(join27(workspaceDir, ".git"));
|
|
22389
22540
|
if (!hasGitRepo) {
|
|
22390
22541
|
console.log("Initializing local Git repository...");
|
|
22391
22542
|
runGit2(workspaceDir, ["init", "-b", "main"]);
|
|
@@ -22472,7 +22623,7 @@ Active workspace: \x1B[36m${workspaceDir}\x1B[0m`);
|
|
|
22472
22623
|
}
|
|
22473
22624
|
});
|
|
22474
22625
|
workspaceCommand.command("data-dir").description("Print the ZAM data directory (database, credentials, config)").option("--json", "Output as JSON").action((opts) => {
|
|
22475
|
-
const dir =
|
|
22626
|
+
const dir = join27(homedir15(), ".zam");
|
|
22476
22627
|
console.log(opts.json ? JSON.stringify({ dataDir: dir }) : dir);
|
|
22477
22628
|
});
|
|
22478
22629
|
workspaceCommand.command("backup").description("Back up the local ZAM database into your workspace").option(
|
|
@@ -22513,9 +22664,9 @@ workspaceCommand.command("backup").description("Back up the local ZAM database i
|
|
|
22513
22664
|
});
|
|
22514
22665
|
|
|
22515
22666
|
// src/cli/app.ts
|
|
22516
|
-
var __dirname =
|
|
22667
|
+
var __dirname = dirname13(fileURLToPath7(import.meta.url));
|
|
22517
22668
|
var pkg = JSON.parse(
|
|
22518
|
-
|
|
22669
|
+
readFileSync19(join28(__dirname, "..", "..", "package.json"), "utf-8")
|
|
22519
22670
|
);
|
|
22520
22671
|
var program = new Command27();
|
|
22521
22672
|
program.name("zam").description(
|