@kage-core/kage-graph-mcp 2.3.0 → 2.3.2
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/LICENSE +674 -0
- package/dist/cli.js +95 -15
- package/dist/index.js +56 -31
- package/dist/kernel.js +621 -45
- package/package.json +2 -2
- package/viewer/console.js +69 -2
- package/viewer/index.html +12 -3
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kage-core/kage-graph-mcp",
|
|
3
|
-
"version": "2.3.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "2.3.2",
|
|
4
|
+
"description": "Team memory for coding agents: captures the decisions, runbooks, and bug fixes that get lost, verified against your code and shared via git. MCP server, zero deps, no account.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist/**/*.js",
|
package/viewer/console.js
CHANGED
|
@@ -66,6 +66,7 @@
|
|
|
66
66
|
|
|
67
67
|
// ---- nav ----
|
|
68
68
|
var META = {
|
|
69
|
+
dashboard: ["kage://dashboard", "Dashboard", "Your team's captured knowledge — decisions, runbooks, and fixes — at a glance."],
|
|
69
70
|
gains: ["kage://gains", "What Kage saved you", "Tokens, dollars, and bad memories caught — receipts, not vibes."],
|
|
70
71
|
overview: ["kage://trust", "Memory trust", "Whether this repo's agent memory can be trusted — at a glance."],
|
|
71
72
|
graph: ["kage://memory-map", "Memory ↔ code map", "Each packet anchored to the files it's grounded in. Hover a node to inspect."],
|
|
@@ -90,8 +91,29 @@
|
|
|
90
91
|
});
|
|
91
92
|
|
|
92
93
|
// ---- load ----
|
|
94
|
+
// Showcase mode: the bundled demo dataset (docs/viewer/data) carries showcase:true.
|
|
95
|
+
// Its timestamps are frozen, so we slide them forward to "now" on load — the daily
|
|
96
|
+
// chart and the feed stay current instead of aging into an empty 14-day window.
|
|
97
|
+
// Real daemon data has no showcase flag and is never touched.
|
|
98
|
+
function rebaseShowcase(activity, value) {
|
|
99
|
+
if (!activity || !activity.showcase) return;
|
|
100
|
+
var allAt = [];
|
|
101
|
+
(activity.events || []).forEach(function (e) { if (e.at) allAt.push(Date.parse(e.at)); });
|
|
102
|
+
if (value && value.events) value.events.forEach(function (e) { if (e.at) allAt.push(Date.parse(e.at)); });
|
|
103
|
+
var latest = allAt.length ? Math.max.apply(null, allAt) : 0;
|
|
104
|
+
if (!latest) return;
|
|
105
|
+
var delta = Date.now() - latest;
|
|
106
|
+
var dayDelta = Math.round(delta / 86400000);
|
|
107
|
+
function shift(e) { if (e && e.at) e.at = new Date(Date.parse(e.at) + delta).toISOString(); }
|
|
108
|
+
(activity.events || []).forEach(shift);
|
|
109
|
+
if (value && value.events) value.events.forEach(shift);
|
|
110
|
+
(activity.daily || []).forEach(function (d) {
|
|
111
|
+
if (d.day) d.day = new Date(Date.parse(d.day + "T00:00:00Z") + dayDelta * 86400000).toISOString().slice(0, 10);
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
93
115
|
Promise.all([getJSON(paths.trust), getJSON(paths.suppressed), getJSON(paths.lifecycle), getJSON(paths.metrics), getJSON(paths.activity), getJSON(paths.value)])
|
|
94
|
-
.then(function (r) { render(r[0], r[1], r[2], r[3], r[4], r[5]); })
|
|
116
|
+
.then(function (r) { rebaseShowcase(r[4], r[5]); render(r[0], r[1], r[2], r[3], r[4], r[5]); })
|
|
95
117
|
.catch(function () { render(null, null, null, null, null, null); });
|
|
96
118
|
|
|
97
119
|
function render(trust, suppressed, lifecycle, metrics, activity, value) {
|
|
@@ -102,12 +124,13 @@
|
|
|
102
124
|
renderGains(value);
|
|
103
125
|
renderHero(trust);
|
|
104
126
|
renderTiles(metrics, state.items);
|
|
127
|
+
renderDashboard(metrics, state.items, value);
|
|
105
128
|
renderAttention(state.items, suppressed);
|
|
106
129
|
renderChips(); renderList();
|
|
107
130
|
renderInsights(metrics, state.items);
|
|
108
131
|
renderActivity(activity);
|
|
109
132
|
var start = (location.hash || "").replace("#", "");
|
|
110
|
-
show(META[start] ? start : "
|
|
133
|
+
show(META[start] ? start : "dashboard");
|
|
111
134
|
}
|
|
112
135
|
|
|
113
136
|
// ---- gains (value ledger receipts) ----
|
|
@@ -320,6 +343,50 @@
|
|
|
320
343
|
function counts(items) {
|
|
321
344
|
var c = {}; items.forEach(function (i) { c[i.health] = (c[i.health] || 0) + 1; }); return c;
|
|
322
345
|
}
|
|
346
|
+
// ---- dashboard (landing overview: what the team has captured, at a glance) ----
|
|
347
|
+
function renderDashboard(metrics, items, value) {
|
|
348
|
+
var cg = (metrics && metrics.code_graph) || {};
|
|
349
|
+
var c = counts(items);
|
|
350
|
+
var types = {}; items.forEach(function (i) { var t = i.type || "memory"; types[t] = (types[t] || 0) + 1; });
|
|
351
|
+
var ev = (value && value.events) || [];
|
|
352
|
+
var totals = (value && value.totals) || summarizeWindow(ev, 0);
|
|
353
|
+
var box = document.getElementById("dashTiles");
|
|
354
|
+
if (box) {
|
|
355
|
+
box.textContent = "";
|
|
356
|
+
[
|
|
357
|
+
{ k: "Memory packets", v: fmt(items.length), s: (c.hot || 0) + " hot · " + (c.healthy || 0) + " healthy", cls: "memory" },
|
|
358
|
+
{ k: "Decisions", v: fmt(types.decision || 0), s: "why the code is the way it is", cls: "code" },
|
|
359
|
+
{ k: "Runbooks & fixes", v: fmt((types.runbook || 0) + (types.bug_fix || 0) + (types.workflow || 0)), s: "how to run it · how it broke", cls: "green" },
|
|
360
|
+
{ k: "Recalls served", v: fmt(totals.recalls || 0), s: (totals.recalls ? "memory reused, not re-derived" : "recall to start the ledger"), cls: "green" },
|
|
361
|
+
].forEach(function (d) { var t = el("div", "tile"); t.appendChild(el("div", "k", d.k)); t.appendChild(el("div", "v " + (d.cls || ""), d.v)); t.appendChild(el("div", "s", d.s)); box.appendChild(t); });
|
|
362
|
+
}
|
|
363
|
+
var cap = document.getElementById("dashCaptures");
|
|
364
|
+
if (cap) {
|
|
365
|
+
cap.textContent = "";
|
|
366
|
+
// Prefer human-readable captures: skip auto-distilled packets whose titles are
|
|
367
|
+
// raw ids / JSON fragments (start with a non-letter, or contain { } < >).
|
|
368
|
+
var clean = items.filter(function (i) { var t = (i.title || "").trim(); return /^[A-Za-z]/.test(t) && !/[{}<>]/.test(t); });
|
|
369
|
+
var pool = clean.length >= 5 ? clean : items;
|
|
370
|
+
var recent = pool.slice().sort(function (a, b) {
|
|
371
|
+
return (Date.parse(b.created_at || b.updated_at || 0) || 0) - (Date.parse(a.created_at || a.updated_at || 0) || 0);
|
|
372
|
+
}).slice(0, 7);
|
|
373
|
+
if (!recent.length) cap.appendChild(el("div", "empty", "No memory captured yet. As your agents work, decisions and fixes land here."));
|
|
374
|
+
else recent.forEach(function (i) { cap.appendChild(memoryRow(i)); });
|
|
375
|
+
}
|
|
376
|
+
var tb = document.getElementById("dashTypeBars");
|
|
377
|
+
if (tb) {
|
|
378
|
+
tb.textContent = "";
|
|
379
|
+
var arr = Object.keys(types).map(function (k) { return [k, types[k]]; }).sort(function (a, b) { return b[1] - a[1]; }).slice(0, 7);
|
|
380
|
+
var max = arr.length ? arr[0][1] : 1;
|
|
381
|
+
if (!arr.length) tb.appendChild(el("div", "empty", "No memory yet."));
|
|
382
|
+
arr.forEach(function (p) {
|
|
383
|
+
var row = el("div", "hbar"); row.appendChild(el("span", "n", p[0]));
|
|
384
|
+
var t = el("span", "t"), f = el("i"); t.appendChild(f); row.appendChild(t); row.appendChild(el("span", "c", String(p[1])));
|
|
385
|
+
tb.appendChild(row); setTimeout(function () { f.style.width = (p[1] / max * 100) + "%"; }, 80);
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
|
|
323
390
|
function renderTiles(metrics, items) {
|
|
324
391
|
var cg = (metrics && metrics.code_graph) || {};
|
|
325
392
|
var act = (state.activity && state.activity.totals) || {};
|
package/viewer/index.html
CHANGED
|
@@ -270,7 +270,8 @@
|
|
|
270
270
|
<div class="brand"><span class="mark">K</span> Kage</div>
|
|
271
271
|
<div class="repocard"><span class="eyebrow">Repository</span><strong id="repo">loading…</strong></div>
|
|
272
272
|
<nav class="nav" id="nav">
|
|
273
|
-
<button data-section="
|
|
273
|
+
<button data-section="dashboard" aria-current="true"><span class="ic">⊞</span> Dashboard</button>
|
|
274
|
+
<button data-section="gains"><span class="ic">⊕</span> Gains</button>
|
|
274
275
|
<button data-section="overview"><span class="ic">◎</span> Trust</button>
|
|
275
276
|
<button data-section="graph"><span class="ic">⬡</span> Memory map</button>
|
|
276
277
|
<button data-section="memory"><span class="ic">▤</span> Memory</button>
|
|
@@ -292,7 +293,15 @@
|
|
|
292
293
|
<p id="subtitle">Tokens, dollars, and bad memories caught — receipts, not vibes.</p>
|
|
293
294
|
</header>
|
|
294
295
|
<div class="wrap">
|
|
295
|
-
<section class="section active" id="section-
|
|
296
|
+
<section class="section active" id="section-dashboard">
|
|
297
|
+
<div class="tiles" id="dashTiles"></div>
|
|
298
|
+
<div class="ins-grid">
|
|
299
|
+
<div class="panel"><h2>Recent captures <span class="sub">— newest knowledge your agents saved</span></h2><div id="dashCaptures"></div></div>
|
|
300
|
+
<div class="panel"><h2>Memory by type</h2><div class="hbars" id="dashTypeBars"></div></div>
|
|
301
|
+
</div>
|
|
302
|
+
</section>
|
|
303
|
+
|
|
304
|
+
<section class="section" id="section-gains">
|
|
296
305
|
<div class="receipt" id="gainsHero"></div>
|
|
297
306
|
<div class="tiles" id="gainsTiles"></div>
|
|
298
307
|
<div class="panel" id="livePanel" hidden><h2><span class="livedot" aria-hidden="true"></span>Live <span class="sub">— memories and value events as they happen</span></h2><div id="liveFeed"></div></div>
|
|
@@ -359,6 +368,6 @@
|
|
|
359
368
|
</div>
|
|
360
369
|
<div class="drawer-backdrop" id="detailBackdrop"></div>
|
|
361
370
|
<aside class="drawer" id="detail" aria-hidden="true"></aside>
|
|
362
|
-
<script src="./console.js?v=
|
|
371
|
+
<script src="./console.js?v=18"></script>
|
|
363
372
|
</body>
|
|
364
373
|
</html>
|