peon-mem 1.0.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/LICENSE +21 -0
- package/README.md +301 -0
- package/bin/peon-mem.mjs +273 -0
- package/dist/brain.d.ts +72 -0
- package/dist/brain.js +224 -0
- package/dist/compression.d.ts +9 -0
- package/dist/compression.js +37 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.js +99 -0
- package/dist/daemon-cli.d.ts +2 -0
- package/dist/daemon-cli.js +54 -0
- package/dist/daemon.d.ts +23 -0
- package/dist/daemon.js +1078 -0
- package/dist/embedding-store.d.ts +43 -0
- package/dist/embedding-store.js +169 -0
- package/dist/embeddings.d.ts +93 -0
- package/dist/embeddings.js +345 -0
- package/dist/entities.d.ts +61 -0
- package/dist/entities.js +191 -0
- package/dist/entity-extraction.d.ts +33 -0
- package/dist/entity-extraction.js +75 -0
- package/dist/eval-metrics.d.ts +27 -0
- package/dist/eval-metrics.js +50 -0
- package/dist/evaluation.d.ts +58 -0
- package/dist/evaluation.js +244 -0
- package/dist/global-extraction.d.ts +15 -0
- package/dist/global-extraction.js +61 -0
- package/dist/global-memory.d.ts +43 -0
- package/dist/global-memory.js +306 -0
- package/dist/global-promotion.d.ts +25 -0
- package/dist/global-promotion.js +29 -0
- package/dist/hyde.d.ts +31 -0
- package/dist/hyde.js +46 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +246 -0
- package/dist/injection.d.ts +38 -0
- package/dist/injection.js +133 -0
- package/dist/logger.d.ts +17 -0
- package/dist/logger.js +63 -0
- package/dist/memory-mutations.d.ts +24 -0
- package/dist/memory-mutations.js +57 -0
- package/dist/memory-store.d.ts +194 -0
- package/dist/memory-store.js +1205 -0
- package/dist/monitor.d.ts +13 -0
- package/dist/monitor.js +977 -0
- package/dist/overview.d.ts +73 -0
- package/dist/overview.js +104 -0
- package/dist/processor.d.ts +90 -0
- package/dist/processor.js +450 -0
- package/dist/quality.d.ts +86 -0
- package/dist/quality.js +338 -0
- package/dist/recuration.d.ts +13 -0
- package/dist/recuration.js +65 -0
- package/dist/reranker.d.ts +34 -0
- package/dist/reranker.js +89 -0
- package/dist/retrieval.d.ts +106 -0
- package/dist/retrieval.js +392 -0
- package/dist/session-index.d.ts +34 -0
- package/dist/session-index.js +87 -0
- package/dist/temporal.d.ts +20 -0
- package/dist/temporal.js +62 -0
- package/dist/token-ab-monitor.d.ts +1 -0
- package/dist/token-ab-monitor.js +7 -0
- package/dist/tools.d.ts +232 -0
- package/dist/tools.js +546 -0
- package/dist/types.d.ts +169 -0
- package/dist/types.js +1 -0
- package/docs/assets/neural-universe.png +0 -0
- package/package.json +57 -0
- package/scripts/claude-peon-hook.mjs +522 -0
- package/scripts/codex-peon-hook.mjs +4 -0
- package/scripts/eval-retrieval-labeled.mjs +135 -0
- package/scripts/eval-retrieval.mjs +96 -0
- package/scripts/evaluate-peon.mjs +47 -0
- package/scripts/install-peon-stl.mjs +82 -0
- package/scripts/install-peon.mjs +318 -0
- package/scripts/lib/eval-ledger.mjs +104 -0
- package/scripts/lib/stl-classify.mjs +44 -0
- package/scripts/longmemeval-eval.mjs +144 -0
- package/scripts/peon-report.mjs +155 -0
- package/scripts/peon-stl.mjs +506 -0
- package/scripts/token-ab-monitor.html +235 -0
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Peon · Token A/B Monitor</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
--bg: #0e0e10; --bg2: #1a1a1d; --bg3: #242428;
|
|
10
|
+
--border: #2e2e33; --text: #e8e8ec; --muted: #7a7a85;
|
|
11
|
+
--green: #3dd68c; --red: #f87171; --blue: #60a5fa;
|
|
12
|
+
--yellow: #fbbf24; --purple: #a78bfa; --mono: "JetBrains Mono", "Fira Code", monospace;
|
|
13
|
+
}
|
|
14
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
15
|
+
body { background: var(--bg); color: var(--text); font-family: system-ui, sans-serif; font-size: 14px; min-height: 100vh; }
|
|
16
|
+
header { background: var(--bg2); border-bottom: 1px solid var(--border); padding: 14px 24px; display: flex; align-items: center; gap: 12px; }
|
|
17
|
+
header h1 { font-size: 16px; font-weight: 600; letter-spacing: -0.3px; }
|
|
18
|
+
header .sub { color: var(--muted); font-size: 12px; }
|
|
19
|
+
.dot { width: 8px; height: 8px; border-radius: 50%; background: var(--green); animation: pulse 2s infinite; }
|
|
20
|
+
@keyframes pulse { 0%,100%{opacity:1} 50%{opacity:0.4} }
|
|
21
|
+
main { padding: 24px; max-width: 1100px; margin: 0 auto; }
|
|
22
|
+
|
|
23
|
+
/* Project filter */
|
|
24
|
+
.filters { display: flex; gap: 10px; margin-bottom: 20px; flex-wrap: wrap; align-items: center; }
|
|
25
|
+
.filters label { color: var(--muted); font-size: 12px; }
|
|
26
|
+
select { background: var(--bg2); border: 1px solid var(--border); color: var(--text); padding: 6px 10px; border-radius: 6px; font-size: 13px; cursor: pointer; }
|
|
27
|
+
|
|
28
|
+
/* Summary cards */
|
|
29
|
+
.cards { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; margin-bottom: 28px; }
|
|
30
|
+
.card { background: var(--bg2); border: 1px solid var(--border); border-radius: 10px; padding: 20px; }
|
|
31
|
+
.card.on { border-color: #22543d; }
|
|
32
|
+
.card.off { border-color: #7f1d1d; }
|
|
33
|
+
.card-label { font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.8px; margin-bottom: 12px; }
|
|
34
|
+
.card.on .card-label { color: var(--green); }
|
|
35
|
+
.card.off .card-label { color: var(--red); }
|
|
36
|
+
.stat { margin-bottom: 10px; }
|
|
37
|
+
.stat-val { font-size: 28px; font-weight: 700; font-family: var(--mono); }
|
|
38
|
+
.stat-lbl { font-size: 11px; color: var(--muted); margin-top: 2px; }
|
|
39
|
+
.stats-row { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; margin-top: 14px; }
|
|
40
|
+
.mini-stat { background: var(--bg3); border-radius: 6px; padding: 10px; }
|
|
41
|
+
.mini-val { font-family: var(--mono); font-size: 14px; font-weight: 600; }
|
|
42
|
+
.mini-lbl { font-size: 10px; color: var(--muted); margin-top: 2px; }
|
|
43
|
+
|
|
44
|
+
/* Delta banner */
|
|
45
|
+
.delta { background: var(--bg2); border: 1px solid var(--border); border-radius: 10px; padding: 16px 20px; margin-bottom: 28px; display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
|
|
46
|
+
.delta-icon { font-size: 24px; }
|
|
47
|
+
.delta-text { flex: 1; }
|
|
48
|
+
.delta-val { font-size: 20px; font-weight: 700; font-family: var(--mono); }
|
|
49
|
+
.delta-val.saving { color: var(--green); }
|
|
50
|
+
.delta-val.costly { color: var(--red); }
|
|
51
|
+
.delta-lbl { font-size: 12px; color: var(--muted); margin-top: 2px; }
|
|
52
|
+
|
|
53
|
+
/* Sessions table */
|
|
54
|
+
.section-title { font-size: 13px; font-weight: 600; color: var(--muted); text-transform: uppercase; letter-spacing: 0.6px; margin-bottom: 12px; }
|
|
55
|
+
table { width: 100%; border-collapse: collapse; background: var(--bg2); border-radius: 10px; overflow: hidden; border: 1px solid var(--border); }
|
|
56
|
+
th { text-align: left; padding: 10px 14px; font-size: 11px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.5px; color: var(--muted); border-bottom: 1px solid var(--border); }
|
|
57
|
+
td { padding: 10px 14px; font-size: 13px; border-bottom: 1px solid var(--border); }
|
|
58
|
+
tr:last-child td { border-bottom: none; }
|
|
59
|
+
tr:hover td { background: var(--bg3); }
|
|
60
|
+
.badge { display: inline-block; padding: 2px 8px; border-radius: 4px; font-size: 11px; font-weight: 600; }
|
|
61
|
+
.badge.on { background: #14532d; color: var(--green); }
|
|
62
|
+
.badge.off { background: #450a0a; color: var(--red); }
|
|
63
|
+
.mono { font-family: var(--mono); font-size: 12px; }
|
|
64
|
+
.muted { color: var(--muted); }
|
|
65
|
+
.empty { text-align: center; padding: 48px; color: var(--muted); }
|
|
66
|
+
.proj { max-width: 200px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--muted); font-family: var(--mono); font-size: 11px; }
|
|
67
|
+
</style>
|
|
68
|
+
</head>
|
|
69
|
+
<body>
|
|
70
|
+
<header>
|
|
71
|
+
<div class="dot"></div>
|
|
72
|
+
<h1>Peon Token A/B Monitor</h1>
|
|
73
|
+
<span class="sub">Compare token usage: Peon ON vs Peon OFF</span>
|
|
74
|
+
</header>
|
|
75
|
+
<main>
|
|
76
|
+
<div class="filters">
|
|
77
|
+
<label>Project:</label>
|
|
78
|
+
<select id="proj-filter"><option value="">All projects</option></select>
|
|
79
|
+
<label style="margin-left:12px">Refresh:</label>
|
|
80
|
+
<select id="refresh-select">
|
|
81
|
+
<option value="10000">10s</option>
|
|
82
|
+
<option value="30000" selected>30s</option>
|
|
83
|
+
<option value="60000">60s</option>
|
|
84
|
+
<option value="0">Manual</option>
|
|
85
|
+
</select>
|
|
86
|
+
</div>
|
|
87
|
+
<div class="cards" id="cards">
|
|
88
|
+
<div class="card on"><div class="card-label">Peon ON</div><div class="empty muted">No data yet</div></div>
|
|
89
|
+
<div class="card off"><div class="card-label">Peon OFF</div><div class="empty muted">No data yet</div></div>
|
|
90
|
+
</div>
|
|
91
|
+
<div class="delta" id="delta" style="display:none"></div>
|
|
92
|
+
<div class="section-title">Session Log</div>
|
|
93
|
+
<table id="sessions-table">
|
|
94
|
+
<thead><tr>
|
|
95
|
+
<th>Time</th><th>Peon</th><th>Project</th><th>Input</th><th>Output</th><th>Cache Read</th><th>Cache Write</th><th>Total</th><th>Model</th>
|
|
96
|
+
</tr></thead>
|
|
97
|
+
<tbody id="sessions-body"><tr><td colspan="9" class="empty">Waiting for sessions…</td></tr></tbody>
|
|
98
|
+
</table>
|
|
99
|
+
</main>
|
|
100
|
+
<script>
|
|
101
|
+
const DAEMON = "http://127.0.0.1:3737";
|
|
102
|
+
let allRecords = [];
|
|
103
|
+
let timer = null;
|
|
104
|
+
|
|
105
|
+
function fmt(n) {
|
|
106
|
+
if (n >= 1e6) return (n/1e6).toFixed(2)+"M";
|
|
107
|
+
if (n >= 1e3) return (n/1e3).toFixed(1)+"k";
|
|
108
|
+
return String(n);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function projName(p) {
|
|
112
|
+
const parts = p.replace(/\\/g,"/").split("/");
|
|
113
|
+
return parts[parts.length-1] || p;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function ts(iso) {
|
|
117
|
+
const d = new Date(iso);
|
|
118
|
+
return d.toLocaleDateString() + " " + d.toLocaleTimeString([], {hour:"2-digit",minute:"2-digit"});
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function aggregate(records) {
|
|
122
|
+
const r = { sessions: 0, input: 0, output: 0, cacheRead: 0, cacheCreate: 0, total: 0 };
|
|
123
|
+
for (const rec of records) {
|
|
124
|
+
r.sessions++;
|
|
125
|
+
r.input += rec.inputTokens || 0;
|
|
126
|
+
r.output += rec.outputTokens || 0;
|
|
127
|
+
r.cacheRead += rec.cacheReadTokens || 0;
|
|
128
|
+
r.cacheCreate += rec.cacheCreateTokens || 0;
|
|
129
|
+
r.total += rec.totalTokens || 0;
|
|
130
|
+
}
|
|
131
|
+
r.avgTotal = r.sessions ? Math.round(r.total / r.sessions) : 0;
|
|
132
|
+
return r;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function renderCards(onRecs, offRecs) {
|
|
136
|
+
function cardHtml(recs, cls, label) {
|
|
137
|
+
const a = aggregate(recs);
|
|
138
|
+
if (!recs.length) return `<div class="card ${cls}"><div class="card-label">${label}</div><div class="empty muted">No sessions yet</div></div>`;
|
|
139
|
+
return `<div class="card ${cls}">
|
|
140
|
+
<div class="card-label">${label}</div>
|
|
141
|
+
<div class="stat"><div class="stat-val">${fmt(a.total)}</div><div class="stat-lbl">total tokens · ${a.sessions} session${a.sessions!==1?"s":""}</div></div>
|
|
142
|
+
<div class="stats-row">
|
|
143
|
+
<div class="mini-stat"><div class="mini-val">${fmt(a.avgTotal)}</div><div class="mini-lbl">avg/session</div></div>
|
|
144
|
+
<div class="mini-stat"><div class="mini-val">${fmt(a.input)}</div><div class="mini-lbl">input</div></div>
|
|
145
|
+
<div class="mini-stat"><div class="mini-val">${fmt(a.output)}</div><div class="mini-lbl">output</div></div>
|
|
146
|
+
</div>
|
|
147
|
+
<div class="stats-row" style="margin-top:8px">
|
|
148
|
+
<div class="mini-stat"><div class="mini-val" style="color:var(--blue)">${fmt(a.cacheRead)}</div><div class="mini-lbl">cache read</div></div>
|
|
149
|
+
<div class="mini-stat"><div class="mini-val" style="color:var(--yellow)">${fmt(a.cacheCreate)}</div><div class="mini-lbl">cache write</div></div>
|
|
150
|
+
</div>
|
|
151
|
+
</div>`;
|
|
152
|
+
}
|
|
153
|
+
document.getElementById("cards").innerHTML =
|
|
154
|
+
cardHtml(onRecs, "on", "Peon ON ✓") + cardHtml(offRecs, "off", "Peon OFF ✗");
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function renderDelta(onRecs, offRecs) {
|
|
158
|
+
const el = document.getElementById("delta");
|
|
159
|
+
if (!onRecs.length || !offRecs.length) { el.style.display = "none"; return; }
|
|
160
|
+
const on = aggregate(onRecs);
|
|
161
|
+
const off = aggregate(offRecs);
|
|
162
|
+
const diffAvg = off.avgTotal - on.avgTotal;
|
|
163
|
+
const pct = off.avgTotal ? Math.round(Math.abs(diffAvg) / off.avgTotal * 100) : 0;
|
|
164
|
+
const saving = diffAvg > 0;
|
|
165
|
+
el.style.display = "flex";
|
|
166
|
+
el.innerHTML = `
|
|
167
|
+
<div class="delta-icon">${saving ? "📉" : "📈"}</div>
|
|
168
|
+
<div class="delta-text">
|
|
169
|
+
<div class="delta-val ${saving?"saving":"costly"}">${saving?"-":"+"} ${fmt(Math.abs(diffAvg))} tokens/session (${pct}%)</div>
|
|
170
|
+
<div class="delta-lbl">${saving
|
|
171
|
+
? `Peon saves ~${fmt(Math.abs(diffAvg))} tokens per session on average (${on.sessions} ON sessions vs ${off.sessions} OFF sessions)`
|
|
172
|
+
: `Peon adds ~${fmt(Math.abs(diffAvg))} tokens per session on average — check injection size`
|
|
173
|
+
}</div>
|
|
174
|
+
</div>`;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function renderTable(records) {
|
|
178
|
+
const tbody = document.getElementById("sessions-body");
|
|
179
|
+
if (!records.length) { tbody.innerHTML = '<tr><td colspan="9" class="empty">No sessions recorded yet. Sessions are logged when they end.</td></tr>'; return; }
|
|
180
|
+
const sorted = [...records].sort((a,b) => b.ts.localeCompare(a.ts));
|
|
181
|
+
tbody.innerHTML = sorted.map(r => `<tr>
|
|
182
|
+
<td class="mono muted">${ts(r.ts)}</td>
|
|
183
|
+
<td><span class="badge ${r.peonEnabled?"on":"off"}">${r.peonEnabled?"ON":"OFF"}</span></td>
|
|
184
|
+
<td><div class="proj" title="${r.projectPath}">${projName(r.projectPath)}</div></td>
|
|
185
|
+
<td class="mono">${fmt(r.inputTokens||0)}</td>
|
|
186
|
+
<td class="mono">${fmt(r.outputTokens||0)}</td>
|
|
187
|
+
<td class="mono" style="color:var(--blue)">${fmt(r.cacheReadTokens||0)}</td>
|
|
188
|
+
<td class="mono" style="color:var(--yellow)">${fmt(r.cacheCreateTokens||0)}</td>
|
|
189
|
+
<td class="mono" style="font-weight:600">${fmt(r.totalTokens||0)}</td>
|
|
190
|
+
<td class="muted" style="font-size:11px">${r.model||"—"}</td>
|
|
191
|
+
</tr>`).join("");
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
function render() {
|
|
195
|
+
const proj = document.getElementById("proj-filter").value;
|
|
196
|
+
const filtered = proj ? allRecords.filter(r => r.projectPath === proj) : allRecords;
|
|
197
|
+
const on = filtered.filter(r => r.peonEnabled);
|
|
198
|
+
const off = filtered.filter(r => !r.peonEnabled);
|
|
199
|
+
renderCards(on, off);
|
|
200
|
+
renderDelta(on, off);
|
|
201
|
+
renderTable(filtered);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function updateProjectFilter(records) {
|
|
205
|
+
const sel = document.getElementById("proj-filter");
|
|
206
|
+
const current = sel.value;
|
|
207
|
+
const projects = [...new Set(records.map(r => r.projectPath))].sort();
|
|
208
|
+
sel.innerHTML = '<option value="">All projects</option>' + projects.map(p => `<option value="${p}"${p===current?" selected":""}>${projName(p)}</option>`).join("");
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
async function refresh() {
|
|
212
|
+
try {
|
|
213
|
+
const res = await fetch(DAEMON + "/token-ab");
|
|
214
|
+
if (!res.ok) throw new Error("daemon error");
|
|
215
|
+
const data = await res.json();
|
|
216
|
+
allRecords = data.records || [];
|
|
217
|
+
updateProjectFilter(allRecords);
|
|
218
|
+
render();
|
|
219
|
+
} catch(e) {
|
|
220
|
+
console.warn("Peon daemon unreachable:", e.message);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
document.getElementById("proj-filter").addEventListener("change", render);
|
|
225
|
+
document.getElementById("refresh-select").addEventListener("change", function() {
|
|
226
|
+
clearInterval(timer);
|
|
227
|
+
const ms = parseInt(this.value);
|
|
228
|
+
if (ms > 0) timer = setInterval(refresh, ms);
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
refresh();
|
|
232
|
+
timer = setInterval(refresh, 30000);
|
|
233
|
+
</script>
|
|
234
|
+
</body>
|
|
235
|
+
</html>
|