zam-core 0.14.0 → 0.15.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 +25 -2
- package/dist/cli/app.js.map +1 -1
- package/dist/cli/commands/mcp.js +149 -12
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/copilot-extension/extension.mjs +1 -0
- 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/index.d.ts +7 -0
- package/dist/index.js +9 -0
- package/dist/index.js.map +1 -1
- package/dist/ui/graph-panel.html +80 -40
- package/dist/ui/okf-panel.html +26 -1
- package/dist/vscode-extension/ZAM_Companion_0.15.0.vsix +0 -0
- package/dist/vscode-extension/extension.cjs +15 -14
- package/dist/vscode-extension/host.bundle.js +3 -2
- package/dist/vscode-extension/manifest.json +2 -2
- package/package.json +1 -1
- package/dist/vscode-extension/ZAM_Companion_0.14.0.vsix +0 -0
package/dist/cli/commands/mcp.js
CHANGED
|
@@ -2140,6 +2140,15 @@ async function listTokens(db, options) {
|
|
|
2140
2140
|
)`);
|
|
2141
2141
|
params.push(options.knowledgeContext);
|
|
2142
2142
|
}
|
|
2143
|
+
if (options?.sourceLinkBases) {
|
|
2144
|
+
const clauses = options.sourceLinkBases.map(
|
|
2145
|
+
() => `(source_link = ? OR source_link LIKE ? || '#%' ESCAPE '\\')`
|
|
2146
|
+
);
|
|
2147
|
+
whereClauses.push(clauses.length ? `(${clauses.join(" OR ")})` : "0 = 1");
|
|
2148
|
+
for (const base of options.sourceLinkBases) {
|
|
2149
|
+
params.push(base, escapeLike(base));
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2143
2152
|
const orderBy = options?.domain || options?.domainPrefix ? "ORDER BY bloom_level, slug" : "ORDER BY bloom_level, domain, slug";
|
|
2144
2153
|
const sql = `SELECT * FROM tokens WHERE ${whereClauses.join(" AND ")} ${orderBy}`;
|
|
2145
2154
|
const tokens = await db.prepare(sql).all(...params);
|
|
@@ -9231,6 +9240,7 @@ var init_bundle = __esm({
|
|
|
9231
9240
|
var io_exports = {};
|
|
9232
9241
|
__export(io_exports, {
|
|
9233
9242
|
DEFAULT_BUNDLE_DIR: () => DEFAULT_BUNDLE_DIR,
|
|
9243
|
+
collectSourceLinkBases: () => collectSourceLinkBases,
|
|
9234
9244
|
findRepoRoot: () => findRepoRoot,
|
|
9235
9245
|
loadBundle: () => loadBundle,
|
|
9236
9246
|
resolveArticlePath: () => resolveArticlePath,
|
|
@@ -9259,6 +9269,12 @@ function resolveBundleDirFromRoots(rootUris, fallback) {
|
|
|
9259
9269
|
}
|
|
9260
9270
|
return dirs.find((dir) => existsSync13(dir)) ?? dirs[0] ?? fallback;
|
|
9261
9271
|
}
|
|
9272
|
+
function collectSourceLinkBases(dir) {
|
|
9273
|
+
const bundle = loadBundle(dir);
|
|
9274
|
+
return bundle.catalog.map(
|
|
9275
|
+
(entry) => entry.resource ?? resolveArticlePath(dir, entry.file)
|
|
9276
|
+
);
|
|
9277
|
+
}
|
|
9262
9278
|
function resolveArticlePath(dir, file) {
|
|
9263
9279
|
if (file.includes("/") || file.includes("\\") || file.includes("..")) {
|
|
9264
9280
|
throw new Error(`invalid article file name: ${file}`);
|
|
@@ -9375,10 +9391,67 @@ var init_io = __esm({
|
|
|
9375
9391
|
}
|
|
9376
9392
|
});
|
|
9377
9393
|
|
|
9394
|
+
// src/cli/okf-focus.ts
|
|
9395
|
+
var okf_focus_exports = {};
|
|
9396
|
+
__export(okf_focus_exports, {
|
|
9397
|
+
getOkfFocusPath: () => getOkfFocusPath,
|
|
9398
|
+
readOkfFocus: () => readOkfFocus,
|
|
9399
|
+
writeOkfFocus: () => writeOkfFocus
|
|
9400
|
+
});
|
|
9401
|
+
import { mkdir as mkdir2, readFile as readFile2, rename as rename2, writeFile as writeFile2 } from "fs/promises";
|
|
9402
|
+
import { homedir as homedir16 } from "os";
|
|
9403
|
+
import { dirname as dirname12, join as join25 } from "path";
|
|
9404
|
+
function getOkfFocusPath(home = homedir16()) {
|
|
9405
|
+
return join25(home, ".zam", "okf-focus.json");
|
|
9406
|
+
}
|
|
9407
|
+
function resolvePath(explicit) {
|
|
9408
|
+
return explicit ?? process.env.ZAM_OKF_FOCUS_PATH ?? getOkfFocusPath();
|
|
9409
|
+
}
|
|
9410
|
+
async function writeOkfFocus(file, bundleDir, opts = {}) {
|
|
9411
|
+
if (file.includes("/") || file.includes("\\") || !file.endsWith(".md")) {
|
|
9412
|
+
throw new Error(`invalid article file name: ${file}`);
|
|
9413
|
+
}
|
|
9414
|
+
const path = resolvePath(opts.path);
|
|
9415
|
+
const focus = {
|
|
9416
|
+
version: 1,
|
|
9417
|
+
file,
|
|
9418
|
+
...bundleDir ? { bundleDir } : {},
|
|
9419
|
+
updatedAt: (opts.now?.() ?? /* @__PURE__ */ new Date()).toISOString()
|
|
9420
|
+
};
|
|
9421
|
+
await mkdir2(dirname12(path), { recursive: true });
|
|
9422
|
+
const tmp = `${path}.tmp`;
|
|
9423
|
+
await writeFile2(tmp, `${JSON.stringify(focus, null, 2)}
|
|
9424
|
+
`, "utf8");
|
|
9425
|
+
await rename2(tmp, path);
|
|
9426
|
+
return focus;
|
|
9427
|
+
}
|
|
9428
|
+
async function readOkfFocus(opts = {}) {
|
|
9429
|
+
try {
|
|
9430
|
+
const raw = await readFile2(resolvePath(opts.path), "utf8");
|
|
9431
|
+
const parsed = JSON.parse(raw);
|
|
9432
|
+
if (parsed.version !== 1 || typeof parsed.file !== "string" || typeof parsed.updatedAt !== "string") {
|
|
9433
|
+
return null;
|
|
9434
|
+
}
|
|
9435
|
+
return {
|
|
9436
|
+
version: 1,
|
|
9437
|
+
file: parsed.file,
|
|
9438
|
+
...typeof parsed.bundleDir === "string" ? { bundleDir: parsed.bundleDir } : {},
|
|
9439
|
+
updatedAt: parsed.updatedAt
|
|
9440
|
+
};
|
|
9441
|
+
} catch {
|
|
9442
|
+
return null;
|
|
9443
|
+
}
|
|
9444
|
+
}
|
|
9445
|
+
var init_okf_focus = __esm({
|
|
9446
|
+
"src/cli/okf-focus.ts"() {
|
|
9447
|
+
"use strict";
|
|
9448
|
+
}
|
|
9449
|
+
});
|
|
9450
|
+
|
|
9378
9451
|
// src/cli/commands/mcp.ts
|
|
9379
9452
|
init_kernel();
|
|
9380
9453
|
import { existsSync as existsSync22, readFileSync as readFileSync19 } from "fs";
|
|
9381
|
-
import { dirname as
|
|
9454
|
+
import { basename as basename6, dirname as dirname13, join as join26 } from "path";
|
|
9382
9455
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
9383
9456
|
import {
|
|
9384
9457
|
RESOURCE_MIME_TYPE,
|
|
@@ -12178,7 +12251,7 @@ async function readWebLink(url) {
|
|
|
12178
12251
|
redirect: "manual",
|
|
12179
12252
|
signal: controller.signal,
|
|
12180
12253
|
headers: {
|
|
12181
|
-
"User-Agent": "ZAM-Content-Studio/0.
|
|
12254
|
+
"User-Agent": "ZAM-Content-Studio/0.15.0"
|
|
12182
12255
|
}
|
|
12183
12256
|
});
|
|
12184
12257
|
if (res.status >= 300 && res.status < 400) {
|
|
@@ -32323,7 +32396,12 @@ bridgeCommand.command("list-tokens").description(
|
|
|
32323
32396
|
).option("--domain <domain>", "Filter by exact domain").option(
|
|
32324
32397
|
"--domain-prefix <prefix>",
|
|
32325
32398
|
"Filter by domain prefix (e.g. company-team) \u2014 uses / separator for hierarchy"
|
|
32326
|
-
).option("--knowledge-context <context>", "Filter by knowledge context").
|
|
32399
|
+
).option("--knowledge-context <context>", "Filter by knowledge context").option(
|
|
32400
|
+
"--source-link-base <base>",
|
|
32401
|
+
"Filter by source-link base (exact or '<base>#<anchor>', as written by OKF imports); repeatable",
|
|
32402
|
+
(value, previous) => [...previous, value],
|
|
32403
|
+
[]
|
|
32404
|
+
).action(async (opts) => {
|
|
32327
32405
|
await withDb2(async (db) => {
|
|
32328
32406
|
const userId = opts.user ? await resolveUser(opts, db, { json: true }) : void 0;
|
|
32329
32407
|
const listOpts = {};
|
|
@@ -32331,6 +32409,8 @@ bridgeCommand.command("list-tokens").description(
|
|
|
32331
32409
|
if (opts.domainPrefix) listOpts.domainPrefix = opts.domainPrefix;
|
|
32332
32410
|
if (opts.knowledgeContext)
|
|
32333
32411
|
listOpts.knowledgeContext = opts.knowledgeContext;
|
|
32412
|
+
if (opts.sourceLinkBase.length)
|
|
32413
|
+
listOpts.sourceLinkBases = opts.sourceLinkBase;
|
|
32334
32414
|
const tokens = await listTokens(
|
|
32335
32415
|
db,
|
|
32336
32416
|
Object.keys(listOpts).length ? listOpts : void 0
|
|
@@ -34143,10 +34223,10 @@ async function publishUiIntent(app, input = {}, opts = {}) {
|
|
|
34143
34223
|
}
|
|
34144
34224
|
|
|
34145
34225
|
// src/cli/commands/mcp.ts
|
|
34146
|
-
var __dirname =
|
|
34147
|
-
var pkgPath =
|
|
34226
|
+
var __dirname = dirname13(fileURLToPath7(import.meta.url));
|
|
34227
|
+
var pkgPath = join26(__dirname, "..", "..", "package.json");
|
|
34148
34228
|
if (!existsSync22(pkgPath)) {
|
|
34149
|
-
pkgPath =
|
|
34229
|
+
pkgPath = join26(__dirname, "..", "..", "..", "package.json");
|
|
34150
34230
|
}
|
|
34151
34231
|
var pkg = JSON.parse(readFileSync19(pkgPath, "utf-8"));
|
|
34152
34232
|
var STUDIO_RESOURCE_URI = "ui://zam/studio";
|
|
@@ -34176,9 +34256,9 @@ var STUDIO_BRIDGE_ALLOWED_COMMANDS = /* @__PURE__ */ new Set([
|
|
|
34176
34256
|
function loadPanelHtml(fileName, placeholderTitle) {
|
|
34177
34257
|
const candidates = [
|
|
34178
34258
|
// dist/cli/commands/mcp.js → dist/ui/
|
|
34179
|
-
|
|
34259
|
+
join26(__dirname, "..", "..", "ui", fileName),
|
|
34180
34260
|
// src/cli/commands/mcp.ts via tsx → <repo>/dist/ui/
|
|
34181
|
-
|
|
34261
|
+
join26(__dirname, "..", "..", "..", "dist", "ui", fileName)
|
|
34182
34262
|
];
|
|
34183
34263
|
for (const candidate of candidates) {
|
|
34184
34264
|
if (existsSync22(candidate)) {
|
|
@@ -34747,7 +34827,7 @@ function createMcpServer(db) {
|
|
|
34747
34827
|
"zam_show_graph",
|
|
34748
34828
|
{
|
|
34749
34829
|
title: "Open ZAM knowledge graph",
|
|
34750
|
-
description: "Open the ZAM 2D knowledge-graph card, centered on a token's direct prerequisites and dependents. Pass `focus` (a token slug) when the conversation already names one;
|
|
34830
|
+
description: "Open the ZAM 2D knowledge-graph card, centered on a token's direct prerequisites and dependents. Pass `focus` (a token slug) when the conversation already names one; without it the card offers scope selectors and defaults to tokens anchored in the current repo's OKF knowledge base.",
|
|
34751
34831
|
inputSchema: {
|
|
34752
34832
|
focus: z.string().optional().describe("Token slug to center the graph on"),
|
|
34753
34833
|
user: z.string().optional().describe("User ID")
|
|
@@ -34769,6 +34849,16 @@ function createMcpServer(db) {
|
|
|
34769
34849
|
{ clientSamplingCapable: getClientSamplingCapable() }
|
|
34770
34850
|
);
|
|
34771
34851
|
const userId = opening.context.user.currentId ?? null;
|
|
34852
|
+
let repoScope;
|
|
34853
|
+
try {
|
|
34854
|
+
const { collectSourceLinkBases: collectSourceLinkBases2, findRepoRoot: findRepoRoot2 } = await Promise.resolve().then(() => (init_io(), io_exports));
|
|
34855
|
+
const bundleDir = await resolveOkfBundleDir();
|
|
34856
|
+
const bases = collectSourceLinkBases2(bundleDir);
|
|
34857
|
+
if (bases.length > 0) {
|
|
34858
|
+
repoScope = { label: basename6(findRepoRoot2(bundleDir)), bases };
|
|
34859
|
+
}
|
|
34860
|
+
} catch {
|
|
34861
|
+
}
|
|
34772
34862
|
await publishUiIntent("graph", { user, focus });
|
|
34773
34863
|
return {
|
|
34774
34864
|
graph: "zam",
|
|
@@ -34776,6 +34866,7 @@ function createMcpServer(db) {
|
|
|
34776
34866
|
version: pkg.version,
|
|
34777
34867
|
user: userId,
|
|
34778
34868
|
companionContext: opening.context,
|
|
34869
|
+
...repoScope ? { repoScope } : {},
|
|
34779
34870
|
...opening.degraded ? { companionContextDegraded: true } : {}
|
|
34780
34871
|
};
|
|
34781
34872
|
})
|
|
@@ -34988,7 +35079,7 @@ function createMcpServer(db) {
|
|
|
34988
35079
|
if (params.include_log) {
|
|
34989
35080
|
const { readFileSync: readFileSync20 } = await import("fs");
|
|
34990
35081
|
try {
|
|
34991
|
-
log = readFileSync20(
|
|
35082
|
+
log = readFileSync20(join26(bundle.dir, "log.md"), "utf8");
|
|
34992
35083
|
} catch {
|
|
34993
35084
|
log = "";
|
|
34994
35085
|
}
|
|
@@ -35104,6 +35195,52 @@ function createMcpServer(db) {
|
|
|
35104
35195
|
}
|
|
35105
35196
|
)
|
|
35106
35197
|
);
|
|
35198
|
+
registerAppTool(
|
|
35199
|
+
server,
|
|
35200
|
+
"zam_okf_focus",
|
|
35201
|
+
{
|
|
35202
|
+
description: "App-only: record which OKF article the visualizer panel currently shows, so chat agents can resolve 'the currently focused article'. Not intended for direct model use.",
|
|
35203
|
+
inputSchema: {
|
|
35204
|
+
file: z.string().describe("Article file name inside the bundle (kebab-case .md)"),
|
|
35205
|
+
bundle_dir: z.string().optional().describe("Absolute bundle directory the panel is browsing")
|
|
35206
|
+
},
|
|
35207
|
+
annotations: {
|
|
35208
|
+
...commonAnnotations,
|
|
35209
|
+
destructiveHint: false,
|
|
35210
|
+
idempotentHint: true
|
|
35211
|
+
},
|
|
35212
|
+
_meta: {
|
|
35213
|
+
ui: { visibility: ["app"] }
|
|
35214
|
+
}
|
|
35215
|
+
},
|
|
35216
|
+
wrapHandler(async (params) => {
|
|
35217
|
+
const { writeOkfFocus: writeOkfFocus2 } = await Promise.resolve().then(() => (init_okf_focus(), okf_focus_exports));
|
|
35218
|
+
const focus = await writeOkfFocus2(params.file, params.bundle_dir);
|
|
35219
|
+
return { recorded: { file: focus.file, updatedAt: focus.updatedAt } };
|
|
35220
|
+
})
|
|
35221
|
+
);
|
|
35222
|
+
server.registerTool(
|
|
35223
|
+
"zam_okf_focused",
|
|
35224
|
+
{
|
|
35225
|
+
description: "The OKF article currently focused in the user's visualizer panel \u2014 resolve requests like 'import this okf', 'import the currently focused article', or 'the open article'. Returns {focused: {file, bundle_dir?, updatedAt} | null}; check updatedAt and confirm the article by name with the user if it looks stale. To import, read the article (zam_okf_read) and follow the zam_okf_import contract.",
|
|
35226
|
+
inputSchema: {},
|
|
35227
|
+
annotations: {
|
|
35228
|
+
...commonAnnotations,
|
|
35229
|
+
readOnlyHint: true
|
|
35230
|
+
}
|
|
35231
|
+
},
|
|
35232
|
+
wrapHandler(async () => {
|
|
35233
|
+
const { readOkfFocus: readOkfFocus2 } = await Promise.resolve().then(() => (init_okf_focus(), okf_focus_exports));
|
|
35234
|
+
const focus = await readOkfFocus2();
|
|
35235
|
+
return {
|
|
35236
|
+
focused: focus ? {
|
|
35237
|
+
file: focus.file,
|
|
35238
|
+
...focus.bundleDir ? { bundle_dir: focus.bundleDir } : {},
|
|
35239
|
+
updatedAt: focus.updatedAt
|
|
35240
|
+
} : null
|
|
35241
|
+
};
|
|
35242
|
+
})
|
|
35243
|
+
);
|
|
35107
35244
|
server.registerTool(
|
|
35108
35245
|
"zam_okf_read_citation",
|
|
35109
35246
|
{
|
|
@@ -35172,13 +35309,13 @@ function createMcpServer(db) {
|
|
|
35172
35309
|
problems = bundle.problems;
|
|
35173
35310
|
const { readFileSync: readFileSync20 } = await import("fs");
|
|
35174
35311
|
try {
|
|
35175
|
-
log = readFileSync20(
|
|
35312
|
+
log = readFileSync20(join26(bundle.dir, "log.md"), "utf8");
|
|
35176
35313
|
} catch {
|
|
35177
35314
|
log = "";
|
|
35178
35315
|
}
|
|
35179
35316
|
try {
|
|
35180
35317
|
const { parseFrontmatter: parseFrontmatter2 } = await Promise.resolve().then(() => (init_bundle(), bundle_exports));
|
|
35181
|
-
const indexRaw = readFileSync20(
|
|
35318
|
+
const indexRaw = readFileSync20(join26(bundle.dir, "index.md"), "utf8");
|
|
35182
35319
|
const { fields } = parseFrontmatter2(indexRaw);
|
|
35183
35320
|
okfVersion = typeof fields.okf_version === "string" ? fields.okf_version : null;
|
|
35184
35321
|
} catch {
|