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