@sesamespace/hivemind 0.7.1 → 0.8.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.
@@ -6,7 +6,7 @@ import {
6
6
  PRIMARY_ROUTES,
7
7
  SesameClient,
8
8
  WORKER_ROUTES
9
- } from "./chunk-G6PPTVAS.js";
9
+ } from "./chunk-A7X4FKQZ.js";
10
10
 
11
11
  // packages/runtime/src/watchdog.ts
12
12
  import { execSync } from "child_process";
@@ -1048,4 +1048,4 @@ export {
1048
1048
  WorkerMemorySync,
1049
1049
  PrimaryMemorySync
1050
1050
  };
1051
- //# sourceMappingURL=chunk-EQRUGDTR.js.map
1051
+ //# sourceMappingURL=chunk-GOW62FNS.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  startPipeline
3
- } from "./chunk-G6PPTVAS.js";
3
+ } from "./chunk-A7X4FKQZ.js";
4
4
 
5
5
  // packages/cli/src/commands/start.ts
6
6
  import { resolve } from "path";
@@ -66,4 +66,4 @@ Options:
66
66
  export {
67
67
  runStartCommand
68
68
  };
69
- //# sourceMappingURL=chunk-KL44NCSP.js.map
69
+ //# sourceMappingURL=chunk-LDTBAMQY.js.map
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  Watchdog
3
- } from "./chunk-EQRUGDTR.js";
3
+ } from "./chunk-GOW62FNS.js";
4
4
  import {
5
5
  defaultSentinelConfig,
6
6
  loadConfig
7
- } from "./chunk-G6PPTVAS.js";
7
+ } from "./chunk-A7X4FKQZ.js";
8
8
 
9
9
  // packages/cli/src/commands/watchdog.ts
10
10
  import { resolve } from "path";
@@ -76,4 +76,4 @@ Options:
76
76
  export {
77
77
  runWatchdogCommand
78
78
  };
79
- //# sourceMappingURL=chunk-JLI4IPKA.js.map
79
+ //# sourceMappingURL=chunk-R6XIZH3I.js.map
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  FleetManager
3
- } from "./chunk-EQRUGDTR.js";
3
+ } from "./chunk-GOW62FNS.js";
4
4
 
5
5
  // packages/cli/src/commands/fleet.ts
6
6
  function formatUptime(seconds) {
@@ -183,4 +183,4 @@ Commands:
183
183
  export {
184
184
  runFleetCommand
185
185
  };
186
- //# sourceMappingURL=chunk-GXNDXM5K.js.map
186
+ //# sourceMappingURL=chunk-YDD5EZ46.js.map
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  runFleetCommand
3
- } from "../chunk-GXNDXM5K.js";
4
- import "../chunk-EQRUGDTR.js";
5
- import "../chunk-G6PPTVAS.js";
3
+ } from "../chunk-YDD5EZ46.js";
4
+ import "../chunk-GOW62FNS.js";
5
+ import "../chunk-A7X4FKQZ.js";
6
6
  import "../chunk-GPI4RU7N.js";
7
7
  export {
8
8
  runFleetCommand
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  runStartCommand
3
- } from "../chunk-KL44NCSP.js";
4
- import "../chunk-EQRUGDTR.js";
5
- import "../chunk-G6PPTVAS.js";
3
+ } from "../chunk-LDTBAMQY.js";
4
+ import "../chunk-GOW62FNS.js";
5
+ import "../chunk-A7X4FKQZ.js";
6
6
  import "../chunk-GPI4RU7N.js";
7
7
  export {
8
8
  runStartCommand
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  runWatchdogCommand
3
- } from "../chunk-JLI4IPKA.js";
4
- import "../chunk-EQRUGDTR.js";
5
- import "../chunk-G6PPTVAS.js";
3
+ } from "../chunk-R6XIZH3I.js";
4
+ import "../chunk-GOW62FNS.js";
5
+ import "../chunk-A7X4FKQZ.js";
6
6
  import "../chunk-GPI4RU7N.js";
7
7
  export {
8
8
  runWatchdogCommand
@@ -0,0 +1,410 @@
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>Hivemind Dashboard</title>
7
+ <style>
8
+ :root {
9
+ --bg: #0d1117; --bg2: #161b22; --bg3: #21262d; --border: #30363d;
10
+ --text: #e6edf3; --text2: #8b949e; --accent: #58a6ff; --accent2: #388bfd;
11
+ --green: #3fb950; --red: #f85149; --yellow: #d29922; --purple: #bc8cff;
12
+ }
13
+ * { margin: 0; padding: 0; box-sizing: border-box; }
14
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; background: var(--bg); color: var(--text); display: flex; height: 100vh; overflow: hidden; }
15
+
16
+ /* Sidebar */
17
+ .sidebar { width: 200px; background: var(--bg2); border-right: 1px solid var(--border); padding: 16px 0; flex-shrink: 0; display: flex; flex-direction: column; }
18
+ .sidebar h1 { font-size: 16px; padding: 0 16px 16px; border-bottom: 1px solid var(--border); color: var(--accent); }
19
+ .sidebar nav { padding: 8px 0; }
20
+ .sidebar a { display: block; padding: 8px 16px; color: var(--text2); text-decoration: none; font-size: 14px; cursor: pointer; }
21
+ .sidebar a:hover, .sidebar a.active { color: var(--text); background: var(--bg3); }
22
+
23
+ /* Main */
24
+ .main { flex: 1; overflow-y: auto; padding: 24px; }
25
+
26
+ /* Filters */
27
+ .filters { display: flex; gap: 12px; margin-bottom: 16px; align-items: center; }
28
+ .filters input, .filters select { background: var(--bg2); border: 1px solid var(--border); color: var(--text); padding: 6px 10px; border-radius: 6px; font-size: 13px; }
29
+ .filters input:focus, .filters select:focus { outline: none; border-color: var(--accent); }
30
+ .filters button { background: var(--accent2); color: #fff; border: none; padding: 6px 14px; border-radius: 6px; cursor: pointer; font-size: 13px; }
31
+
32
+ /* Request list */
33
+ .req-row { background: var(--bg2); border: 1px solid var(--border); border-radius: 8px; margin-bottom: 8px; cursor: pointer; transition: border-color 0.15s; }
34
+ .req-row:hover { border-color: var(--accent); }
35
+ .req-summary { display: grid; grid-template-columns: 160px 100px 100px 120px 80px 80px; gap: 8px; padding: 10px 14px; align-items: center; font-size: 13px; }
36
+ .req-summary .ts { color: var(--text2); font-variant-numeric: tabular-nums; }
37
+ .req-summary .sender { color: var(--green); }
38
+ .req-summary .ctx { color: var(--purple); }
39
+ .req-summary .model { color: var(--text2); }
40
+ .req-summary .latency { color: var(--yellow); text-align: right; }
41
+ .req-summary .tokens { color: var(--text2); text-align: right; }
42
+
43
+ /* Detail */
44
+ .req-detail { padding: 0 14px 14px; border-top: 1px solid var(--border); display: none; }
45
+ .req-detail.open { display: block; }
46
+ .section { margin-top: 12px; }
47
+ .section-header { font-size: 12px; font-weight: 600; color: var(--accent); text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 6px; cursor: pointer; user-select: none; }
48
+ .section-header::before { content: '▸ '; }
49
+ .section-header.open::before { content: '▾ '; }
50
+ .section-body { display: none; }
51
+ .section-body.open { display: block; }
52
+ .section-body pre { background: var(--bg); border: 1px solid var(--border); border-radius: 6px; padding: 10px; font-size: 12px; line-height: 1.5; white-space: pre-wrap; word-break: break-word; max-height: 400px; overflow-y: auto; }
53
+ .episode { background: var(--bg); border: 1px solid var(--border); border-radius: 4px; padding: 8px; margin-bottom: 4px; font-size: 12px; }
54
+ .episode .meta { color: var(--text2); font-size: 11px; margin-bottom: 2px; }
55
+ .episode .score { color: var(--yellow); }
56
+ .l3-entry { background: var(--bg); border-left: 3px solid var(--purple); padding: 6px 10px; margin-bottom: 4px; font-size: 12px; }
57
+
58
+ /* Token bar */
59
+ .token-bar { display: flex; height: 20px; border-radius: 4px; overflow: hidden; margin-top: 4px; font-size: 10px; }
60
+ .token-bar div { display: flex; align-items: center; justify-content: center; color: #fff; min-width: 30px; }
61
+ .tb-sys { background: #58a6ff; }
62
+ .tb-hist { background: #bc8cff; }
63
+ .tb-user { background: #3fb950; }
64
+
65
+ /* Config */
66
+ .config-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
67
+ .config-item { background: var(--bg); border: 1px solid var(--border); border-radius: 4px; padding: 8px; text-align: center; }
68
+ .config-item .label { font-size: 10px; color: var(--text2); text-transform: uppercase; }
69
+ .config-item .value { font-size: 14px; font-weight: 600; margin-top: 2px; }
70
+
71
+ /* Memory browser */
72
+ .ctx-card { background: var(--bg2); border: 1px solid var(--border); border-radius: 8px; padding: 14px; margin-bottom: 8px; }
73
+ .ctx-card h3 { font-size: 14px; color: var(--accent); margin-bottom: 4px; }
74
+ .ctx-card .meta { font-size: 12px; color: var(--text2); }
75
+ .btn-sm { background: var(--bg3); border: 1px solid var(--border); color: var(--text2); padding: 4px 8px; border-radius: 4px; cursor: pointer; font-size: 11px; }
76
+ .btn-sm:hover { border-color: var(--accent); color: var(--text); }
77
+ .btn-danger { border-color: var(--red); color: var(--red); }
78
+ .btn-danger:hover { background: var(--red); color: #fff; }
79
+
80
+ /* Pagination */
81
+ .pagination { display: flex; gap: 8px; margin-top: 16px; justify-content: center; align-items: center; font-size: 13px; color: var(--text2); }
82
+ .pagination button { background: var(--bg2); border: 1px solid var(--border); color: var(--text); padding: 4px 12px; border-radius: 4px; cursor: pointer; }
83
+ .pagination button:disabled { opacity: 0.4; cursor: default; }
84
+
85
+ .hidden { display: none; }
86
+ .view { display: none; }
87
+ .view.active { display: block; }
88
+
89
+ /* Memory browser sub-nav */
90
+ .mem-tabs { display: flex; gap: 8px; margin-bottom: 16px; }
91
+ .mem-tab { padding: 6px 14px; border-radius: 6px; background: var(--bg2); border: 1px solid var(--border); color: var(--text2); cursor: pointer; font-size: 13px; }
92
+ .mem-tab.active { border-color: var(--accent); color: var(--accent); }
93
+ </style>
94
+ </head>
95
+ <body>
96
+ <div class="sidebar">
97
+ <h1>🧠 Hivemind</h1>
98
+ <nav>
99
+ <a data-view="requests" class="active">Requests</a>
100
+ <a data-view="memory">Memory</a>
101
+ <a data-view="contexts">Contexts</a>
102
+ </nav>
103
+ </div>
104
+ <div class="main">
105
+ <!-- Requests View -->
106
+ <div id="v-requests" class="view active">
107
+ <div class="filters">
108
+ <input type="text" id="f-context" placeholder="Filter context…" />
109
+ <input type="text" id="f-sender" placeholder="Filter sender…" />
110
+ <button onclick="loadRequests()">Filter</button>
111
+ </div>
112
+ <div id="req-list"></div>
113
+ <div class="pagination" id="req-pagination"></div>
114
+ </div>
115
+
116
+ <!-- Memory View -->
117
+ <div id="v-memory" class="view">
118
+ <div class="mem-tabs">
119
+ <div class="mem-tab active" data-mtab="l3">L3 Knowledge</div>
120
+ <div class="mem-tab" data-mtab="l2">L2 Episodes</div>
121
+ </div>
122
+ <div id="mem-ctx-select" style="margin-bottom:12px">
123
+ <select id="mem-context"><option value="">Select context…</option></select>
124
+ </div>
125
+ <div id="mem-l3" class="view active"></div>
126
+ <div id="mem-l2" class="view"></div>
127
+ </div>
128
+
129
+ <!-- Contexts View -->
130
+ <div id="v-contexts" class="view">
131
+ <div id="ctx-list"></div>
132
+ </div>
133
+ </div>
134
+
135
+ <script>
136
+ const API = '';
137
+ let reqOffset = 0;
138
+ const REQ_LIMIT = 30;
139
+
140
+ // Navigation
141
+ document.querySelectorAll('.sidebar a').forEach(a => {
142
+ a.addEventListener('click', () => {
143
+ document.querySelectorAll('.sidebar a').forEach(x => x.classList.remove('active'));
144
+ a.classList.add('active');
145
+ document.querySelectorAll('.view').forEach(v => {
146
+ if (v.closest('.main')) v.classList.remove('active');
147
+ });
148
+ const viewId = 'v-' + a.dataset.view;
149
+ document.getElementById(viewId)?.classList.add('active');
150
+ if (a.dataset.view === 'contexts') loadContexts();
151
+ if (a.dataset.view === 'memory') loadMemoryContexts();
152
+ });
153
+ });
154
+
155
+ // Memory sub-tabs
156
+ document.querySelectorAll('.mem-tab').forEach(t => {
157
+ t.addEventListener('click', () => {
158
+ document.querySelectorAll('.mem-tab').forEach(x => x.classList.remove('active'));
159
+ t.classList.add('active');
160
+ document.getElementById('mem-l3').classList.toggle('active', t.dataset.mtab === 'l3');
161
+ document.getElementById('mem-l2').classList.toggle('active', t.dataset.mtab === 'l2');
162
+ });
163
+ });
164
+
165
+ document.getElementById('mem-context').addEventListener('change', () => {
166
+ const ctx = document.getElementById('mem-context').value;
167
+ if (ctx) { loadL3(ctx); loadL2(ctx); }
168
+ });
169
+
170
+ // Requests
171
+ async function loadRequests() {
172
+ const ctx = document.getElementById('f-context').value;
173
+ const sender = document.getElementById('f-sender').value;
174
+ const params = new URLSearchParams({ limit: REQ_LIMIT, offset: reqOffset });
175
+ if (ctx) params.set('context', ctx);
176
+ if (sender) params.set('sender', sender);
177
+
178
+ const res = await fetch(`${API}/api/requests?${params}`);
179
+ const data = await res.json();
180
+
181
+ const list = document.getElementById('req-list');
182
+ list.innerHTML = '';
183
+
184
+ for (const r of data.requests) {
185
+ const row = document.createElement('div');
186
+ row.className = 'req-row';
187
+ const ts = new Date(r.timestamp).toLocaleString();
188
+ const latency = r.response_latency_ms + 'ms';
189
+ const tokens = r.token_est_total;
190
+ const model = r.response_model.split('/').pop().slice(0, 15);
191
+
192
+ row.innerHTML = `
193
+ <div class="req-summary">
194
+ <span class="ts">${ts}</span>
195
+ <span class="sender">${esc(r.sender_handle || 'stdin')}</span>
196
+ <span class="ctx">${esc(r.context)}</span>
197
+ <span class="model">${esc(model)}</span>
198
+ <span class="latency">${latency}</span>
199
+ <span class="tokens">~${tokens}t</span>
200
+ </div>
201
+ <div class="req-detail" id="detail-${r.id}"></div>
202
+ `;
203
+
204
+ row.querySelector('.req-summary').addEventListener('click', () => {
205
+ const detail = document.getElementById('detail-' + r.id);
206
+ if (detail.classList.contains('open')) {
207
+ detail.classList.remove('open');
208
+ } else {
209
+ renderDetail(detail, r);
210
+ detail.classList.add('open');
211
+ }
212
+ });
213
+ list.appendChild(row);
214
+ }
215
+
216
+ // Pagination
217
+ const pag = document.getElementById('req-pagination');
218
+ const page = Math.floor(reqOffset / REQ_LIMIT) + 1;
219
+ const totalPages = Math.ceil(data.total / REQ_LIMIT);
220
+ pag.innerHTML = `
221
+ <button ${reqOffset === 0 ? 'disabled' : ''} onclick="reqOffset -= ${REQ_LIMIT}; loadRequests()">← Prev</button>
222
+ <span>Page ${page} of ${totalPages} (${data.total} total)</span>
223
+ <button ${reqOffset + REQ_LIMIT >= data.total ? 'disabled' : ''} onclick="reqOffset += ${REQ_LIMIT}; loadRequests()">Next →</button>
224
+ `;
225
+ }
226
+
227
+ function renderDetail(el, r) {
228
+ const comps = typeof r.system_prompt_components === 'string' ? JSON.parse(r.system_prompt_components) : r.system_prompt_components;
229
+ const history = typeof r.conversation_history === 'string' ? JSON.parse(r.conversation_history) : r.conversation_history;
230
+ const config = typeof r.config_snapshot === 'string' ? JSON.parse(r.config_snapshot) : r.config_snapshot;
231
+
232
+ const totalTokens = r.token_est_total || 1;
233
+ const sysPct = Math.round((r.token_est_system / totalTokens) * 100);
234
+ const histPct = Math.round((r.token_est_history / totalTokens) * 100);
235
+ const userPct = 100 - sysPct - histPct;
236
+
237
+ let html = '';
238
+
239
+ // Config
240
+ html += `<div class="section"><div class="config-grid">
241
+ <div class="config-item"><div class="label">Model</div><div class="value">${esc(config?.model || r.response_model)}</div></div>
242
+ <div class="config-item"><div class="label">Latency</div><div class="value">${r.response_latency_ms}ms</div></div>
243
+ <div class="config-item"><div class="label">Top K</div><div class="value">${config?.topK ?? '?'}</div></div>
244
+ <div class="config-item"><div class="label">Temperature</div><div class="value">${config?.temperature ?? '?'}</div></div>
245
+ </div></div>`;
246
+
247
+ // Token bar
248
+ html += `<div class="section">
249
+ <div class="section-header open">Token Breakdown (~${totalTokens} total)</div>
250
+ <div class="section-body open">
251
+ <div class="token-bar">
252
+ <div class="tb-sys" style="width:${sysPct}%">sys ${r.token_est_system}</div>
253
+ <div class="tb-hist" style="width:${histPct}%">${r.token_est_history > 0 ? 'hist ' + r.token_est_history : ''}</div>
254
+ <div class="tb-user" style="width:${Math.max(userPct, 5)}%">user ${r.token_est_user}</div>
255
+ </div>
256
+ </div>
257
+ </div>`;
258
+
259
+ // User message
260
+ html += section('User Message', `<pre>${esc(r.user_message)}</pre>`, true);
261
+
262
+ // Response
263
+ const skipped = r.response_skipped ? ' <span style="color:var(--yellow)">[SKIPPED]</span>' : '';
264
+ html += section('Response' + skipped, `<pre>${esc(r.response_content)}</pre>`, true);
265
+
266
+ // L3 Knowledge
267
+ if (comps?.l3Knowledge?.length > 0) {
268
+ const l3Html = comps.l3Knowledge.map(k => `<div class="l3-entry">${esc(k)}</div>`).join('');
269
+ html += section(`L3 Knowledge (${comps.l3Knowledge.length})`, l3Html, true);
270
+ }
271
+
272
+ // L2 Episodes
273
+ if (comps?.l2Episodes?.length > 0) {
274
+ const epHtml = comps.l2Episodes.map(ep => `
275
+ <div class="episode">
276
+ <div class="meta">${esc(ep.role)} · ${esc(ep.context_name)} · <span class="score">score: ${ep.score?.toFixed(3)}</span> · ${new Date(ep.timestamp).toLocaleString()}</div>
277
+ ${esc(ep.content)}
278
+ </div>
279
+ `).join('');
280
+ html += section(`L2 Episodes (${comps.l2Episodes.length})`, epHtml, true);
281
+ }
282
+
283
+ // L1 History
284
+ if (history?.length > 0) {
285
+ const histHtml = history.map(m => `<div class="episode"><div class="meta">${esc(m.role)}</div>${esc(m.content)}</div>`).join('');
286
+ html += section(`L1 History (${history.length} turns)`, histHtml, false);
287
+ }
288
+
289
+ // Identity (collapsed by default)
290
+ if (comps?.identity) {
291
+ html += section('Identity Files', `<pre>${esc(comps.identity)}</pre>`, false);
292
+ }
293
+
294
+ el.innerHTML = html;
295
+
296
+ // Wire section toggles
297
+ el.querySelectorAll('.section-header').forEach(h => {
298
+ h.addEventListener('click', () => {
299
+ h.classList.toggle('open');
300
+ h.nextElementSibling?.classList.toggle('open');
301
+ });
302
+ });
303
+ }
304
+
305
+ function section(title, content, startOpen) {
306
+ return `<div class="section">
307
+ <div class="section-header ${startOpen ? 'open' : ''}">${title}</div>
308
+ <div class="section-body ${startOpen ? 'open' : ''}">${content}</div>
309
+ </div>`;
310
+ }
311
+
312
+ // Contexts
313
+ async function loadContexts() {
314
+ try {
315
+ const res = await fetch(`${API}/api/contexts`);
316
+ const data = await res.json();
317
+ const contexts = data.contexts || [];
318
+ const list = document.getElementById('ctx-list');
319
+ if (contexts.length === 0) {
320
+ list.innerHTML = '<p style="color:var(--text2)">No contexts found (memory daemon may be offline)</p>';
321
+ return;
322
+ }
323
+ list.innerHTML = contexts.map(c => `
324
+ <div class="ctx-card">
325
+ <h3>${esc(c.name)}</h3>
326
+ <div class="meta">${c.episode_count ?? '?'} episodes · created ${new Date(c.created_at).toLocaleDateString()}</div>
327
+ ${c.description ? `<div class="meta">${esc(c.description)}</div>` : ''}
328
+ </div>
329
+ `).join('');
330
+ } catch (err) {
331
+ document.getElementById('ctx-list').innerHTML = `<p style="color:var(--red)">Failed to load contexts: ${esc(err.message)}</p>`;
332
+ }
333
+ }
334
+
335
+ // Memory browser
336
+ async function loadMemoryContexts() {
337
+ try {
338
+ const res = await fetch(`${API}/api/contexts`);
339
+ const data = await res.json();
340
+ const sel = document.getElementById('mem-context');
341
+ const current = sel.value;
342
+ sel.innerHTML = '<option value="">Select context…</option>';
343
+ for (const c of (data.contexts || [])) {
344
+ sel.innerHTML += `<option value="${esc(c.name)}">${esc(c.name)} (${c.episode_count ?? '?'} eps)</option>`;
345
+ }
346
+ if (current) { sel.value = current; loadL3(current); loadL2(current); }
347
+ } catch {}
348
+ }
349
+
350
+ async function loadL3(ctx) {
351
+ const el = document.getElementById('mem-l3');
352
+ try {
353
+ const res = await fetch(`${API}/api/contexts/${encodeURIComponent(ctx)}/l3`);
354
+ const data = await res.json();
355
+ const entries = data.entries || [];
356
+ if (entries.length === 0) {
357
+ el.innerHTML = '<p style="color:var(--text2)">No L3 knowledge entries</p>';
358
+ return;
359
+ }
360
+ el.innerHTML = entries.map(e => `
361
+ <div class="l3-entry" style="display:flex;justify-content:space-between;align-items:start;margin-bottom:8px">
362
+ <div style="flex:1">${esc(e.content)}<br><span style="font-size:11px;color:var(--text2)">access: ${e.access_count} · density: ${e.connection_density?.toFixed(2)}</span></div>
363
+ <button class="btn-sm btn-danger" onclick="deleteL3('${esc(e.id)}','${esc(ctx)}')">Delete</button>
364
+ </div>
365
+ `).join('');
366
+ } catch (err) {
367
+ el.innerHTML = `<p style="color:var(--red)">Failed: ${esc(err.message)}</p>`;
368
+ }
369
+ }
370
+
371
+ async function deleteL3(id, ctx) {
372
+ if (!confirm('Delete this L3 entry?')) return;
373
+ await fetch(`${API}/api/l3/${encodeURIComponent(id)}`, { method: 'DELETE' });
374
+ loadL3(ctx);
375
+ }
376
+
377
+ async function loadL2(ctx) {
378
+ const el = document.getElementById('mem-l2');
379
+ try {
380
+ const res = await fetch(`${API}/api/contexts/${encodeURIComponent(ctx)}/episodes`);
381
+ const data = await res.json();
382
+ const episodes = Array.isArray(data) ? data : (data.episodes || []);
383
+ if (episodes.length === 0) {
384
+ el.innerHTML = '<p style="color:var(--text2)">No episodes</p>';
385
+ return;
386
+ }
387
+ el.innerHTML = episodes.slice(0, 100).map(ep => `
388
+ <div class="episode">
389
+ <div class="meta">${esc(ep.role)} · ${new Date(ep.timestamp).toLocaleString()} · layer: ${ep.layer || 'L2'}</div>
390
+ ${esc(ep.content)}
391
+ </div>
392
+ `).join('');
393
+ if (episodes.length > 100) {
394
+ el.innerHTML += `<p style="color:var(--text2)">Showing 100 of ${episodes.length}</p>`;
395
+ }
396
+ } catch (err) {
397
+ el.innerHTML = `<p style="color:var(--red)">Failed: ${esc(err.message)}</p>`;
398
+ }
399
+ }
400
+
401
+ function esc(s) {
402
+ if (!s) return '';
403
+ return String(s).replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;').replace(/"/g,'&quot;');
404
+ }
405
+
406
+ // Auto-load
407
+ loadRequests();
408
+ </script>
409
+ </body>
410
+ </html>
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  PrimaryMemorySync,
5
5
  Watchdog,
6
6
  WorkerMemorySync
7
- } from "./chunk-EQRUGDTR.js";
7
+ } from "./chunk-GOW62FNS.js";
8
8
  import {
9
9
  Agent,
10
10
  CompactionManager,
@@ -14,6 +14,7 @@ import {
14
14
  MemoryClient,
15
15
  SesameClient,
16
16
  SessionStore,
17
+ SkillsEngine,
17
18
  TaskEngine,
18
19
  WorkerRuntime,
19
20
  WorkerServer,
@@ -26,7 +27,7 @@ import {
26
27
  loadConfig,
27
28
  startPipeline,
28
29
  startWorker
29
- } from "./chunk-G6PPTVAS.js";
30
+ } from "./chunk-A7X4FKQZ.js";
30
31
  import "./chunk-GPI4RU7N.js";
31
32
  export {
32
33
  Agent,
@@ -40,6 +41,7 @@ export {
40
41
  PrimaryMemorySync,
41
42
  SesameClient,
42
43
  SessionStore,
44
+ SkillsEngine,
43
45
  TaskEngine,
44
46
  Watchdog,
45
47
  WorkerMemorySync,
package/dist/main.js CHANGED
@@ -4,10 +4,10 @@ import {
4
4
  } from "./chunk-DODOQGIL.js";
5
5
  import {
6
6
  runStartCommand
7
- } from "./chunk-KL44NCSP.js";
7
+ } from "./chunk-LDTBAMQY.js";
8
8
  import {
9
9
  runFleetCommand
10
- } from "./chunk-GXNDXM5K.js";
10
+ } from "./chunk-YDD5EZ46.js";
11
11
  import {
12
12
  runServiceCommand
13
13
  } from "./chunk-IJRAVHQC.js";
@@ -16,9 +16,9 @@ import {
16
16
  } from "./chunk-LJHJGDKY.js";
17
17
  import {
18
18
  runWatchdogCommand
19
- } from "./chunk-JLI4IPKA.js";
20
- import "./chunk-EQRUGDTR.js";
21
- import "./chunk-G6PPTVAS.js";
19
+ } from "./chunk-R6XIZH3I.js";
20
+ import "./chunk-GOW62FNS.js";
21
+ import "./chunk-A7X4FKQZ.js";
22
22
  import "./chunk-GPI4RU7N.js";
23
23
 
24
24
  // packages/cli/src/main.ts
package/dist/start.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  loadConfig,
4
4
  startPipeline,
5
5
  startWorker
6
- } from "./chunk-G6PPTVAS.js";
6
+ } from "./chunk-A7X4FKQZ.js";
7
7
  import "./chunk-GPI4RU7N.js";
8
8
 
9
9
  // packages/runtime/src/start.ts