@sesamespace/hivemind 0.10.0 → 0.11.1
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/.pnpmrc.json +1 -0
- package/AUTO-DEBUG-DESIGN.md +267 -0
- package/AUTOMATIC-MEMORY-MANAGEMENT.md +109 -0
- package/DASHBOARD-PLAN.md +206 -0
- package/MEMORY-ENHANCEMENT-PLAN.md +211 -0
- package/TOOL-USE-DESIGN.md +173 -0
- package/dist/{chunk-FBQBBAPZ.js → chunk-4C6B2AMB.js} +2 -2
- package/dist/{chunk-FK6WYXRM.js → chunk-4YXOQGQC.js} +2 -2
- package/dist/{chunk-IXBIAX76.js → chunk-K6KL2VD6.js} +2 -2
- package/dist/{chunk-IJRAVHQC.js → chunk-LWJCKTQP.js} +51 -11
- package/dist/chunk-LWJCKTQP.js.map +1 -0
- package/dist/{chunk-BHCDOHSK.js → chunk-LYL5GG2F.js} +3 -3
- package/dist/{chunk-M3A2WRXM.js → chunk-OB6OXLPC.js} +430 -2
- package/dist/chunk-OB6OXLPC.js.map +1 -0
- package/dist/{chunk-DPLCEMEC.js → chunk-ZA4NWNS6.js} +2 -2
- package/dist/commands/fleet.js +3 -3
- package/dist/commands/init.js +3 -3
- package/dist/commands/service.js +1 -1
- package/dist/commands/start.js +3 -3
- package/dist/commands/watchdog.js +3 -3
- package/dist/dashboard.html +100 -60
- package/dist/index.js +2 -2
- package/dist/main.js +7 -7
- package/dist/start.js +1 -1
- package/docs/TOOL-PARITY-PLAN.md +191 -0
- package/package.json +23 -24
- package/src/memory/dashboard-integration.ts +295 -0
- package/src/memory/index.ts +187 -0
- package/src/memory/performance-test.ts +208 -0
- package/src/memory/processors/agent-sync.ts +312 -0
- package/src/memory/processors/command-learner.ts +298 -0
- package/src/memory/processors/memory-api-client.ts +105 -0
- package/src/memory/processors/message-flow-integration.ts +168 -0
- package/src/memory/processors/research-digester.ts +204 -0
- package/test-caitlin-access.md +11 -0
- package/dist/chunk-IJRAVHQC.js.map +0 -1
- package/dist/chunk-M3A2WRXM.js.map +0 -1
- package/install.sh +0 -162
- package/packages/memory/Cargo.lock +0 -6480
- package/packages/memory/Cargo.toml +0 -21
- package/packages/memory/src/src/context.rs +0 -179
- package/packages/memory/src/src/embeddings.rs +0 -51
- package/packages/memory/src/src/main.rs +0 -887
- package/packages/memory/src/src/promotion.rs +0 -808
- package/packages/memory/src/src/scoring.rs +0 -142
- package/packages/memory/src/src/store.rs +0 -460
- package/packages/memory/src/src/tasks.rs +0 -321
- /package/dist/{chunk-FBQBBAPZ.js.map → chunk-4C6B2AMB.js.map} +0 -0
- /package/dist/{chunk-FK6WYXRM.js.map → chunk-4YXOQGQC.js.map} +0 -0
- /package/dist/{chunk-IXBIAX76.js.map → chunk-K6KL2VD6.js.map} +0 -0
- /package/dist/{chunk-BHCDOHSK.js.map → chunk-LYL5GG2F.js.map} +0 -0
- /package/dist/{chunk-DPLCEMEC.js.map → chunk-ZA4NWNS6.js.map} +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
startPipeline
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-OB6OXLPC.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-
|
|
69
|
+
//# sourceMappingURL=chunk-ZA4NWNS6.js.map
|
package/dist/commands/fleet.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runFleetCommand
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-4C6B2AMB.js";
|
|
4
|
+
import "../chunk-K6KL2VD6.js";
|
|
5
|
+
import "../chunk-OB6OXLPC.js";
|
|
6
6
|
import "../chunk-DGUM43GV.js";
|
|
7
7
|
export {
|
|
8
8
|
runFleetCommand
|
package/dist/commands/init.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runInitCommand
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-4YXOQGQC.js";
|
|
4
|
+
import "../chunk-K6KL2VD6.js";
|
|
5
|
+
import "../chunk-OB6OXLPC.js";
|
|
6
6
|
import "../chunk-DGUM43GV.js";
|
|
7
7
|
export {
|
|
8
8
|
runInitCommand
|
package/dist/commands/service.js
CHANGED
package/dist/commands/start.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runStartCommand
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-ZA4NWNS6.js";
|
|
4
|
+
import "../chunk-K6KL2VD6.js";
|
|
5
|
+
import "../chunk-OB6OXLPC.js";
|
|
6
6
|
import "../chunk-DGUM43GV.js";
|
|
7
7
|
export {
|
|
8
8
|
runStartCommand
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
runWatchdogCommand
|
|
3
|
-
} from "../chunk-
|
|
4
|
-
import "../chunk-
|
|
5
|
-
import "../chunk-
|
|
3
|
+
} from "../chunk-LYL5GG2F.js";
|
|
4
|
+
import "../chunk-K6KL2VD6.js";
|
|
5
|
+
import "../chunk-OB6OXLPC.js";
|
|
6
6
|
import "../chunk-DGUM43GV.js";
|
|
7
7
|
export {
|
|
8
8
|
runWatchdogCommand
|
package/dist/dashboard.html
CHANGED
|
@@ -406,26 +406,36 @@ async function loadHealthView() {
|
|
|
406
406
|
const tbody = document.getElementById('ctx-summary-body');
|
|
407
407
|
const scoringEl = document.getElementById('scoring-config-section');
|
|
408
408
|
|
|
409
|
+
let stats = null;
|
|
410
|
+
let contexts = [];
|
|
411
|
+
|
|
412
|
+
// Fetch stats and contexts independently so partial data still shows
|
|
409
413
|
try {
|
|
410
|
-
const
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
if (!statsRes.ok || !ctxRes.ok) {
|
|
416
|
-
showNotification('Failed to load system stats', 'error');
|
|
417
|
-
cards.innerHTML = '<p style="color:var(--red)">Failed to load stats (daemon may be offline)</p>';
|
|
418
|
-
return;
|
|
414
|
+
const ctxRes = await fetch(API + '/api/contexts');
|
|
415
|
+
if (ctxRes.ok) {
|
|
416
|
+
const ctxData = await ctxRes.json();
|
|
417
|
+
contexts = ctxData.contexts || [];
|
|
419
418
|
}
|
|
419
|
+
} catch {}
|
|
420
420
|
|
|
421
|
-
|
|
422
|
-
const
|
|
423
|
-
|
|
421
|
+
try {
|
|
422
|
+
const statsRes = await fetch(API + '/api/stats');
|
|
423
|
+
if (statsRes.ok) stats = await statsRes.json();
|
|
424
|
+
} catch {}
|
|
424
425
|
|
|
425
|
-
|
|
426
|
+
if (!stats && contexts.length === 0) {
|
|
427
|
+
cards.innerHTML = '<p style="color:var(--red)">Cannot connect to memory daemon</p>';
|
|
428
|
+
showNotification('Health view failed: daemon may be offline', 'error');
|
|
429
|
+
return;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
try {
|
|
426
433
|
const reqCountRes = await fetch(API + '/api/requests?limit=1');
|
|
427
|
-
|
|
434
|
+
var reqCount = reqCountRes.ok ? (await reqCountRes.json()).total || 0 : '?';
|
|
435
|
+
} catch { var reqCount = '?'; }
|
|
428
436
|
|
|
437
|
+
if (stats) {
|
|
438
|
+
const totalEpisodes = Object.values(stats.total_episodes || {}).reduce((a, b) => a + b, 0);
|
|
429
439
|
cards.innerHTML = `
|
|
430
440
|
<div class="status-card"><div class="label">Daemon Status</div><div class="value" style="color:var(${daemonStatus === 'ok' ? '--green' : '--red'})">${daemonStatus === 'ok' ? 'Online' : daemonStatus}</div><div class="sub">v${esc(daemonVersion)}</div></div>
|
|
431
441
|
<div class="status-card"><div class="label">Embedding Model</div><div class="value" style="font-size:14px">${esc(stats.embedding_model)}</div></div>
|
|
@@ -434,26 +444,37 @@ async function loadHealthView() {
|
|
|
434
444
|
<div class="status-card"><div class="label">Access Records</div><div class="value">${stats.total_access_records}</div></div>
|
|
435
445
|
<div class="status-card"><div class="label">Request Logs</div><div class="value">${reqCount}</div></div>
|
|
436
446
|
`;
|
|
447
|
+
} else {
|
|
448
|
+
const totalEpisodes = contexts.reduce((a, c) => a + (c.episode_count || 0), 0);
|
|
449
|
+
cards.innerHTML = `
|
|
450
|
+
<div class="status-card"><div class="label">Daemon Status</div><div class="value" style="color:var(${daemonStatus === 'ok' ? '--green' : '--red'})">${daemonStatus === 'ok' ? 'Online' : daemonStatus}</div><div class="sub">v${esc(daemonVersion)}</div></div>
|
|
451
|
+
<div class="status-card"><div class="label">Stats</div><div class="value" style="font-size:14px;color:var(--yellow)">Unavailable</div><div class="sub">/stats endpoint not found — rebuild daemon</div></div>
|
|
452
|
+
<div class="status-card"><div class="label">Total Episodes</div><div class="value">${totalEpisodes}</div><div class="sub">${contexts.length} contexts</div></div>
|
|
453
|
+
<div class="status-card"><div class="label">Request Logs</div><div class="value">${reqCount}</div></div>
|
|
454
|
+
`;
|
|
455
|
+
}
|
|
437
456
|
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
457
|
+
// Context summary table — always populate from contexts data
|
|
458
|
+
tbody.innerHTML = '';
|
|
459
|
+
for (const c of contexts) {
|
|
460
|
+
const epCount = stats ? (stats.total_episodes?.[c.name] ?? c.episode_count ?? 0) : (c.episode_count ?? 0);
|
|
461
|
+
const tr = document.createElement('tr');
|
|
462
|
+
tr.innerHTML = `<td style="color:var(--accent)">${esc(c.name)}</td><td>${epCount}</td><td>-</td><td>${c.created_at ? new Date(c.created_at).toLocaleDateString() : '-'}</td>`;
|
|
463
|
+
tbody.appendChild(tr);
|
|
464
|
+
}
|
|
446
465
|
|
|
447
|
-
|
|
448
|
-
|
|
466
|
+
// Scoring section
|
|
467
|
+
const defaultHL = (stats && stats.default_half_life_hours) || 48;
|
|
468
|
+
if (stats) {
|
|
449
469
|
scoringEl.innerHTML = `
|
|
450
470
|
<p style="color:var(--text2);font-size:13px;margin-bottom:12px">Default half-life: <strong>${defaultHL}h</strong>. Episodes lose ~50% relevance weight every ${defaultHL} hours.</p>
|
|
451
471
|
${renderDecayCurve(defaultHL)}
|
|
452
472
|
`;
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
473
|
+
} else {
|
|
474
|
+
scoringEl.innerHTML = `
|
|
475
|
+
<p style="color:var(--yellow);font-size:13px;margin-bottom:12px">Stats unavailable — showing default half-life: <strong>${defaultHL}h</strong>.</p>
|
|
476
|
+
${renderDecayCurve(defaultHL)}
|
|
477
|
+
`;
|
|
457
478
|
}
|
|
458
479
|
}
|
|
459
480
|
|
|
@@ -998,37 +1019,41 @@ async function loadPromotion() {
|
|
|
998
1019
|
|
|
999
1020
|
async function loadThresholds() {
|
|
1000
1021
|
const el = document.getElementById('promo-thresholds');
|
|
1022
|
+
let stats = null;
|
|
1023
|
+
let statsUnavailable = false;
|
|
1001
1024
|
try {
|
|
1002
1025
|
const res = await fetch(API + '/api/stats');
|
|
1003
|
-
if (
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
</div>
|
|
1026
|
+
if (res.ok) stats = await res.json();
|
|
1027
|
+
else statsUnavailable = true;
|
|
1028
|
+
} catch { statsUnavailable = true; }
|
|
1029
|
+
|
|
1030
|
+
const t = (stats && stats.promotion_thresholds) || { access: 5, cooccurrence: 3 };
|
|
1031
|
+
const warning = statsUnavailable ? '<p style="color:var(--yellow);font-size:12px;margin-bottom:12px;padding:8px;border:1px solid var(--yellow);border-radius:4px">/stats endpoint unavailable — showing default thresholds (access: 5, cooccurrence: 3). Rebuild daemon to enable.</p>' : '';
|
|
1032
|
+
|
|
1033
|
+
el.innerHTML = `
|
|
1034
|
+
${warning}
|
|
1035
|
+
<div class="status-grid" style="margin-bottom:24px">
|
|
1036
|
+
<div class="status-card">
|
|
1037
|
+
<div class="label">Access Threshold</div>
|
|
1038
|
+
<div class="value">${t.access}</div>
|
|
1039
|
+
<div class="sub">Episode must be accessed at least ${t.access} times</div>
|
|
1018
1040
|
</div>
|
|
1019
|
-
<
|
|
1020
|
-
|
|
1021
|
-
<
|
|
1022
|
-
<
|
|
1023
|
-
<li>The episode has been accessed (retrieved in search results) at least <strong>${t.access} times</strong></li>
|
|
1024
|
-
<li>The episode has co-occurred with other episodes at least <strong>${t.cooccurrence} times total</strong> (connection density)</li>
|
|
1025
|
-
</ol>
|
|
1026
|
-
<p>Once promoted, the episode's content is stored as long-term semantic knowledge (L3) and included in future system prompts for that context.</p>
|
|
1041
|
+
<div class="status-card">
|
|
1042
|
+
<div class="label">Co-occurrence Threshold</div>
|
|
1043
|
+
<div class="value">${t.cooccurrence}</div>
|
|
1044
|
+
<div class="sub">Episode must co-occur with others at least ${t.cooccurrence} times</div>
|
|
1027
1045
|
</div>
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1046
|
+
</div>
|
|
1047
|
+
<h3 style="margin-bottom:12px">How Promotion Works</h3>
|
|
1048
|
+
<div style="color:var(--text2);font-size:13px;line-height:1.8">
|
|
1049
|
+
<p><strong>L2 → L3 promotion</strong> happens when an episode meets <em>both</em> thresholds:</p>
|
|
1050
|
+
<ol style="margin:8px 0 8px 20px">
|
|
1051
|
+
<li>The episode has been accessed (retrieved in search results) at least <strong>${t.access} times</strong></li>
|
|
1052
|
+
<li>The episode has co-occurred with other episodes at least <strong>${t.cooccurrence} times total</strong> (connection density)</li>
|
|
1053
|
+
</ol>
|
|
1054
|
+
<p>Once promoted, the episode's content is stored as long-term semantic knowledge (L3) and included in future system prompts for that context.</p>
|
|
1055
|
+
</div>
|
|
1056
|
+
`;
|
|
1032
1057
|
}
|
|
1033
1058
|
|
|
1034
1059
|
async function loadCandidates() {
|
|
@@ -1036,7 +1061,14 @@ async function loadCandidates() {
|
|
|
1036
1061
|
el.innerHTML = '<p style="color:var(--text2)">Loading candidates...</p>';
|
|
1037
1062
|
try {
|
|
1038
1063
|
const res = await fetch(API + '/api/access/top?limit=50');
|
|
1039
|
-
if (!res.ok) {
|
|
1064
|
+
if (!res.ok) {
|
|
1065
|
+
if (res.status === 404) {
|
|
1066
|
+
el.innerHTML = '<p style="color:var(--yellow);padding:12px;border:1px solid var(--yellow);border-radius:4px">/access/top endpoint not found (404). The running daemon binary may be outdated. Rebuild with: <code style="background:var(--bg);padding:2px 6px;border-radius:3px">cd packages/memory && cargo build --release</code> and restart the daemon.</p>';
|
|
1067
|
+
} else {
|
|
1068
|
+
el.innerHTML = `<p style="color:var(--red)">Failed to load candidates (HTTP ${res.status})</p>`;
|
|
1069
|
+
}
|
|
1070
|
+
return;
|
|
1071
|
+
}
|
|
1040
1072
|
const data = await res.json();
|
|
1041
1073
|
const records = data.records || [];
|
|
1042
1074
|
|
|
@@ -1086,6 +1118,7 @@ async function loadScoringTab() {
|
|
|
1086
1118
|
// Fetch scoring for each context
|
|
1087
1119
|
const scoringData = {};
|
|
1088
1120
|
let defaultHL = 48;
|
|
1121
|
+
let scoringAvailable = true;
|
|
1089
1122
|
for (const c of contexts) {
|
|
1090
1123
|
try {
|
|
1091
1124
|
const sRes = await fetch(API + '/api/contexts/' + encodeURIComponent(c.name) + '/scoring');
|
|
@@ -1093,23 +1126,30 @@ async function loadScoringTab() {
|
|
|
1093
1126
|
const sd = await sRes.json();
|
|
1094
1127
|
scoringData[c.name] = sd;
|
|
1095
1128
|
defaultHL = sd.default_half_life_hours || 48;
|
|
1129
|
+
} else if (sRes.status === 404) {
|
|
1130
|
+
scoringAvailable = false;
|
|
1096
1131
|
}
|
|
1097
1132
|
} catch {}
|
|
1098
1133
|
}
|
|
1099
1134
|
|
|
1100
|
-
let html =
|
|
1135
|
+
let html = '';
|
|
1136
|
+
if (!scoringAvailable) {
|
|
1137
|
+
html += '<p style="color:var(--yellow);font-size:12px;margin-bottom:12px;padding:8px;border:1px solid var(--yellow);border-radius:4px">/scoring endpoint not found — the running daemon may be outdated. Showing default values. Rebuild daemon to enable per-context scoring configuration.</p>';
|
|
1138
|
+
}
|
|
1139
|
+
html += `<p style="color:var(--text2);font-size:13px;margin-bottom:16px">Default half-life: <strong>${defaultHL}h</strong>. Settings reset when daemon restarts (in-memory only).</p>`;
|
|
1101
1140
|
|
|
1102
1141
|
html += '<table class="data-table"><thead><tr><th>Context</th><th>Half-Life (hours)</th><th>Custom?</th><th>Decay Curve</th><th>Actions</th></tr></thead><tbody>';
|
|
1103
1142
|
for (const c of contexts) {
|
|
1104
1143
|
const sd = scoringData[c.name] || {};
|
|
1105
1144
|
const hl = sd.half_life_hours || defaultHL;
|
|
1106
1145
|
const isCustom = sd.is_default === false;
|
|
1146
|
+
const sourceLabel = !scoringAvailable ? '<span style="color:var(--text2)">Default (endpoint unavailable)</span>' : (isCustom ? '<span style="color:var(--yellow)">Yes</span>' : 'Default');
|
|
1107
1147
|
html += `<tr>
|
|
1108
1148
|
<td style="color:var(--accent)">${esc(c.name)}</td>
|
|
1109
|
-
<td><input type="number" value="${hl}" min="1" max="8760" step="1" style="width:80px;background:var(--bg);border:1px solid var(--border);color:var(--text);padding:4px;border-radius:4px" id="hl-${esc(c.name)}" /></td>
|
|
1110
|
-
<td>${
|
|
1149
|
+
<td><input type="number" value="${hl}" min="1" max="8760" step="1" style="width:80px;background:var(--bg);border:1px solid var(--border);color:var(--text);padding:4px;border-radius:4px" id="hl-${esc(c.name)}" ${!scoringAvailable ? 'disabled' : ''} /></td>
|
|
1150
|
+
<td>${sourceLabel}</td>
|
|
1111
1151
|
<td>${renderDecayCurve(hl)}</td>
|
|
1112
|
-
<td><button class="btn-sm" onclick="saveScoring('${esc(c.name)}')">Save</button></td>
|
|
1152
|
+
<td><button class="btn-sm" onclick="saveScoring('${esc(c.name)}')" ${!scoringAvailable ? 'disabled' : ''}>Save</button></td>
|
|
1113
1153
|
</tr>`;
|
|
1114
1154
|
}
|
|
1115
1155
|
html += '</tbody></table>';
|
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
PrimaryMemorySync,
|
|
5
5
|
Watchdog,
|
|
6
6
|
WorkerMemorySync
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-K6KL2VD6.js";
|
|
8
8
|
import {
|
|
9
9
|
Agent,
|
|
10
10
|
AutoDebugger,
|
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
setLogLevel,
|
|
35
35
|
startPipeline,
|
|
36
36
|
startWorker
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-OB6OXLPC.js";
|
|
38
38
|
import "./chunk-DGUM43GV.js";
|
|
39
39
|
export {
|
|
40
40
|
Agent,
|
package/dist/main.js
CHANGED
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
runInitCommand
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-4YXOQGQC.js";
|
|
5
5
|
import {
|
|
6
6
|
runStartCommand
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-ZA4NWNS6.js";
|
|
8
8
|
import {
|
|
9
9
|
runFleetCommand
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-4C6B2AMB.js";
|
|
11
11
|
import {
|
|
12
12
|
runServiceCommand
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-LWJCKTQP.js";
|
|
14
14
|
import {
|
|
15
15
|
runUpgradeCommand
|
|
16
16
|
} from "./chunk-ICSJNKI6.js";
|
|
17
17
|
import {
|
|
18
18
|
runWatchdogCommand
|
|
19
|
-
} from "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
19
|
+
} from "./chunk-LYL5GG2F.js";
|
|
20
|
+
import "./chunk-K6KL2VD6.js";
|
|
21
|
+
import "./chunk-OB6OXLPC.js";
|
|
22
22
|
import "./chunk-DGUM43GV.js";
|
|
23
23
|
|
|
24
24
|
// packages/cli/src/commands/session.ts
|
package/dist/start.js
CHANGED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
# Hivemind Tool Parity Plan
|
|
2
|
+
|
|
3
|
+
*Goal: Bring Hivemind tool capabilities to parity with OpenClaw/Pi, then beyond.*
|
|
4
|
+
|
|
5
|
+
*Created: 2026-03-01 | Last updated: 2026-03-01*
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Context
|
|
10
|
+
|
|
11
|
+
OpenClaw uses [Pi](https://github.com/badlogic/pi-mono/) as its underlying coding agent (see [Armin's article](https://lucumr.pocoo.org/2026/1/31/pi/)). Pi provides 4 core tools: `read`, `write`, `edit`, `bash`. OpenClaw layers orchestration on top: messaging, scheduling, sub-agents, browser control, vision, TTS, device control, and more.
|
|
12
|
+
|
|
13
|
+
Hivemind is a **headless messaging agent** (not a TUI coding agent like Pi), but it needs equivalent capabilities. Hivemind's competitive edge is its **3-layer semantic memory** (L2 episodic + L3 semantic), which neither Pi nor OpenClaw have.
|
|
14
|
+
|
|
15
|
+
**Principle: Build, don't integrate.** Study Pi's source for inspiration, write our own implementations. No external dependency risk, tailored to our headless/messaging paradigm.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## What's Already Implemented ✅
|
|
20
|
+
|
|
21
|
+
### Core Tools (shipped in v0.6.0-v0.7.2)
|
|
22
|
+
| Tool | Status | Notes |
|
|
23
|
+
|------|--------|-------|
|
|
24
|
+
| `shell` | ✅ Shipped | Workspace-scoped, configurable timeout |
|
|
25
|
+
| `read_file` | ✅ Shipped | With offset/limit for large files |
|
|
26
|
+
| `write_file` | ✅ Shipped | Auto-creates directories |
|
|
27
|
+
| `edit_file` | ✅ Shipped | Exact-match find-and-replace |
|
|
28
|
+
| `list_files` | ✅ Shipped | Directory listing |
|
|
29
|
+
| `web_search` | ✅ Shipped | Brave Search API |
|
|
30
|
+
| `web_fetch` | ✅ Shipped | URL → readable text |
|
|
31
|
+
|
|
32
|
+
### Memory Tools (shipped in v0.7.0)
|
|
33
|
+
| Tool | Status | Notes |
|
|
34
|
+
|------|--------|-------|
|
|
35
|
+
| `memory_search` | ✅ Shipped | L2 semantic search per context |
|
|
36
|
+
| `memory_contexts` | ✅ Shipped | List all contexts |
|
|
37
|
+
| `memory_l3` | ✅ Shipped | View promoted knowledge |
|
|
38
|
+
| `memory_cross_search` | ✅ Shipped | Search across all contexts |
|
|
39
|
+
|
|
40
|
+
### Infrastructure (shipped in v0.7.0)
|
|
41
|
+
| Feature | Status | Notes |
|
|
42
|
+
|---------|--------|-------|
|
|
43
|
+
| Agentic tool-use loop | ✅ Shipped | OpenAI-compatible function calling via OpenRouter, max 25 iterations |
|
|
44
|
+
| Tool registry | ✅ Shipped | Pluggable registration system |
|
|
45
|
+
| Session persistence | ✅ Shipped | JSONL per context, survives restarts |
|
|
46
|
+
| Lossless compaction | ✅ Shipped | Saves episodes to L2 before summarizing |
|
|
47
|
+
| MEMORY.md | ✅ Shipped | Global + per-context agent-managed memory files |
|
|
48
|
+
| Skills discovery | ✅ Shipped | Auto-scan workspace/skills/*/SKILL.md |
|
|
49
|
+
| Events system | ✅ Shipped | File-based immediate/one-shot/periodic scheduling |
|
|
50
|
+
| Token budget management | ✅ Shipped | Context limit + response reserve |
|
|
51
|
+
| Dashboard | ✅ Shipped | Request inspector, memory browser, context overview |
|
|
52
|
+
| Service install | ✅ Shipped | launchd services (agent + memory daemon + watchdog) |
|
|
53
|
+
| One-line installer | ✅ Shipped | `curl -sL api.sesame.space/api/v1/hivemind/install | bash -s -- <key>` |
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## What's Not Implemented Yet
|
|
58
|
+
|
|
59
|
+
### Tier 1 — Essential (Phase 1-2) ✅ COMPLETE
|
|
60
|
+
|
|
61
|
+
| # | Tool/Feature | Status | Tools Added |
|
|
62
|
+
|---|-------------|--------|------------|
|
|
63
|
+
| 1 | **Event/scheduling tools** | ✅ Shipped | `create_event`, `list_events`, `delete_event` |
|
|
64
|
+
| 2 | **Enhanced Sesame messaging** | ✅ Shipped | `send_message` |
|
|
65
|
+
| 3 | **Sub-agent spawning** | ✅ Shipped | `spawn_agent`, `list_agents`, `kill_agent` |
|
|
66
|
+
| 4 | **Web browsing** | ✅ Shipped | `browse` (extract/screenshot/click/type/evaluate) |
|
|
67
|
+
|
|
68
|
+
### Tier 2 — Important (Phase 3) ✅ COMPLETE
|
|
69
|
+
|
|
70
|
+
| # | Tool/Feature | Status | Tools Added |
|
|
71
|
+
|---|-------------|--------|------------|
|
|
72
|
+
| 5 | **Image/vision analysis** | ✅ Shipped | `analyze_image` |
|
|
73
|
+
| 6 | **Git operations** | ✅ Shipped | `git_status`, `git_diff`, `git_commit`, `git_log`, `git_push` |
|
|
74
|
+
| 7 | **Cross-context messaging** | ⬚ Deferred | (existing cross-context search covers most cases) |
|
|
75
|
+
|
|
76
|
+
### Tier 3 — System & Mac Capabilities ✅ COMPLETE
|
|
77
|
+
|
|
78
|
+
| # | Tool/Feature | Status | Tools Added |
|
|
79
|
+
|---|-------------|--------|------------|
|
|
80
|
+
| 8 | **System management** | ✅ Shipped | `system_info`, `process_list`, `process_kill`, `service_control`, `disk_usage`, `network_info` |
|
|
81
|
+
| 9 | **macOS automation** | ✅ Shipped | `run_applescript`, `notify`, `clipboard_read`, `clipboard_write`, `open_url`, `screenshot` |
|
|
82
|
+
| 10 | **Data handling** | ✅ Shipped | `sqlite_query`, `archive_create`, `archive_extract`, `pdf_extract` |
|
|
83
|
+
| 11 | **HTTP server/client** | ✅ Shipped | `http_serve`, `http_stop`, `http_request` |
|
|
84
|
+
| 12 | **File watching** | ✅ Shipped | `watch_start`, `watch_stop`, `watch_list` |
|
|
85
|
+
|
|
86
|
+
### Tier 4 — Future (not yet implemented)
|
|
87
|
+
|
|
88
|
+
| # | Tool/Feature | What It Does | Notes |
|
|
89
|
+
|---|-------------|-------------|-------|
|
|
90
|
+
| 13 | **Skills/extensions system** | Formalized hot-reloadable skills with tool registration | Inspired by Pi's extension system |
|
|
91
|
+
| 14 | **TTS** | Text-to-speech output via API | ElevenLabs API |
|
|
92
|
+
| 15 | **SSH** | Remote machine access | Could use shell + ssh CLI |
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Implementation Plan
|
|
97
|
+
|
|
98
|
+
### Phase 1: Event Tools + Enhanced Messaging
|
|
99
|
+
**Estimate: 1-2 coding sessions**
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
packages/runtime/src/tools/
|
|
103
|
+
events.ts — NEW: create_event, list_events, delete_event
|
|
104
|
+
messaging.ts — NEW: send_message (to any Sesame channel/user)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Event tools:** Wrap the existing `EventsWatcher` infrastructure. Agent can create one-shot (reminders) and periodic (cron-like) events. Events fire as messages processed by the agent.
|
|
108
|
+
|
|
109
|
+
**Messaging tools:** Use existing Sesame SDK to send messages to arbitrary channels. Agent can proactively reach out, not just reply to incoming messages.
|
|
110
|
+
|
|
111
|
+
**Dependencies:** None new. Uses existing EventsWatcher + Sesame SDK.
|
|
112
|
+
|
|
113
|
+
### Phase 2: Sub-agents + Web Browsing
|
|
114
|
+
**Estimate: 3-4 coding sessions**
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
packages/runtime/src/tools/
|
|
118
|
+
spawn.ts — NEW: spawn_agent, list_agents, kill_agent
|
|
119
|
+
browser.ts — NEW: browse_url, browser_action
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Sub-agents:** Fork a new agent process with `hivemind start --context <name> --task "<prompt>"`. Parent tracks child PIDs. Results reported back via Sesame message or shared file. Timeout and cleanup built in.
|
|
123
|
+
|
|
124
|
+
**Web browsing:** Headless Playwright for full web interaction. Agent can navigate, click, fill forms, extract content from JS-rendered pages. Single dependency (`playwright`), but it's the right tool for this — curl/fetch can't handle SPAs, authentication flows, or dynamic content.
|
|
125
|
+
|
|
126
|
+
**Why Playwright:** We considered avoiding it (heavy dep), but web browsing is a core capability for agents that need to "do anything a human can do on a computer." Pi/OpenClaw use it. The alternative (shell + curl) only handles static pages.
|
|
127
|
+
|
|
128
|
+
### Phase 3: Vision + Git
|
|
129
|
+
**Estimate: 1-2 coding sessions**
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
packages/runtime/src/tools/
|
|
133
|
+
vision.ts — NEW: analyze_image
|
|
134
|
+
git.ts — NEW: git_status, git_diff, git_commit, git_push
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
**Vision:** Single HTTP call to OpenRouter with vision-capable model. Accept image URL or base64.
|
|
138
|
+
|
|
139
|
+
**Git:** Thin wrappers around git CLI with structured output. Reduces token usage vs raw `shell` git output. Safety: confirmation before push.
|
|
140
|
+
|
|
141
|
+
### Phase 4: Skills/Extensions System
|
|
142
|
+
**Estimate: 2-3 coding sessions**
|
|
143
|
+
|
|
144
|
+
Formalize the existing skills discovery into a proper extension system:
|
|
145
|
+
- Skills can register new tools dynamically
|
|
146
|
+
- Hot-reload on file change (inspired by Pi's extension system)
|
|
147
|
+
- Agent can write and install its own skills
|
|
148
|
+
- Skills persist across restarts
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Architecture Notes
|
|
153
|
+
|
|
154
|
+
### Tool Registration Pattern
|
|
155
|
+
All tools follow the existing registry pattern:
|
|
156
|
+
```typescript
|
|
157
|
+
// Each tool file exports a register function
|
|
158
|
+
export function registerEventTools(registry: ToolRegistry, dataDir: string): void {
|
|
159
|
+
registry.register("create_event", description, schema, executor);
|
|
160
|
+
// ...
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Security Model
|
|
165
|
+
- **Shell:** Workspace-scoped, configurable timeout (existing)
|
|
166
|
+
- **Files:** Scoped to workspace (existing)
|
|
167
|
+
- **Messaging:** Authenticated via existing Sesame connection
|
|
168
|
+
- **Sub-agents:** Inherit parent permissions, isolated context
|
|
169
|
+
- **Events:** File-based, local only
|
|
170
|
+
- **Browser:** Sandboxed Playwright instance, no persistent state
|
|
171
|
+
- **Git:** Confirmation before push
|
|
172
|
+
|
|
173
|
+
### What Hivemind Has That OpenClaw/Pi Don't
|
|
174
|
+
- **3-layer semantic memory** (L2 episodic + L3 semantic with automatic promotion)
|
|
175
|
+
- **Cross-context knowledge sharing** with isolation by default
|
|
176
|
+
- **Memory-augmented responses** (every LLM call enriched with relevant history)
|
|
177
|
+
- **Dashboard** for debugging LLM calls + memory state
|
|
178
|
+
- **Token budget management** with configurable limits
|
|
179
|
+
|
|
180
|
+
This isn't just parity — it's parity + memory, which is the competitive edge.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
184
|
+
## Superseded Documents
|
|
185
|
+
|
|
186
|
+
- `TOOL-USE-DESIGN.md` (root) — Original tool architecture design. **Fully implemented** in v0.6.0-v0.7.2. Kept for historical reference.
|
|
187
|
+
- `DASHBOARD-PLAN.md` (root) — Dashboard design. **Fully implemented**. Kept for reference.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
*This is the authoritative plan for Hivemind tool development. Update this document as phases complete.*
|
package/package.json
CHANGED
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sesamespace/hivemind",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Cognitive architecture for AI agents with multi-layered memory",
|
|
5
|
-
"
|
|
6
|
-
|
|
7
|
-
"
|
|
5
|
+
"scripts": {
|
|
6
|
+
"build": "tsup",
|
|
7
|
+
"typecheck": "pnpm -r typecheck",
|
|
8
|
+
"lint": "pnpm -r lint",
|
|
9
|
+
"test": "pnpm -r test",
|
|
10
|
+
"prepublishOnly": "pnpm install --frozen-lockfile && tsup"
|
|
8
11
|
},
|
|
9
|
-
"files": [
|
|
10
|
-
"dist/",
|
|
11
|
-
"config/",
|
|
12
|
-
"packages/memory/",
|
|
13
|
-
"install.sh",
|
|
14
|
-
"README.md"
|
|
15
|
-
],
|
|
16
12
|
"engines": {
|
|
17
|
-
"node": ">=20.0.0"
|
|
13
|
+
"node": ">=20.0.0",
|
|
14
|
+
"pnpm": ">=9.0.0"
|
|
18
15
|
},
|
|
19
16
|
"dependencies": {
|
|
20
|
-
"
|
|
17
|
+
"@sesamespace/sdk": "^0.1.6",
|
|
18
|
+
"smol-toml": "^1.6.0",
|
|
19
|
+
"axios": "^1.7.9",
|
|
20
|
+
"express": "^4.21.2"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"tsup": "^8.5.1"
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"hivemind": "dist/main.js"
|
|
21
27
|
},
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"sesame",
|
|
27
|
-
"cognitive-architecture"
|
|
28
|
-
],
|
|
29
|
-
"license": "UNLICENSED",
|
|
30
|
-
"repository": {
|
|
31
|
-
"type": "git",
|
|
32
|
-
"url": "https://github.com/baileydavis2026/hivemind"
|
|
28
|
+
"pnpm": {
|
|
29
|
+
"onlyBuiltDependencies": [
|
|
30
|
+
"better-sqlite3"
|
|
31
|
+
]
|
|
33
32
|
}
|
|
34
33
|
}
|