@sesamespace/hivemind 0.5.4 → 0.5.5

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.
Files changed (96) hide show
  1. package/.github/workflows/memory-release.yml +89 -0
  2. package/config/default.toml +12 -0
  3. package/data/lancedb/contexts.lance/_transactions/0-c4755ab9-b604-4d90-851f-0491f3cbcbce.txn +2 -0
  4. package/data/lancedb/contexts.lance/_versions/1.manifest +0 -0
  5. package/data/lancedb/episode_access.lance/_transactions/0-407a6366-0dca-490a-868b-ea63bee3b40c.txn +2 -0
  6. package/data/lancedb/episode_access.lance/_versions/1.manifest +0 -0
  7. package/data/lancedb/episode_cooccurrence.lance/_transactions/0-0e103c7f-29d7-4f09-8100-505c076f01ae.txn +1 -0
  8. package/data/lancedb/episode_cooccurrence.lance/_versions/1.manifest +0 -0
  9. package/data/lancedb/episodes.lance/_transactions/0-e678cbac-792b-4a9d-a457-17b0d4d23607.txn +1 -0
  10. package/data/lancedb/episodes.lance/_versions/1.manifest +0 -0
  11. package/data/lancedb/l3_knowledge.lance/_transactions/0-cdb3561f-3a59-4e15-bded-e93c5f9a50e3.txn +1 -0
  12. package/data/lancedb/l3_knowledge.lance/_versions/1.manifest +0 -0
  13. package/data/lancedb/tasks.lance/_transactions/0-d1cf10ec-1eb8-48b4-bbbe-34b3a1083664.txn +4 -0
  14. package/data/lancedb/tasks.lance/_versions/1.manifest +0 -0
  15. package/dist/{chunk-MHDLSAJ3.js → chunk-2OIRJFI5.js} +14 -30
  16. package/dist/chunk-2OIRJFI5.js.map +1 -0
  17. package/dist/chunk-7D4SUZUM.js +38 -0
  18. package/dist/chunk-7D4SUZUM.js.map +1 -0
  19. package/dist/chunk-LRK64BAK.js +3601 -0
  20. package/dist/chunk-LRK64BAK.js.map +1 -0
  21. package/dist/chunk-MBS5A6BZ.js +132 -0
  22. package/dist/chunk-MBS5A6BZ.js.map +1 -0
  23. package/dist/{chunk-LNV373IF.js → chunk-OQ272HKA.js} +3 -28
  24. package/dist/chunk-OQ272HKA.js.map +1 -0
  25. package/dist/{chunk-CGSXJVSS.js → chunk-RXCV57H3.js} +2 -2
  26. package/dist/{chunk-S3RVZBPZ.js → chunk-YEOAEJ62.js} +2 -2
  27. package/dist/commands/fleet.js +4 -3
  28. package/dist/commands/init.js +2 -1
  29. package/dist/commands/service.js +2 -1
  30. package/dist/commands/start.js +4 -3
  31. package/dist/commands/upgrade.js +1 -0
  32. package/dist/index.js +3 -2
  33. package/dist/main.js +7 -6
  34. package/dist/main.js.map +1 -1
  35. package/dist/start.js +2 -1
  36. package/dist/start.js.map +1 -1
  37. package/package.json +1 -1
  38. package/PLANNING.md +0 -383
  39. package/TASKS.md +0 -60
  40. package/dist/chunk-LNV373IF.js.map +0 -1
  41. package/dist/chunk-MHDLSAJ3.js.map +0 -1
  42. package/dist/chunk-PPQGQHXJ.js +0 -151
  43. package/dist/chunk-PPQGQHXJ.js.map +0 -1
  44. package/dist/chunk-YHRGEWAZ.js +0 -2326
  45. package/dist/chunk-YHRGEWAZ.js.map +0 -1
  46. package/install.sh +0 -120
  47. package/npm-package.json +0 -26
  48. package/packages/cli/package.json +0 -23
  49. package/packages/cli/src/commands/fleet.ts +0 -206
  50. package/packages/cli/src/commands/init.ts +0 -252
  51. package/packages/cli/src/commands/service.ts +0 -159
  52. package/packages/cli/src/commands/start.ts +0 -78
  53. package/packages/cli/src/commands/upgrade.ts +0 -158
  54. package/packages/cli/src/main.ts +0 -64
  55. package/packages/cli/tsconfig.json +0 -8
  56. package/packages/memory/Cargo.lock +0 -6480
  57. package/packages/memory/Cargo.toml +0 -21
  58. package/packages/memory/src/context.rs +0 -179
  59. package/packages/memory/src/embeddings.rs +0 -51
  60. package/packages/memory/src/main.rs +0 -626
  61. package/packages/memory/src/promotion.rs +0 -637
  62. package/packages/memory/src/scoring.rs +0 -131
  63. package/packages/memory/src/store.rs +0 -460
  64. package/packages/memory/src/tasks.rs +0 -321
  65. package/packages/runtime/package.json +0 -24
  66. package/packages/runtime/src/__tests__/fleet-integration.test.ts +0 -235
  67. package/packages/runtime/src/__tests__/fleet.test.ts +0 -207
  68. package/packages/runtime/src/__tests__/integration.test.ts +0 -434
  69. package/packages/runtime/src/agent.ts +0 -255
  70. package/packages/runtime/src/config.ts +0 -130
  71. package/packages/runtime/src/context.ts +0 -192
  72. package/packages/runtime/src/fleet/fleet-manager.ts +0 -399
  73. package/packages/runtime/src/fleet/memory-sync.ts +0 -362
  74. package/packages/runtime/src/fleet/primary-client.ts +0 -285
  75. package/packages/runtime/src/fleet/worker-protocol.ts +0 -158
  76. package/packages/runtime/src/fleet/worker-server.ts +0 -246
  77. package/packages/runtime/src/index.ts +0 -57
  78. package/packages/runtime/src/llm-client.ts +0 -65
  79. package/packages/runtime/src/memory-client.ts +0 -309
  80. package/packages/runtime/src/pipeline.ts +0 -187
  81. package/packages/runtime/src/prompt.ts +0 -173
  82. package/packages/runtime/src/sesame.ts +0 -226
  83. package/packages/runtime/src/start.ts +0 -20
  84. package/packages/runtime/src/task-engine.ts +0 -113
  85. package/packages/runtime/src/worker.ts +0 -339
  86. package/packages/runtime/tsconfig.json +0 -8
  87. package/pnpm-workspace.yaml +0 -2
  88. package/run-aidan.sh +0 -23
  89. package/scripts/bootstrap.sh +0 -196
  90. package/scripts/build-npm.sh +0 -92
  91. package/scripts/com.hivemind.agent.plist +0 -44
  92. package/scripts/com.hivemind.memory.plist +0 -31
  93. package/tsconfig.json +0 -22
  94. package/tsup.config.ts +0 -27
  95. /package/dist/{chunk-CGSXJVSS.js.map → chunk-RXCV57H3.js.map} +0 -0
  96. /package/dist/{chunk-S3RVZBPZ.js.map → chunk-YEOAEJ62.js.map} +0 -0
@@ -1,399 +0,0 @@
1
- /**
2
- * Fleet Manager — high-level orchestration layer on top of PrimaryClient.
3
- *
4
- * Provides:
5
- * - Worker provisioning (register by URL)
6
- * - Context assignment and migration between workers
7
- * - Aggregate fleet status / dashboard data
8
- * - Worker discovery and removal
9
- */
10
-
11
- import { PrimaryClient } from "./primary-client.js";
12
- import {
13
- WORKER_ROUTES,
14
- HEALTH_TIMEOUT_MS,
15
- } from "./worker-protocol.js";
16
- import type {
17
- WorkerInfo,
18
- WorkerHealthResponse,
19
- WorkerHealthStatus,
20
- WorkerCapabilities,
21
- ContextAssignResponse,
22
- WorkerStatus,
23
- WorkerActivity,
24
- } from "./worker-protocol.js";
25
-
26
- // --- Dashboard Types ---
27
-
28
- export interface WorkerSummary {
29
- id: string;
30
- url: string;
31
- health: WorkerHealthStatus;
32
- contexts: string[];
33
- current_task: string | null;
34
- activity: WorkerActivity;
35
- uptime_seconds: number | null;
36
- capabilities: WorkerCapabilities;
37
- last_heartbeat: string;
38
- }
39
-
40
- export interface FleetDashboard {
41
- total_workers: number;
42
- healthy: number;
43
- degraded: number;
44
- unreachable: number;
45
- total_contexts: number;
46
- workers: WorkerSummary[];
47
- unassigned_contexts: string[];
48
- generated_at: string;
49
- }
50
-
51
- export interface MigrationResult {
52
- context_name: string;
53
- from_worker: string;
54
- to_worker: string;
55
- success: boolean;
56
- reason?: string;
57
- }
58
-
59
- export class FleetManager {
60
- private primary: PrimaryClient;
61
- private latestHealth: Map<string, WorkerHealthResponse> = new Map();
62
- private latestStatus: Map<string, WorkerStatus> = new Map();
63
- private knownContexts: Set<string> = new Set();
64
-
65
- constructor(primary?: PrimaryClient) {
66
- this.primary = primary ?? new PrimaryClient();
67
- }
68
-
69
- getPrimary(): PrimaryClient {
70
- return this.primary;
71
- }
72
-
73
- // --- Worker Provisioning ---
74
-
75
- /**
76
- * Register a new worker by URL. Probes the worker's health endpoint
77
- * to discover capabilities, then registers it with the Primary.
78
- */
79
- async addWorker(url: string): Promise<WorkerInfo> {
80
- // Normalise trailing slash
81
- const baseUrl = url.replace(/\/+$/, "");
82
-
83
- // Probe worker health to discover capabilities
84
- const capabilities = await this.probeWorker(baseUrl);
85
-
86
- const reg = this.primary.handleRegistration({ url: baseUrl, capabilities });
87
-
88
- const worker = this.primary.getWorker(reg.worker_id);
89
- if (!worker) {
90
- throw new Error("Worker registered but not found in registry");
91
- }
92
-
93
- return worker;
94
- }
95
-
96
- /** Remove a worker from the fleet, unassigning its contexts first. */
97
- async removeWorker(workerId: string): Promise<boolean> {
98
- const worker = this.primary.getWorker(workerId);
99
- if (!worker) return false;
100
-
101
- // Unassign all contexts from this worker
102
- for (const ctx of [...worker.assigned_contexts]) {
103
- await this.primary.unassignContext(workerId, ctx);
104
- }
105
-
106
- return this.primary.deregister(workerId);
107
- }
108
-
109
- // --- Context Assignment ---
110
-
111
- /** Assign a context to a specific worker. */
112
- async assignContext(
113
- workerId: string,
114
- contextName: string,
115
- description = "",
116
- ): Promise<ContextAssignResponse> {
117
- const result = await this.primary.assignContext(workerId, contextName, description);
118
- if (result.accepted) {
119
- this.knownContexts.add(contextName);
120
- }
121
- return result;
122
- }
123
-
124
- /** Migrate a context from one worker to another. */
125
- async migrateContext(
126
- contextName: string,
127
- toWorkerId: string,
128
- ): Promise<MigrationResult> {
129
- const fromWorker = this.primary.findWorkerForContext(contextName);
130
-
131
- if (!fromWorker) {
132
- // Context isn't assigned anywhere — just assign to target
133
- const resp = await this.primary.assignContext(toWorkerId, contextName);
134
- return {
135
- context_name: contextName,
136
- from_worker: "(none)",
137
- to_worker: toWorkerId,
138
- success: resp.accepted,
139
- reason: resp.accepted ? undefined : resp.reason,
140
- };
141
- }
142
-
143
- if (fromWorker.id === toWorkerId) {
144
- return {
145
- context_name: contextName,
146
- from_worker: fromWorker.id,
147
- to_worker: toWorkerId,
148
- success: false,
149
- reason: "Context already assigned to this worker",
150
- };
151
- }
152
-
153
- // Assign to new worker first, then unassign from old
154
- const assignResult = await this.primary.assignContext(toWorkerId, contextName);
155
- if (!assignResult.accepted) {
156
- return {
157
- context_name: contextName,
158
- from_worker: fromWorker.id,
159
- to_worker: toWorkerId,
160
- success: false,
161
- reason: assignResult.reason ?? "Target worker rejected assignment",
162
- };
163
- }
164
-
165
- await this.primary.unassignContext(fromWorker.id, contextName);
166
-
167
- return {
168
- context_name: contextName,
169
- from_worker: fromWorker.id,
170
- to_worker: toWorkerId,
171
- success: true,
172
- };
173
- }
174
-
175
- // --- Status & Health ---
176
-
177
- /** Refresh health for all workers. */
178
- async refreshHealth(): Promise<void> {
179
- const workers = this.primary.getWorkers();
180
-
181
- const checks = workers.map(async (w) => {
182
- const health = await this.primary.checkHealth(w.id);
183
- if (health) {
184
- this.latestHealth.set(w.id, health);
185
- } else {
186
- // Mark unreachable but keep stale data
187
- this.latestHealth.set(w.id, {
188
- worker_id: w.id,
189
- status: "unreachable",
190
- uptime_seconds: 0,
191
- assigned_contexts: w.assigned_contexts,
192
- active_context: null,
193
- memory_daemon_ok: false,
194
- ollama_ok: false,
195
- });
196
- }
197
- });
198
-
199
- await Promise.all(checks);
200
- }
201
-
202
- /** Record a status report (called when worker POSTs status to Primary). */
203
- recordStatus(workerId: string, status: WorkerStatus): void {
204
- this.latestStatus.set(workerId, status);
205
- }
206
-
207
- /** Get the full fleet dashboard. */
208
- async getDashboard(): Promise<FleetDashboard> {
209
- await this.refreshHealth();
210
-
211
- const workers = this.primary.getWorkers();
212
- let healthy = 0;
213
- let degraded = 0;
214
- let unreachable = 0;
215
- let totalContexts = 0;
216
-
217
- const workerSummaries: WorkerSummary[] = workers.map((w) => {
218
- const health = this.latestHealth.get(w.id);
219
- const status = this.latestStatus.get(w.id);
220
-
221
- const healthStatus: WorkerHealthStatus = health?.status ?? "unreachable";
222
- if (healthStatus === "healthy") healthy++;
223
- else if (healthStatus === "degraded") degraded++;
224
- else unreachable++;
225
-
226
- totalContexts += w.assigned_contexts.length;
227
-
228
- return {
229
- id: w.id,
230
- url: w.url,
231
- health: healthStatus,
232
- contexts: w.assigned_contexts,
233
- current_task: status?.current_task ?? null,
234
- activity: status?.activity ?? "idle",
235
- uptime_seconds: health?.uptime_seconds ?? null,
236
- capabilities: w.capabilities,
237
- last_heartbeat: w.last_heartbeat,
238
- };
239
- });
240
-
241
- // Determine unassigned contexts
242
- const assignedContexts = new Set(workers.flatMap((w) => w.assigned_contexts));
243
- const unassigned = [...this.knownContexts].filter((c) => !assignedContexts.has(c));
244
-
245
- return {
246
- total_workers: workers.length,
247
- healthy,
248
- degraded,
249
- unreachable,
250
- total_contexts: totalContexts,
251
- workers: workerSummaries,
252
- unassigned_contexts: unassigned,
253
- generated_at: new Date().toISOString(),
254
- };
255
- }
256
-
257
- /** Get a quick status summary without refreshing health. */
258
- getStatusSnapshot(): FleetDashboard {
259
- const workers = this.primary.getWorkers();
260
- let healthy = 0;
261
- let degraded = 0;
262
- let unreachable = 0;
263
- let totalContexts = 0;
264
-
265
- const workerSummaries: WorkerSummary[] = workers.map((w) => {
266
- const health = this.latestHealth.get(w.id);
267
- const status = this.latestStatus.get(w.id);
268
-
269
- const healthStatus: WorkerHealthStatus = health?.status ?? "unreachable";
270
- if (healthStatus === "healthy") healthy++;
271
- else if (healthStatus === "degraded") degraded++;
272
- else unreachable++;
273
-
274
- totalContexts += w.assigned_contexts.length;
275
-
276
- return {
277
- id: w.id,
278
- url: w.url,
279
- health: healthStatus,
280
- contexts: w.assigned_contexts,
281
- current_task: status?.current_task ?? null,
282
- activity: status?.activity ?? "idle",
283
- uptime_seconds: health?.uptime_seconds ?? null,
284
- capabilities: w.capabilities,
285
- last_heartbeat: w.last_heartbeat,
286
- };
287
- });
288
-
289
- const assignedContexts = new Set(workers.flatMap((w) => w.assigned_contexts));
290
- const unassigned = [...this.knownContexts].filter((c) => !assignedContexts.has(c));
291
-
292
- return {
293
- total_workers: workers.length,
294
- healthy,
295
- degraded,
296
- unreachable,
297
- total_contexts: totalContexts,
298
- workers: workerSummaries,
299
- unassigned_contexts: unassigned,
300
- generated_at: new Date().toISOString(),
301
- };
302
- }
303
-
304
- // --- Worker Discovery ---
305
-
306
- /**
307
- * Scan a list of candidate URLs for workers. Returns the URLs
308
- * that responded to a health probe. Useful for auto-detecting
309
- * workers on a local network.
310
- */
311
- async discoverWorkers(candidateUrls: string[]): Promise<string[]> {
312
- const found: string[] = [];
313
-
314
- const probes = candidateUrls.map(async (url) => {
315
- const baseUrl = url.replace(/\/+$/, "");
316
- try {
317
- const controller = new AbortController();
318
- const timeout = setTimeout(() => controller.abort(), HEALTH_TIMEOUT_MS);
319
-
320
- const resp = await fetch(`${baseUrl}${WORKER_ROUTES.health}`, {
321
- signal: controller.signal,
322
- });
323
- clearTimeout(timeout);
324
-
325
- if (resp.ok) {
326
- found.push(baseUrl);
327
- }
328
- } catch {
329
- // Not reachable, skip
330
- }
331
- });
332
-
333
- await Promise.all(probes);
334
- return found;
335
- }
336
-
337
- /**
338
- * Scan a subnet-style range for workers. Generates URLs for
339
- * a base IP with ports and probes them.
340
- * Example: scanSubnet("192.168.1", [10, 11, 12], 3100)
341
- */
342
- async scanSubnet(
343
- baseIp: string,
344
- hostIds: number[],
345
- port: number,
346
- ): Promise<string[]> {
347
- const urls = hostIds.map((id) => `http://${baseIp}.${id}:${port}`);
348
- return this.discoverWorkers(urls);
349
- }
350
-
351
- /** Track a context name so it appears in unassigned lists. */
352
- registerContext(contextName: string): void {
353
- this.knownContexts.add(contextName);
354
- }
355
-
356
- /** Start health polling (delegates to PrimaryClient). */
357
- startHealthPolling(intervalMs?: number): void {
358
- this.primary.startHealthPolling(intervalMs);
359
- }
360
-
361
- /** Stop health polling. */
362
- stopHealthPolling(): void {
363
- this.primary.stopHealthPolling();
364
- }
365
-
366
- // --- Internal ---
367
-
368
- private async probeWorker(baseUrl: string): Promise<WorkerCapabilities> {
369
- try {
370
- const controller = new AbortController();
371
- const timeout = setTimeout(() => controller.abort(), HEALTH_TIMEOUT_MS);
372
-
373
- const resp = await fetch(`${baseUrl}${WORKER_ROUTES.health}`, {
374
- signal: controller.signal,
375
- });
376
- clearTimeout(timeout);
377
-
378
- if (resp.ok) {
379
- const health = (await resp.json()) as WorkerHealthResponse;
380
- return {
381
- max_contexts: health.assigned_contexts.length + 4, // assume capacity
382
- has_ollama: health.ollama_ok,
383
- has_memory_daemon: health.memory_daemon_ok,
384
- available_models: [],
385
- };
386
- }
387
- } catch {
388
- // Fall through to defaults
389
- }
390
-
391
- // Return default capabilities if probe fails
392
- return {
393
- max_contexts: 4,
394
- has_ollama: false,
395
- has_memory_daemon: false,
396
- available_models: [],
397
- };
398
- }
399
- }