@sesamespace/hivemind 0.5.4 → 0.5.7

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 (86) hide show
  1. package/.github/workflows/memory-release.yml +89 -0
  2. package/config/default.toml +12 -0
  3. package/dist/{chunk-YHRGEWAZ.js → chunk-4U4GKI3X.js} +121 -34
  4. package/dist/chunk-4U4GKI3X.js.map +1 -0
  5. package/{packages/cli/src/commands/start.ts → dist/chunk-62S2NGMN.js} +39 -38
  6. package/dist/chunk-62S2NGMN.js.map +1 -0
  7. package/dist/{chunk-CGSXJVSS.js → chunk-7RTJSPMX.js} +2 -2
  8. package/dist/chunk-IJRAVHQC.js +327 -0
  9. package/dist/chunk-IJRAVHQC.js.map +1 -0
  10. package/dist/{chunk-MHDLSAJ3.js → chunk-JXLLCKMG.js} +102 -5
  11. package/dist/chunk-JXLLCKMG.js.map +1 -0
  12. package/dist/{chunk-SJI2KAIN.js → chunk-LJHJGDKY.js} +8 -2
  13. package/dist/chunk-LJHJGDKY.js.map +1 -0
  14. package/dist/{chunk-LNV373IF.js → chunk-LSOEUOTO.js} +2 -2
  15. package/dist/{chunk-S3RVZBPZ.js → chunk-PFN3BITA.js} +322 -2
  16. package/dist/chunk-PFN3BITA.js.map +1 -0
  17. package/dist/commands/fleet.js +3 -3
  18. package/dist/commands/init.js +1 -1
  19. package/dist/commands/service.js +1 -1
  20. package/dist/commands/start.js +3 -3
  21. package/dist/commands/upgrade.js +1 -1
  22. package/dist/commands/watchdog.js +10 -0
  23. package/dist/commands/watchdog.js.map +1 -0
  24. package/dist/index.js +6 -2
  25. package/dist/main.js +22 -12
  26. package/dist/main.js.map +1 -1
  27. package/dist/start.js +1 -1
  28. package/package.json +4 -3
  29. package/PLANNING.md +0 -383
  30. package/TASKS.md +0 -60
  31. package/dist/chunk-MHDLSAJ3.js.map +0 -1
  32. package/dist/chunk-PPQGQHXJ.js +0 -151
  33. package/dist/chunk-PPQGQHXJ.js.map +0 -1
  34. package/dist/chunk-S3RVZBPZ.js.map +0 -1
  35. package/dist/chunk-SJI2KAIN.js.map +0 -1
  36. package/dist/chunk-YHRGEWAZ.js.map +0 -1
  37. package/install.sh +0 -120
  38. package/npm-package.json +0 -26
  39. package/packages/cli/package.json +0 -23
  40. package/packages/cli/src/commands/fleet.ts +0 -206
  41. package/packages/cli/src/commands/init.ts +0 -252
  42. package/packages/cli/src/commands/service.ts +0 -159
  43. package/packages/cli/src/commands/upgrade.ts +0 -158
  44. package/packages/cli/src/main.ts +0 -64
  45. package/packages/cli/tsconfig.json +0 -8
  46. package/packages/memory/Cargo.lock +0 -6480
  47. package/packages/memory/Cargo.toml +0 -21
  48. package/packages/memory/src/context.rs +0 -179
  49. package/packages/memory/src/embeddings.rs +0 -51
  50. package/packages/memory/src/main.rs +0 -626
  51. package/packages/memory/src/promotion.rs +0 -637
  52. package/packages/memory/src/scoring.rs +0 -131
  53. package/packages/memory/src/store.rs +0 -460
  54. package/packages/memory/src/tasks.rs +0 -321
  55. package/packages/runtime/package.json +0 -24
  56. package/packages/runtime/src/__tests__/fleet-integration.test.ts +0 -235
  57. package/packages/runtime/src/__tests__/fleet.test.ts +0 -207
  58. package/packages/runtime/src/__tests__/integration.test.ts +0 -434
  59. package/packages/runtime/src/agent.ts +0 -255
  60. package/packages/runtime/src/config.ts +0 -130
  61. package/packages/runtime/src/context.ts +0 -192
  62. package/packages/runtime/src/fleet/fleet-manager.ts +0 -399
  63. package/packages/runtime/src/fleet/memory-sync.ts +0 -362
  64. package/packages/runtime/src/fleet/primary-client.ts +0 -285
  65. package/packages/runtime/src/fleet/worker-protocol.ts +0 -158
  66. package/packages/runtime/src/fleet/worker-server.ts +0 -246
  67. package/packages/runtime/src/index.ts +0 -57
  68. package/packages/runtime/src/llm-client.ts +0 -65
  69. package/packages/runtime/src/memory-client.ts +0 -309
  70. package/packages/runtime/src/pipeline.ts +0 -187
  71. package/packages/runtime/src/prompt.ts +0 -173
  72. package/packages/runtime/src/sesame.ts +0 -226
  73. package/packages/runtime/src/start.ts +0 -20
  74. package/packages/runtime/src/task-engine.ts +0 -113
  75. package/packages/runtime/src/worker.ts +0 -339
  76. package/packages/runtime/tsconfig.json +0 -8
  77. package/pnpm-workspace.yaml +0 -2
  78. package/run-aidan.sh +0 -23
  79. package/scripts/bootstrap.sh +0 -196
  80. package/scripts/build-npm.sh +0 -92
  81. package/scripts/com.hivemind.agent.plist +0 -44
  82. package/scripts/com.hivemind.memory.plist +0 -31
  83. package/tsconfig.json +0 -22
  84. package/tsup.config.ts +0 -27
  85. /package/dist/{chunk-CGSXJVSS.js.map → chunk-7RTJSPMX.js.map} +0 -0
  86. /package/dist/{chunk-LNV373IF.js.map → chunk-LSOEUOTO.js.map} +0 -0
@@ -1,158 +0,0 @@
1
- /**
2
- * Shared types for Primary <-> Worker communication protocol.
3
- *
4
- * Communication is HTTP-based:
5
- * - Primary calls Worker endpoints to assign contexts, check health
6
- * - Worker calls Primary endpoints to register, report status
7
- */
8
-
9
- // --- Worker Identity & Registration ---
10
-
11
- export interface WorkerInfo {
12
- id: string;
13
- url: string;
14
- capabilities: WorkerCapabilities;
15
- assigned_contexts: string[];
16
- registered_at: string;
17
- last_heartbeat: string;
18
- }
19
-
20
- export interface WorkerCapabilities {
21
- max_contexts: number;
22
- has_ollama: boolean;
23
- has_memory_daemon: boolean;
24
- available_models: string[];
25
- }
26
-
27
- export interface WorkerRegistrationRequest {
28
- url: string;
29
- capabilities: WorkerCapabilities;
30
- }
31
-
32
- export interface WorkerRegistrationResponse {
33
- worker_id: string;
34
- registered_at: string;
35
- }
36
-
37
- // --- Health Checks ---
38
-
39
- export type WorkerHealthStatus = "healthy" | "degraded" | "unreachable";
40
-
41
- export interface WorkerHealthResponse {
42
- worker_id: string;
43
- status: WorkerHealthStatus;
44
- uptime_seconds: number;
45
- assigned_contexts: string[];
46
- active_context: string | null;
47
- memory_daemon_ok: boolean;
48
- ollama_ok: boolean;
49
- }
50
-
51
- // --- Context Assignment ---
52
-
53
- export interface ContextAssignment {
54
- context_name: string;
55
- context_description: string;
56
- assigned_at: string;
57
- }
58
-
59
- export interface ContextAssignRequest {
60
- context_name: string;
61
- context_description: string;
62
- }
63
-
64
- export interface ContextAssignResponse {
65
- context_name: string;
66
- accepted: boolean;
67
- reason?: string;
68
- }
69
-
70
- // --- Worker Status Reporting ---
71
-
72
- export type WorkerActivity = "idle" | "working" | "error";
73
-
74
- export interface WorkerStatus {
75
- worker_id: string;
76
- activity: WorkerActivity;
77
- current_context: string | null;
78
- current_task: string | null;
79
- error?: string;
80
- reported_at: string;
81
- }
82
-
83
- export interface WorkerStatusReport {
84
- activity: WorkerActivity;
85
- current_context: string | null;
86
- current_task: string | null;
87
- error?: string;
88
- }
89
-
90
- // --- Memory Sync ---
91
-
92
- /** L3 knowledge entries synced from Worker to Primary. */
93
- export interface SyncPullRequest {
94
- worker_id: string;
95
- context_name: string;
96
- entries: SyncL3Entry[];
97
- }
98
-
99
- /** An L3 entry with a last-modified timestamp for conflict resolution. */
100
- export interface SyncL3Entry {
101
- id: string;
102
- source_episode_id: string;
103
- context_name: string;
104
- content: string;
105
- promoted_at: string;
106
- access_count: number;
107
- connection_density: number;
108
- updated_at: string;
109
- }
110
-
111
- export interface SyncPullResponse {
112
- accepted: number;
113
- rejected: number;
114
- }
115
-
116
- /** Global context updates pushed from Primary to Worker. */
117
- export interface SyncPushRequest {
118
- entries: SyncL3Entry[];
119
- episodes: SyncL2Episode[];
120
- }
121
-
122
- /** L2 episodes synced as append-only (no conflict resolution needed). */
123
- export interface SyncL2Episode {
124
- id: string;
125
- timestamp: string;
126
- context_name: string;
127
- role: string;
128
- content: string;
129
- }
130
-
131
- export interface SyncPushResponse {
132
- l3_accepted: number;
133
- l2_appended: number;
134
- }
135
-
136
- // --- Protocol Constants ---
137
-
138
- export const WORKER_API_PREFIX = "/workers";
139
-
140
- /** Primary-side routes (Worker calls these) */
141
- export const PRIMARY_ROUTES = {
142
- register: `${WORKER_API_PREFIX}/register`,
143
- status: (workerId: string) => `${WORKER_API_PREFIX}/${encodeURIComponent(workerId)}/status`,
144
- syncPull: `${WORKER_API_PREFIX}/sync/pull`,
145
- } as const;
146
-
147
- /** Worker-side routes (Primary calls these) */
148
- export const WORKER_ROUTES = {
149
- health: "/health",
150
- assign: "/assign",
151
- unassign: (contextName: string) => `/assign/${encodeURIComponent(contextName)}`,
152
- status: "/status",
153
- syncPush: "/sync/push",
154
- } as const;
155
-
156
- export const DEFAULT_HEALTH_INTERVAL_MS = 30_000;
157
- export const HEALTH_TIMEOUT_MS = 5_000;
158
- export const DEFAULT_SYNC_INTERVAL_MS = 60_000;
@@ -1,246 +0,0 @@
1
- /**
2
- * Worker-side HTTP server that exposes endpoints for the Primary to call.
3
- *
4
- * Uses Node's built-in http module — no external framework needed for these few routes.
5
- *
6
- * Endpoints:
7
- * GET /health — Health check
8
- * POST /assign — Accept a context assignment
9
- * DELETE /assign/:contextName — Release a context
10
- * GET /status — Current activity status
11
- */
12
-
13
- import { createServer, type Server, type IncomingMessage, type ServerResponse } from "http";
14
- import type {
15
- WorkerHealthResponse,
16
- WorkerStatusReport,
17
- ContextAssignRequest,
18
- ContextAssignResponse,
19
- ContextAssignment,
20
- SyncPushRequest,
21
- SyncPushResponse,
22
- } from "./worker-protocol.js";
23
-
24
- export interface WorkerServerOptions {
25
- workerId: string;
26
- port: number;
27
- maxContexts?: number;
28
- memoryDaemonUrl?: string;
29
- ollamaUrl?: string;
30
- }
31
-
32
- export class WorkerServer {
33
- private server: Server | null = null;
34
- private workerId: string;
35
- private port: number;
36
- private startTime: number;
37
- private assignedContexts: Map<string, ContextAssignment> = new Map();
38
- private activeContext: string | null = null;
39
- private currentTask: string | null = null;
40
- private maxContexts: number;
41
- private memoryDaemonUrl: string | null;
42
- private ollamaUrl: string | null;
43
- private onAssignCallback: ((contextName: string, description: string) => void) | null = null;
44
- private onSyncPushCallback: ((req: SyncPushRequest) => Promise<SyncPushResponse>) | null = null;
45
-
46
- constructor(opts: WorkerServerOptions) {
47
- this.workerId = opts.workerId;
48
- this.port = opts.port;
49
- this.startTime = Date.now();
50
- this.maxContexts = opts.maxContexts ?? 4;
51
- this.memoryDaemonUrl = opts.memoryDaemonUrl ?? null;
52
- this.ollamaUrl = opts.ollamaUrl ?? null;
53
- }
54
-
55
- /** Start listening. */
56
- async start(): Promise<void> {
57
- return new Promise((resolve, reject) => {
58
- this.server = createServer((req, res) => this.handleRequest(req, res));
59
-
60
- this.server.on("error", reject);
61
- this.server.listen(this.port, () => resolve());
62
- });
63
- }
64
-
65
- /** Stop the server. */
66
- async stop(): Promise<void> {
67
- return new Promise((resolve) => {
68
- if (!this.server) {
69
- resolve();
70
- return;
71
- }
72
- this.server.close(() => resolve());
73
- });
74
- }
75
-
76
- getPort(): number {
77
- return this.port;
78
- }
79
-
80
- getAssignedContexts(): string[] {
81
- return Array.from(this.assignedContexts.keys());
82
- }
83
-
84
- setActiveContext(name: string | null): void {
85
- this.activeContext = name;
86
- }
87
-
88
- setCurrentTask(taskId: string | null): void {
89
- this.currentTask = taskId;
90
- }
91
-
92
- /** Register a callback for when a new context is assigned. */
93
- onContextAssigned(cb: (contextName: string, description: string) => void): void {
94
- this.onAssignCallback = cb;
95
- }
96
-
97
- /** Register a handler for incoming sync push requests from Primary. */
98
- onSyncPush(cb: (req: SyncPushRequest) => Promise<SyncPushResponse>): void {
99
- this.onSyncPushCallback = cb;
100
- }
101
-
102
- // --- Request Router ---
103
-
104
- private async handleRequest(req: IncomingMessage, res: ServerResponse): Promise<void> {
105
- const url = new URL(req.url ?? "/", `http://localhost:${this.port}`);
106
- const path = url.pathname;
107
- const method = req.method ?? "GET";
108
-
109
- try {
110
- if (method === "GET" && path === "/health") {
111
- return this.handleHealth(res);
112
- }
113
-
114
- if (method === "POST" && path === "/assign") {
115
- const body = await readBody(req);
116
- return this.handleAssign(body, res);
117
- }
118
-
119
- // DELETE /assign/:contextName
120
- if (method === "DELETE" && path.startsWith("/assign/")) {
121
- const contextName = decodeURIComponent(path.slice("/assign/".length));
122
- return this.handleUnassign(contextName, res);
123
- }
124
-
125
- if (method === "GET" && path === "/status") {
126
- return this.handleStatus(res);
127
- }
128
-
129
- if (method === "POST" && path === "/sync/push") {
130
- const body = await readBody(req);
131
- return this.handleSyncPush(body, res);
132
- }
133
-
134
- sendJson(res, 404, { error: "Not found" });
135
- } catch (err) {
136
- const msg = err instanceof Error ? err.message : String(err);
137
- sendJson(res, 500, { error: msg });
138
- }
139
- }
140
-
141
- // --- Handlers ---
142
-
143
- private handleHealth(res: ServerResponse): void {
144
- const uptimeMs = Date.now() - this.startTime;
145
-
146
- const body: WorkerHealthResponse = {
147
- worker_id: this.workerId,
148
- status: "healthy",
149
- uptime_seconds: Math.floor(uptimeMs / 1000),
150
- assigned_contexts: Array.from(this.assignedContexts.keys()),
151
- active_context: this.activeContext,
152
- memory_daemon_ok: this.memoryDaemonUrl !== null,
153
- ollama_ok: this.ollamaUrl !== null,
154
- };
155
-
156
- sendJson(res, 200, body);
157
- }
158
-
159
- private handleAssign(raw: string, res: ServerResponse): void {
160
- const req = JSON.parse(raw) as ContextAssignRequest;
161
-
162
- if (this.assignedContexts.size >= this.maxContexts) {
163
- const body: ContextAssignResponse = {
164
- context_name: req.context_name,
165
- accepted: false,
166
- reason: "Worker at max context capacity",
167
- };
168
- sendJson(res, 200, body);
169
- return;
170
- }
171
-
172
- const assignment: ContextAssignment = {
173
- context_name: req.context_name,
174
- context_description: req.context_description,
175
- assigned_at: new Date().toISOString(),
176
- };
177
-
178
- this.assignedContexts.set(req.context_name, assignment);
179
-
180
- // Notify the worker runtime about the new context
181
- if (this.onAssignCallback) {
182
- this.onAssignCallback(req.context_name, req.context_description);
183
- }
184
-
185
- const body: ContextAssignResponse = {
186
- context_name: req.context_name,
187
- accepted: true,
188
- };
189
- sendJson(res, 200, body);
190
- }
191
-
192
- private handleUnassign(contextName: string, res: ServerResponse): void {
193
- const existed = this.assignedContexts.delete(contextName);
194
-
195
- if (this.activeContext === contextName) {
196
- this.activeContext = null;
197
- this.currentTask = null;
198
- }
199
-
200
- sendJson(res, existed ? 200 : 404, {
201
- context_name: contextName,
202
- removed: existed,
203
- });
204
- }
205
-
206
- private handleStatus(res: ServerResponse): void {
207
- const report: WorkerStatusReport = {
208
- activity: this.currentTask ? "working" : "idle",
209
- current_context: this.activeContext,
210
- current_task: this.currentTask,
211
- };
212
-
213
- sendJson(res, 200, report);
214
- }
215
-
216
- private async handleSyncPush(raw: string, res: ServerResponse): Promise<void> {
217
- if (!this.onSyncPushCallback) {
218
- sendJson(res, 501, { error: "Sync push handler not registered" });
219
- return;
220
- }
221
-
222
- const req = JSON.parse(raw) as SyncPushRequest;
223
- const result = await this.onSyncPushCallback(req);
224
- sendJson(res, 200, result);
225
- }
226
- }
227
-
228
- // --- Helpers ---
229
-
230
- function readBody(req: IncomingMessage): Promise<string> {
231
- return new Promise((resolve, reject) => {
232
- const chunks: Buffer[] = [];
233
- req.on("data", (chunk: Buffer) => chunks.push(chunk));
234
- req.on("end", () => resolve(Buffer.concat(chunks).toString("utf-8")));
235
- req.on("error", reject);
236
- });
237
- }
238
-
239
- function sendJson(res: ServerResponse, status: number, body: unknown): void {
240
- const payload = JSON.stringify(body);
241
- res.writeHead(status, {
242
- "Content-Type": "application/json",
243
- "Content-Length": Buffer.byteLength(payload),
244
- });
245
- res.end(payload);
246
- }
@@ -1,57 +0,0 @@
1
- export { Agent } from "./agent.js";
2
- export { MemoryClient } from "./memory-client.js";
3
- export { LLMClient } from "./llm-client.js";
4
- export { ContextManager } from "./context.js";
5
- export { TaskEngine } from "./task-engine.js";
6
- export { loadConfig } from "./config.js";
7
- export { buildSystemPrompt, buildMessages } from "./prompt.js";
8
- export { SesameClient } from "./sesame.js";
9
- export { startPipeline } from "./pipeline.js";
10
-
11
- export type { HivemindConfig, AgentConfig, LLMConfig, MemoryConfig, SesameConfig, WorkerModeConfig } from "./config.js";
12
- export type { ChatMessage, ChatResponse } from "./llm-client.js";
13
- export type {
14
- Episode,
15
- ScoredEpisode,
16
- EpisodeInput,
17
- ContextInfo,
18
- CrossContextResult,
19
- PromotionResult,
20
- L3Entry,
21
- TaskRecord,
22
- TaskInput,
23
- } from "./memory-client.js";
24
- export type { AgentResponse } from "./agent.js";
25
- export type { SesameMessage } from "./sesame.js";
26
- export type { ContextMetadata, ContextSwitchResult } from "./context.js";
27
- export type { TaskCommand, TaskStatus } from "./task-engine.js";
28
-
29
- // Fleet (Phase 3)
30
- export { PrimaryClient } from "./fleet/primary-client.js";
31
- export { WorkerServer } from "./fleet/worker-server.js";
32
- export { WorkerRuntime, startWorker } from "./worker.js";
33
- export { FleetManager } from "./fleet/fleet-manager.js";
34
- export { WorkerMemorySync, PrimaryMemorySync } from "./fleet/memory-sync.js";
35
- export type { FleetDashboard, WorkerSummary, MigrationResult } from "./fleet/fleet-manager.js";
36
- export type { WorkerServerOptions } from "./fleet/worker-server.js";
37
- export type { WorkerSyncOptions, PrimarySyncOptions } from "./fleet/memory-sync.js";
38
- export type {
39
- WorkerInfo,
40
- WorkerCapabilities,
41
- WorkerRegistrationRequest,
42
- WorkerRegistrationResponse,
43
- WorkerHealthResponse,
44
- WorkerHealthStatus,
45
- WorkerStatus,
46
- WorkerStatusReport,
47
- WorkerActivity,
48
- ContextAssignment,
49
- ContextAssignRequest,
50
- ContextAssignResponse,
51
- SyncPullRequest,
52
- SyncPullResponse,
53
- SyncPushRequest,
54
- SyncPushResponse,
55
- SyncL3Entry,
56
- SyncL2Episode,
57
- } from "./fleet/worker-protocol.js";
@@ -1,65 +0,0 @@
1
- import type { LLMConfig } from "./config.js";
2
-
3
- export interface ChatMessage {
4
- role: "system" | "user" | "assistant";
5
- content: string;
6
- }
7
-
8
- export interface ChatResponse {
9
- content: string;
10
- model: string;
11
- usage?: {
12
- prompt_tokens: number;
13
- completion_tokens: number;
14
- total_tokens: number;
15
- };
16
- }
17
-
18
- export class LLMClient {
19
- private baseUrl: string;
20
- private model: string;
21
- private maxTokens: number;
22
- private temperature: number;
23
- private apiKey: string;
24
-
25
- constructor(config: LLMConfig) {
26
- this.baseUrl = config.base_url;
27
- this.model = config.model;
28
- this.maxTokens = config.max_tokens;
29
- this.temperature = config.temperature;
30
- this.apiKey = config.api_key ?? "";
31
- }
32
-
33
- async chat(messages: ChatMessage[]): Promise<ChatResponse> {
34
- const resp = await fetch(`${this.baseUrl}/chat/completions`, {
35
- method: "POST",
36
- headers: {
37
- "Content-Type": "application/json",
38
- ...(this.apiKey ? { Authorization: `Bearer ${this.apiKey}` } : {}),
39
- },
40
- body: JSON.stringify({
41
- model: this.model,
42
- messages,
43
- max_tokens: this.maxTokens,
44
- temperature: this.temperature,
45
- }),
46
- });
47
-
48
- if (!resp.ok) {
49
- const body = await resp.text();
50
- throw new Error(`LLM request failed: ${resp.status} ${body}`);
51
- }
52
-
53
- const data = (await resp.json()) as {
54
- choices: Array<{ message: { content: string } }>;
55
- model: string;
56
- usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };
57
- };
58
-
59
- return {
60
- content: data.choices[0].message.content,
61
- model: data.model,
62
- usage: data.usage,
63
- };
64
- }
65
- }