zam-core 0.10.2 → 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/.agent/skills/zam/SKILL.md +31 -5
- package/.agents/skills/zam/SKILL.md +31 -5
- package/.claude/skills/zam/SKILL.md +31 -5
- package/dist/cli/app.js +568 -275
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/commands/mcp.js +148 -50
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/copilot-extension/host.bundle.js +1 -1
- package/dist/copilot-extension/manifest.json +1 -1
- package/dist/copilot-extension/mcp-client.bundle.mjs +1 -1
- package/dist/vscode-extension/ZAM_Companion_0.10.3.vsix +0 -0
- package/dist/vscode-extension/extension.cjs +109 -0
- package/dist/vscode-extension/host.bundle.js +5331 -0
- package/dist/vscode-extension/manifest.json +5 -0
- 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 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 (!
|
|
5489
|
+
if (!packageRoot4) return "";
|
|
5490
5490
|
if (agent === "codex") {
|
|
5491
|
-
const codexPath = join8(
|
|
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
|
-
|
|
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(
|
|
5506
|
+
let path = join8(packageRoot4, ".agent", "skills", "zam", "SKILL.md");
|
|
5507
5507
|
if (existsSync7(path)) return path;
|
|
5508
|
-
path = join8(
|
|
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
|
|
6812
|
-
import { dirname as
|
|
6813
|
-
import { fileURLToPath as
|
|
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
|
|
6819
|
-
import { homedir as
|
|
6820
|
-
import { dirname as
|
|
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.";
|
|
@@ -7290,7 +7424,7 @@ ${zamExtension}
|
|
|
7290
7424
|
opts.copilotHome ?? join12(opts.home, ".copilot"),
|
|
7291
7425
|
"mcp-config.json"
|
|
7292
7426
|
);
|
|
7293
|
-
hint = "Restart GitHub Copilot or start a new session to load the 'zam' MCP server and its
|
|
7427
|
+
hint = "Restart GitHub Copilot or start a new session to load the 'zam' MCP server and its focused Recall, Graph, and Settings canvases.";
|
|
7294
7428
|
let existing = {};
|
|
7295
7429
|
if (exists(targetPath)) {
|
|
7296
7430
|
existing = parseMcpJsonConfig(targetPath, read(targetPath));
|
|
@@ -7429,6 +7563,116 @@ function installCopilotExtension(options) {
|
|
|
7429
7563
|
};
|
|
7430
7564
|
}
|
|
7431
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
|
+
|
|
7432
7676
|
// src/cli/commands/agent.ts
|
|
7433
7677
|
var C = {
|
|
7434
7678
|
reset: "\x1B[0m",
|
|
@@ -7444,6 +7688,7 @@ var CONNECT_HARNESSES = [
|
|
|
7444
7688
|
"claude-desktop",
|
|
7445
7689
|
"antigravity",
|
|
7446
7690
|
"codex",
|
|
7691
|
+
"vscode",
|
|
7447
7692
|
"opencode",
|
|
7448
7693
|
"goose",
|
|
7449
7694
|
"copilot"
|
|
@@ -7452,7 +7697,7 @@ function isConnectHarnessId(value) {
|
|
|
7452
7697
|
return CONNECT_HARNESSES.includes(value);
|
|
7453
7698
|
}
|
|
7454
7699
|
function agentsMdPresent(cwd = process.cwd()) {
|
|
7455
|
-
return
|
|
7700
|
+
return existsSync15(join15(cwd, "AGENTS.md"));
|
|
7456
7701
|
}
|
|
7457
7702
|
function printStatus() {
|
|
7458
7703
|
const installed = hasCommand("opencode");
|
|
@@ -7558,16 +7803,34 @@ var openCmd = new Command("open").description("Open an agent harness in the work
|
|
|
7558
7803
|
const workspace = opts.dir ?? process.cwd();
|
|
7559
7804
|
launchHarness(harness, { executable, workspace, shell });
|
|
7560
7805
|
});
|
|
7561
|
-
var connectCmd = new Command("connect").description(
|
|
7562
|
-
"
|
|
7563
|
-
|
|
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"
|
|
7564
7811
|
).option(
|
|
7565
7812
|
"--print",
|
|
7566
7813
|
"Print configuration changes instead of writing them to disk"
|
|
7567
7814
|
).action(async (harnessArg, opts) => {
|
|
7568
|
-
|
|
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) {
|
|
7569
7832
|
console.error(
|
|
7570
|
-
|
|
7833
|
+
"No supported user-scoped agent harness was detected. Install Codex, VS Code, or another supported host, or pass a harness explicitly."
|
|
7571
7834
|
);
|
|
7572
7835
|
process.exit(1);
|
|
7573
7836
|
}
|
|
@@ -7578,87 +7841,117 @@ var connectCmd = new Command("connect").description("Configure the ZAM MCP serve
|
|
|
7578
7841
|
);
|
|
7579
7842
|
zamPath = "zam";
|
|
7580
7843
|
}
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
result = connectHarnessMcp(harnessArg, {
|
|
7584
|
-
zamPath,
|
|
7585
|
-
cwd: process.cwd(),
|
|
7586
|
-
home: homedir10(),
|
|
7587
|
-
copilotHome: process.env.COPILOT_HOME
|
|
7588
|
-
});
|
|
7589
|
-
} catch (error) {
|
|
7590
|
-
console.error(
|
|
7591
|
-
`Error preparing MCP configuration: ${error instanceof Error ? error.message : String(error)}`
|
|
7592
|
-
);
|
|
7593
|
-
process.exit(1);
|
|
7594
|
-
}
|
|
7595
|
-
let copilotExtension;
|
|
7596
|
-
if (harnessArg === "copilot") {
|
|
7844
|
+
for (const harness of harnesses) {
|
|
7845
|
+
let result;
|
|
7597
7846
|
try {
|
|
7598
|
-
|
|
7599
|
-
home: homedir10(),
|
|
7847
|
+
result = connectHarnessMcp(harness, {
|
|
7600
7848
|
zamPath,
|
|
7601
|
-
|
|
7849
|
+
cwd: process.cwd(),
|
|
7850
|
+
home,
|
|
7851
|
+
copilotHome: process.env.COPILOT_HOME
|
|
7602
7852
|
});
|
|
7603
7853
|
} catch (error) {
|
|
7604
7854
|
console.error(
|
|
7605
|
-
`Error preparing
|
|
7855
|
+
`Error preparing ${harness} MCP configuration: ${error instanceof Error ? error.message : String(error)}`
|
|
7606
7856
|
);
|
|
7607
7857
|
process.exit(1);
|
|
7608
7858
|
}
|
|
7609
|
-
|
|
7610
|
-
|
|
7611
|
-
|
|
7612
|
-
|
|
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:
|
|
7613
7895
|
${result.content}`);
|
|
7614
|
-
|
|
7615
|
-
|
|
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) {
|
|
7616
7909
|
console.log(
|
|
7617
|
-
|
|
7910
|
+
`${C.green}\u2713${C.reset} ${harness}: MCP server 'zam' already configured in ${result.path}`
|
|
7618
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
|
+
}
|
|
7619
7925
|
}
|
|
7620
|
-
return;
|
|
7621
|
-
}
|
|
7622
|
-
if (result.alreadyConfigured) {
|
|
7623
|
-
console.log(
|
|
7624
|
-
`${C.green}\u2713${C.reset} MCP server 'zam' already configured in ${result.path}`
|
|
7625
|
-
);
|
|
7626
7926
|
if (copilotExtension) {
|
|
7627
7927
|
console.log(
|
|
7628
|
-
`${C.green}\u2713${C.reset} MCP Apps extension ${copilotExtension.action} at ${copilotExtension.destinationDir}`
|
|
7928
|
+
`${C.green}\u2713${C.reset} Copilot MCP Apps extension ${copilotExtension.action} at ${copilotExtension.destinationDir}`
|
|
7629
7929
|
);
|
|
7630
7930
|
}
|
|
7631
|
-
|
|
7632
|
-
return;
|
|
7633
|
-
}
|
|
7634
|
-
try {
|
|
7635
|
-
mkdirSync9(dirname6(result.path), { recursive: true });
|
|
7636
|
-
writeFileSync8(result.path, result.content, "utf-8");
|
|
7637
|
-
console.log(
|
|
7638
|
-
`${C.green}\u2713${C.reset} Wrote MCP configuration to ${result.path}`
|
|
7639
|
-
);
|
|
7640
|
-
if (copilotExtension) {
|
|
7931
|
+
if (vscodeExtension) {
|
|
7641
7932
|
console.log(
|
|
7642
|
-
`${C.green}\u2713${C.reset}
|
|
7933
|
+
`${C.green}\u2713${C.reset} ZAM Companion ${vscodeExtension.action} from ${vscodeExtension.vsixPath}`
|
|
7643
7934
|
);
|
|
7644
7935
|
}
|
|
7645
7936
|
console.log(` ${C.dim}${result.hint}${C.reset}`);
|
|
7646
|
-
}
|
|
7647
|
-
|
|
7648
|
-
|
|
7937
|
+
}
|
|
7938
|
+
if (!opts.print) {
|
|
7939
|
+
const skills = distributeGlobalSkills(home);
|
|
7940
|
+
const installed = skills.filter((result) => result.success).length;
|
|
7941
|
+
console.log(
|
|
7942
|
+
`${C.green}\u2713${C.reset} Refreshed ${installed}/${skills.length} global ZAM skill installations`
|
|
7649
7943
|
);
|
|
7650
|
-
process.exit(1);
|
|
7651
7944
|
}
|
|
7652
7945
|
});
|
|
7653
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);
|
|
7654
7947
|
|
|
7655
7948
|
// src/cli/commands/bridge.ts
|
|
7656
7949
|
init_kernel();
|
|
7657
|
-
import { execFileSync as
|
|
7950
|
+
import { execFileSync as execFileSync4 } from "child_process";
|
|
7658
7951
|
import { randomBytes as randomBytes2 } from "crypto";
|
|
7659
|
-
import { existsSync as
|
|
7660
|
-
import { homedir as
|
|
7661
|
-
import { join as
|
|
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";
|
|
7662
7955
|
import { Command as Command2 } from "commander";
|
|
7663
7956
|
import { ulid as ulid9 } from "ulid";
|
|
7664
7957
|
|
|
@@ -7669,7 +7962,7 @@ import fs from "fs";
|
|
|
7669
7962
|
// src/cli/llm/client.ts
|
|
7670
7963
|
init_kernel();
|
|
7671
7964
|
import { spawn as spawn2 } from "child_process";
|
|
7672
|
-
import { existsSync as
|
|
7965
|
+
import { existsSync as existsSync16, readFileSync as readFileSync12, statSync as statSync2 } from "fs";
|
|
7673
7966
|
var DEFAULT_LLM_URL = "http://localhost:8000/v1";
|
|
7674
7967
|
var DEFAULT_LLM_MAX_TOKENS = 1e4;
|
|
7675
7968
|
var RECALL_QUESTION_MAX_OUTPUT_TOKENS = 400;
|
|
@@ -8385,7 +8678,7 @@ async function extractTextFromScanViaLLM(db, imagePath) {
|
|
|
8385
8678
|
"Vision role is not enabled in settings (llm.vision.enabled)"
|
|
8386
8679
|
);
|
|
8387
8680
|
}
|
|
8388
|
-
if (!
|
|
8681
|
+
if (!existsSync16(imagePath)) {
|
|
8389
8682
|
throw new Error(`Scan file not found: ${imagePath}`);
|
|
8390
8683
|
}
|
|
8391
8684
|
const stat = statSync2(imagePath);
|
|
@@ -8406,7 +8699,7 @@ async function extractTextFromScanViaLLM(db, imagePath) {
|
|
|
8406
8699
|
if (!mime) {
|
|
8407
8700
|
throw new Error("Unsupported scan format; use PNG, JPEG, or WebP");
|
|
8408
8701
|
}
|
|
8409
|
-
const imageBytes =
|
|
8702
|
+
const imageBytes = readFileSync12(imagePath);
|
|
8410
8703
|
const dataUrl = `data:${mime};base64,${imageBytes.toString("base64")}`;
|
|
8411
8704
|
const visionEndpoint = await getVisionConfig(db);
|
|
8412
8705
|
const langName = LANGUAGE_NAMES[p.locale] || "English";
|
|
@@ -8838,7 +9131,7 @@ function spawnLocalRunner(url, model, hint) {
|
|
|
8838
9131
|
const { runner, port } = detectRunner(url, model, hint);
|
|
8839
9132
|
try {
|
|
8840
9133
|
if (runner === "fastflowlm") {
|
|
8841
|
-
const flmExe =
|
|
9134
|
+
const flmExe = existsSync16("C:\\Program Files\\flm\\flm.exe") ? "C:\\Program Files\\flm\\flm.exe" : "flm";
|
|
8842
9135
|
if (!hasCommand("flm") && flmExe === "flm") return;
|
|
8843
9136
|
spawn2(flmExe, ["serve", model, "--port", port], {
|
|
8844
9137
|
detached: true,
|
|
@@ -8859,7 +9152,7 @@ function spawnLocalRunner(url, model, hint) {
|
|
|
8859
9152
|
async function startLocalRunner(url, model, locale, hint) {
|
|
8860
9153
|
const { runner, port } = detectRunner(url, model, hint);
|
|
8861
9154
|
if (runner === "fastflowlm") {
|
|
8862
|
-
const flmExe =
|
|
9155
|
+
const flmExe = existsSync16("C:\\Program Files\\flm\\flm.exe") ? "C:\\Program Files\\flm\\flm.exe" : "flm";
|
|
8863
9156
|
if (!hasCommand("flm") && flmExe === "flm") {
|
|
8864
9157
|
console.warn(
|
|
8865
9158
|
"\x1B[31m\u2717 FastFlowLM is configured but could not be found on the system.\x1B[0m"
|
|
@@ -9338,8 +9631,8 @@ async function readImageOCR(db, imagePath) {
|
|
|
9338
9631
|
|
|
9339
9632
|
// src/cli/bridge-handlers.ts
|
|
9340
9633
|
init_kernel();
|
|
9341
|
-
import { mkdirSync as
|
|
9342
|
-
import { join as
|
|
9634
|
+
import { mkdirSync as mkdirSync12, writeFileSync as writeFileSync10 } from "fs";
|
|
9635
|
+
import { join as join18 } from "path";
|
|
9343
9636
|
|
|
9344
9637
|
// src/cli/knowledge-contexts.ts
|
|
9345
9638
|
init_kernel();
|
|
@@ -9586,16 +9879,16 @@ async function resolveSuggestMinSimilarity(db) {
|
|
|
9586
9879
|
}
|
|
9587
9880
|
|
|
9588
9881
|
// src/cli/update/latest-version.ts
|
|
9589
|
-
import { readFileSync as
|
|
9590
|
-
import { dirname as
|
|
9591
|
-
import { fileURLToPath as
|
|
9882
|
+
import { readFileSync as readFileSync13 } from "fs";
|
|
9883
|
+
import { dirname as dirname8, join as join16 } from "path";
|
|
9884
|
+
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
9592
9885
|
var GITHUB_REPO = "zam-os/zam";
|
|
9593
9886
|
function currentVersion() {
|
|
9594
|
-
const here =
|
|
9887
|
+
const here = dirname8(fileURLToPath4(import.meta.url));
|
|
9595
9888
|
for (const up of ["..", "../..", "../../.."]) {
|
|
9596
9889
|
try {
|
|
9597
9890
|
const pkg2 = JSON.parse(
|
|
9598
|
-
|
|
9891
|
+
readFileSync13(join16(here, up, "package.json"), "utf-8")
|
|
9599
9892
|
);
|
|
9600
9893
|
if (pkg2.version) return pkg2.version;
|
|
9601
9894
|
} catch {
|
|
@@ -9625,13 +9918,13 @@ async function fetchLatestVersion(repo) {
|
|
|
9625
9918
|
|
|
9626
9919
|
// src/cli/workspaces/active.ts
|
|
9627
9920
|
init_kernel();
|
|
9628
|
-
import { existsSync as
|
|
9629
|
-
import { homedir as
|
|
9630
|
-
import { basename as basename3, join as
|
|
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";
|
|
9631
9924
|
var LEGACY_WORKSPACE_DIR_KEY = "personal.workspace_dir";
|
|
9632
9925
|
var DEFAULT_WORKSPACE_ID = "personal";
|
|
9633
9926
|
function defaultWorkspaceDir() {
|
|
9634
|
-
return
|
|
9927
|
+
return join17(homedir12(), "Documents", "zam");
|
|
9635
9928
|
}
|
|
9636
9929
|
function normalizeWorkspacePath(path) {
|
|
9637
9930
|
const resolved = resolve4(path);
|
|
@@ -9686,13 +9979,13 @@ async function ensureActiveWorkspace(db) {
|
|
|
9686
9979
|
await migrateLegacyWorkspaceDir(db);
|
|
9687
9980
|
const active = getActiveWorkspace();
|
|
9688
9981
|
if (active) {
|
|
9689
|
-
|
|
9982
|
+
mkdirSync11(active.path, { recursive: true });
|
|
9690
9983
|
return active;
|
|
9691
9984
|
}
|
|
9692
9985
|
const configured = getConfiguredWorkspaces()[0];
|
|
9693
9986
|
if (configured) {
|
|
9694
9987
|
setActiveWorkspaceId(configured.id);
|
|
9695
|
-
|
|
9988
|
+
mkdirSync11(configured.path, { recursive: true });
|
|
9696
9989
|
return configured;
|
|
9697
9990
|
}
|
|
9698
9991
|
const workspace = {
|
|
@@ -9701,7 +9994,7 @@ async function ensureActiveWorkspace(db) {
|
|
|
9701
9994
|
kind: "personal",
|
|
9702
9995
|
path: defaultWorkspaceDir()
|
|
9703
9996
|
};
|
|
9704
|
-
|
|
9997
|
+
mkdirSync11(workspace.path, { recursive: true });
|
|
9705
9998
|
upsertConfiguredWorkspace(workspace);
|
|
9706
9999
|
setActiveWorkspaceId(workspace.id);
|
|
9707
10000
|
await clearLegacyWorkspaceDir(db);
|
|
@@ -9740,7 +10033,7 @@ async function removeWorkspaceAndResolveActive(db, id) {
|
|
|
9740
10033
|
};
|
|
9741
10034
|
}
|
|
9742
10035
|
function existingWorkspaceDirOrHome(workspace) {
|
|
9743
|
-
return
|
|
10036
|
+
return existsSync17(workspace.path) ? workspace.path : homedir12();
|
|
9744
10037
|
}
|
|
9745
10038
|
|
|
9746
10039
|
// src/cli/bridge-handlers.ts
|
|
@@ -10512,11 +10805,11 @@ async function backupCreate(db, params) {
|
|
|
10512
10805
|
const targetDir = params.dir || (await ensureActiveWorkspace(db)).path;
|
|
10513
10806
|
const snapshot = await exportSnapshot(db);
|
|
10514
10807
|
const manifest = verifySnapshot(snapshot);
|
|
10515
|
-
const backupDir =
|
|
10516
|
-
|
|
10808
|
+
const backupDir = join18(targetDir, "zam-backups");
|
|
10809
|
+
mkdirSync12(backupDir, { recursive: true });
|
|
10517
10810
|
const stamp = manifest.createdAt.replace(/[:.]/g, "-");
|
|
10518
|
-
const path =
|
|
10519
|
-
|
|
10811
|
+
const path = join18(backupDir, `zam-snapshot-${stamp}.sql`);
|
|
10812
|
+
writeFileSync10(path, snapshot, "utf-8");
|
|
10520
10813
|
return {
|
|
10521
10814
|
ok: true,
|
|
10522
10815
|
path,
|
|
@@ -13201,9 +13494,9 @@ function getCurriculumProvider(id) {
|
|
|
13201
13494
|
// src/cli/llm/vision.ts
|
|
13202
13495
|
init_kernel();
|
|
13203
13496
|
import { randomBytes } from "crypto";
|
|
13204
|
-
import { readFileSync as
|
|
13497
|
+
import { readFileSync as readFileSync14 } from "fs";
|
|
13205
13498
|
import { tmpdir as tmpdir2 } from "os";
|
|
13206
|
-
import { basename as basename4, join as
|
|
13499
|
+
import { basename as basename4, join as join19 } from "path";
|
|
13207
13500
|
var LANGUAGE_NAMES2 = {
|
|
13208
13501
|
en: "English",
|
|
13209
13502
|
de: "German",
|
|
@@ -13239,13 +13532,13 @@ async function observeUiSnapshotViaLLM(db, input8) {
|
|
|
13239
13532
|
const imageUrls = [];
|
|
13240
13533
|
const isVideo = /\.(mp4|mov|m4v|avi|mkv|webm)$/i.test(input8.imagePath);
|
|
13241
13534
|
if (isVideo) {
|
|
13242
|
-
const { mkdirSync:
|
|
13535
|
+
const { mkdirSync: mkdirSync18, readdirSync: readdirSync3, rmSync: rmSync4 } = await import("fs");
|
|
13243
13536
|
const { execSync: execSync6 } = await import("child_process");
|
|
13244
|
-
const tempDir =
|
|
13537
|
+
const tempDir = join19(
|
|
13245
13538
|
tmpdir2(),
|
|
13246
13539
|
`zam-frames-${randomBytes(4).toString("hex")}`
|
|
13247
13540
|
);
|
|
13248
|
-
|
|
13541
|
+
mkdirSync18(tempDir, { recursive: true });
|
|
13249
13542
|
try {
|
|
13250
13543
|
execSync6(
|
|
13251
13544
|
`ffmpeg -i "${input8.imagePath}" -vf "fps=1/3,scale=1280:-1" -vsync vfr "${tempDir}/frame_%03d.png"`,
|
|
@@ -13274,7 +13567,7 @@ async function observeUiSnapshotViaLLM(db, input8) {
|
|
|
13274
13567
|
}
|
|
13275
13568
|
}
|
|
13276
13569
|
for (const file of sampledFiles) {
|
|
13277
|
-
const bytes =
|
|
13570
|
+
const bytes = readFileSync14(join19(tempDir, file));
|
|
13278
13571
|
imageUrls.push(`data:image/png;base64,${bytes.toString("base64")}`);
|
|
13279
13572
|
}
|
|
13280
13573
|
} finally {
|
|
@@ -13284,7 +13577,7 @@ async function observeUiSnapshotViaLLM(db, input8) {
|
|
|
13284
13577
|
}
|
|
13285
13578
|
}
|
|
13286
13579
|
} else {
|
|
13287
|
-
const imageBytes =
|
|
13580
|
+
const imageBytes = readFileSync14(input8.imagePath);
|
|
13288
13581
|
const ext = input8.imagePath.split(".").pop()?.toLowerCase();
|
|
13289
13582
|
const mime = ext === "jpg" || ext === "jpeg" ? "image/jpeg" : "image/png";
|
|
13290
13583
|
imageUrls.push(`data:${mime};base64,${imageBytes.toString("base64")}`);
|
|
@@ -13753,36 +14046,36 @@ async function withProviderScope(machine, action) {
|
|
|
13753
14046
|
|
|
13754
14047
|
// src/cli/provisioning/index.ts
|
|
13755
14048
|
import {
|
|
13756
|
-
existsSync as
|
|
14049
|
+
existsSync as existsSync18,
|
|
13757
14050
|
lstatSync as lstatSync2,
|
|
13758
|
-
mkdirSync as
|
|
13759
|
-
readFileSync as
|
|
14051
|
+
mkdirSync as mkdirSync13,
|
|
14052
|
+
readFileSync as readFileSync15,
|
|
13760
14053
|
realpathSync,
|
|
13761
14054
|
rmSync as rmSync2,
|
|
13762
14055
|
symlinkSync,
|
|
13763
|
-
writeFileSync as
|
|
14056
|
+
writeFileSync as writeFileSync11
|
|
13764
14057
|
} from "fs";
|
|
13765
|
-
import { basename as basename5, dirname as
|
|
13766
|
-
import { fileURLToPath as
|
|
13767
|
-
var
|
|
13768
|
-
|
|
13769
|
-
|
|
13770
|
-
].find((candidate) =>
|
|
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));
|
|
13771
14064
|
var ALL_SETUP_AGENTS = ["claude", "copilot", "codex", "agent"];
|
|
13772
14065
|
var SKILL_PAIRS = [
|
|
13773
14066
|
{
|
|
13774
|
-
from:
|
|
13775
|
-
to:
|
|
14067
|
+
from: join20(packageRoot3, ".claude", "skills", "zam", "SKILL.md"),
|
|
14068
|
+
to: join20(".claude", "skills", "zam", "SKILL.md"),
|
|
13776
14069
|
agents: ["claude", "copilot"]
|
|
13777
14070
|
},
|
|
13778
14071
|
{
|
|
13779
|
-
from:
|
|
13780
|
-
to:
|
|
14072
|
+
from: join20(packageRoot3, ".agent", "skills", "zam", "SKILL.md"),
|
|
14073
|
+
to: join20(".agent", "skills", "zam", "SKILL.md"),
|
|
13781
14074
|
agents: ["agent"]
|
|
13782
14075
|
},
|
|
13783
14076
|
{
|
|
13784
|
-
from:
|
|
13785
|
-
to:
|
|
14077
|
+
from: join20(packageRoot3, ".agents", "skills", "zam", "SKILL.md"),
|
|
14078
|
+
to: join20(".agents", "skills", "zam", "SKILL.md"),
|
|
13786
14079
|
agents: ["codex"]
|
|
13787
14080
|
}
|
|
13788
14081
|
];
|
|
@@ -13842,15 +14135,15 @@ function linkPointsTo(sourceDir, destinationDir) {
|
|
|
13842
14135
|
function isZamSkillCopy(destinationDir) {
|
|
13843
14136
|
try {
|
|
13844
14137
|
if (!lstatSync2(destinationDir).isDirectory()) return false;
|
|
13845
|
-
const skillFile =
|
|
13846
|
-
if (!
|
|
13847
|
-
return /^name:\s*zam\s*$/m.test(
|
|
14138
|
+
const skillFile = join20(destinationDir, "SKILL.md");
|
|
14139
|
+
if (!existsSync18(skillFile)) return false;
|
|
14140
|
+
return /^name:\s*zam\s*$/m.test(readFileSync15(skillFile, "utf8"));
|
|
13848
14141
|
} catch {
|
|
13849
14142
|
return false;
|
|
13850
14143
|
}
|
|
13851
14144
|
}
|
|
13852
14145
|
function classifySkillDestination(sourceDir, destinationDir) {
|
|
13853
|
-
if (!
|
|
14146
|
+
if (!existsSync18(sourceDir)) return "source-missing";
|
|
13854
14147
|
if (!isSymbolicLink(destinationDir) && pathsResolveToSameDirectory(sourceDir, destinationDir)) {
|
|
13855
14148
|
return "source-directory";
|
|
13856
14149
|
}
|
|
@@ -13867,9 +14160,9 @@ function wireSkills(cwd = process.cwd(), agents = parseSetupAgents(), opts = {})
|
|
|
13867
14160
|
};
|
|
13868
14161
|
for (const { from, to, agents: pairAgents } of SKILL_PAIRS) {
|
|
13869
14162
|
if (!pairAgents.some((agent) => agents.has(agent))) continue;
|
|
13870
|
-
const sourceDir =
|
|
13871
|
-
const destinationDir =
|
|
13872
|
-
const label =
|
|
14163
|
+
const sourceDir = dirname9(from);
|
|
14164
|
+
const destinationDir = dirname9(join20(cwd, to));
|
|
14165
|
+
const label = dirname9(to);
|
|
13873
14166
|
const state = classifySkillDestination(sourceDir, destinationDir);
|
|
13874
14167
|
if (state === "source-missing") {
|
|
13875
14168
|
if (!opts.quiet) {
|
|
@@ -13926,7 +14219,7 @@ function wireSkills(cwd = process.cwd(), agents = parseSetupAgents(), opts = {})
|
|
|
13926
14219
|
if (destinationExists) {
|
|
13927
14220
|
rmSync2(destinationDir, { recursive: true, force: true });
|
|
13928
14221
|
}
|
|
13929
|
-
|
|
14222
|
+
mkdirSync13(dirname9(destinationDir), { recursive: true });
|
|
13930
14223
|
symlinkSync(
|
|
13931
14224
|
sourceDir,
|
|
13932
14225
|
destinationDir,
|
|
@@ -13942,8 +14235,8 @@ function inspectSkillLinks(cwd = process.cwd(), agents = parseSetupAgents()) {
|
|
|
13942
14235
|
const results = [];
|
|
13943
14236
|
for (const { from, to, agents: pairAgents } of SKILL_PAIRS) {
|
|
13944
14237
|
if (!pairAgents.some((agent) => agents.has(agent))) continue;
|
|
13945
|
-
const sourceDir =
|
|
13946
|
-
const destinationDir =
|
|
14238
|
+
const sourceDir = dirname9(from);
|
|
14239
|
+
const destinationDir = dirname9(join20(cwd, to));
|
|
13947
14240
|
results.push({
|
|
13948
14241
|
agents: pairAgents,
|
|
13949
14242
|
source: sourceDir,
|
|
@@ -13969,15 +14262,15 @@ function upsertMarkedBlock(dest, blockBody, dryRun) {
|
|
|
13969
14262
|
const block = `${ZAM_BLOCK_START}
|
|
13970
14263
|
${blockBody.trim()}
|
|
13971
14264
|
${ZAM_BLOCK_END}`;
|
|
13972
|
-
if (!
|
|
14265
|
+
if (!existsSync18(dest)) {
|
|
13973
14266
|
if (!dryRun) {
|
|
13974
|
-
|
|
13975
|
-
|
|
14267
|
+
mkdirSync13(dirname9(dest), { recursive: true });
|
|
14268
|
+
writeFileSync11(dest, `${block}
|
|
13976
14269
|
`, "utf8");
|
|
13977
14270
|
}
|
|
13978
14271
|
return "write";
|
|
13979
14272
|
}
|
|
13980
|
-
const existing =
|
|
14273
|
+
const existing = readFileSync15(dest, "utf8");
|
|
13981
14274
|
if (existing.includes(block)) return "skip";
|
|
13982
14275
|
const start = existing.indexOf(ZAM_BLOCK_START);
|
|
13983
14276
|
const end = existing.indexOf(ZAM_BLOCK_END);
|
|
@@ -13985,7 +14278,7 @@ ${ZAM_BLOCK_END}`;
|
|
|
13985
14278
|
|
|
13986
14279
|
${block}
|
|
13987
14280
|
`;
|
|
13988
|
-
if (!dryRun)
|
|
14281
|
+
if (!dryRun) writeFileSync11(dest, next, "utf8");
|
|
13989
14282
|
return start >= 0 && end > start ? "update" : "write";
|
|
13990
14283
|
}
|
|
13991
14284
|
function logInstructionAction(action, label, dryRun) {
|
|
@@ -13997,8 +14290,8 @@ function logInstructionAction(action, label, dryRun) {
|
|
|
13997
14290
|
}
|
|
13998
14291
|
function writeClaudeMd(skipClaudeMd, cwd = process.cwd(), opts = {}) {
|
|
13999
14292
|
if (skipClaudeMd) return;
|
|
14000
|
-
const dest =
|
|
14001
|
-
if (
|
|
14293
|
+
const dest = join20(cwd, "CLAUDE.md");
|
|
14294
|
+
if (existsSync18(dest)) {
|
|
14002
14295
|
if (!opts.updateExisting) {
|
|
14003
14296
|
console.log(` skip CLAUDE.md (already present)`);
|
|
14004
14297
|
return;
|
|
@@ -14041,14 +14334,14 @@ Use \`zam connector setup turso\` to store cloud credentials in
|
|
|
14041
14334
|
if (opts.dryRun) {
|
|
14042
14335
|
console.log(` would write CLAUDE.md`);
|
|
14043
14336
|
} else {
|
|
14044
|
-
|
|
14337
|
+
writeFileSync11(dest, content, "utf8");
|
|
14045
14338
|
console.log(` write CLAUDE.md`);
|
|
14046
14339
|
}
|
|
14047
14340
|
}
|
|
14048
14341
|
function writeAgentsMd(skipAgentsMd, cwd = process.cwd(), opts = {}) {
|
|
14049
14342
|
if (skipAgentsMd) return;
|
|
14050
|
-
const dest =
|
|
14051
|
-
if (
|
|
14343
|
+
const dest = join20(cwd, "AGENTS.md");
|
|
14344
|
+
if (existsSync18(dest)) {
|
|
14052
14345
|
if (!opts.updateExisting) {
|
|
14053
14346
|
console.log(` skip AGENTS.md (already present)`);
|
|
14054
14347
|
return;
|
|
@@ -14098,12 +14391,12 @@ Codex discovers repository skills under \`.agents/skills/\`. Run
|
|
|
14098
14391
|
if (opts.dryRun) {
|
|
14099
14392
|
console.log(` would write AGENTS.md`);
|
|
14100
14393
|
} else {
|
|
14101
|
-
|
|
14394
|
+
writeFileSync11(dest, content, "utf8");
|
|
14102
14395
|
console.log(` write AGENTS.md`);
|
|
14103
14396
|
}
|
|
14104
14397
|
}
|
|
14105
14398
|
function writeCopilotInstructions(cwd = process.cwd(), opts = {}) {
|
|
14106
|
-
const dest =
|
|
14399
|
+
const dest = join20(cwd, ".github", "copilot-instructions.md");
|
|
14107
14400
|
const action = upsertMarkedBlock(
|
|
14108
14401
|
dest,
|
|
14109
14402
|
`## ZAM learning sessions
|
|
@@ -14144,13 +14437,13 @@ async function resolveUser(opts, db, resolveOpts) {
|
|
|
14144
14437
|
}
|
|
14145
14438
|
|
|
14146
14439
|
// src/cli/workspaces/backup.ts
|
|
14147
|
-
import { mkdirSync as
|
|
14148
|
-
import { join as
|
|
14440
|
+
import { mkdirSync as mkdirSync14 } from "fs";
|
|
14441
|
+
import { join as join21 } from "path";
|
|
14149
14442
|
async function backupDatabaseTo(db, targetDir) {
|
|
14150
|
-
const backupDir =
|
|
14151
|
-
|
|
14443
|
+
const backupDir = join21(targetDir, "zam-backups");
|
|
14444
|
+
mkdirSync14(backupDir, { recursive: true });
|
|
14152
14445
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
14153
|
-
const dest =
|
|
14446
|
+
const dest = join21(backupDir, `zam-${stamp}.db`);
|
|
14154
14447
|
await db.exec(`VACUUM INTO '${dest.replace(/'/g, "''")}'`);
|
|
14155
14448
|
return dest;
|
|
14156
14449
|
}
|
|
@@ -14281,20 +14574,20 @@ bridgeCommand.command("workspace-info").description("Report the workspace dir, i
|
|
|
14281
14574
|
activeWorkspace,
|
|
14282
14575
|
workspaceDir: activeWorkspace.path,
|
|
14283
14576
|
defaultWorkspaceDir: defaultWorkspaceDir(),
|
|
14284
|
-
dataDir:
|
|
14577
|
+
dataDir: join22(homedir13(), ".zam")
|
|
14285
14578
|
});
|
|
14286
14579
|
});
|
|
14287
14580
|
});
|
|
14288
14581
|
function provisionConfiguredWorkspaces() {
|
|
14289
14582
|
return getConfiguredWorkspaces().flatMap(
|
|
14290
|
-
(workspace) =>
|
|
14583
|
+
(workspace) => existsSync19(workspace.path) ? wireSkills(workspace.path, parseSetupAgents(), { quiet: true }) : []
|
|
14291
14584
|
);
|
|
14292
14585
|
}
|
|
14293
14586
|
function buildWorkspaceLinkHealth(workspaces) {
|
|
14294
14587
|
const agents = parseSetupAgents();
|
|
14295
14588
|
const map = {};
|
|
14296
14589
|
for (const workspace of workspaces) {
|
|
14297
|
-
if (!
|
|
14590
|
+
if (!existsSync19(workspace.path)) continue;
|
|
14298
14591
|
const links = inspectSkillLinks(workspace.path, agents);
|
|
14299
14592
|
map[workspace.id] = {
|
|
14300
14593
|
health: summarizeSkillLinkHealth(links),
|
|
@@ -14324,7 +14617,7 @@ bridgeCommand.command("workspace-list").description("List configured ZAM workspa
|
|
|
14324
14617
|
activeWorkspace,
|
|
14325
14618
|
workspaceDir: activeWorkspace.path,
|
|
14326
14619
|
defaultWorkspaceDir: defaultWorkspaceDir(),
|
|
14327
|
-
dataDir:
|
|
14620
|
+
dataDir: join22(homedir13(), ".zam"),
|
|
14328
14621
|
linkHealth: buildWorkspaceLinkHealth(workspaces)
|
|
14329
14622
|
});
|
|
14330
14623
|
});
|
|
@@ -14339,7 +14632,7 @@ bridgeCommand.command("workspace-repair-links").description(
|
|
|
14339
14632
|
if (!id) jsonError("A non-empty --id is required");
|
|
14340
14633
|
const workspace = getConfiguredWorkspaces().find((item) => item.id === id);
|
|
14341
14634
|
if (!workspace) jsonError(`Workspace "${id}" is not configured`);
|
|
14342
|
-
if (!
|
|
14635
|
+
if (!existsSync19(workspace.path)) {
|
|
14343
14636
|
jsonError(`Workspace path does not exist: ${workspace.path}`);
|
|
14344
14637
|
}
|
|
14345
14638
|
const agents = parseSetupAgents(opts.agents);
|
|
@@ -14371,7 +14664,7 @@ bridgeCommand.command("workspace-add").description("Register an existing directo
|
|
|
14371
14664
|
const raw = String(opts.path ?? "").trim();
|
|
14372
14665
|
if (!raw) jsonError("A non-empty --path is required");
|
|
14373
14666
|
const path = resolve5(raw);
|
|
14374
|
-
if (!
|
|
14667
|
+
if (!existsSync19(path)) jsonError(`Workspace path does not exist: ${path}`);
|
|
14375
14668
|
const id = opts.id ? String(opts.id).trim() : void 0;
|
|
14376
14669
|
if (opts.id && !id) jsonError("A non-empty --id is required");
|
|
14377
14670
|
const kind = parseBridgeWorkspaceKind(opts.kind);
|
|
@@ -14416,7 +14709,7 @@ bridgeCommand.command("set-workspace-dir").description("Set the personal workspa
|
|
|
14416
14709
|
const raw = String(opts.dir ?? "").trim();
|
|
14417
14710
|
if (!raw) jsonError("A non-empty --dir is required");
|
|
14418
14711
|
const dir = resolve5(raw);
|
|
14419
|
-
if (!
|
|
14712
|
+
if (!existsSync19(dir)) jsonError(`Workspace path does not exist: ${dir}`);
|
|
14420
14713
|
const skillLinks = wireSkills(dir, parseSetupAgents(), { quiet: true });
|
|
14421
14714
|
await withDb2(async (db) => {
|
|
14422
14715
|
const workspace = await activateWorkspacePath(db, dir);
|
|
@@ -14479,7 +14772,7 @@ bridgeCommand.command("agent-open").description("Launch an agent harness in the
|
|
|
14479
14772
|
jsonError(`Workspace is not configured: ${opts.workspace}`);
|
|
14480
14773
|
}
|
|
14481
14774
|
const activeWorkspace = await ensureActiveWorkspace(db);
|
|
14482
|
-
const workspace = opts.dir ?
|
|
14775
|
+
const workspace = opts.dir ? existsSync19(opts.dir) ? opts.dir : homedir13() : existingWorkspaceDirOrHome(configuredWorkspace ?? activeWorkspace);
|
|
14483
14776
|
launchHarness(harness, {
|
|
14484
14777
|
executable,
|
|
14485
14778
|
workspace,
|
|
@@ -14851,7 +15144,7 @@ bridgeCommand.command("discover-skills").description(
|
|
|
14851
15144
|
"20"
|
|
14852
15145
|
).action(async (opts) => {
|
|
14853
15146
|
try {
|
|
14854
|
-
const monitorDir =
|
|
15147
|
+
const monitorDir = join22(homedir13(), ".zam", "monitor");
|
|
14855
15148
|
let files;
|
|
14856
15149
|
try {
|
|
14857
15150
|
files = readdirSync2(monitorDir).filter((f) => f.endsWith(".jsonl"));
|
|
@@ -14864,7 +15157,7 @@ bridgeCommand.command("discover-skills").description(
|
|
|
14864
15157
|
return;
|
|
14865
15158
|
}
|
|
14866
15159
|
const limit = Number(opts.limit);
|
|
14867
|
-
const sorted = files.map((f) => ({ name: f, path:
|
|
15160
|
+
const sorted = files.map((f) => ({ name: f, path: join22(monitorDir, f) })).sort((a, b) => b.name.localeCompare(a.name)).slice(0, limit);
|
|
14868
15161
|
const sessionCommands = /* @__PURE__ */ new Map();
|
|
14869
15162
|
for (const file of sorted) {
|
|
14870
15163
|
const sessionId = file.name.replace(".jsonl", "");
|
|
@@ -14976,7 +15269,7 @@ bridgeCommand.command("observe-ui-snapshot").description(
|
|
|
14976
15269
|
});
|
|
14977
15270
|
function resolveWindowsPowerShell() {
|
|
14978
15271
|
try {
|
|
14979
|
-
|
|
15272
|
+
execFileSync4("where.exe", ["pwsh.exe"], { stdio: "ignore" });
|
|
14980
15273
|
return "pwsh";
|
|
14981
15274
|
} catch {
|
|
14982
15275
|
return "powershell";
|
|
@@ -14991,7 +15284,7 @@ function captureScreenshot(outputPath, hwnd, processName) {
|
|
|
14991
15284
|
throw new Error(`Invalid process name format: ${processName}`);
|
|
14992
15285
|
}
|
|
14993
15286
|
if (platform === "win32") {
|
|
14994
|
-
const stdout =
|
|
15287
|
+
const stdout = execFileSync4(
|
|
14995
15288
|
resolveWindowsPowerShell(),
|
|
14996
15289
|
[
|
|
14997
15290
|
"-NoProfile",
|
|
@@ -15304,13 +15597,13 @@ Write-CaptureResult "fullscreen" $hwndVal $matchedBy
|
|
|
15304
15597
|
} else if (platform === "darwin") {
|
|
15305
15598
|
if (hwnd) {
|
|
15306
15599
|
const parsedHwnd = hwnd.startsWith("0x") ? parseInt(hwnd, 16) : parseInt(hwnd, 10);
|
|
15307
|
-
|
|
15600
|
+
execFileSync4("screencapture", ["-l", String(parsedHwnd), outputPath], {
|
|
15308
15601
|
stdio: "pipe"
|
|
15309
15602
|
});
|
|
15310
15603
|
return { method: "screencapture-window", target: null };
|
|
15311
15604
|
} else if (processName) {
|
|
15312
15605
|
try {
|
|
15313
|
-
const windowId =
|
|
15606
|
+
const windowId = execFileSync4(
|
|
15314
15607
|
"osascript",
|
|
15315
15608
|
[
|
|
15316
15609
|
"-e",
|
|
@@ -15319,17 +15612,17 @@ Write-CaptureResult "fullscreen" $hwndVal $matchedBy
|
|
|
15319
15612
|
{ encoding: "utf8", stdio: ["pipe", "pipe", "ignore"] }
|
|
15320
15613
|
).trim();
|
|
15321
15614
|
if (windowId && /^\d+$/.test(windowId)) {
|
|
15322
|
-
|
|
15615
|
+
execFileSync4("screencapture", ["-l", windowId, outputPath], {
|
|
15323
15616
|
stdio: "pipe"
|
|
15324
15617
|
});
|
|
15325
15618
|
return { method: "screencapture-window", target: null };
|
|
15326
15619
|
}
|
|
15327
15620
|
} catch {
|
|
15328
15621
|
}
|
|
15329
|
-
|
|
15622
|
+
execFileSync4("screencapture", ["-x", outputPath], { stdio: "pipe" });
|
|
15330
15623
|
return { method: "screencapture-full", target: null };
|
|
15331
15624
|
} else {
|
|
15332
|
-
|
|
15625
|
+
execFileSync4("screencapture", ["-x", outputPath], { stdio: "pipe" });
|
|
15333
15626
|
return { method: "screencapture-full", target: null };
|
|
15334
15627
|
}
|
|
15335
15628
|
} else {
|
|
@@ -15366,7 +15659,7 @@ bridgeCommand.command("capture-ui").description("Capture a screenshot for agent-
|
|
|
15366
15659
|
return;
|
|
15367
15660
|
}
|
|
15368
15661
|
}
|
|
15369
|
-
const outputPath = opts.image ?? opts.output ??
|
|
15662
|
+
const outputPath = opts.image ?? opts.output ?? join22(tmpdir3(), `zam-capture-${randomBytes2(4).toString("hex")}.png`);
|
|
15370
15663
|
const captureResult = isProvided ? { method: "provided", target: null } : captureScreenshot(outputPath, opts.hwnd, opts.processName);
|
|
15371
15664
|
if (!isProvided) {
|
|
15372
15665
|
const post = decidePostCapture(policy, {
|
|
@@ -15394,7 +15687,7 @@ bridgeCommand.command("capture-ui").description("Capture a screenshot for agent-
|
|
|
15394
15687
|
return;
|
|
15395
15688
|
}
|
|
15396
15689
|
}
|
|
15397
|
-
const imageBytes =
|
|
15690
|
+
const imageBytes = readFileSync16(outputPath);
|
|
15398
15691
|
const base64 = imageBytes.toString("base64");
|
|
15399
15692
|
jsonOut2({
|
|
15400
15693
|
sessionId: opts.session ?? null,
|
|
@@ -15421,11 +15714,11 @@ bridgeCommand.command("start-recording").description("Start screen recording in
|
|
|
15421
15714
|
return;
|
|
15422
15715
|
}
|
|
15423
15716
|
const sessionId = opts.session;
|
|
15424
|
-
const statePath =
|
|
15717
|
+
const statePath = join22(tmpdir3(), `zam-recording-${sessionId}.json`);
|
|
15425
15718
|
const defaultExt = platform === "win32" ? ".mkv" : ".mov";
|
|
15426
|
-
const outputPath = opts.output ??
|
|
15427
|
-
const { existsSync:
|
|
15428
|
-
if (
|
|
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)) {
|
|
15429
15722
|
jsonOut2({
|
|
15430
15723
|
sessionId,
|
|
15431
15724
|
started: false,
|
|
@@ -15433,7 +15726,7 @@ bridgeCommand.command("start-recording").description("Start screen recording in
|
|
|
15433
15726
|
});
|
|
15434
15727
|
return;
|
|
15435
15728
|
}
|
|
15436
|
-
const logPath =
|
|
15729
|
+
const logPath = join22(tmpdir3(), `zam-recording-${sessionId}.log`);
|
|
15437
15730
|
let logFd;
|
|
15438
15731
|
try {
|
|
15439
15732
|
logFd = openSync(logPath, "w");
|
|
@@ -15479,7 +15772,7 @@ bridgeCommand.command("start-recording").description("Start screen recording in
|
|
|
15479
15772
|
}
|
|
15480
15773
|
child.unref();
|
|
15481
15774
|
if (child.pid) {
|
|
15482
|
-
|
|
15775
|
+
writeFileSync16(
|
|
15483
15776
|
statePath,
|
|
15484
15777
|
JSON.stringify({
|
|
15485
15778
|
pid: child.pid,
|
|
@@ -15515,9 +15808,9 @@ bridgeCommand.command("stop-recording").description(
|
|
|
15515
15808
|
return;
|
|
15516
15809
|
}
|
|
15517
15810
|
const sessionId = opts.session;
|
|
15518
|
-
const statePath =
|
|
15519
|
-
const { existsSync:
|
|
15520
|
-
if (!
|
|
15811
|
+
const statePath = join22(tmpdir3(), `zam-recording-${sessionId}.json`);
|
|
15812
|
+
const { existsSync: existsSync28, readFileSync: readFileSync21, rmSync: rmSync4 } = await import("fs");
|
|
15813
|
+
if (!existsSync28(statePath)) {
|
|
15521
15814
|
jsonOut2({
|
|
15522
15815
|
sessionId,
|
|
15523
15816
|
stopped: false,
|
|
@@ -15525,7 +15818,7 @@ bridgeCommand.command("stop-recording").description(
|
|
|
15525
15818
|
});
|
|
15526
15819
|
return;
|
|
15527
15820
|
}
|
|
15528
|
-
const state = JSON.parse(
|
|
15821
|
+
const state = JSON.parse(readFileSync21(statePath, "utf8"));
|
|
15529
15822
|
const { pid, outputPath } = state;
|
|
15530
15823
|
try {
|
|
15531
15824
|
process.kill(pid, "SIGINT");
|
|
@@ -15554,7 +15847,7 @@ bridgeCommand.command("stop-recording").description(
|
|
|
15554
15847
|
rmSync4(statePath, { force: true });
|
|
15555
15848
|
} catch {
|
|
15556
15849
|
}
|
|
15557
|
-
if (!
|
|
15850
|
+
if (!existsSync28(outputPath)) {
|
|
15558
15851
|
jsonOut2({
|
|
15559
15852
|
sessionId,
|
|
15560
15853
|
stopped: false,
|
|
@@ -15791,7 +16084,7 @@ bridgeCommand.command("cloud-model-hint").description("Suggest a cloud model for
|
|
|
15791
16084
|
});
|
|
15792
16085
|
bridgeCommand.command("local-llm-hints").description("Detect installed local LLM servers and suggest defaults (JSON)").action(() => {
|
|
15793
16086
|
const profile = getSystemProfile();
|
|
15794
|
-
const flmInstalled = hasCommand("flm") ||
|
|
16087
|
+
const flmInstalled = hasCommand("flm") || existsSync19("C:\\Program Files\\flm\\flm.exe");
|
|
15795
16088
|
const ollamaInstalled = isOllamaInstalled();
|
|
15796
16089
|
const runners = [
|
|
15797
16090
|
{ id: "flm", label: "FastFlowLM", installed: flmInstalled },
|
|
@@ -18341,26 +18634,26 @@ var doctorCommand = new Command5("doctor").description(
|
|
|
18341
18634
|
// src/cli/commands/git-sync.ts
|
|
18342
18635
|
init_kernel();
|
|
18343
18636
|
import { execSync as execSync5 } from "child_process";
|
|
18344
|
-
import { chmodSync as chmodSync2, existsSync as
|
|
18345
|
-
import { join as
|
|
18637
|
+
import { chmodSync as chmodSync2, existsSync as existsSync20, writeFileSync as writeFileSync12 } from "fs";
|
|
18638
|
+
import { join as join23 } from "path";
|
|
18346
18639
|
import { Command as Command6 } from "commander";
|
|
18347
18640
|
function installHook2() {
|
|
18348
|
-
const gitDir =
|
|
18349
|
-
if (!
|
|
18641
|
+
const gitDir = join23(process.cwd(), ".git");
|
|
18642
|
+
if (!existsSync20(gitDir)) {
|
|
18350
18643
|
console.error(
|
|
18351
18644
|
"Error: Current directory is not the root of a Git repository."
|
|
18352
18645
|
);
|
|
18353
18646
|
process.exit(1);
|
|
18354
18647
|
}
|
|
18355
|
-
const hooksDir =
|
|
18356
|
-
const hookPath =
|
|
18648
|
+
const hooksDir = join23(gitDir, "hooks");
|
|
18649
|
+
const hookPath = join23(hooksDir, "post-commit");
|
|
18357
18650
|
const hookContent = `#!/bin/sh
|
|
18358
18651
|
# ZAM Spaced Repetition Auto-Stale Hook
|
|
18359
18652
|
# Triggered automatically on git commits to decay modified concept cards.
|
|
18360
18653
|
zam git-sync --commit HEAD --quiet
|
|
18361
18654
|
`;
|
|
18362
18655
|
try {
|
|
18363
|
-
|
|
18656
|
+
writeFileSync12(hookPath, hookContent, { encoding: "utf-8", flag: "w" });
|
|
18364
18657
|
try {
|
|
18365
18658
|
chmodSync2(hookPath, "755");
|
|
18366
18659
|
} catch (_e) {
|
|
@@ -18463,7 +18756,7 @@ ZAM Auto-Stale Complete: Scanned ${changedFiles.length} file(s).`
|
|
|
18463
18756
|
|
|
18464
18757
|
// src/cli/commands/goal.ts
|
|
18465
18758
|
init_kernel();
|
|
18466
|
-
import { existsSync as
|
|
18759
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync15 } from "fs";
|
|
18467
18760
|
import { resolve as resolve6 } from "path";
|
|
18468
18761
|
import { input as input2 } from "@inquirer/prompts";
|
|
18469
18762
|
import { Command as Command7 } from "commander";
|
|
@@ -18487,7 +18780,7 @@ goalCommand.command("list").description("List all goals").option(
|
|
|
18487
18780
|
"Filter by status (active, completed, paused, abandoned)"
|
|
18488
18781
|
).option("--tree", "Show goals as a tree with parent/child relationships").option("--json", "Output as JSON").action(async (opts) => {
|
|
18489
18782
|
const goalsDir = await resolveGoalsDir();
|
|
18490
|
-
if (!
|
|
18783
|
+
if (!existsSync21(goalsDir)) {
|
|
18491
18784
|
console.error(`Goals directory not found: ${goalsDir}`);
|
|
18492
18785
|
console.error(
|
|
18493
18786
|
"Set it with: zam settings set personal.goals_dir /path/to/goals"
|
|
@@ -18588,8 +18881,8 @@ ${"\u2500".repeat(50)}`);
|
|
|
18588
18881
|
});
|
|
18589
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) => {
|
|
18590
18883
|
const goalsDir = await resolveGoalsDir();
|
|
18591
|
-
if (!
|
|
18592
|
-
|
|
18884
|
+
if (!existsSync21(goalsDir)) {
|
|
18885
|
+
mkdirSync15(goalsDir, { recursive: true });
|
|
18593
18886
|
}
|
|
18594
18887
|
let slug = opts.slug;
|
|
18595
18888
|
let title = opts.title;
|
|
@@ -18649,22 +18942,22 @@ goalCommand.command("status <slug> <status>").description("Update a goal's statu
|
|
|
18649
18942
|
|
|
18650
18943
|
// src/cli/commands/init.ts
|
|
18651
18944
|
init_kernel();
|
|
18652
|
-
import { existsSync as
|
|
18653
|
-
import { homedir as
|
|
18654
|
-
import { join as
|
|
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";
|
|
18655
18948
|
import { confirm, input as input3 } from "@inquirer/prompts";
|
|
18656
18949
|
import { Command as Command8 } from "commander";
|
|
18657
|
-
var HOME2 =
|
|
18950
|
+
var HOME2 = homedir14();
|
|
18658
18951
|
function printLine(char = "\u2550", len = 60, color = "\x1B[36m") {
|
|
18659
18952
|
console.log(`${color}${char.repeat(len)}\x1B[0m`);
|
|
18660
18953
|
}
|
|
18661
18954
|
function bootstrapSandboxWorkspace(workspaceDir) {
|
|
18662
|
-
|
|
18663
|
-
|
|
18664
|
-
|
|
18665
|
-
const worldviewFile =
|
|
18666
|
-
if (!
|
|
18667
|
-
|
|
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(
|
|
18668
18961
|
worldviewFile,
|
|
18669
18962
|
`# Personal Worldview
|
|
18670
18963
|
|
|
@@ -18676,9 +18969,9 @@ Here, I declare the core concepts and principles I want to master.
|
|
|
18676
18969
|
"utf8"
|
|
18677
18970
|
);
|
|
18678
18971
|
}
|
|
18679
|
-
const goalsFile =
|
|
18680
|
-
if (!
|
|
18681
|
-
|
|
18972
|
+
const goalsFile = join24(workspaceDir, "goals", "goals.md");
|
|
18973
|
+
if (!existsSync22(goalsFile)) {
|
|
18974
|
+
writeFileSync13(
|
|
18682
18975
|
goalsFile,
|
|
18683
18976
|
`# Personal Goals
|
|
18684
18977
|
|
|
@@ -18700,7 +18993,7 @@ var initCommand = new Command8("init").description("Launch the guided interactiv
|
|
|
18700
18993
|
);
|
|
18701
18994
|
printLine();
|
|
18702
18995
|
console.log("\n\x1B[1m[1/5] Setting up Local Workspace Sandbox\x1B[0m");
|
|
18703
|
-
const defaultWorkspace =
|
|
18996
|
+
const defaultWorkspace = join24(HOME2, "Documents", "zam");
|
|
18704
18997
|
const workspacePath = resolve7(
|
|
18705
18998
|
await input3({
|
|
18706
18999
|
message: "Choose your ZAM workspace directory:",
|
|
@@ -19902,7 +20195,7 @@ observerCommand.command("revoke <process>").description("Remove a process from o
|
|
|
19902
20195
|
|
|
19903
20196
|
// src/cli/commands/profile.ts
|
|
19904
20197
|
init_kernel();
|
|
19905
|
-
import { dirname as
|
|
20198
|
+
import { dirname as dirname10, resolve as resolve8 } from "path";
|
|
19906
20199
|
import { Command as Command13 } from "commander";
|
|
19907
20200
|
var C2 = {
|
|
19908
20201
|
reset: "\x1B[0m",
|
|
@@ -19943,7 +20236,7 @@ var profileCommand = new Command13("profile").description("Show or change this m
|
|
|
19943
20236
|
mode: getInstallMode(),
|
|
19944
20237
|
personalDir,
|
|
19945
20238
|
syncProvider: detectSyncProvider(personalDir),
|
|
19946
|
-
dataDir:
|
|
20239
|
+
dataDir: dirname10(dbPath),
|
|
19947
20240
|
dbPath
|
|
19948
20241
|
};
|
|
19949
20242
|
if (opts.json) {
|
|
@@ -20332,7 +20625,7 @@ ${"\u2550".repeat(50)}`);
|
|
|
20332
20625
|
|
|
20333
20626
|
// src/cli/commands/session.ts
|
|
20334
20627
|
init_kernel();
|
|
20335
|
-
import { readFileSync as
|
|
20628
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
20336
20629
|
import { input as input6, select as select2 } from "@inquirer/prompts";
|
|
20337
20630
|
import { Command as Command16 } from "commander";
|
|
20338
20631
|
var sessionCommand = new Command16("session").description(
|
|
@@ -20523,7 +20816,7 @@ function loadPatternFile(path) {
|
|
|
20523
20816
|
if (!path) return [];
|
|
20524
20817
|
let parsed;
|
|
20525
20818
|
try {
|
|
20526
|
-
parsed = JSON.parse(
|
|
20819
|
+
parsed = JSON.parse(readFileSync17(path, "utf-8"));
|
|
20527
20820
|
} catch (err) {
|
|
20528
20821
|
throw new Error(
|
|
20529
20822
|
`Cannot read synthesis patterns from ${path}: ${err.message}`
|
|
@@ -20714,7 +21007,7 @@ sessionCommand.command("end").description("End a session and show summary").requ
|
|
|
20714
21007
|
|
|
20715
21008
|
// src/cli/commands/settings.ts
|
|
20716
21009
|
init_kernel();
|
|
20717
|
-
import { existsSync as
|
|
21010
|
+
import { existsSync as existsSync23 } from "fs";
|
|
20718
21011
|
import { Command as Command17 } from "commander";
|
|
20719
21012
|
var settingsCommand = new Command17("settings").description(
|
|
20720
21013
|
"Manage user settings"
|
|
@@ -20879,7 +21172,7 @@ settingsCommand.command("repos").description("Show or set Personal, Team, and Or
|
|
|
20879
21172
|
console.log("\nValidation:");
|
|
20880
21173
|
for (const [name, path] of Object.entries(paths)) {
|
|
20881
21174
|
if (path) {
|
|
20882
|
-
const exists =
|
|
21175
|
+
const exists = existsSync23(path);
|
|
20883
21176
|
console.log(
|
|
20884
21177
|
` ${name.padEnd(9)}: ${exists ? "\x1B[32m\u2713 Valid folder\x1B[0m" : "\x1B[31m\u2717 Directory does not exist\x1B[0m"}`
|
|
20885
21178
|
);
|
|
@@ -21076,8 +21369,8 @@ skillCommand.command("add").description("Register a new agent skill").requiredOp
|
|
|
21076
21369
|
|
|
21077
21370
|
// src/cli/commands/snapshot.ts
|
|
21078
21371
|
init_kernel();
|
|
21079
|
-
import { existsSync as
|
|
21080
|
-
import { dirname as
|
|
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";
|
|
21081
21374
|
import { Command as Command20 } from "commander";
|
|
21082
21375
|
function defaultOutName() {
|
|
21083
21376
|
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\.\d+Z$/, "").replace(/:/g, "-");
|
|
@@ -21106,12 +21399,12 @@ var exportCmd = new Command20("export").description("Write a portable SQL-text s
|
|
|
21106
21399
|
process.stdout.write(snapshot);
|
|
21107
21400
|
return;
|
|
21108
21401
|
}
|
|
21109
|
-
const out = opts.out ??
|
|
21110
|
-
const dir =
|
|
21111
|
-
if (dir && dir !== "." && !
|
|
21112
|
-
|
|
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 });
|
|
21113
21406
|
}
|
|
21114
|
-
|
|
21407
|
+
writeFileSync14(out, snapshot, "utf-8");
|
|
21115
21408
|
console.log(`Snapshot written: ${out}`);
|
|
21116
21409
|
console.log(
|
|
21117
21410
|
` ${total} row(s)${nonEmpty.length ? ` \u2014 ${nonEmpty.join(", ")}` : ""}`
|
|
@@ -21125,11 +21418,11 @@ var exportCmd = new Command20("export").description("Write a portable SQL-text s
|
|
|
21125
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) => {
|
|
21126
21419
|
let db;
|
|
21127
21420
|
try {
|
|
21128
|
-
if (!
|
|
21421
|
+
if (!existsSync24(file)) {
|
|
21129
21422
|
console.error(`Error: Snapshot file not found: ${file}`);
|
|
21130
21423
|
process.exit(1);
|
|
21131
21424
|
}
|
|
21132
|
-
const snapshot =
|
|
21425
|
+
const snapshot = readFileSync18(file, "utf-8");
|
|
21133
21426
|
db = await openDatabaseWithSync({ initialize: true });
|
|
21134
21427
|
const result = await importSnapshot(db, snapshot, { force: opts.force });
|
|
21135
21428
|
await db.close();
|
|
@@ -21147,11 +21440,11 @@ var importCmd = new Command20("import").description("Restore a snapshot into the
|
|
|
21147
21440
|
});
|
|
21148
21441
|
var verifyCmd = new Command20("verify").description("Check a snapshot's manifest and checksum without importing").argument("<file>", "Snapshot file to verify").action((file) => {
|
|
21149
21442
|
try {
|
|
21150
|
-
if (!
|
|
21443
|
+
if (!existsSync24(file)) {
|
|
21151
21444
|
console.error(`Error: Snapshot file not found: ${file}`);
|
|
21152
21445
|
process.exit(1);
|
|
21153
21446
|
}
|
|
21154
|
-
const manifest = verifySnapshot(
|
|
21447
|
+
const manifest = verifySnapshot(readFileSync18(file, "utf-8"));
|
|
21155
21448
|
const { total, nonEmpty } = summarize(manifest.tables);
|
|
21156
21449
|
console.log(`Valid snapshot (format v${manifest.version})`);
|
|
21157
21450
|
console.log(` created: ${manifest.createdAt}`);
|
|
@@ -21700,10 +21993,10 @@ tokenCommand.command("reembed").description("Backfill or refresh semantic-search
|
|
|
21700
21993
|
// src/cli/commands/ui.ts
|
|
21701
21994
|
init_kernel();
|
|
21702
21995
|
import { spawn as spawn3, spawnSync } from "child_process";
|
|
21703
|
-
import { existsSync as
|
|
21704
|
-
import { homedir as
|
|
21705
|
-
import { dirname as
|
|
21706
|
-
import { fileURLToPath as
|
|
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";
|
|
21707
22000
|
import { Command as Command23 } from "commander";
|
|
21708
22001
|
var C3 = {
|
|
21709
22002
|
reset: "\x1B[0m",
|
|
@@ -21714,14 +22007,14 @@ var C3 = {
|
|
|
21714
22007
|
dim: "\x1B[2m"
|
|
21715
22008
|
};
|
|
21716
22009
|
function findDesktopDir() {
|
|
21717
|
-
const starts = [process.cwd(),
|
|
22010
|
+
const starts = [process.cwd(), dirname12(fileURLToPath6(import.meta.url))];
|
|
21718
22011
|
for (const start of starts) {
|
|
21719
22012
|
let dir = start;
|
|
21720
22013
|
for (let i = 0; i < 10; i++) {
|
|
21721
|
-
if (
|
|
21722
|
-
return
|
|
22014
|
+
if (existsSync25(join26(dir, "desktop", "src-tauri", "tauri.conf.json"))) {
|
|
22015
|
+
return join26(dir, "desktop");
|
|
21723
22016
|
}
|
|
21724
|
-
const parent =
|
|
22017
|
+
const parent = dirname12(dir);
|
|
21725
22018
|
if (parent === dir) break;
|
|
21726
22019
|
dir = parent;
|
|
21727
22020
|
}
|
|
@@ -21729,30 +22022,30 @@ function findDesktopDir() {
|
|
|
21729
22022
|
return null;
|
|
21730
22023
|
}
|
|
21731
22024
|
function findBuiltApp(desktopDir) {
|
|
21732
|
-
const releaseDir =
|
|
22025
|
+
const releaseDir = join26(desktopDir, "src-tauri", "target", "release");
|
|
21733
22026
|
if (process.platform === "win32") {
|
|
21734
22027
|
for (const name of ["ZAM.exe", "zam.exe", "zam-desktop.exe"]) {
|
|
21735
|
-
const p =
|
|
21736
|
-
if (
|
|
22028
|
+
const p = join26(releaseDir, name);
|
|
22029
|
+
if (existsSync25(p)) return p;
|
|
21737
22030
|
}
|
|
21738
22031
|
} else if (process.platform === "darwin") {
|
|
21739
|
-
const app =
|
|
21740
|
-
if (
|
|
22032
|
+
const app = join26(releaseDir, "bundle", "macos", "ZAM.app");
|
|
22033
|
+
if (existsSync25(app)) return app;
|
|
21741
22034
|
} else {
|
|
21742
22035
|
for (const name of ["zam", "ZAM", "zam-desktop"]) {
|
|
21743
|
-
const p =
|
|
21744
|
-
if (
|
|
22036
|
+
const p = join26(releaseDir, name);
|
|
22037
|
+
if (existsSync25(p)) return p;
|
|
21745
22038
|
}
|
|
21746
22039
|
}
|
|
21747
22040
|
return null;
|
|
21748
22041
|
}
|
|
21749
22042
|
function findInstalledApp() {
|
|
21750
22043
|
const candidates = process.platform === "win32" ? [
|
|
21751
|
-
process.env.LOCALAPPDATA &&
|
|
21752
|
-
process.env.ProgramFiles &&
|
|
21753
|
-
process.env["ProgramFiles(x86)"] &&
|
|
21754
|
-
] : process.platform === "darwin" ? ["/Applications/ZAM.app",
|
|
21755
|
-
return candidates.find((candidate) => candidate &&
|
|
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;
|
|
21756
22049
|
}
|
|
21757
22050
|
function runNpm(args, opts) {
|
|
21758
22051
|
const res = spawnSync("npm", args, {
|
|
@@ -21763,7 +22056,7 @@ function runNpm(args, opts) {
|
|
|
21763
22056
|
return res.status ?? 1;
|
|
21764
22057
|
}
|
|
21765
22058
|
function ensureDesktopDeps(desktopDir) {
|
|
21766
|
-
if (
|
|
22059
|
+
if (existsSync25(join26(desktopDir, "node_modules"))) return true;
|
|
21767
22060
|
console.log(
|
|
21768
22061
|
`${C3.cyan}Installing desktop dependencies (one-time)...${C3.reset}`
|
|
21769
22062
|
);
|
|
@@ -21789,13 +22082,13 @@ function requireRust() {
|
|
|
21789
22082
|
function hasMsvcBuildTools() {
|
|
21790
22083
|
if (process.platform !== "win32") return true;
|
|
21791
22084
|
const pf86 = process.env["ProgramFiles(x86)"] || "C:\\Program Files (x86)";
|
|
21792
|
-
const vswhere =
|
|
22085
|
+
const vswhere = join26(
|
|
21793
22086
|
pf86,
|
|
21794
22087
|
"Microsoft Visual Studio",
|
|
21795
22088
|
"Installer",
|
|
21796
22089
|
"vswhere.exe"
|
|
21797
22090
|
);
|
|
21798
|
-
if (!
|
|
22091
|
+
if (!existsSync25(vswhere)) return false;
|
|
21799
22092
|
const res = spawnSync(
|
|
21800
22093
|
vswhere,
|
|
21801
22094
|
[
|
|
@@ -21827,7 +22120,7 @@ function requireMsvcOnWindows() {
|
|
|
21827
22120
|
return false;
|
|
21828
22121
|
}
|
|
21829
22122
|
function warnIfCliMissing(repoRoot) {
|
|
21830
|
-
if (!
|
|
22123
|
+
if (!existsSync25(join26(repoRoot, "dist", "cli", "index.js"))) {
|
|
21831
22124
|
console.warn(
|
|
21832
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}`
|
|
21833
22126
|
);
|
|
@@ -21890,7 +22183,7 @@ var uiCommand = new Command23("ui").description("Launch the ZAM Desktop GUI (Act
|
|
|
21890
22183
|
).option("--shortcut", "Create Desktop + Start-menu shortcuts to the GUI").action((opts) => {
|
|
21891
22184
|
const installedApp = findInstalledApp();
|
|
21892
22185
|
if (!opts.dev && !opts.build && !opts.shortcut && installedApp) {
|
|
21893
|
-
launchApp(installedApp,
|
|
22186
|
+
launchApp(installedApp, homedir15());
|
|
21894
22187
|
return;
|
|
21895
22188
|
}
|
|
21896
22189
|
const desktopDir = findDesktopDir();
|
|
@@ -21900,7 +22193,7 @@ var uiCommand = new Command23("ui").description("Launch the ZAM Desktop GUI (Act
|
|
|
21900
22193
|
);
|
|
21901
22194
|
process.exit(1);
|
|
21902
22195
|
}
|
|
21903
|
-
const repoRoot =
|
|
22196
|
+
const repoRoot = dirname12(desktopDir);
|
|
21904
22197
|
if (opts.build) {
|
|
21905
22198
|
if (!requireRust()) process.exit(1);
|
|
21906
22199
|
if (!requireMsvcOnWindows()) process.exit(1);
|
|
@@ -21911,7 +22204,7 @@ var uiCommand = new Command23("ui").description("Launch the ZAM Desktop GUI (Act
|
|
|
21911
22204
|
);
|
|
21912
22205
|
const code = runNpm(["run", "tauri", "build"], { cwd: desktopDir });
|
|
21913
22206
|
if (code === 0) {
|
|
21914
|
-
const bundle =
|
|
22207
|
+
const bundle = join26(
|
|
21915
22208
|
desktopDir,
|
|
21916
22209
|
"src-tauri",
|
|
21917
22210
|
"target",
|
|
@@ -21951,7 +22244,7 @@ ${C3.green}\u2713 Done. Installer is in:${C3.reset}
|
|
|
21951
22244
|
);
|
|
21952
22245
|
process.exit(1);
|
|
21953
22246
|
}
|
|
21954
|
-
createShortcuts(shortcutTarget,
|
|
22247
|
+
createShortcuts(shortcutTarget, dirname12(shortcutTarget));
|
|
21955
22248
|
return;
|
|
21956
22249
|
}
|
|
21957
22250
|
if (builtApp) {
|
|
@@ -21989,9 +22282,9 @@ ${C3.dim}After that, 'zam ui' launches it directly.${C3.reset}`
|
|
|
21989
22282
|
// src/cli/commands/update.ts
|
|
21990
22283
|
init_kernel();
|
|
21991
22284
|
import { spawnSync as spawnSync2 } from "child_process";
|
|
21992
|
-
import { existsSync as
|
|
21993
|
-
import { dirname as
|
|
21994
|
-
import { fileURLToPath as
|
|
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";
|
|
21995
22288
|
import { confirm as confirm3 } from "@inquirer/prompts";
|
|
21996
22289
|
import { Command as Command24 } from "commander";
|
|
21997
22290
|
var CHANNELS = [
|
|
@@ -22012,7 +22305,7 @@ var C4 = {
|
|
|
22012
22305
|
function versionAt(dir) {
|
|
22013
22306
|
try {
|
|
22014
22307
|
const pkg2 = JSON.parse(
|
|
22015
|
-
|
|
22308
|
+
readFileSync19(join27(dir, "package.json"), "utf-8")
|
|
22016
22309
|
);
|
|
22017
22310
|
return pkg2.version ?? "unknown";
|
|
22018
22311
|
} catch {
|
|
@@ -22070,14 +22363,14 @@ var checkCmd = new Command24("check").description("Check whether a newer ZAM has
|
|
|
22070
22363
|
}
|
|
22071
22364
|
);
|
|
22072
22365
|
function findSourceRepo() {
|
|
22073
|
-
let dir = realpathSync2(
|
|
22074
|
-
let parent =
|
|
22366
|
+
let dir = realpathSync2(dirname13(fileURLToPath7(import.meta.url)));
|
|
22367
|
+
let parent = dirname13(dir);
|
|
22075
22368
|
while (parent !== dir) {
|
|
22076
|
-
if (
|
|
22369
|
+
if (existsSync26(join27(dir, ".git"))) return dir;
|
|
22077
22370
|
dir = parent;
|
|
22078
|
-
parent =
|
|
22371
|
+
parent = dirname13(dir);
|
|
22079
22372
|
}
|
|
22080
|
-
return
|
|
22373
|
+
return existsSync26(join27(dir, ".git")) ? dir : null;
|
|
22081
22374
|
}
|
|
22082
22375
|
function runGit(cwd, args, capture) {
|
|
22083
22376
|
const res = spawnSync2("git", args, {
|
|
@@ -22098,7 +22391,7 @@ function runNpm2(args, cwd) {
|
|
|
22098
22391
|
function smokeTestBuild(src) {
|
|
22099
22392
|
const res = spawnSync2(
|
|
22100
22393
|
process.execPath,
|
|
22101
|
-
[
|
|
22394
|
+
[join27(src, "dist", "cli", "index.js"), "--version"],
|
|
22102
22395
|
{
|
|
22103
22396
|
cwd: src,
|
|
22104
22397
|
encoding: "utf8",
|
|
@@ -22178,7 +22471,7 @@ Fix it manually in ${src} (try \`npm ci && npm run build\`, and check your Node
|
|
|
22178
22471
|
console.log(`${C4.dim}\u2192 zam setup --force${C4.reset}`);
|
|
22179
22472
|
const setup = spawnSync2(
|
|
22180
22473
|
process.execPath,
|
|
22181
|
-
[
|
|
22474
|
+
[join27(src, "dist", "cli", "index.js"), "setup", "--force"],
|
|
22182
22475
|
{ cwd: process.cwd(), stdio: "inherit" }
|
|
22183
22476
|
);
|
|
22184
22477
|
if (setup.status !== 0) {
|
|
@@ -22290,15 +22583,15 @@ var whoamiCommand = new Command25("whoami").description("Show or set the default
|
|
|
22290
22583
|
|
|
22291
22584
|
// src/cli/commands/workspace.ts
|
|
22292
22585
|
init_kernel();
|
|
22293
|
-
import { execFileSync as
|
|
22294
|
-
import { existsSync as
|
|
22295
|
-
import { homedir as
|
|
22296
|
-
import { join as
|
|
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";
|
|
22297
22590
|
import { confirm as confirm4, input as input7 } from "@inquirer/prompts";
|
|
22298
22591
|
import { Command as Command26 } from "commander";
|
|
22299
22592
|
function runGit2(cwd, args) {
|
|
22300
22593
|
try {
|
|
22301
|
-
return
|
|
22594
|
+
return execFileSync5("git", args, {
|
|
22302
22595
|
cwd,
|
|
22303
22596
|
stdio: "pipe",
|
|
22304
22597
|
encoding: "utf8"
|
|
@@ -22377,7 +22670,7 @@ workspaceCommand.command("list").description("List configured ZAM workspaces").o
|
|
|
22377
22670
|
const workspaces = getConfiguredWorkspaces();
|
|
22378
22671
|
const agents = parseSetupAgents();
|
|
22379
22672
|
const linkHealth = Object.fromEntries(
|
|
22380
|
-
workspaces.filter((workspace) =>
|
|
22673
|
+
workspaces.filter((workspace) => existsSync27(workspace.path)).map((workspace) => [
|
|
22381
22674
|
workspace.id,
|
|
22382
22675
|
summarizeSkillLinkHealth(inspectSkillLinks(workspace.path, agents))
|
|
22383
22676
|
])
|
|
@@ -22420,7 +22713,7 @@ workspaceCommand.command("add <id>").description("Register an existing directory
|
|
|
22420
22713
|
).option("--scopes <list>", "Comma-separated knowledge scopes").option("--default-agent <id>", "Default agent harness for this workspace").action((id, opts) => {
|
|
22421
22714
|
try {
|
|
22422
22715
|
const path = resolve10(String(opts.path));
|
|
22423
|
-
if (!
|
|
22716
|
+
if (!existsSync27(path)) {
|
|
22424
22717
|
console.error(`Workspace path does not exist: ${path}`);
|
|
22425
22718
|
process.exit(1);
|
|
22426
22719
|
}
|
|
@@ -22514,7 +22807,7 @@ workspaceCommand.command("publish").description("Publish your local workspace sa
|
|
|
22514
22807
|
);
|
|
22515
22808
|
process.exit(1);
|
|
22516
22809
|
}
|
|
22517
|
-
if (!
|
|
22810
|
+
if (!existsSync27(workspaceDir)) {
|
|
22518
22811
|
console.error(
|
|
22519
22812
|
`\x1B[31m\u2717 Workspace directory does not exist: ${workspaceDir}\x1B[0m`
|
|
22520
22813
|
);
|
|
@@ -22528,15 +22821,15 @@ Active workspace: \x1B[36m${workspaceDir}\x1B[0m`);
|
|
|
22528
22821
|
);
|
|
22529
22822
|
process.exit(1);
|
|
22530
22823
|
}
|
|
22531
|
-
const gitignorePath =
|
|
22532
|
-
if (!
|
|
22533
|
-
|
|
22824
|
+
const gitignorePath = join28(workspaceDir, ".gitignore");
|
|
22825
|
+
if (!existsSync27(gitignorePath)) {
|
|
22826
|
+
writeFileSync15(
|
|
22534
22827
|
gitignorePath,
|
|
22535
22828
|
"node_modules/\n.agent/\n.agents/\n.claude/\n.gemini/\n.goose/\n*.log\n",
|
|
22536
22829
|
"utf8"
|
|
22537
22830
|
);
|
|
22538
22831
|
}
|
|
22539
|
-
const hasGitRepo =
|
|
22832
|
+
const hasGitRepo = existsSync27(join28(workspaceDir, ".git"));
|
|
22540
22833
|
if (!hasGitRepo) {
|
|
22541
22834
|
console.log("Initializing local Git repository...");
|
|
22542
22835
|
runGit2(workspaceDir, ["init", "-b", "main"]);
|
|
@@ -22568,7 +22861,7 @@ Active workspace: \x1B[36m${workspaceDir}\x1B[0m`);
|
|
|
22568
22861
|
if (proceedGh) {
|
|
22569
22862
|
try {
|
|
22570
22863
|
console.log(`Creating GitHub repository ${repoName}...`);
|
|
22571
|
-
|
|
22864
|
+
execFileSync5("gh", ghRepoCreateArgs(repoName, repoVisibility), {
|
|
22572
22865
|
cwd: workspaceDir,
|
|
22573
22866
|
stdio: "inherit"
|
|
22574
22867
|
});
|
|
@@ -22623,7 +22916,7 @@ Active workspace: \x1B[36m${workspaceDir}\x1B[0m`);
|
|
|
22623
22916
|
}
|
|
22624
22917
|
});
|
|
22625
22918
|
workspaceCommand.command("data-dir").description("Print the ZAM data directory (database, credentials, config)").option("--json", "Output as JSON").action((opts) => {
|
|
22626
|
-
const dir =
|
|
22919
|
+
const dir = join28(homedir16(), ".zam");
|
|
22627
22920
|
console.log(opts.json ? JSON.stringify({ dataDir: dir }) : dir);
|
|
22628
22921
|
});
|
|
22629
22922
|
workspaceCommand.command("backup").description("Back up the local ZAM database into your workspace").option(
|
|
@@ -22664,9 +22957,9 @@ workspaceCommand.command("backup").description("Back up the local ZAM database i
|
|
|
22664
22957
|
});
|
|
22665
22958
|
|
|
22666
22959
|
// src/cli/app.ts
|
|
22667
|
-
var __dirname =
|
|
22960
|
+
var __dirname = dirname14(fileURLToPath8(import.meta.url));
|
|
22668
22961
|
var pkg = JSON.parse(
|
|
22669
|
-
|
|
22962
|
+
readFileSync20(join29(__dirname, "..", "..", "package.json"), "utf-8")
|
|
22670
22963
|
);
|
|
22671
22964
|
var program = new Command27();
|
|
22672
22965
|
program.name("zam").description(
|