mindgraph-mcp 0.23.0 → 0.24.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/README.md +5 -2
- package/dist/cli.js +448 -188
- package/dist/index.js +226 -129
- package/dist/server.d.mts +4 -0
- package/dist/server.d.ts +4 -0
- package/dist/server.js +32 -2
- package/dist/server.mjs +32 -2
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -22,30 +22,85 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
22
22
|
mod
|
|
23
23
|
));
|
|
24
24
|
|
|
25
|
+
// src/call-ledger.ts
|
|
26
|
+
var import_node_crypto = __toESM(require("crypto"));
|
|
27
|
+
var import_node_fs = __toESM(require("fs"));
|
|
28
|
+
var import_node_os = __toESM(require("os"));
|
|
29
|
+
var import_node_path = __toESM(require("path"));
|
|
30
|
+
var TTL_MS = 10 * 6e4;
|
|
31
|
+
function callsDir(options) {
|
|
32
|
+
return import_node_path.default.join(
|
|
33
|
+
options.runtimeDir || process.env.MINDGRAPH_RUNTIME_DIR || import_node_path.default.join(import_node_os.default.homedir(), ".mindgraph", "runtime"),
|
|
34
|
+
"calls"
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
function stableJson(value) {
|
|
38
|
+
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
39
|
+
if (value && typeof value === "object") {
|
|
40
|
+
return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson(item)}`).join(",")}}`;
|
|
41
|
+
}
|
|
42
|
+
return JSON.stringify(value) ?? "null";
|
|
43
|
+
}
|
|
44
|
+
function bareToolName(name) {
|
|
45
|
+
const cut = name.lastIndexOf("__");
|
|
46
|
+
return cut === -1 ? name : name.slice(cut + 2);
|
|
47
|
+
}
|
|
48
|
+
function callKey(toolName, toolInput) {
|
|
49
|
+
return import_node_crypto.default.createHash("sha256").update(`${bareToolName(toolName)}\0${stableJson(toolInput)}`).digest("hex");
|
|
50
|
+
}
|
|
51
|
+
function resolvePendingCall(toolName, toolInput, options = {}) {
|
|
52
|
+
const now = (options.now ?? Date.now)();
|
|
53
|
+
const dir = callsDir(options);
|
|
54
|
+
const prefix = `${callKey(toolName, toolInput)}.`;
|
|
55
|
+
let names;
|
|
56
|
+
try {
|
|
57
|
+
names = import_node_fs.default.readdirSync(dir).filter((name) => name.startsWith(prefix) && name.endsWith(".json"));
|
|
58
|
+
} catch {
|
|
59
|
+
return void 0;
|
|
60
|
+
}
|
|
61
|
+
let matches = [];
|
|
62
|
+
for (const name of names) {
|
|
63
|
+
try {
|
|
64
|
+
const record = JSON.parse(
|
|
65
|
+
import_node_fs.default.readFileSync(import_node_path.default.join(dir, name), "utf8")
|
|
66
|
+
);
|
|
67
|
+
if (typeof record.createdAt === "number" && now - record.createdAt <= TTL_MS && record.fills && typeof record.fills === "object") {
|
|
68
|
+
matches.push(record);
|
|
69
|
+
}
|
|
70
|
+
} catch {
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
if (matches.length > 1) {
|
|
74
|
+
const projectDir = options.projectDir ?? process.env.CLAUDE_PROJECT_DIR;
|
|
75
|
+
matches = projectDir ? matches.filter((record) => record.projectDir === projectDir) : [];
|
|
76
|
+
}
|
|
77
|
+
return matches.length === 1 ? matches[0].fills : void 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
25
80
|
// src/index.ts
|
|
26
81
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
27
82
|
var import_mindgraph3 = require("mindgraph");
|
|
28
83
|
|
|
29
84
|
// src/hook-env.ts
|
|
30
|
-
var
|
|
31
|
-
var
|
|
32
|
-
var
|
|
33
|
-
var
|
|
85
|
+
var import_node_crypto2 = __toESM(require("crypto"));
|
|
86
|
+
var import_node_fs2 = __toESM(require("fs"));
|
|
87
|
+
var import_node_os2 = __toESM(require("os"));
|
|
88
|
+
var import_node_path2 = __toESM(require("path"));
|
|
34
89
|
function stableAgentId() {
|
|
35
90
|
let user = "user";
|
|
36
91
|
try {
|
|
37
|
-
user =
|
|
92
|
+
user = import_node_os2.default.userInfo().username || "user";
|
|
38
93
|
} catch {
|
|
39
94
|
}
|
|
40
|
-
const digest =
|
|
95
|
+
const digest = import_node_crypto2.default.createHash("sha256").update(`${user}@${import_node_os2.default.hostname()}`).digest("hex").slice(0, 12);
|
|
41
96
|
return `u-${digest}`;
|
|
42
97
|
}
|
|
43
98
|
function hookEnvPath(dir) {
|
|
44
|
-
return
|
|
99
|
+
return import_node_path2.default.join(dir || import_node_path2.default.join(import_node_os2.default.homedir(), ".mindgraph"), "hooks.json");
|
|
45
100
|
}
|
|
46
101
|
function loadHookEnv(dir) {
|
|
47
102
|
try {
|
|
48
|
-
const raw =
|
|
103
|
+
const raw = import_node_fs2.default.readFileSync(hookEnvPath(dir), "utf8");
|
|
49
104
|
const parsed = JSON.parse(raw);
|
|
50
105
|
return {
|
|
51
106
|
baseUrl: typeof parsed.baseUrl === "string" ? parsed.baseUrl : void 0,
|
|
@@ -357,6 +412,14 @@ function hiddenSections(payload) {
|
|
|
357
412
|
function renderContext(response, maxChars) {
|
|
358
413
|
const payload = obj(response);
|
|
359
414
|
if (!payload) return void 0;
|
|
415
|
+
if (typeof payload.context_text === "string" && payload.context_text.length > 0) {
|
|
416
|
+
const text2 = payload.context_text;
|
|
417
|
+
if (maxChars !== void 0 && text2.length > maxChars) {
|
|
418
|
+
return `${text2.slice(0, maxChars)}
|
|
419
|
+
[truncated to ${maxChars} characters]`;
|
|
420
|
+
}
|
|
421
|
+
return text2;
|
|
422
|
+
}
|
|
360
423
|
const graph = obj(payload.graph);
|
|
361
424
|
const rawNodes = Array.isArray(graph?.nodes) ? graph.nodes : [];
|
|
362
425
|
const shaped = rawNodes.filter(isNodeShaped);
|
|
@@ -579,15 +642,15 @@ function renderTraversal(response, maxChars) {
|
|
|
579
642
|
const labelByUid = /* @__PURE__ */ new Map();
|
|
580
643
|
for (const node of nodes) labelByUid.set(str(node.uid), str(node.label) || "?");
|
|
581
644
|
if (paths.length > 0) {
|
|
582
|
-
const items = paths.map((raw) => obj(raw)).filter((
|
|
583
|
-
const uids = Array.isArray(
|
|
584
|
-
const labels = Array.isArray(
|
|
645
|
+
const items = paths.map((raw) => obj(raw)).filter((path6) => Boolean(path6)).map((path6, index) => {
|
|
646
|
+
const uids = Array.isArray(path6.node_uids) ? path6.node_uids.map(String) : [];
|
|
647
|
+
const labels = Array.isArray(path6.labels) ? path6.labels.map(String) : Array.isArray(path6.nodes) ? path6.nodes.map((hop) => {
|
|
585
648
|
const hopNode = obj(hop);
|
|
586
649
|
return str(hopNode?.label) || labelByUid.get(str(hopNode?.uid) || "") || str(hop) || "?";
|
|
587
650
|
}) : [];
|
|
588
651
|
const route = labels.length > 0 ? labels.join(" \u2192 ") : uids.join(" \u2192 ") || "(path)";
|
|
589
|
-
const cost = num(
|
|
590
|
-
const confidence = num(
|
|
652
|
+
const cost = num(path6.cost) ?? num(path6.path_cost);
|
|
653
|
+
const confidence = num(path6.path_confidence);
|
|
591
654
|
const meta = [
|
|
592
655
|
cost !== void 0 ? `cost ${cost}` : void 0,
|
|
593
656
|
confidence !== void 0 ? `confidence ${confidence}` : void 0
|
|
@@ -1589,7 +1652,7 @@ ${conversation}`
|
|
|
1589
1652
|
}
|
|
1590
1653
|
|
|
1591
1654
|
// src/memory-tool.ts
|
|
1592
|
-
var
|
|
1655
|
+
var import_node_crypto3 = require("crypto");
|
|
1593
1656
|
var RESULT_SCHEMA_VERSION = "mindgraph.memory.result.v1";
|
|
1594
1657
|
var DEFAULT_OUTPUT_CHARS = 8e3;
|
|
1595
1658
|
var MIN_OUTPUT_CHARS = 512;
|
|
@@ -1737,15 +1800,15 @@ function obj2(value) {
|
|
|
1737
1800
|
function text(value) {
|
|
1738
1801
|
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
1739
1802
|
}
|
|
1740
|
-
function
|
|
1741
|
-
if (Array.isArray(value)) return `[${value.map(
|
|
1803
|
+
function stableJson2(value) {
|
|
1804
|
+
if (Array.isArray(value)) return `[${value.map(stableJson2).join(",")}]`;
|
|
1742
1805
|
if (value && typeof value === "object") {
|
|
1743
|
-
return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${
|
|
1806
|
+
return `{${Object.entries(value).filter(([, item]) => item !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson2(item)}`).join(",")}}`;
|
|
1744
1807
|
}
|
|
1745
1808
|
return JSON.stringify(value);
|
|
1746
1809
|
}
|
|
1747
1810
|
function sha256(value) {
|
|
1748
|
-
return (0,
|
|
1811
|
+
return (0, import_node_crypto3.createHash)("sha256").update(value).digest("hex");
|
|
1749
1812
|
}
|
|
1750
1813
|
function outputBudget(value) {
|
|
1751
1814
|
if (typeof value !== "number" || !Number.isFinite(value)) return DEFAULT_OUTPUT_CHARS;
|
|
@@ -2051,7 +2114,7 @@ async function handleMemoryTool(client2, args, config = {}) {
|
|
|
2051
2114
|
scope_uids: Array.isArray(args.scope_uids) ? args.scope_uids.map(String) : void 0
|
|
2052
2115
|
});
|
|
2053
2116
|
const contextId = `ctx_${sha256(
|
|
2054
|
-
|
|
2117
|
+
stableJson2({ mode, scope, strategy, query: text(args.query), rendered_hash: renderedHash })
|
|
2055
2118
|
).slice(0, 24)}`;
|
|
2056
2119
|
const bounded = candidates.length > items.length || rendered2.includes("item(s) omitted");
|
|
2057
2120
|
const result = {
|
|
@@ -2212,15 +2275,15 @@ async function readGovernedResource(client2, uri, governanceConfig, memoryConfig
|
|
|
2212
2275
|
}
|
|
2213
2276
|
|
|
2214
2277
|
// src/tools.ts
|
|
2215
|
-
var
|
|
2278
|
+
var import_node_crypto6 = require("crypto");
|
|
2216
2279
|
|
|
2217
2280
|
// src/codegraph.ts
|
|
2218
2281
|
var import_node_child_process = require("child_process");
|
|
2219
|
-
var
|
|
2282
|
+
var import_node_fs3 = require("fs");
|
|
2220
2283
|
var import_promises = require("fs/promises");
|
|
2221
|
-
var
|
|
2222
|
-
var
|
|
2223
|
-
var
|
|
2284
|
+
var import_node_os3 = require("os");
|
|
2285
|
+
var import_node_path3 = require("path");
|
|
2286
|
+
var import_node_crypto4 = require("crypto");
|
|
2224
2287
|
var UnknownRepositoryError = class extends Error {
|
|
2225
2288
|
constructor(repo) {
|
|
2226
2289
|
super(
|
|
@@ -2251,14 +2314,14 @@ function unavailabilityCaveats(reason, message) {
|
|
|
2251
2314
|
var DEFAULT_TIMEOUT_MS = 5e3;
|
|
2252
2315
|
var DEFAULT_STATUS_TTL_MS = 6e4;
|
|
2253
2316
|
var MAX_OUTPUT_BYTES = 5 * 1024 * 1024;
|
|
2254
|
-
function normalizePath(
|
|
2255
|
-
return
|
|
2317
|
+
function normalizePath(path6) {
|
|
2318
|
+
return path6.replaceAll("\\", "/").replace(/^\.\//, "");
|
|
2256
2319
|
}
|
|
2257
2320
|
function normalizeSignature(signature) {
|
|
2258
2321
|
return signature.replace(/\s+/g, " ").trim();
|
|
2259
2322
|
}
|
|
2260
|
-
function languageFromPath(
|
|
2261
|
-
const extension = (0,
|
|
2323
|
+
function languageFromPath(path6) {
|
|
2324
|
+
const extension = (0, import_node_path3.extname)(path6).toLowerCase();
|
|
2262
2325
|
return {
|
|
2263
2326
|
".c": "c",
|
|
2264
2327
|
".cc": "cpp",
|
|
@@ -2307,30 +2370,30 @@ function normalizeRemote(remote) {
|
|
|
2307
2370
|
}
|
|
2308
2371
|
}
|
|
2309
2372
|
function pathContains(root, candidate) {
|
|
2310
|
-
const child = (0,
|
|
2311
|
-
return child === "" || child !== ".." && !child.startsWith(`..${
|
|
2373
|
+
const child = (0, import_node_path3.relative)(root, candidate);
|
|
2374
|
+
return child === "" || child !== ".." && !child.startsWith(`..${import_node_path3.sep}`) && !(0, import_node_path3.isAbsolute)(child);
|
|
2312
2375
|
}
|
|
2313
2376
|
function nearestExistingDirectory(candidate) {
|
|
2314
|
-
let current = (0,
|
|
2377
|
+
let current = (0, import_node_path3.resolve)(candidate);
|
|
2315
2378
|
for (; ; ) {
|
|
2316
|
-
if ((0,
|
|
2379
|
+
if ((0, import_node_fs3.existsSync)(current)) {
|
|
2317
2380
|
try {
|
|
2318
|
-
return (0,
|
|
2381
|
+
return (0, import_node_fs3.statSync)(current).isDirectory() ? current : (0, import_node_path3.dirname)(current);
|
|
2319
2382
|
} catch {
|
|
2320
2383
|
}
|
|
2321
2384
|
}
|
|
2322
|
-
const parent = (0,
|
|
2385
|
+
const parent = (0, import_node_path3.dirname)(current);
|
|
2323
2386
|
if (parent === current) return current;
|
|
2324
2387
|
current = parent;
|
|
2325
2388
|
}
|
|
2326
2389
|
}
|
|
2327
2390
|
function findWorkspaceFile(start, explicit) {
|
|
2328
|
-
if (explicit) return (0,
|
|
2329
|
-
let current = (0,
|
|
2391
|
+
if (explicit) return (0, import_node_path3.resolve)(start, explicit);
|
|
2392
|
+
let current = (0, import_node_path3.resolve)(start);
|
|
2330
2393
|
for (; ; ) {
|
|
2331
|
-
const candidate = (0,
|
|
2332
|
-
if ((0,
|
|
2333
|
-
const parent = (0,
|
|
2394
|
+
const candidate = (0, import_node_path3.join)(current, ".mindgraph", "workspace.json");
|
|
2395
|
+
if ((0, import_node_fs3.existsSync)(candidate)) return candidate;
|
|
2396
|
+
const parent = (0, import_node_path3.dirname)(current);
|
|
2334
2397
|
if (parent === current) return void 0;
|
|
2335
2398
|
current = parent;
|
|
2336
2399
|
}
|
|
@@ -2417,7 +2480,7 @@ var CodegraphAdapter = class {
|
|
|
2417
2480
|
async resolveRepository(repo, fallbackSpaceUid) {
|
|
2418
2481
|
const configured = await this.resolveRepositories(fallbackSpaceUid);
|
|
2419
2482
|
const selected = repo && configured.find((candidate) => candidate.repoId === repo) || repo && configured.find(
|
|
2420
|
-
(candidate) => candidate.repoRoot === repo || (0,
|
|
2483
|
+
(candidate) => candidate.repoRoot === repo || (0, import_node_path3.basename)(candidate.repoRoot) === repo
|
|
2421
2484
|
) || (!repo ? [...configured].sort((a, b) => b.repoRoot.length - a.repoRoot.length).find((candidate) => pathContains(candidate.repoRoot, this.cwd)) : void 0) || (!repo && configured.length === 1 ? configured[0] : void 0);
|
|
2422
2485
|
if (selected) {
|
|
2423
2486
|
return !repo && this.env.MINDGRAPH_REPO_ID ? this.resolveRepositoryIdentity(
|
|
@@ -2427,10 +2490,10 @@ var CodegraphAdapter = class {
|
|
|
2427
2490
|
) : selected;
|
|
2428
2491
|
}
|
|
2429
2492
|
if (repo) {
|
|
2430
|
-
const requestedPath = await (0, import_promises.realpath)((0,
|
|
2431
|
-
() => (0,
|
|
2493
|
+
const requestedPath = await (0, import_promises.realpath)((0, import_node_path3.resolve)(this.cwd, repo)).catch(
|
|
2494
|
+
() => (0, import_node_path3.resolve)(this.cwd, repo)
|
|
2432
2495
|
);
|
|
2433
|
-
if (!(0,
|
|
2496
|
+
if (!(0, import_node_fs3.existsSync)(requestedPath)) {
|
|
2434
2497
|
const current = await this.currentRepository(fallbackSpaceUid);
|
|
2435
2498
|
if (current.repoId === repo) return current;
|
|
2436
2499
|
throw new UnknownRepositoryError(repo);
|
|
@@ -2446,8 +2509,8 @@ var CodegraphAdapter = class {
|
|
|
2446
2509
|
}
|
|
2447
2510
|
async currentRepository(fallbackSpaceUid) {
|
|
2448
2511
|
const requestedRoot = this.env.MINDGRAPH_REPO_ROOT || this.cwd;
|
|
2449
|
-
const requestedPath = await (0, import_promises.realpath)((0,
|
|
2450
|
-
() => (0,
|
|
2512
|
+
const requestedPath = await (0, import_promises.realpath)((0, import_node_path3.resolve)(this.cwd, requestedRoot)).catch(
|
|
2513
|
+
() => (0, import_node_path3.resolve)(this.cwd, requestedRoot)
|
|
2451
2514
|
);
|
|
2452
2515
|
const repoRoot = await this.gitRoot(requestedPath) ?? requestedPath;
|
|
2453
2516
|
return this.resolveRepositoryIdentity(
|
|
@@ -2468,7 +2531,7 @@ var CodegraphAdapter = class {
|
|
|
2468
2531
|
);
|
|
2469
2532
|
}
|
|
2470
2533
|
async resolveRepositoryIdentity(root, explicitRepoId, spaceUid) {
|
|
2471
|
-
const repoRoot = await (0, import_promises.realpath)(root).catch(() => (0,
|
|
2534
|
+
const repoRoot = await (0, import_promises.realpath)(root).catch(() => (0, import_node_path3.resolve)(root));
|
|
2472
2535
|
const cacheKey = `${repoRoot}\0${explicitRepoId ?? ""}\0${spaceUid ?? ""}`;
|
|
2473
2536
|
const cached = this.identityCache.get(cacheKey);
|
|
2474
2537
|
if (cached) return cached;
|
|
@@ -2498,20 +2561,20 @@ var CodegraphAdapter = class {
|
|
|
2498
2561
|
this.env
|
|
2499
2562
|
).catch(() => "");
|
|
2500
2563
|
if (!rawCommonDir.trim()) {
|
|
2501
|
-
return `local:${(0,
|
|
2564
|
+
return `local:${(0, import_node_path3.basename)(repoRoot)}`;
|
|
2502
2565
|
}
|
|
2503
|
-
const commonDir = (0,
|
|
2504
|
-
const identityDir = (0,
|
|
2505
|
-
const identityFile = (0,
|
|
2566
|
+
const commonDir = (0, import_node_path3.resolve)(repoRoot, rawCommonDir.trim());
|
|
2567
|
+
const identityDir = (0, import_node_path3.join)(commonDir, "mindgraph");
|
|
2568
|
+
const identityFile = (0, import_node_path3.join)(identityDir, "repository-id");
|
|
2506
2569
|
try {
|
|
2507
|
-
const existing = (0,
|
|
2570
|
+
const existing = (0, import_node_fs3.readFileSync)(identityFile, "utf8").trim();
|
|
2508
2571
|
if (existing) return existing;
|
|
2509
2572
|
} catch {
|
|
2510
2573
|
}
|
|
2511
|
-
(0,
|
|
2512
|
-
const generated = (0,
|
|
2574
|
+
(0, import_node_fs3.mkdirSync)(identityDir, { recursive: true, mode: 448 });
|
|
2575
|
+
const generated = (0, import_node_crypto4.randomUUID)();
|
|
2513
2576
|
try {
|
|
2514
|
-
(0,
|
|
2577
|
+
(0, import_node_fs3.writeFileSync)(identityFile, `${generated}
|
|
2515
2578
|
`, {
|
|
2516
2579
|
encoding: "utf8",
|
|
2517
2580
|
flag: "wx",
|
|
@@ -2520,7 +2583,7 @@ var CodegraphAdapter = class {
|
|
|
2520
2583
|
return generated;
|
|
2521
2584
|
} catch (cause) {
|
|
2522
2585
|
if (cause.code !== "EEXIST") throw cause;
|
|
2523
|
-
const winner = (0,
|
|
2586
|
+
const winner = (0, import_node_fs3.readFileSync)(identityFile, "utf8").trim();
|
|
2524
2587
|
if (!winner) throw new Error(`empty repository identity file: ${identityFile}`);
|
|
2525
2588
|
return winner;
|
|
2526
2589
|
}
|
|
@@ -2533,12 +2596,12 @@ var CodegraphAdapter = class {
|
|
|
2533
2596
|
Math.min(this.timeoutMs, 2e3),
|
|
2534
2597
|
this.env
|
|
2535
2598
|
).catch(() => "");
|
|
2536
|
-
return raw.trim() ? (0,
|
|
2599
|
+
return raw.trim() ? (0, import_node_path3.resolve)(start, raw.trim()) : void 0;
|
|
2537
2600
|
}
|
|
2538
2601
|
/** Why the workspace map yielded no repositories — for callers that were
|
|
2539
2602
|
* explicitly asked to fan out and would otherwise return silently empty. */
|
|
2540
2603
|
workspaceDiagnostic() {
|
|
2541
|
-
if (!this.workspaceFile || !(0,
|
|
2604
|
+
if (!this.workspaceFile || !(0, import_node_fs3.existsSync)(this.workspaceFile)) {
|
|
2542
2605
|
return "no .mindgraph/workspace.json was found between the working directory and the filesystem root";
|
|
2543
2606
|
}
|
|
2544
2607
|
return `${this.workspaceFile} is malformed or declares no repositories`;
|
|
@@ -2658,7 +2721,7 @@ var CodegraphAdapter = class {
|
|
|
2658
2721
|
return this.resolveRepository(ref.repo || defaultRepo, fallbackSpaceUid);
|
|
2659
2722
|
}
|
|
2660
2723
|
if (ref.path) {
|
|
2661
|
-
const requested = (0,
|
|
2724
|
+
const requested = (0, import_node_path3.isAbsolute)(ref.path) ? (0, import_node_path3.resolve)(ref.path) : (0, import_node_path3.resolve)(this.cwd, ref.path);
|
|
2662
2725
|
const absolute = await (0, import_promises.realpath)(requested).catch(() => requested);
|
|
2663
2726
|
const configured = await this.resolveRepositories(fallbackSpaceUid);
|
|
2664
2727
|
const defining = [...configured].sort((a, b) => b.repoRoot.length - a.repoRoot.length).find((candidate) => pathContains(candidate.repoRoot, absolute));
|
|
@@ -2735,19 +2798,19 @@ var CodegraphAdapter = class {
|
|
|
2735
2798
|
}
|
|
2736
2799
|
configuredRepositories() {
|
|
2737
2800
|
const configured = [];
|
|
2738
|
-
if (this.workspaceFile && (0,
|
|
2801
|
+
if (this.workspaceFile && (0, import_node_fs3.existsSync)(this.workspaceFile)) {
|
|
2739
2802
|
try {
|
|
2740
2803
|
const parsed = JSON.parse(
|
|
2741
|
-
(0,
|
|
2804
|
+
(0, import_node_fs3.readFileSync)(this.workspaceFile, "utf8")
|
|
2742
2805
|
);
|
|
2743
2806
|
if (parsed.v === 1 && Array.isArray(parsed.repositories)) {
|
|
2744
|
-
const configDirectory = (0,
|
|
2745
|
-
const base = (0,
|
|
2807
|
+
const configDirectory = (0, import_node_path3.dirname)(this.workspaceFile);
|
|
2808
|
+
const base = (0, import_node_path3.basename)(configDirectory) === ".mindgraph" ? (0, import_node_path3.dirname)(configDirectory) : configDirectory;
|
|
2746
2809
|
for (const repository of parsed.repositories) {
|
|
2747
2810
|
if (!repository || typeof repository.root !== "string") continue;
|
|
2748
2811
|
configured.push({
|
|
2749
2812
|
repoId: typeof repository.repo_id === "string" ? repository.repo_id : void 0,
|
|
2750
|
-
repoRoot: (0,
|
|
2813
|
+
repoRoot: (0, import_node_path3.resolve)(base, repository.root),
|
|
2751
2814
|
spaceUid: typeof repository.space_uid === "string" ? repository.space_uid : void 0
|
|
2752
2815
|
});
|
|
2753
2816
|
}
|
|
@@ -2762,7 +2825,7 @@ var CodegraphAdapter = class {
|
|
|
2762
2825
|
for (const [repoId, config] of Object.entries(parsed)) {
|
|
2763
2826
|
configured.push({
|
|
2764
2827
|
repoId,
|
|
2765
|
-
repoRoot: (0,
|
|
2828
|
+
repoRoot: (0, import_node_path3.resolve)(
|
|
2766
2829
|
this.cwd,
|
|
2767
2830
|
typeof config === "string" ? config : config.root
|
|
2768
2831
|
),
|
|
@@ -2790,9 +2853,9 @@ var CodegraphAdapter = class {
|
|
|
2790
2853
|
const hits = await this.runJson(args);
|
|
2791
2854
|
let candidates = hits.map(asNode).map(toCandidate).filter((item) => item !== null);
|
|
2792
2855
|
if (ref.path) {
|
|
2793
|
-
const absolutePath = (0,
|
|
2856
|
+
const absolutePath = (0, import_node_path3.isAbsolute)(ref.path) ? await (0, import_promises.realpath)(ref.path).catch(() => ref.path) : void 0;
|
|
2794
2857
|
const wanted = normalizePath(
|
|
2795
|
-
absolutePath ? (0,
|
|
2858
|
+
absolutePath ? (0, import_node_path3.relative)(repository.repoRoot, absolutePath) : ref.path
|
|
2796
2859
|
);
|
|
2797
2860
|
candidates = candidates.filter((candidate) => candidate.path === wanted);
|
|
2798
2861
|
}
|
|
@@ -2893,7 +2956,7 @@ var CodegraphAdapter = class {
|
|
|
2893
2956
|
const candidates = [
|
|
2894
2957
|
this.env.MINDGRAPH_CODEGRAPH_BIN,
|
|
2895
2958
|
"codegraph",
|
|
2896
|
-
(0,
|
|
2959
|
+
(0, import_node_path3.resolve)((0, import_node_os3.homedir)(), ".local", "bin", "codegraph")
|
|
2897
2960
|
].filter((candidate, index, all) => {
|
|
2898
2961
|
return Boolean(candidate) && all.indexOf(candidate) === index;
|
|
2899
2962
|
});
|
|
@@ -3494,9 +3557,9 @@ function primaryUids(value) {
|
|
|
3494
3557
|
}
|
|
3495
3558
|
|
|
3496
3559
|
// src/sync-tool.ts
|
|
3497
|
-
var
|
|
3498
|
-
var
|
|
3499
|
-
var
|
|
3560
|
+
var import_node_crypto5 = __toESM(require("crypto"));
|
|
3561
|
+
var import_node_fs4 = __toESM(require("fs"));
|
|
3562
|
+
var import_node_path4 = __toESM(require("path"));
|
|
3500
3563
|
var ok3 = (data) => ({
|
|
3501
3564
|
content: [{ type: "text", text: JSON.stringify(data) }]
|
|
3502
3565
|
});
|
|
@@ -3573,12 +3636,12 @@ var SYNC_TOOL = {
|
|
|
3573
3636
|
}
|
|
3574
3637
|
};
|
|
3575
3638
|
function safePath(root, candidate) {
|
|
3576
|
-
const absolute =
|
|
3577
|
-
const relative2 =
|
|
3578
|
-
if (relative2.startsWith("..") ||
|
|
3639
|
+
const absolute = import_node_path4.default.resolve(root, candidate);
|
|
3640
|
+
const relative2 = import_node_path4.default.relative(root, absolute);
|
|
3641
|
+
if (relative2.startsWith("..") || import_node_path4.default.isAbsolute(relative2)) {
|
|
3579
3642
|
throw new Error(`path escapes repository root: ${candidate}`);
|
|
3580
3643
|
}
|
|
3581
|
-
if (
|
|
3644
|
+
if (import_node_fs4.default.existsSync(absolute)) {
|
|
3582
3645
|
if (!pathContains(realPathOf(root), realPathOf(absolute))) {
|
|
3583
3646
|
throw new Error(`path escapes repository root via symlink: ${candidate}`);
|
|
3584
3647
|
}
|
|
@@ -3587,26 +3650,26 @@ function safePath(root, candidate) {
|
|
|
3587
3650
|
}
|
|
3588
3651
|
function realPathOf(target) {
|
|
3589
3652
|
try {
|
|
3590
|
-
return
|
|
3653
|
+
return import_node_fs4.default.realpathSync(target);
|
|
3591
3654
|
} catch {
|
|
3592
|
-
return
|
|
3655
|
+
return import_node_path4.default.resolve(target);
|
|
3593
3656
|
}
|
|
3594
3657
|
}
|
|
3595
3658
|
function markdownFiles(target, realRoot, visited = /* @__PURE__ */ new Set()) {
|
|
3596
|
-
if (!
|
|
3659
|
+
if (!import_node_fs4.default.existsSync(target)) return [];
|
|
3597
3660
|
const real = realPathOf(target);
|
|
3598
3661
|
if (!pathContains(realRoot, real)) return [];
|
|
3599
|
-
const stat =
|
|
3662
|
+
const stat = import_node_fs4.default.statSync(target);
|
|
3600
3663
|
if (stat.isFile()) return target.endsWith(".md") ? [target] : [];
|
|
3601
3664
|
if (!stat.isDirectory() || visited.has(real)) return [];
|
|
3602
3665
|
visited.add(real);
|
|
3603
|
-
return
|
|
3666
|
+
return import_node_fs4.default.readdirSync(target, { withFileTypes: true }).flatMap((entry) => markdownFiles(import_node_path4.default.join(target, entry.name), realRoot, visited));
|
|
3604
3667
|
}
|
|
3605
3668
|
function fileDescriptor(root, absolute) {
|
|
3606
|
-
const content =
|
|
3669
|
+
const content = import_node_fs4.default.readFileSync(absolute, "utf8");
|
|
3607
3670
|
return {
|
|
3608
|
-
logical_path:
|
|
3609
|
-
content_hash:
|
|
3671
|
+
logical_path: import_node_path4.default.relative(root, absolute).split(import_node_path4.default.sep).join("/"),
|
|
3672
|
+
content_hash: import_node_crypto5.default.createHash("sha256").update(content).digest("hex"),
|
|
3610
3673
|
bytes: Buffer.byteLength(content),
|
|
3611
3674
|
content
|
|
3612
3675
|
};
|
|
@@ -3675,7 +3738,7 @@ async function handleSyncTool(client2, args) {
|
|
|
3675
3738
|
}
|
|
3676
3739
|
if (action === "status" && request.logical_path && request.file_present !== false) {
|
|
3677
3740
|
const absolute = safePath(root, String(request.logical_path));
|
|
3678
|
-
request.file_present =
|
|
3741
|
+
request.file_present = import_node_fs4.default.existsSync(absolute);
|
|
3679
3742
|
if (request.file_present && !request.content_hash) {
|
|
3680
3743
|
request.content_hash = fileDescriptor(root, absolute).content_hash;
|
|
3681
3744
|
}
|
|
@@ -3748,10 +3811,10 @@ var RESOLUTION_PROPERTIES = {
|
|
|
3748
3811
|
description: "Alias for confirm_new on a near-duplicate response"
|
|
3749
3812
|
}
|
|
3750
3813
|
};
|
|
3751
|
-
function
|
|
3752
|
-
if (Array.isArray(value)) return `[${value.map(
|
|
3814
|
+
function stableJson3(value) {
|
|
3815
|
+
if (Array.isArray(value)) return `[${value.map(stableJson3).join(",")}]`;
|
|
3753
3816
|
if (value && typeof value === "object") {
|
|
3754
|
-
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${
|
|
3817
|
+
return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, item]) => `${JSON.stringify(key)}:${stableJson3(item)}`).join(",")}}`;
|
|
3755
3818
|
}
|
|
3756
3819
|
return JSON.stringify(value);
|
|
3757
3820
|
}
|
|
@@ -3765,8 +3828,8 @@ function defaultWriteIdempotencyKey(tool, args) {
|
|
|
3765
3828
|
([key]) => key !== "invocation_context" && key !== "idempotency_key"
|
|
3766
3829
|
)
|
|
3767
3830
|
);
|
|
3768
|
-
return (0,
|
|
3769
|
-
|
|
3831
|
+
return (0, import_node_crypto6.createHash)("sha256").update(
|
|
3832
|
+
stableJson3({
|
|
3770
3833
|
harness_session_id: sessionId,
|
|
3771
3834
|
harness_turn_id: context?.harnessTurnId ?? null,
|
|
3772
3835
|
tool,
|
|
@@ -4478,6 +4541,15 @@ var TOOLS = [
|
|
|
4478
4541
|
type: "string",
|
|
4479
4542
|
description: "ISO-8601 date (e.g. '2021-06') for context: nodes with validity windows are annotated as of this date instead of today"
|
|
4480
4543
|
},
|
|
4544
|
+
as_of: {
|
|
4545
|
+
type: "string",
|
|
4546
|
+
description: "ISO-8601 date for context: answer with what had been STATED by this date (a node is admitted when one of its sources was stated on or before it; fact dates never exclude it). Use for 'what did we know / what was the value as of <date>' questions."
|
|
4547
|
+
},
|
|
4548
|
+
retrieval_mode: {
|
|
4549
|
+
type: "string",
|
|
4550
|
+
enum: ["normal", "exhaustive"],
|
|
4551
|
+
description: "context: 'exhaustive' widens retrieval for list/count questions ('how many different \u2026 across', 'what two \u2026'); omitted lets the server's cue decide."
|
|
4552
|
+
},
|
|
4481
4553
|
created_after: {
|
|
4482
4554
|
type: "number",
|
|
4483
4555
|
description: "Unix seconds \u2014 'recent' action: only nodes ingested after this time"
|
|
@@ -5706,6 +5778,8 @@ async function handleRetrieve(client2, args, profile) {
|
|
|
5706
5778
|
salience_min,
|
|
5707
5779
|
article_limit,
|
|
5708
5780
|
valid_at,
|
|
5781
|
+
as_of,
|
|
5782
|
+
retrieval_mode,
|
|
5709
5783
|
created_after,
|
|
5710
5784
|
created_before,
|
|
5711
5785
|
explain,
|
|
@@ -5734,9 +5808,15 @@ async function handleRetrieve(client2, args, profile) {
|
|
|
5734
5808
|
// the advertised knob must not get a silent no-op).
|
|
5735
5809
|
...article_limit !== void 0 ? { article_limit } : include_documents === false || profile === "coding" && !include_documents ? { article_limit: 0 } : {},
|
|
5736
5810
|
valid_at,
|
|
5811
|
+
as_of,
|
|
5812
|
+
retrieval_mode,
|
|
5737
5813
|
include_graph,
|
|
5738
5814
|
graph_expansion_limit: graph_expansion_limit ?? 3,
|
|
5739
|
-
graph_max_depth: graph_max_depth ?? 2
|
|
5815
|
+
graph_max_depth: graph_max_depth ?? 2,
|
|
5816
|
+
// Evidence plan R2: the server's canonical rendering under a token
|
|
5817
|
+
// budget derived from the character budget; the local renderer is
|
|
5818
|
+
// the fallback for servers that predate it.
|
|
5819
|
+
...format === "json" ? {} : { format: "text", max_tokens: Math.max(256, Math.floor((max_output_chars ?? 24e3) / 4)) }
|
|
5740
5820
|
}),
|
|
5741
5821
|
(raw) => renderContext(raw, max_output_chars)
|
|
5742
5822
|
);
|
|
@@ -6210,7 +6290,12 @@ function buildMindGraphServer(wiring) {
|
|
|
6210
6290
|
});
|
|
6211
6291
|
server2.setRequestHandler(import_types.CallToolRequestSchema, async (request) => {
|
|
6212
6292
|
const { name, arguments: args } = request.params;
|
|
6213
|
-
const rawArgs = {
|
|
6293
|
+
const rawArgs = {
|
|
6294
|
+
...args || {},
|
|
6295
|
+
// H1: session, lease and invocation fields the local hook recorded for
|
|
6296
|
+
// this exact call (stdio only; hosted mode has no local hook).
|
|
6297
|
+
...hosted ? {} : wiring.resolveHookFields?.(name, args || {})
|
|
6298
|
+
};
|
|
6214
6299
|
const toolArgs = { ...rawArgs };
|
|
6215
6300
|
let governanceConfig = wiring.governance;
|
|
6216
6301
|
if (hosted) {
|
|
@@ -6275,16 +6360,16 @@ function buildMindGraphServer(wiring) {
|
|
|
6275
6360
|
}
|
|
6276
6361
|
|
|
6277
6362
|
// src/index.ts
|
|
6278
|
-
var
|
|
6363
|
+
var import_node_path6 = __toESM(require("path"));
|
|
6279
6364
|
|
|
6280
6365
|
// src/hook-installer.ts
|
|
6281
|
-
var
|
|
6282
|
-
var
|
|
6283
|
-
var
|
|
6284
|
-
var
|
|
6366
|
+
var import_node_fs5 = __toESM(require("fs"));
|
|
6367
|
+
var import_node_os4 = __toESM(require("os"));
|
|
6368
|
+
var import_node_path5 = __toESM(require("path"));
|
|
6369
|
+
var import_node_crypto7 = __toESM(require("crypto"));
|
|
6285
6370
|
function storedFeatures(homeDir) {
|
|
6286
6371
|
const { promptRecall, capture } = loadHookEnv(
|
|
6287
|
-
|
|
6372
|
+
import_node_path5.default.join(homeDir || import_node_os4.default.homedir(), ".mindgraph")
|
|
6288
6373
|
);
|
|
6289
6374
|
return { promptRecall, capture };
|
|
6290
6375
|
}
|
|
@@ -6298,24 +6383,24 @@ function windowsCommand(harness) {
|
|
|
6298
6383
|
}
|
|
6299
6384
|
var RUNNER_VERSION_RELATIVE = `${RUNNER_RELATIVE}.version`;
|
|
6300
6385
|
function installHookRunner(sourceFile, homeDir, version) {
|
|
6301
|
-
const target =
|
|
6302
|
-
|
|
6303
|
-
const temporary = `${target}.${process.pid}.${
|
|
6304
|
-
|
|
6305
|
-
|
|
6306
|
-
const versionPath =
|
|
6386
|
+
const target = import_node_path5.default.join(homeDir || import_node_os4.default.homedir(), RUNNER_RELATIVE);
|
|
6387
|
+
import_node_fs5.default.mkdirSync(import_node_path5.default.dirname(target), { recursive: true });
|
|
6388
|
+
const temporary = `${target}.${process.pid}.${import_node_crypto7.default.randomUUID()}.tmp`;
|
|
6389
|
+
import_node_fs5.default.copyFileSync(sourceFile, temporary);
|
|
6390
|
+
import_node_fs5.default.renameSync(temporary, target);
|
|
6391
|
+
const versionPath = import_node_path5.default.join(homeDir || import_node_os4.default.homedir(), RUNNER_VERSION_RELATIVE);
|
|
6307
6392
|
if (version) {
|
|
6308
|
-
|
|
6393
|
+
import_node_fs5.default.writeFileSync(versionPath, `${version}
|
|
6309
6394
|
`);
|
|
6310
6395
|
} else {
|
|
6311
|
-
|
|
6396
|
+
import_node_fs5.default.rmSync(versionPath, { force: true });
|
|
6312
6397
|
}
|
|
6313
6398
|
return target;
|
|
6314
6399
|
}
|
|
6315
6400
|
function installedHookRunnerVersion(homeDir) {
|
|
6316
6401
|
try {
|
|
6317
|
-
const raw =
|
|
6318
|
-
|
|
6402
|
+
const raw = import_node_fs5.default.readFileSync(
|
|
6403
|
+
import_node_path5.default.join(homeDir || import_node_os4.default.homedir(), RUNNER_VERSION_RELATIVE),
|
|
6319
6404
|
"utf8"
|
|
6320
6405
|
).trim();
|
|
6321
6406
|
return raw || void 0;
|
|
@@ -6340,11 +6425,11 @@ function refreshHookRunner(serverVersion, sourceBundle, homeDir) {
|
|
|
6340
6425
|
if (process.env.MINDGRAPH_HOOK_AUTOUPDATE === "off") {
|
|
6341
6426
|
return { refreshed: false, reason: "disabled" };
|
|
6342
6427
|
}
|
|
6343
|
-
const home = homeDir ||
|
|
6344
|
-
if (!
|
|
6428
|
+
const home = homeDir || import_node_os4.default.homedir();
|
|
6429
|
+
if (!import_node_fs5.default.existsSync(import_node_path5.default.join(home, RUNNER_RELATIVE))) {
|
|
6345
6430
|
return { refreshed: false, reason: "no_runner" };
|
|
6346
6431
|
}
|
|
6347
|
-
if (!
|
|
6432
|
+
if (!import_node_fs5.default.existsSync(sourceBundle)) {
|
|
6348
6433
|
return { refreshed: false, reason: "no_source" };
|
|
6349
6434
|
}
|
|
6350
6435
|
const server2 = parseSemver(serverVersion);
|
|
@@ -6375,8 +6460,8 @@ function refreshOwnedClaudeHooks(projectDir = process.cwd(), homeDir) {
|
|
|
6375
6460
|
for (const scope of scopes) {
|
|
6376
6461
|
try {
|
|
6377
6462
|
const file = settingsPath("claude-code", scope, projectDir, void 0, homeDir);
|
|
6378
|
-
if (!
|
|
6379
|
-
if (!
|
|
6463
|
+
if (!import_node_fs5.default.existsSync(file)) continue;
|
|
6464
|
+
if (!import_node_fs5.default.readFileSync(file, "utf8").includes(OWNER_MARKER)) continue;
|
|
6380
6465
|
installHooks(
|
|
6381
6466
|
"claude-code",
|
|
6382
6467
|
scope,
|
|
@@ -6396,15 +6481,15 @@ function versionSkewNote(serverVersion, homeDir) {
|
|
|
6396
6481
|
if (!runnerVersion || runnerVersion === serverVersion) return void 0;
|
|
6397
6482
|
return `NOTE: the installed MindGraph hook runner is v${runnerVersion} but this MCP server is v${serverVersion} \u2014 hook behavior and tool contracts may be out of sync. Tell the user to run: npx -y mindgraph-mcp@latest install-hooks (refreshes the pinned runner).`;
|
|
6398
6483
|
}
|
|
6399
|
-
function settingsPath(harness, scope, projectDir = process.cwd(), codexHomeDir = process.env.CODEX_HOME ||
|
|
6484
|
+
function settingsPath(harness, scope, projectDir = process.cwd(), codexHomeDir = process.env.CODEX_HOME || import_node_path5.default.join(import_node_os4.default.homedir(), ".codex"), homeDir) {
|
|
6400
6485
|
if (harness === "codex") {
|
|
6401
|
-
return scope === "user" ?
|
|
6486
|
+
return scope === "user" ? import_node_path5.default.join(codexHomeDir, "hooks.json") : import_node_path5.default.join(projectDir, ".codex", "hooks.json");
|
|
6402
6487
|
}
|
|
6403
|
-
return scope === "user" ?
|
|
6488
|
+
return scope === "user" ? import_node_path5.default.join(homeDir || import_node_os4.default.homedir(), ".claude", "settings.json") : import_node_path5.default.join(projectDir, ".claude", "settings.json");
|
|
6404
6489
|
}
|
|
6405
6490
|
function readSettings(file) {
|
|
6406
|
-
if (!
|
|
6407
|
-
return JSON.parse(
|
|
6491
|
+
if (!import_node_fs5.default.existsSync(file)) return {};
|
|
6492
|
+
return JSON.parse(import_node_fs5.default.readFileSync(file, "utf8"));
|
|
6408
6493
|
}
|
|
6409
6494
|
function ownedHook(harness, timeout, additionalContextLimit) {
|
|
6410
6495
|
return {
|
|
@@ -6416,6 +6501,7 @@ function ownedHook(harness, timeout, additionalContextLimit) {
|
|
|
6416
6501
|
...additionalContextLimit === void 0 ? {} : { additionalContextLimit }
|
|
6417
6502
|
};
|
|
6418
6503
|
}
|
|
6504
|
+
var CLAUDE_POST_TOOL_MATCHER = "mcp__mindgraph__.*|Edit|MultiEdit|Write|NotebookEdit|Bash|Task|Agent";
|
|
6419
6505
|
function desiredEntries(harness, features = {}) {
|
|
6420
6506
|
const common = {
|
|
6421
6507
|
SessionStart: [
|
|
@@ -6448,7 +6534,17 @@ function desiredEntries(harness, features = {}) {
|
|
|
6448
6534
|
],
|
|
6449
6535
|
// PostToolUse awaits the lease renewal round-trip, which fires exactly
|
|
6450
6536
|
// when the tenant is cold (post-idle reclaim) — 5s killed it mid-claim.
|
|
6451
|
-
|
|
6537
|
+
// Claude Code: only the tools the hook acts on (MindGraph calls, edits,
|
|
6538
|
+
// and the shell/agent calls that keep a lease alive). Read, Grep and Glob
|
|
6539
|
+
// are most of a session's tool calls and the hook did nothing useful for
|
|
6540
|
+
// them but start a process (roadmap H8). Codex names its tools
|
|
6541
|
+
// differently, so it keeps the catch-all.
|
|
6542
|
+
PostToolUse: [
|
|
6543
|
+
{
|
|
6544
|
+
matcher: harness === "claude-code" ? CLAUDE_POST_TOOL_MATCHER : ".*",
|
|
6545
|
+
hooks: [ownedHook(harness, 10)]
|
|
6546
|
+
}
|
|
6547
|
+
],
|
|
6452
6548
|
Stop: [{ hooks: [ownedHook(harness, 5)] }],
|
|
6453
6549
|
// SessionEnd makes up to two sequential cloud calls (abandon_iteration +
|
|
6454
6550
|
// session close) — the SAME cold-tenant latency SessionStart needs 30s
|
|
@@ -6482,13 +6578,13 @@ function entryHasOwnedHook(value) {
|
|
|
6482
6578
|
return Array.isArray(hooks) && hooks.some((hook) => hookCommand(hook)?.includes(OWNER_MARKER));
|
|
6483
6579
|
}
|
|
6484
6580
|
function writeSettings(file, settings) {
|
|
6485
|
-
|
|
6486
|
-
const temporary = `${file}.${process.pid}.${
|
|
6487
|
-
|
|
6581
|
+
import_node_fs5.default.mkdirSync(import_node_path5.default.dirname(file), { recursive: true });
|
|
6582
|
+
const temporary = `${file}.${process.pid}.${import_node_crypto7.default.randomUUID()}.tmp`;
|
|
6583
|
+
import_node_fs5.default.writeFileSync(temporary, `${JSON.stringify(settings, null, 2)}
|
|
6488
6584
|
`, {
|
|
6489
6585
|
mode: 384
|
|
6490
6586
|
});
|
|
6491
|
-
|
|
6587
|
+
import_node_fs5.default.renameSync(temporary, file);
|
|
6492
6588
|
}
|
|
6493
6589
|
function installHooks(harness, scope, projectDir = process.cwd(), codexHomeDir, homeDir, features = {}) {
|
|
6494
6590
|
const file = settingsPath(harness, scope, projectDir, codexHomeDir, homeDir);
|
|
@@ -6613,7 +6709,7 @@ if (PROFILE === "coding") {
|
|
|
6613
6709
|
- Capture corrections, decisions with rationale, fixes that survived meaningful failed attempts, durable invariants/preferences, and blockers with evidence.
|
|
6614
6710
|
- If a write returns \`near_duplicate\`, choose \`reuse_uid\` or \`supersedes_uid\`; use \`confirm_new\` only for genuinely distinct facts.
|
|
6615
6711
|
- Do not capture routine mechanics, transient command output, facts cheaply derivable from code, unsupported speculation as high-confidence lessons, or completion without evidence.
|
|
6616
|
-
- Adapter context is owned by ${HARNESS}; omit invocation_context because
|
|
6712
|
+
- Adapter context is owned by ${HARNESS}; omit invocation_context because the adapter supplies it.`;
|
|
6617
6713
|
} else {
|
|
6618
6714
|
INSTRUCTIONS = INSTRUCTIONS.split("\n").filter(
|
|
6619
6715
|
(line) => !line.includes("mindgraph_code") && !line.includes("`code`") && !line.includes("Typed code anchors")
|
|
@@ -6621,7 +6717,7 @@ if (PROFILE === "coding") {
|
|
|
6621
6717
|
}
|
|
6622
6718
|
var RUNNER_REFRESH = (() => {
|
|
6623
6719
|
try {
|
|
6624
|
-
return refreshHookRunner("0.
|
|
6720
|
+
return refreshHookRunner("0.24.0", import_node_path6.default.join(__dirname, "cli.js"));
|
|
6625
6721
|
} catch {
|
|
6626
6722
|
return void 0;
|
|
6627
6723
|
}
|
|
@@ -6635,12 +6731,12 @@ if (RUNNER_REFRESH?.refreshed) {
|
|
|
6635
6731
|
}
|
|
6636
6732
|
})();
|
|
6637
6733
|
console.error(
|
|
6638
|
-
`[mindgraph-mcp] refreshed pinned hook runner ${RUNNER_REFRESH.runnerVersion ? `v${RUNNER_REFRESH.runnerVersion}` : "(pre-sidecar)"} \u2192 v${"0.
|
|
6734
|
+
`[mindgraph-mcp] refreshed pinned hook runner ${RUNNER_REFRESH.runnerVersion ? `v${RUNNER_REFRESH.runnerVersion}` : "(pre-sidecar)"} \u2192 v${"0.24.0"}` + (refreshedSettings.length > 0 ? `; refreshed owned hook entries in ${refreshedSettings.join(", ")}` : "")
|
|
6639
6735
|
);
|
|
6640
6736
|
}
|
|
6641
6737
|
var HOOK_SKEW_NOTE = (() => {
|
|
6642
6738
|
try {
|
|
6643
|
-
return versionSkewNote("0.
|
|
6739
|
+
return versionSkewNote("0.24.0");
|
|
6644
6740
|
} catch {
|
|
6645
6741
|
return void 0;
|
|
6646
6742
|
}
|
|
@@ -6661,7 +6757,7 @@ var GOVERNANCE_CONFIG = {
|
|
|
6661
6757
|
}
|
|
6662
6758
|
};
|
|
6663
6759
|
var MEMORY_RUNTIME_CONFIG = {
|
|
6664
|
-
serverVersion: "0.
|
|
6760
|
+
serverVersion: "0.24.0",
|
|
6665
6761
|
baseUrl: BASE_URL,
|
|
6666
6762
|
profile: PROFILE,
|
|
6667
6763
|
harness: HARNESS,
|
|
@@ -6670,18 +6766,19 @@ var MEMORY_RUNTIME_CONFIG = {
|
|
|
6670
6766
|
};
|
|
6671
6767
|
var server = buildMindGraphServer({
|
|
6672
6768
|
client,
|
|
6673
|
-
serverVersion: "0.
|
|
6769
|
+
serverVersion: "0.24.0",
|
|
6674
6770
|
instructions: INSTRUCTIONS,
|
|
6675
6771
|
profile: PROFILE,
|
|
6676
6772
|
agentId: AGENT_ID,
|
|
6677
6773
|
governance: GOVERNANCE_CONFIG,
|
|
6678
|
-
memory: MEMORY_RUNTIME_CONFIG
|
|
6774
|
+
memory: MEMORY_RUNTIME_CONFIG,
|
|
6775
|
+
resolveHookFields: (name, args) => resolvePendingCall(name, args)
|
|
6679
6776
|
});
|
|
6680
6777
|
async function main() {
|
|
6681
6778
|
const transport = new import_stdio.StdioServerTransport();
|
|
6682
6779
|
await server.connect(transport);
|
|
6683
6780
|
console.error(
|
|
6684
|
-
`MindGraph MCP server v${"0.
|
|
6781
|
+
`MindGraph MCP server v${"0.24.0"} running on stdio (${BASE_URL})`
|
|
6685
6782
|
);
|
|
6686
6783
|
}
|
|
6687
6784
|
main().catch((error2) => {
|