@kage-core/kage-graph-mcp 1.1.36 → 1.1.38
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 +101 -2
- package/dist/cli.js +451 -3
- package/dist/daemon.js +344 -7
- package/dist/index.js +382 -3
- package/dist/kernel.js +3790 -76
- package/package.json +1 -1
- package/viewer/app.js +1448 -86
- package/viewer/data.html +8 -15
- package/viewer/graph.html +8 -15
- package/viewer/index.html +19 -15
- package/viewer/intel.html +8 -15
- package/viewer/memory.html +79 -15
- package/viewer/owners.html +8 -15
- package/viewer/review.html +20 -16
- package/viewer/styles.css +751 -124
package/dist/daemon.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.viewerStaticHeaders = viewerStaticHeaders;
|
|
4
|
+
exports.viewerRedirectLocation = viewerRedirectLocation;
|
|
5
|
+
exports.viewerBenchmarkReport = viewerBenchmarkReport;
|
|
6
|
+
exports.daemonContextReport = daemonContextReport;
|
|
3
7
|
exports.readDaemonStatus = readDaemonStatus;
|
|
4
8
|
exports.daemonDoctor = daemonDoctor;
|
|
5
9
|
exports.stopDaemon = stopDaemon;
|
|
@@ -34,6 +38,107 @@ function contentType(filePath) {
|
|
|
34
38
|
return "text/markdown; charset=utf-8";
|
|
35
39
|
return "application/octet-stream";
|
|
36
40
|
}
|
|
41
|
+
function viewerStaticHeaders(filePath) {
|
|
42
|
+
return {
|
|
43
|
+
"content-type": contentType(filePath),
|
|
44
|
+
"x-content-type-options": "nosniff",
|
|
45
|
+
"referrer-policy": "no-referrer",
|
|
46
|
+
"cross-origin-opener-policy": "same-origin",
|
|
47
|
+
"content-security-policy": [
|
|
48
|
+
"default-src 'self'",
|
|
49
|
+
"script-src 'self'",
|
|
50
|
+
"script-src-attr 'none'",
|
|
51
|
+
"style-src 'self' 'unsafe-inline'",
|
|
52
|
+
"img-src 'self' data:",
|
|
53
|
+
"connect-src 'self'",
|
|
54
|
+
"font-src 'none'",
|
|
55
|
+
"object-src 'none'",
|
|
56
|
+
"base-uri 'none'",
|
|
57
|
+
"frame-ancestors 'none'",
|
|
58
|
+
].join("; "),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function viewerRedirectLocation(pathname, search, fallbackSearch) {
|
|
62
|
+
if (pathname !== "/" && pathname !== "/viewer" && pathname !== "/viewer/")
|
|
63
|
+
return null;
|
|
64
|
+
return `/viewer/index.html${search || fallbackSearch}`;
|
|
65
|
+
}
|
|
66
|
+
function viewerBenchmarkReport(projectDir) {
|
|
67
|
+
const gates = (0, kernel_js_1.benchmarkProject)(projectDir);
|
|
68
|
+
const memoryQuality = (0, kernel_js_1.benchmarkCodingMemoryQuality)();
|
|
69
|
+
const memoryScale = (0, kernel_js_1.benchmarkMemoryScale)({ sizes: [240], topK: 10 });
|
|
70
|
+
const requiredGates = gates.gates.filter((gate) => gate.required);
|
|
71
|
+
const requiredGatePasses = requiredGates.filter((gate) => gate.pass).length;
|
|
72
|
+
const requiredGatePercent = requiredGates.length ? Math.round((requiredGatePasses / requiredGates.length) * 100) : (gates.ok ? 100 : 0);
|
|
73
|
+
const recallAt10 = Number(memoryQuality.summary.recall_at_10_percent ?? memoryQuality.summary.recall_at_k_percent ?? 0);
|
|
74
|
+
const sourceDiversity = memoryQuality.source_diversity;
|
|
75
|
+
const scaleHitRate = Number(memoryScale.summary.largest_hit_rate_percent ?? 0);
|
|
76
|
+
const scaleContextCut = Number(memoryScale.summary.largest_context_reduction_percent ?? 0);
|
|
77
|
+
return {
|
|
78
|
+
...gates,
|
|
79
|
+
summary: memoryQuality.summary,
|
|
80
|
+
memory_quality: {
|
|
81
|
+
dataset: memoryQuality.dataset,
|
|
82
|
+
summary: memoryQuality.summary,
|
|
83
|
+
source_diversity: memoryQuality.source_diversity,
|
|
84
|
+
by_category: memoryQuality.by_category,
|
|
85
|
+
baselines: memoryQuality.baselines,
|
|
86
|
+
caveats: memoryQuality.caveats,
|
|
87
|
+
},
|
|
88
|
+
memory_scale: {
|
|
89
|
+
sizes: memoryScale.sizes,
|
|
90
|
+
summary: memoryScale.summary,
|
|
91
|
+
results: memoryScale.results,
|
|
92
|
+
caveats: memoryScale.caveats,
|
|
93
|
+
},
|
|
94
|
+
proof_ledger: [
|
|
95
|
+
{
|
|
96
|
+
id: "memory-quality",
|
|
97
|
+
label: "Coding-memory retrieval",
|
|
98
|
+
metric: `${recallAt10.toFixed(2)}% R@10, ${memoryQuality.summary.ndcg_at_10.toFixed(4)} NDCG@10`,
|
|
99
|
+
target: ">=95% R@10 and >=0.85 NDCG@10",
|
|
100
|
+
actual: recallAt10,
|
|
101
|
+
unit: "percent",
|
|
102
|
+
pass: recallAt10 >= 95 && memoryQuality.summary.ndcg_at_10 >= 0.85,
|
|
103
|
+
command: "kage benchmark --memory-quality --json",
|
|
104
|
+
next_action: "Use this as the fast coding-memory retrieval proof before publishing benchmark claims.",
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
id: "source-diversity",
|
|
108
|
+
label: "Source diversity",
|
|
109
|
+
metric: `${sourceDiversity.unique_sources} sources in top ${sourceDiversity.top_k}; max ${sourceDiversity.max_results_from_one_source} from one source`,
|
|
110
|
+
target: ">=2 sources and <=3 results from one observed session",
|
|
111
|
+
actual: sourceDiversity.unique_sources,
|
|
112
|
+
unit: "score",
|
|
113
|
+
pass: sourceDiversity.pass,
|
|
114
|
+
command: "kage benchmark --memory-quality --json",
|
|
115
|
+
next_action: sourceDiversity.pass ? "Use this to prove noisy sessions cannot crowd out independent repo memory." : "Inspect recall source diversity before publishing memory-quality claims.",
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
id: "memory-scale",
|
|
119
|
+
label: "Memory scale sanity",
|
|
120
|
+
metric: `${memoryScale.summary.largest_packets} packets, ${scaleHitRate.toFixed(2)}% hit rate, ${scaleContextCut.toFixed(2)}% context cut`,
|
|
121
|
+
target: ">=95% hit rate and >=80% context reduction",
|
|
122
|
+
actual: scaleHitRate,
|
|
123
|
+
unit: "percent",
|
|
124
|
+
pass: scaleHitRate >= 95 && scaleContextCut >= 80,
|
|
125
|
+
command: "kage benchmark --scale --sizes 240 --json",
|
|
126
|
+
next_action: "Run kage benchmark --scale --sizes 240,1000,5000 --json for a larger release proof.",
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
id: "local-gates",
|
|
130
|
+
label: "Repo trust gates",
|
|
131
|
+
metric: `${requiredGatePasses}/${requiredGates.length || gates.gates.length} required gates passing`,
|
|
132
|
+
target: "100% required gates passing",
|
|
133
|
+
actual: requiredGatePercent,
|
|
134
|
+
unit: "percent",
|
|
135
|
+
pass: gates.ok,
|
|
136
|
+
command: "kage benchmark --project . --json",
|
|
137
|
+
next_action: gates.ok ? "Keep this green before handoff, README updates, or release." : "Fix failing repo benchmark gates before sharing this memory state.",
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
};
|
|
141
|
+
}
|
|
37
142
|
function statusPath(projectDir) {
|
|
38
143
|
return (0, node_path_1.join)(daemonDir(projectDir), "status.json");
|
|
39
144
|
}
|
|
@@ -64,6 +169,83 @@ function readBody(req) {
|
|
|
64
169
|
req.on("error", reject);
|
|
65
170
|
});
|
|
66
171
|
}
|
|
172
|
+
function stringArray(value) {
|
|
173
|
+
if (Array.isArray(value))
|
|
174
|
+
return value.map(String).filter(Boolean);
|
|
175
|
+
if (typeof value === "string")
|
|
176
|
+
return value.split(",").map((item) => item.trim()).filter(Boolean);
|
|
177
|
+
return [];
|
|
178
|
+
}
|
|
179
|
+
function filePathHints(query) {
|
|
180
|
+
const matches = query.match(/[A-Za-z0-9_./@-]+\.(?:ts|tsx|js|jsx|mjs|cjs|py|go|rs|java|kt|kts|rb|php|cs|c|h|cc|cpp|hpp|swift|json|md)\b/g) ?? [];
|
|
181
|
+
return [...new Set(matches.map((match) => match.replace(/^\.\//, "")).filter((match) => !/^https?:\/\//.test(match)))];
|
|
182
|
+
}
|
|
183
|
+
function wantsDependencyPath(query) {
|
|
184
|
+
return /\b(connect|connected|dependency|depend|depends|path|impact|flow|trace)\b/i.test(query);
|
|
185
|
+
}
|
|
186
|
+
function riskContextBlock(result) {
|
|
187
|
+
const targets = Object.values(result.targets);
|
|
188
|
+
if (!targets.length)
|
|
189
|
+
return "";
|
|
190
|
+
const lines = targets.slice(0, 5).map((item) => {
|
|
191
|
+
const coChange = item.git.co_change_partners.length
|
|
192
|
+
? ` Co-change: ${item.git.co_change_partners.slice(0, 3).map((partner) => `${partner.file_path} (${partner.count})`).join(", ")}.`
|
|
193
|
+
: "";
|
|
194
|
+
return `- ${item.risk_summary}${coChange}`;
|
|
195
|
+
});
|
|
196
|
+
return `\n## Risk Signals\n${lines.join("\n")}`;
|
|
197
|
+
}
|
|
198
|
+
function daemonContextReport(projectDir, body) {
|
|
199
|
+
const query = String(body.query ?? "");
|
|
200
|
+
const limit = Number(body.limit ?? 5);
|
|
201
|
+
const validation = (0, kernel_js_1.validateProject)(projectDir);
|
|
202
|
+
const recallResult = (0, kernel_js_1.recall)(projectDir, query, limit, Boolean(body.explain));
|
|
203
|
+
const graphResult = (0, kernel_js_1.queryGraph)(projectDir, query, 5);
|
|
204
|
+
const explicitTargets = [...stringArray(body.targets), ...filePathHints(query)];
|
|
205
|
+
const changedFiles = stringArray(body.changed_files);
|
|
206
|
+
const riskResult = explicitTargets.length || changedFiles.length ? (0, kernel_js_1.kageRisk)(projectDir, explicitTargets, changedFiles) : null;
|
|
207
|
+
const pathHints = filePathHints(query);
|
|
208
|
+
const dependencyResult = wantsDependencyPath(query) && pathHints.length >= 2
|
|
209
|
+
? (0, kernel_js_1.kageDependencyPath)(projectDir, pathHints[0], pathHints[1])
|
|
210
|
+
: null;
|
|
211
|
+
const reconciliation = (0, kernel_js_1.kageMemoryReconciliation)(projectDir, {
|
|
212
|
+
sessionId: typeof body.session_id === "string" ? body.session_id : undefined,
|
|
213
|
+
limit: 5,
|
|
214
|
+
});
|
|
215
|
+
const teammateBrief = (0, kernel_js_1.kageTeammateBrief)(projectDir, {
|
|
216
|
+
query,
|
|
217
|
+
targets: explicitTargets,
|
|
218
|
+
changedFiles,
|
|
219
|
+
recallResult,
|
|
220
|
+
riskResult,
|
|
221
|
+
reconciliation,
|
|
222
|
+
});
|
|
223
|
+
const learningLedger = typeof body.session_id === "string" && body.session_id.trim()
|
|
224
|
+
? (0, kernel_js_1.kageSessionLearningLedger)(projectDir, { sessionId: body.session_id, limit: 20 })
|
|
225
|
+
: null;
|
|
226
|
+
const validationText = validation.ok ? "Memory healthy." : `Warnings: ${validation.warnings.join("; ")}`;
|
|
227
|
+
const contextBlock = [
|
|
228
|
+
recallResult.context_block,
|
|
229
|
+
teammateBrief.context_block,
|
|
230
|
+
learningLedger ? learningLedger.context_block : "",
|
|
231
|
+
graphResult.context_block ? `\n## Graph Facts\n${graphResult.context_block}` : "",
|
|
232
|
+
riskResult ? riskContextBlock(riskResult) : "",
|
|
233
|
+
dependencyResult ? `\n## Dependency Path\n${dependencyResult.summary}${dependencyResult.path.length ? `\nPath: ${dependencyResult.path.join(" -> ")}` : ""}` : "",
|
|
234
|
+
reconciliation.unresolved_count ? `\n## Memory Reconciliation\n${reconciliation.agent_instruction}` : "",
|
|
235
|
+
`\n_${validationText}_`,
|
|
236
|
+
].filter(Boolean).join("");
|
|
237
|
+
return {
|
|
238
|
+
context_block: contextBlock,
|
|
239
|
+
recall: recallResult,
|
|
240
|
+
graph: graphResult,
|
|
241
|
+
teammate_brief: teammateBrief,
|
|
242
|
+
learning_ledger: learningLedger,
|
|
243
|
+
risk: riskResult,
|
|
244
|
+
dependency_path: dependencyResult,
|
|
245
|
+
validation,
|
|
246
|
+
memory_reconciliation: reconciliation,
|
|
247
|
+
};
|
|
248
|
+
}
|
|
67
249
|
function readDaemonStatus(projectDir) {
|
|
68
250
|
const path = statusPath(projectDir);
|
|
69
251
|
if (!(0, node_fs_1.existsSync)(path))
|
|
@@ -93,9 +275,22 @@ function daemonDoctor(projectDir) {
|
|
|
93
275
|
status,
|
|
94
276
|
endpoints: [
|
|
95
277
|
`GET http://${DEFAULT_HOST}:${restPort}/health`,
|
|
278
|
+
`POST http://${DEFAULT_HOST}:${restPort}/kage/context`,
|
|
96
279
|
`POST http://${DEFAULT_HOST}:${restPort}/kage/recall`,
|
|
280
|
+
`POST http://${DEFAULT_HOST}:${restPort}/kage/capture`,
|
|
281
|
+
`POST http://${DEFAULT_HOST}:${restPort}/kage/learn`,
|
|
282
|
+
`POST http://${DEFAULT_HOST}:${restPort}/kage/feedback`,
|
|
97
283
|
`POST http://${DEFAULT_HOST}:${restPort}/kage/observe`,
|
|
98
284
|
`POST http://${DEFAULT_HOST}:${restPort}/kage/distill`,
|
|
285
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/learning-ledger`,
|
|
286
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/replay`,
|
|
287
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/setup-doctor`,
|
|
288
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/profile`,
|
|
289
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/xray`,
|
|
290
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/capabilities`,
|
|
291
|
+
`GET http://${DEFAULT_HOST}:${restPort}/kage/context-slots`,
|
|
292
|
+
`POST http://${DEFAULT_HOST}:${restPort}/kage/context-slots`,
|
|
293
|
+
`DELETE http://${DEFAULT_HOST}:${restPort}/kage/context-slots/:label`,
|
|
99
294
|
`GET http://${DEFAULT_HOST}:${restPort}/kage/metrics`,
|
|
100
295
|
`GET http://${DEFAULT_HOST}:${restPort}/kage/quality`,
|
|
101
296
|
`GET http://${DEFAULT_HOST}:${restPort}/kage/inbox`,
|
|
@@ -187,12 +382,71 @@ async function startDaemon(projectDir, options = {}) {
|
|
|
187
382
|
json(res, 200, (0, kernel_js_1.qualityReport)(projectDir));
|
|
188
383
|
return;
|
|
189
384
|
}
|
|
385
|
+
if (req.method === "GET" && url.pathname === "/kage/profile") {
|
|
386
|
+
json(res, 200, (0, kernel_js_1.kageProjectProfile)(projectDir));
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (req.method === "GET" && url.pathname === "/kage/xray") {
|
|
390
|
+
json(res, 200, (0, kernel_js_1.kageRepoXray)(projectDir));
|
|
391
|
+
return;
|
|
392
|
+
}
|
|
393
|
+
if (req.method === "GET" && url.pathname === "/kage/capabilities") {
|
|
394
|
+
json(res, 200, (0, kernel_js_1.kageCapabilityAudit)(projectDir));
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
if (req.method === "GET" && url.pathname === "/kage/replay") {
|
|
398
|
+
json(res, 200, (0, kernel_js_1.kageSessionReplay)(projectDir, {
|
|
399
|
+
sessionId: url.searchParams.get("session") ?? undefined,
|
|
400
|
+
limit: Number(url.searchParams.get("limit") ?? 200),
|
|
401
|
+
}));
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
404
|
+
if (req.method === "GET" && url.pathname === "/kage/learning-ledger") {
|
|
405
|
+
json(res, 200, (0, kernel_js_1.kageSessionLearningLedger)(projectDir, {
|
|
406
|
+
sessionId: url.searchParams.get("session") ?? undefined,
|
|
407
|
+
limit: Number(url.searchParams.get("limit") ?? 50),
|
|
408
|
+
}));
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
if (req.method === "GET" && url.pathname === "/kage/context-slots") {
|
|
412
|
+
json(res, 200, (0, kernel_js_1.kageContextSlots)(projectDir));
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
if (req.method === "GET" && url.pathname === "/kage/lifecycle") {
|
|
416
|
+
json(res, 200, (0, kernel_js_1.kageMemoryLifecycle)(projectDir));
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
if (req.method === "GET" && url.pathname === "/kage/memory-audit") {
|
|
420
|
+
json(res, 200, (0, kernel_js_1.kageMemoryAudit)(projectDir, Number(url.searchParams.get("limit") ?? 100)));
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
if (req.method === "GET" && url.pathname === "/kage/handoff") {
|
|
424
|
+
json(res, 200, (0, kernel_js_1.kageMemoryHandoff)(projectDir));
|
|
425
|
+
return;
|
|
426
|
+
}
|
|
427
|
+
if (req.method === "GET" && url.pathname === "/kage/timeline") {
|
|
428
|
+
json(res, 200, (0, kernel_js_1.kageMemoryTimeline)(projectDir, Number(url.searchParams.get("days") ?? 14)));
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
if (req.method === "GET" && url.pathname === "/kage/lineage") {
|
|
432
|
+
json(res, 200, (0, kernel_js_1.kageMemoryLineage)(projectDir));
|
|
433
|
+
return;
|
|
434
|
+
}
|
|
190
435
|
if (req.method === "GET" && url.pathname === "/kage/inbox") {
|
|
191
436
|
json(res, 200, (0, kernel_js_1.memoryInbox)(projectDir));
|
|
192
437
|
return;
|
|
193
438
|
}
|
|
194
439
|
if (req.method === "GET" && url.pathname === "/kage/benchmark") {
|
|
195
|
-
json(res, 200, (0, kernel_js_1.benchmarkProject)(projectDir));
|
|
440
|
+
json(res, 200, url.searchParams.get("mode") === "memory_quality" ? (0, kernel_js_1.benchmarkCodingMemoryQuality)() : (0, kernel_js_1.benchmarkProject)(projectDir));
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
if (req.method === "GET" && url.pathname === "/kage/setup-doctor") {
|
|
444
|
+
json(res, 200, (0, kernel_js_1.setupDoctor)(projectDir));
|
|
445
|
+
return;
|
|
446
|
+
}
|
|
447
|
+
if (req.method === "POST" && url.pathname === "/kage/context") {
|
|
448
|
+
const body = await readBody(req);
|
|
449
|
+
json(res, 200, daemonContextReport(projectDir, body));
|
|
196
450
|
return;
|
|
197
451
|
}
|
|
198
452
|
if (req.method === "POST" && url.pathname === "/kage/recall") {
|
|
@@ -200,6 +454,63 @@ async function startDaemon(projectDir, options = {}) {
|
|
|
200
454
|
json(res, 200, (0, kernel_js_1.recall)(projectDir, String(body.query ?? ""), Number(body.limit ?? 5), Boolean(body.explain)));
|
|
201
455
|
return;
|
|
202
456
|
}
|
|
457
|
+
if (req.method === "POST" && url.pathname === "/kage/capture") {
|
|
458
|
+
const body = await readBody(req);
|
|
459
|
+
const result = (0, kernel_js_1.capture)({
|
|
460
|
+
projectDir,
|
|
461
|
+
title: String(body.title ?? ""),
|
|
462
|
+
summary: body.summary == null ? undefined : String(body.summary),
|
|
463
|
+
body: String(body.body ?? body.learning ?? ""),
|
|
464
|
+
type: body.type == null ? undefined : String(body.type),
|
|
465
|
+
tags: stringArray(body.tags),
|
|
466
|
+
paths: stringArray(body.paths),
|
|
467
|
+
stack: stringArray(body.stack),
|
|
468
|
+
});
|
|
469
|
+
json(res, result.ok ? 200 : 400, result);
|
|
470
|
+
return;
|
|
471
|
+
}
|
|
472
|
+
if (req.method === "POST" && url.pathname === "/kage/learn") {
|
|
473
|
+
const body = await readBody(req);
|
|
474
|
+
const result = (0, kernel_js_1.learn)({
|
|
475
|
+
projectDir,
|
|
476
|
+
learning: String(body.learning ?? body.body ?? ""),
|
|
477
|
+
title: body.title == null ? undefined : String(body.title),
|
|
478
|
+
type: body.type == null ? undefined : String(body.type),
|
|
479
|
+
evidence: body.evidence == null ? undefined : String(body.evidence),
|
|
480
|
+
verifiedBy: body.verified_by == null ? body.verifiedBy == null ? undefined : String(body.verifiedBy) : String(body.verified_by),
|
|
481
|
+
tags: stringArray(body.tags),
|
|
482
|
+
paths: stringArray(body.paths),
|
|
483
|
+
stack: stringArray(body.stack),
|
|
484
|
+
});
|
|
485
|
+
json(res, result.ok ? 200 : 400, result);
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
if (req.method === "POST" && url.pathname === "/kage/feedback") {
|
|
489
|
+
const body = await readBody(req);
|
|
490
|
+
const result = (0, kernel_js_1.recordFeedback)(projectDir, String(body.packet_id ?? body.packet ?? ""), String(body.kind ?? ""));
|
|
491
|
+
json(res, result.ok ? 200 : 400, result);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
if (req.method === "POST" && url.pathname === "/kage/context-slots") {
|
|
495
|
+
const body = await readBody(req);
|
|
496
|
+
const result = (0, kernel_js_1.setContextSlot)(projectDir, {
|
|
497
|
+
label: String(body.label ?? ""),
|
|
498
|
+
content: String(body.content ?? ""),
|
|
499
|
+
description: body.description == null ? undefined : String(body.description),
|
|
500
|
+
pinned: body.pinned == null ? undefined : Boolean(body.pinned),
|
|
501
|
+
size_limit: body.size_limit == null ? undefined : Number(body.size_limit),
|
|
502
|
+
paths: stringArray(body.paths),
|
|
503
|
+
tags: stringArray(body.tags),
|
|
504
|
+
});
|
|
505
|
+
json(res, result.ok ? 200 : 400, result);
|
|
506
|
+
return;
|
|
507
|
+
}
|
|
508
|
+
if (req.method === "DELETE" && url.pathname.startsWith("/kage/context-slots/")) {
|
|
509
|
+
const label = decodeURIComponent(url.pathname.slice("/kage/context-slots/".length));
|
|
510
|
+
const result = (0, kernel_js_1.deleteContextSlot)(projectDir, label);
|
|
511
|
+
json(res, result.ok ? 200 : 404, result);
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
203
514
|
if (req.method === "POST" && url.pathname === "/kage/observe") {
|
|
204
515
|
const body = await readBody(req);
|
|
205
516
|
json(res, 200, (0, kernel_js_1.observe)(projectDir, body));
|
|
@@ -244,11 +555,24 @@ async function startViewer(projectDir, options = {}) {
|
|
|
244
555
|
const qualityPath = (0, node_path_1.join)(reportsDir, "quality.json");
|
|
245
556
|
const benchmarkPath = (0, node_path_1.join)(reportsDir, "benchmark.json");
|
|
246
557
|
const contributorsPath = (0, node_path_1.join)(reportsDir, "contributors.json");
|
|
558
|
+
const profilePath = (0, node_path_1.join)(reportsDir, "profile.json");
|
|
559
|
+
const xrayPath = (0, node_path_1.join)(reportsDir, "xray.json");
|
|
560
|
+
const capabilitiesPath = (0, node_path_1.join)(reportsDir, "capabilities.json");
|
|
561
|
+
const slotsPath = (0, node_path_1.join)(reportsDir, "context-slots.json");
|
|
247
562
|
const decisionsPath = (0, node_path_1.join)(reportsDir, "decisions.json");
|
|
248
563
|
const riskPath = (0, node_path_1.join)(reportsDir, "risk.json");
|
|
249
564
|
const moduleHealthPath = (0, node_path_1.join)(reportsDir, "module-health.json");
|
|
250
565
|
const graphInsightsPath = (0, node_path_1.join)(reportsDir, "graph-insights.json");
|
|
251
566
|
const workspacePath = (0, node_path_1.join)(reportsDir, "workspace.json");
|
|
567
|
+
const sessionsPath = (0, node_path_1.join)(reportsDir, "sessions.json");
|
|
568
|
+
const replayPath = (0, node_path_1.join)(reportsDir, "replay.json");
|
|
569
|
+
const memoryAccessPath = (0, node_path_1.join)(reportsDir, "memory-access.json");
|
|
570
|
+
const memoryAuditPath = (0, node_path_1.join)(reportsDir, "memory-audit.json");
|
|
571
|
+
const handoffPath = (0, node_path_1.join)(reportsDir, "handoff.json");
|
|
572
|
+
const lifecyclePath = (0, node_path_1.join)(reportsDir, "lifecycle.json");
|
|
573
|
+
const timelinePath = (0, node_path_1.join)(reportsDir, "timeline.json");
|
|
574
|
+
const lineagePath = (0, node_path_1.join)(reportsDir, "lineage.json");
|
|
575
|
+
const setupPath = (0, node_path_1.join)(reportsDir, "setup.json");
|
|
252
576
|
// Pre-generate lightweight JSON reports so the viewer can load them directly.
|
|
253
577
|
try {
|
|
254
578
|
(0, node_fs_1.mkdirSync)(reportsDir, { recursive: true });
|
|
@@ -257,24 +581,37 @@ async function startViewer(projectDir, options = {}) {
|
|
|
257
581
|
const inbox = (0, kernel_js_1.memoryInbox)(projectDir);
|
|
258
582
|
(0, node_fs_1.writeFileSync)(inboxPath, JSON.stringify(inbox, null, 2));
|
|
259
583
|
(0, node_fs_1.writeFileSync)(qualityPath, JSON.stringify((0, kernel_js_1.qualityReport)(projectDir), null, 2));
|
|
260
|
-
(0, node_fs_1.writeFileSync)(benchmarkPath, JSON.stringify((
|
|
584
|
+
(0, node_fs_1.writeFileSync)(benchmarkPath, JSON.stringify(viewerBenchmarkReport(projectDir), null, 2));
|
|
261
585
|
(0, node_fs_1.writeFileSync)(contributorsPath, JSON.stringify((0, kernel_js_1.kageContributors)(projectDir), null, 2));
|
|
586
|
+
(0, node_fs_1.writeFileSync)(profilePath, JSON.stringify((0, kernel_js_1.kageProjectProfile)(projectDir), null, 2));
|
|
587
|
+
(0, node_fs_1.writeFileSync)(xrayPath, JSON.stringify((0, kernel_js_1.kageRepoXray)(projectDir), null, 2));
|
|
588
|
+
(0, node_fs_1.writeFileSync)(capabilitiesPath, JSON.stringify((0, kernel_js_1.kageCapabilityAudit)(projectDir), null, 2));
|
|
589
|
+
(0, node_fs_1.writeFileSync)(slotsPath, JSON.stringify((0, kernel_js_1.kageContextSlots)(projectDir), null, 2));
|
|
262
590
|
(0, node_fs_1.writeFileSync)(decisionsPath, JSON.stringify((0, kernel_js_1.kageDecisionIntelligence)(projectDir), null, 2));
|
|
263
591
|
(0, node_fs_1.writeFileSync)(riskPath, JSON.stringify((0, kernel_js_1.kageRisk)(projectDir), null, 2));
|
|
264
592
|
(0, node_fs_1.writeFileSync)(moduleHealthPath, JSON.stringify((0, kernel_js_1.kageModuleHealth)(projectDir), null, 2));
|
|
265
593
|
(0, node_fs_1.writeFileSync)(graphInsightsPath, JSON.stringify((0, kernel_js_1.kageGraphInsights)(projectDir), null, 2));
|
|
266
594
|
(0, node_fs_1.writeFileSync)(workspacePath, JSON.stringify((0, kernel_js_1.kageWorkspace)(projectDir), null, 2));
|
|
595
|
+
(0, node_fs_1.writeFileSync)(sessionsPath, JSON.stringify((0, kernel_js_1.kageSessionCaptureReport)(projectDir), null, 2));
|
|
596
|
+
(0, node_fs_1.writeFileSync)(replayPath, JSON.stringify((0, kernel_js_1.kageSessionReplay)(projectDir), null, 2));
|
|
597
|
+
(0, node_fs_1.writeFileSync)(memoryAccessPath, JSON.stringify((0, kernel_js_1.kageMemoryAccess)(projectDir), null, 2));
|
|
598
|
+
(0, node_fs_1.writeFileSync)(memoryAuditPath, JSON.stringify((0, kernel_js_1.kageMemoryAudit)(projectDir), null, 2));
|
|
599
|
+
(0, node_fs_1.writeFileSync)(handoffPath, JSON.stringify((0, kernel_js_1.kageMemoryHandoff)(projectDir), null, 2));
|
|
600
|
+
(0, node_fs_1.writeFileSync)(lifecyclePath, JSON.stringify((0, kernel_js_1.kageMemoryLifecycle)(projectDir), null, 2));
|
|
601
|
+
(0, node_fs_1.writeFileSync)(timelinePath, JSON.stringify((0, kernel_js_1.kageMemoryTimeline)(projectDir), null, 2));
|
|
602
|
+
(0, node_fs_1.writeFileSync)(lineagePath, JSON.stringify((0, kernel_js_1.kageMemoryLineage)(projectDir), null, 2));
|
|
603
|
+
(0, node_fs_1.writeFileSync)(setupPath, JSON.stringify((0, kernel_js_1.setupDoctor)(projectDir), null, 2));
|
|
267
604
|
}
|
|
268
605
|
catch {
|
|
269
606
|
// non-fatal: viewer will show 404 for reports if generation fails
|
|
270
607
|
}
|
|
271
|
-
const url = `http://${host}:${port}/viewer/index.html?graph=${encodeURIComponent(graphPath)}&code=${encodeURIComponent(codePath)}&metrics=${encodeURIComponent(metricsPath)}&inbox=${encodeURIComponent(inboxPath)}&review=${encodeURIComponent(reviewPath)}&pending=${encodeURIComponent(pendingDir)}&quality=${encodeURIComponent(qualityPath)}&benchmark=${encodeURIComponent(benchmarkPath)}&contributors=${encodeURIComponent(contributorsPath)}&decisions=${encodeURIComponent(decisionsPath)}&risk=${encodeURIComponent(riskPath)}&moduleHealth=${encodeURIComponent(moduleHealthPath)}&graphInsights=${encodeURIComponent(graphInsightsPath)}&workspace=${encodeURIComponent(workspacePath)}&view=code`;
|
|
608
|
+
const url = `http://${host}:${port}/viewer/index.html?graph=${encodeURIComponent(graphPath)}&code=${encodeURIComponent(codePath)}&metrics=${encodeURIComponent(metricsPath)}&inbox=${encodeURIComponent(inboxPath)}&review=${encodeURIComponent(reviewPath)}&pending=${encodeURIComponent(pendingDir)}&quality=${encodeURIComponent(qualityPath)}&benchmark=${encodeURIComponent(benchmarkPath)}&contributors=${encodeURIComponent(contributorsPath)}&profile=${encodeURIComponent(profilePath)}&xray=${encodeURIComponent(xrayPath)}&capabilities=${encodeURIComponent(capabilitiesPath)}&slots=${encodeURIComponent(slotsPath)}&decisions=${encodeURIComponent(decisionsPath)}&risk=${encodeURIComponent(riskPath)}&moduleHealth=${encodeURIComponent(moduleHealthPath)}&graphInsights=${encodeURIComponent(graphInsightsPath)}&workspace=${encodeURIComponent(workspacePath)}&sessions=${encodeURIComponent(sessionsPath)}&replay=${encodeURIComponent(replayPath)}&memoryAccess=${encodeURIComponent(memoryAccessPath)}&memoryAudit=${encodeURIComponent(memoryAuditPath)}&handoff=${encodeURIComponent(handoffPath)}&lifecycle=${encodeURIComponent(lifecyclePath)}&timeline=${encodeURIComponent(timelinePath)}&lineage=${encodeURIComponent(lineagePath)}&setup=${encodeURIComponent(setupPath)}&view=code`;
|
|
272
609
|
const server = (0, node_http_1.createServer)((req, res) => {
|
|
273
610
|
const requestUrl = new URL(req.url ?? "/", `http://${host}:${port}`);
|
|
274
611
|
let filePath = null;
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
res.writeHead(302, { location:
|
|
612
|
+
const redirectLocation = viewerRedirectLocation(requestUrl.pathname, requestUrl.search, new URL(url).search);
|
|
613
|
+
if (redirectLocation) {
|
|
614
|
+
res.writeHead(302, { location: redirectLocation });
|
|
278
615
|
res.end();
|
|
279
616
|
return;
|
|
280
617
|
}
|
|
@@ -303,7 +640,7 @@ async function startViewer(projectDir, options = {}) {
|
|
|
303
640
|
json(res, 200, { ok: true, files });
|
|
304
641
|
return;
|
|
305
642
|
}
|
|
306
|
-
res.writeHead(200,
|
|
643
|
+
res.writeHead(200, viewerStaticHeaders(filePath));
|
|
307
644
|
res.end((0, node_fs_1.readFileSync)(filePath));
|
|
308
645
|
});
|
|
309
646
|
await new Promise((resolveListen) => server.listen(port, host, resolveListen));
|