@sesamespace/hivemind 0.2.0 → 0.3.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.
Files changed (72) hide show
  1. package/PLANNING.md +383 -0
  2. package/TASKS.md +60 -0
  3. package/install.sh +187 -0
  4. package/npm-package.json +28 -0
  5. package/package.json +13 -20
  6. package/packages/cli/package.json +23 -0
  7. package/{dist/chunk-DVR2KBL7.js → packages/cli/src/commands/fleet.ts} +50 -30
  8. package/packages/cli/src/commands/init.ts +230 -0
  9. package/{dist/chunk-MBS5A6BZ.js → packages/cli/src/commands/service.ts} +51 -42
  10. package/{dist/chunk-RNK5Q5GR.js → packages/cli/src/commands/start.ts} +12 -14
  11. package/{dist/main.js → packages/cli/src/main.ts} +12 -18
  12. package/packages/cli/tsconfig.json +8 -0
  13. package/packages/memory/Cargo.lock +6480 -0
  14. package/packages/memory/Cargo.toml +21 -0
  15. package/packages/memory/src/context.rs +179 -0
  16. package/packages/memory/src/embeddings.rs +51 -0
  17. package/packages/memory/src/main.rs +626 -0
  18. package/packages/memory/src/promotion.rs +637 -0
  19. package/packages/memory/src/scoring.rs +131 -0
  20. package/packages/memory/src/store.rs +460 -0
  21. package/packages/memory/src/tasks.rs +321 -0
  22. package/packages/runtime/package.json +24 -0
  23. package/packages/runtime/src/__tests__/fleet-integration.test.ts +235 -0
  24. package/packages/runtime/src/__tests__/fleet.test.ts +207 -0
  25. package/packages/runtime/src/__tests__/integration.test.ts +434 -0
  26. package/packages/runtime/src/agent.ts +255 -0
  27. package/packages/runtime/src/config.ts +130 -0
  28. package/packages/runtime/src/context.ts +192 -0
  29. package/packages/runtime/src/fleet/fleet-manager.ts +399 -0
  30. package/packages/runtime/src/fleet/memory-sync.ts +362 -0
  31. package/packages/runtime/src/fleet/primary-client.ts +285 -0
  32. package/packages/runtime/src/fleet/worker-protocol.ts +158 -0
  33. package/packages/runtime/src/fleet/worker-server.ts +246 -0
  34. package/packages/runtime/src/index.ts +57 -0
  35. package/packages/runtime/src/llm-client.ts +65 -0
  36. package/packages/runtime/src/memory-client.ts +309 -0
  37. package/packages/runtime/src/pipeline.ts +151 -0
  38. package/packages/runtime/src/prompt.ts +173 -0
  39. package/packages/runtime/src/sesame.ts +174 -0
  40. package/{dist/start.js → packages/runtime/src/start.ts} +7 -9
  41. package/packages/runtime/src/task-engine.ts +113 -0
  42. package/packages/runtime/src/worker.ts +339 -0
  43. package/packages/runtime/tsconfig.json +8 -0
  44. package/pnpm-workspace.yaml +2 -0
  45. package/run-aidan.sh +23 -0
  46. package/scripts/bootstrap.sh +196 -0
  47. package/scripts/build-npm.sh +94 -0
  48. package/scripts/com.hivemind.agent.plist +44 -0
  49. package/scripts/com.hivemind.memory.plist +31 -0
  50. package/tsconfig.json +22 -0
  51. package/tsup.config.ts +28 -0
  52. package/dist/chunk-2I2O6X5D.js +0 -1408
  53. package/dist/chunk-2I2O6X5D.js.map +0 -1
  54. package/dist/chunk-DVR2KBL7.js.map +0 -1
  55. package/dist/chunk-MBS5A6BZ.js.map +0 -1
  56. package/dist/chunk-NVJ424TB.js +0 -731
  57. package/dist/chunk-NVJ424TB.js.map +0 -1
  58. package/dist/chunk-RNK5Q5GR.js.map +0 -1
  59. package/dist/chunk-XNOWVLXD.js +0 -160
  60. package/dist/chunk-XNOWVLXD.js.map +0 -1
  61. package/dist/commands/fleet.js +0 -9
  62. package/dist/commands/fleet.js.map +0 -1
  63. package/dist/commands/init.js +0 -7
  64. package/dist/commands/init.js.map +0 -1
  65. package/dist/commands/service.js +0 -7
  66. package/dist/commands/service.js.map +0 -1
  67. package/dist/commands/start.js +0 -9
  68. package/dist/commands/start.js.map +0 -1
  69. package/dist/index.js +0 -41
  70. package/dist/index.js.map +0 -1
  71. package/dist/main.js.map +0 -1
  72. package/dist/start.js.map +0 -1
package/package.json CHANGED
@@ -1,28 +1,21 @@
1
1
  {
2
2
  "name": "@sesamespace/hivemind",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Cognitive architecture for AI agents with multi-layered memory",
5
- "type": "module",
6
- "bin": {
7
- "hivemind": "dist/main.js"
8
- },
9
- "main": "dist/index.js",
10
- "files": [
11
- "dist",
12
- "config",
13
- "README.md"
14
- ],
15
- "dependencies": {
16
- "@iarna/toml": "^2.2.5",
17
- "@sesamespace/sdk": "^0.1.6",
18
- "ws": "^8.18.0"
5
+ "scripts": {
6
+ "build": "pnpm -r build",
7
+ "typecheck": "pnpm -r typecheck",
8
+ "lint": "pnpm -r lint",
9
+ "test": "pnpm -r test"
19
10
  },
20
11
  "engines": {
21
- "node": ">=20.0.0"
12
+ "node": ">=20.0.0",
13
+ "pnpm": ">=9.0.0"
14
+ },
15
+ "dependencies": {
16
+ "@sesamespace/sdk": "^0.1.6"
22
17
  },
23
- "license": "MIT",
24
- "repository": {
25
- "type": "git",
26
- "url": "https://github.com/baileydavis2026/hivemind"
18
+ "devDependencies": {
19
+ "tsup": "^8.5.1"
27
20
  }
28
21
  }
@@ -0,0 +1,23 @@
1
+ {
2
+ "name": "@hivemind/cli",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "bin": {
7
+ "hivemind": "dist/main.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "typecheck": "tsc --noEmit",
12
+ "dev": "tsx src/main.ts",
13
+ "test": "echo \"No tests yet\""
14
+ },
15
+ "dependencies": {
16
+ "@hivemind/runtime": "workspace:*"
17
+ },
18
+ "devDependencies": {
19
+ "@types/node": "^20.14.0",
20
+ "tsx": "^4.16.0",
21
+ "typescript": "^5.5.0"
22
+ }
23
+ }
@@ -1,40 +1,53 @@
1
- import {
2
- FleetManager
3
- } from "./chunk-NVJ424TB.js";
1
+ /**
2
+ * CLI commands for fleet management.
3
+ *
4
+ * Usage:
5
+ * hivemind fleet status — Show fleet dashboard
6
+ * hivemind fleet add-worker <url> — Register a worker by URL
7
+ * hivemind fleet remove-worker <worker-id> — Remove a worker from the fleet
8
+ * hivemind fleet assign <worker-id> <context> — Assign a context to a worker
9
+ * hivemind fleet migrate <context> <worker-id> — Migrate a context to another worker
10
+ * hivemind fleet discover <url1> [url2] ... — Probe URLs for workers
11
+ */
4
12
 
5
- // packages/cli/src/commands/fleet.ts
6
- function formatUptime(seconds) {
7
- if (seconds == null) return "\u2014";
13
+ import { FleetManager } from "@hivemind/runtime";
14
+ import type { FleetDashboard, WorkerSummary } from "@hivemind/runtime";
15
+
16
+ function formatUptime(seconds: number | null): string {
17
+ if (seconds == null) return "—";
8
18
  if (seconds < 60) return `${seconds}s`;
9
19
  if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
10
20
  const h = Math.floor(seconds / 3600);
11
- const m = Math.floor(seconds % 3600 / 60);
21
+ const m = Math.floor((seconds % 3600) / 60);
12
22
  return `${h}h ${m}m`;
13
23
  }
14
- function formatHealth(status) {
24
+
25
+ function formatHealth(status: string): string {
15
26
  switch (status) {
16
- case "healthy":
17
- return "OK";
18
- case "degraded":
19
- return "DEGRADED";
20
- case "unreachable":
21
- return "DOWN";
22
- default:
23
- return status.toUpperCase();
27
+ case "healthy": return "OK";
28
+ case "degraded": return "DEGRADED";
29
+ case "unreachable": return "DOWN";
30
+ default: return status.toUpperCase();
24
31
  }
25
32
  }
26
- function printDashboard(dashboard) {
33
+
34
+ function printDashboard(dashboard: FleetDashboard): void {
27
35
  console.log("\n=== Hivemind Fleet ===\n");
28
36
  console.log(`Workers: ${dashboard.total_workers} (${dashboard.healthy} healthy, ${dashboard.degraded} degraded, ${dashboard.unreachable} unreachable)`);
29
37
  console.log(`Contexts assigned: ${dashboard.total_contexts}`);
38
+
30
39
  if (dashboard.unassigned_contexts.length > 0) {
31
40
  console.log(`Unassigned contexts: ${dashboard.unassigned_contexts.join(", ")}`);
32
41
  }
42
+
33
43
  console.log("");
44
+
34
45
  if (dashboard.workers.length === 0) {
35
46
  console.log("No workers registered. Use 'fleet add-worker <url>' to add one.");
36
47
  return;
37
48
  }
49
+
50
+ // Table header
38
51
  const cols = { id: 12, url: 30, health: 8, activity: 10, contexts: 25, task: 20, uptime: 8 };
39
52
  const header = [
40
53
  "ID".padEnd(cols.id),
@@ -43,38 +56,44 @@ function printDashboard(dashboard) {
43
56
  "ACTIVITY".padEnd(cols.activity),
44
57
  "CONTEXTS".padEnd(cols.contexts),
45
58
  "TASK".padEnd(cols.task),
46
- "UPTIME".padEnd(cols.uptime)
59
+ "UPTIME".padEnd(cols.uptime),
47
60
  ].join(" ");
48
61
  console.log(header);
49
62
  console.log("-".repeat(header.length));
63
+
50
64
  for (const w of dashboard.workers) {
51
65
  const row = [
52
66
  w.id.padEnd(cols.id),
53
67
  w.url.slice(0, cols.url).padEnd(cols.url),
54
68
  formatHealth(w.health).padEnd(cols.health),
55
69
  w.activity.padEnd(cols.activity),
56
- (w.contexts.join(", ") || "\u2014").slice(0, cols.contexts).padEnd(cols.contexts),
57
- (w.current_task ?? "\u2014").slice(0, cols.task).padEnd(cols.task),
58
- formatUptime(w.uptime_seconds).padEnd(cols.uptime)
70
+ (w.contexts.join(", ") || "").slice(0, cols.contexts).padEnd(cols.contexts),
71
+ (w.current_task ?? "").slice(0, cols.task).padEnd(cols.task),
72
+ formatUptime(w.uptime_seconds).padEnd(cols.uptime),
59
73
  ].join(" ");
60
74
  console.log(row);
61
75
  }
62
- console.log(`
63
- Generated: ${dashboard.generated_at}`);
76
+
77
+ console.log(`\nGenerated: ${dashboard.generated_at}`);
64
78
  }
65
- async function runFleetCommand(args) {
79
+
80
+ export async function runFleetCommand(args: string[]): Promise<void> {
66
81
  const subcommand = args[0];
82
+
67
83
  if (!subcommand) {
68
84
  printUsage();
69
85
  process.exit(1);
70
86
  }
87
+
71
88
  const fleet = new FleetManager();
89
+
72
90
  switch (subcommand) {
73
91
  case "status": {
74
92
  const dashboard = await fleet.getDashboard();
75
93
  printDashboard(dashboard);
76
94
  break;
77
95
  }
96
+
78
97
  case "add-worker": {
79
98
  const url = args[1];
80
99
  if (!url) {
@@ -95,6 +114,7 @@ async function runFleetCommand(args) {
95
114
  }
96
115
  break;
97
116
  }
117
+
98
118
  case "remove-worker": {
99
119
  const workerId = args[1];
100
120
  if (!workerId) {
@@ -110,6 +130,7 @@ async function runFleetCommand(args) {
110
130
  }
111
131
  break;
112
132
  }
133
+
113
134
  case "assign": {
114
135
  const workerId = args[1];
115
136
  const context = args[2];
@@ -126,6 +147,7 @@ async function runFleetCommand(args) {
126
147
  }
127
148
  break;
128
149
  }
150
+
129
151
  case "migrate": {
130
152
  const context = args[1];
131
153
  const toWorker = args[2];
@@ -142,6 +164,7 @@ async function runFleetCommand(args) {
142
164
  }
143
165
  break;
144
166
  }
167
+
145
168
  case "discover": {
146
169
  const urls = args.slice(1);
147
170
  if (urls.length === 0) {
@@ -160,13 +183,15 @@ async function runFleetCommand(args) {
160
183
  }
161
184
  break;
162
185
  }
186
+
163
187
  default:
164
188
  console.error(`Unknown fleet subcommand: ${subcommand}`);
165
189
  printUsage();
166
190
  process.exit(1);
167
191
  }
168
192
  }
169
- function printUsage() {
193
+
194
+ function printUsage(): void {
170
195
  console.log(`
171
196
  Usage: hivemind fleet <command> [args]
172
197
 
@@ -179,8 +204,3 @@ Commands:
179
204
  discover <url1> [url2] ... Probe URLs for workers
180
205
  `.trim());
181
206
  }
182
-
183
- export {
184
- runFleetCommand
185
- };
186
- //# sourceMappingURL=chunk-DVR2KBL7.js.map
@@ -0,0 +1,230 @@
1
+ import { resolve, dirname } from "path";
2
+ import { existsSync, writeFileSync, mkdirSync, readFileSync } from "fs";
3
+ import { createInterface } from "readline";
4
+ import { SesameClient } from "@sesamespace/sdk";
5
+
6
+ const HIVEMIND_DIR = resolve(process.env.HIVEMIND_HOME || ".");
7
+ const CONFIG_DIR = resolve(HIVEMIND_DIR, "config");
8
+ const WORKSPACE_DIR = resolve(HIVEMIND_DIR, "workspace");
9
+ const ENV_FILE = resolve(HIVEMIND_DIR, ".env");
10
+ const LOCAL_TOML = resolve(CONFIG_DIR, "local.toml");
11
+
12
+ const VAULT_CONFIG_NAME = "hivemind-config";
13
+
14
+ interface ProvisioningConfig {
15
+ agentName: string;
16
+ agentHandle: string;
17
+ agentId: string;
18
+ personality?: string;
19
+ llmApiKey?: string;
20
+ llmBaseUrl?: string;
21
+ llmModel?: string;
22
+ fleetRole?: string;
23
+ channels: Array<{ id: string; name: string | null; kind: string }>;
24
+ }
25
+
26
+ async function prompt(question: string): Promise<string> {
27
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
28
+ return new Promise((resolve) => {
29
+ rl.question(question, (answer) => {
30
+ rl.close();
31
+ resolve(answer.trim());
32
+ });
33
+ });
34
+ }
35
+
36
+ export async function runInitCommand(args: string[]): Promise<void> {
37
+ const nonInteractive = args.includes("--yes") || args.includes("-y") || args.includes("--non-interactive");
38
+ const filteredArgs = args.filter((a) => !["--yes", "-y", "--non-interactive", "--help", "-h"].includes(a));
39
+ let sesameApiKey = filteredArgs[0];
40
+
41
+ if (args.includes("--help") || args.includes("-h")) {
42
+ printHelp();
43
+ return;
44
+ }
45
+
46
+ console.log(`
47
+ ╦ ╦╦╦ ╦╔═╗╔╦╗╦╔╗╔╔╦╗
48
+ ╠═╣║╚╗╔╝║╣ ║║║║║║║ ║║
49
+ ╩ ╩╩ ╚╝ ╚═╝╩ ╩╩╝╚╝═╩╝
50
+ Agent Initialization
51
+ `);
52
+
53
+ // --- Step 1: Get Sesame API key ---
54
+ if (!sesameApiKey) {
55
+ sesameApiKey = await prompt(" Sesame API key: ");
56
+ }
57
+ if (!sesameApiKey) {
58
+ console.error("Error: Sesame API key is required");
59
+ process.exit(1);
60
+ }
61
+
62
+ // --- Step 2: Connect to Sesame and fetch manifest ---
63
+ console.log("\n→ Connecting to Sesame...");
64
+ const sdk = new SesameClient({
65
+ apiUrl: "https://api.sesame.space",
66
+ wsUrl: "wss://ws.sesame.space",
67
+ apiKey: sesameApiKey,
68
+ });
69
+
70
+ let config: ProvisioningConfig;
71
+ try {
72
+ const manifest = await sdk.getManifest();
73
+ console.log(` ✓ Authenticated as ${manifest.agent.handle} (${manifest.agent.id})`);
74
+ console.log(` ✓ Workspace: ${manifest.workspace.name}`);
75
+ console.log(` ✓ Channels: ${manifest.channels.length}`);
76
+ for (const ch of manifest.channels) {
77
+ console.log(` - ${ch.name || ch.id} (${ch.kind})`);
78
+ }
79
+
80
+ config = {
81
+ agentName: manifest.agent.handle,
82
+ agentHandle: manifest.agent.handle,
83
+ agentId: manifest.agent.id,
84
+ channels: manifest.channels.map((ch) => ({
85
+ id: ch.id,
86
+ name: ch.name,
87
+ kind: ch.kind,
88
+ })),
89
+ };
90
+
91
+ // --- Step 3: Check vault for config ---
92
+ console.log("\n→ Checking vault for provisioning config...");
93
+ try {
94
+ const vaultResp = await sdk.listVaultItems() as any;
95
+ const items = vaultResp.items || vaultResp.data || [];
96
+ const configItem = items.find((i: any) => i.name === VAULT_CONFIG_NAME);
97
+
98
+ if (configItem) {
99
+ console.log(` ✓ Found ${VAULT_CONFIG_NAME} vault item`);
100
+ const revealResp = await sdk.revealItem(configItem.id) as any;
101
+ const fields = revealResp.fields || revealResp.data || {};
102
+
103
+ config.llmApiKey = fields.llm_api_key || fields.openrouter_api_key;
104
+ config.llmBaseUrl = fields.llm_base_url;
105
+ config.llmModel = fields.llm_model;
106
+ config.personality = fields.agent_personality || fields.personality;
107
+ config.fleetRole = fields.fleet_role;
108
+
109
+ if (config.llmApiKey) console.log(" ✓ LLM API key loaded from vault");
110
+ if (config.personality) console.log(` ✓ Personality: ${config.personality.slice(0, 60)}...`);
111
+ if (config.fleetRole) console.log(` ✓ Fleet role: ${config.fleetRole}`);
112
+ } else {
113
+ console.log(" ! No hivemind-config vault item found");
114
+ console.log(" ! Will prompt for LLM API key instead");
115
+ }
116
+ } catch (err) {
117
+ console.log(` ! Could not read vault: ${(err as Error).message}`);
118
+ }
119
+ } catch (err) {
120
+ console.error(`\n ✗ Failed to connect to Sesame: ${(err as Error).message}`);
121
+ console.error(" Check your API key and try again.");
122
+ process.exit(1);
123
+ } finally {
124
+ sdk.disconnect();
125
+ }
126
+
127
+ // --- Step 4: Prompt for anything missing (skip in non-interactive mode) ---
128
+ if (!config.llmApiKey && !nonInteractive) {
129
+ config.llmApiKey = await prompt("\n OpenRouter API key: ");
130
+ } else if (!config.llmApiKey) {
131
+ console.log(" ! No LLM API key found in vault — set LLM_API_KEY in .env after init");
132
+ }
133
+
134
+ if (!nonInteractive) {
135
+ const nameOverride = await prompt(` Agent name [${config.agentName}]: `);
136
+ if (nameOverride) config.agentName = nameOverride;
137
+ }
138
+
139
+ // --- Step 5: Write config files ---
140
+ console.log("\n→ Writing configuration...");
141
+
142
+ mkdirSync(CONFIG_DIR, { recursive: true });
143
+ mkdirSync(WORKSPACE_DIR, { recursive: true });
144
+
145
+ // Write workspace identity files
146
+ const soulPath = resolve(WORKSPACE_DIR, "SOUL.md");
147
+ if (!existsSync(soulPath)) {
148
+ const personality = config.personality || "A helpful, capable agent.";
149
+ writeFileSync(soulPath, `# SOUL.md — Who You Are
150
+
151
+ ${personality}
152
+
153
+ ---
154
+
155
+ _This file defines your personality and values. Edit it to evolve who you are._
156
+ `);
157
+ console.log(` ✓ ${soulPath}`);
158
+ }
159
+
160
+ const identityPath = resolve(WORKSPACE_DIR, "IDENTITY.md");
161
+ if (!existsSync(identityPath)) {
162
+ writeFileSync(identityPath, `# IDENTITY.md
163
+
164
+ - **Name:** ${config.agentName}
165
+ - **Handle:** ${config.agentHandle}
166
+ - **Agent ID:** ${config.agentId}
167
+ `);
168
+ console.log(` ✓ ${identityPath}`);
169
+ }
170
+
171
+ // Write local.toml (overrides)
172
+ const localToml = `# Generated by hivemind init — ${new Date().toISOString()}
173
+ # Overrides config/default.toml with agent-specific settings
174
+
175
+ [agent]
176
+ name = "${config.agentName}"
177
+ ${config.personality ? `personality = "${config.personality.replace(/"/g, '\\"')}"` : "# personality = (using default)"}
178
+ workspace = "workspace"
179
+
180
+ ${config.llmModel ? `[llm]\nmodel = "${config.llmModel}"` : "# [llm] using defaults"}
181
+ ${config.llmBaseUrl ? `# base_url = "${config.llmBaseUrl}"` : ""}
182
+ `;
183
+
184
+ writeFileSync(LOCAL_TOML, localToml);
185
+ console.log(` ✓ ${LOCAL_TOML}`);
186
+
187
+ // Write .env
188
+ const envContent = `# Hivemind Agent — ${config.agentName}
189
+ # Generated by hivemind init — ${new Date().toISOString()}
190
+ SESAME_API_KEY=${sesameApiKey}
191
+ LLM_API_KEY=${config.llmApiKey || ""}
192
+ AGENT_NAME=${config.agentName}
193
+ `;
194
+
195
+ writeFileSync(ENV_FILE, envContent, { mode: 0o600 });
196
+ console.log(` ✓ ${ENV_FILE} (chmod 600)`);
197
+
198
+ // --- Done ---
199
+ console.log(`
200
+ ✓ Hivemind initialized for ${config.agentName}!
201
+
202
+ To start the agent:
203
+ ./start.sh
204
+
205
+ To start in background:
206
+ nohup ./start.sh > /tmp/hivemind.log 2>&1 &
207
+
208
+ Agent ID: ${config.agentId}
209
+ Channels: ${config.channels.map((c) => c.name || c.id).join(", ")}
210
+ Fleet role: ${config.fleetRole || "standalone"}
211
+ `);
212
+ }
213
+
214
+ function printHelp(): void {
215
+ console.log(`hivemind init — Initialize a Hivemind agent from Sesame
216
+
217
+ Usage: hivemind init [sesame-api-key]
218
+
219
+ The API key can also be passed as the first argument.
220
+
221
+ What it does:
222
+ 1. Connects to Sesame and fetches agent identity
223
+ 2. Reads provisioning config from Sesame vault (if available)
224
+ 3. Prompts for any missing configuration
225
+ 4. Writes config/local.toml and .env
226
+
227
+ Options:
228
+ -h, --help Show this help
229
+ `);
230
+ }
@@ -1,15 +1,15 @@
1
- // packages/cli/src/commands/service.ts
2
1
  import { resolve } from "path";
3
2
  import { readFileSync, writeFileSync, existsSync, mkdirSync } from "fs";
4
3
  import { execSync } from "child_process";
5
4
  import { homedir } from "os";
6
- import { fileURLToPath } from "url";
7
- import { dirname } from "path";
8
- var LAUNCH_AGENTS_DIR = resolve(homedir(), "Library/LaunchAgents");
9
- var AGENT_LABEL = "com.hivemind.agent";
10
- var MEMORY_LABEL = "com.hivemind.memory";
11
- async function runServiceCommand(args) {
5
+
6
+ const LAUNCH_AGENTS_DIR = resolve(homedir(), "Library/LaunchAgents");
7
+ const AGENT_LABEL = "com.hivemind.agent";
8
+ const MEMORY_LABEL = "com.hivemind.memory";
9
+
10
+ export async function runServiceCommand(args: string[]): Promise<void> {
12
11
  const subcommand = args[0];
12
+
13
13
  switch (subcommand) {
14
14
  case "install":
15
15
  await installServices(args.slice(1));
@@ -32,85 +32,95 @@ async function runServiceCommand(args) {
32
32
  break;
33
33
  }
34
34
  }
35
- async function installServices(_args) {
35
+
36
+ async function installServices(_args: string[]): Promise<void> {
36
37
  const hivemindHome = process.env.HIVEMIND_HOME || process.cwd();
37
- console.log(`
38
- \u2192 Installing launchd services for ${hivemindHome}
39
- `);
38
+
39
+ console.log(`\n→ Installing launchd services for ${hivemindHome}\n`);
40
+
40
41
  mkdirSync(LAUNCH_AGENTS_DIR, { recursive: true });
42
+
43
+ // Find plist templates
41
44
  const scriptDirs = [
42
45
  resolve(hivemindHome, "scripts"),
43
- resolve(dirname(dirname(dirname(fileURLToPath(import.meta.url)))), "scripts")
46
+ resolve(dirname(dirname(dirname(fileURLToPath(import.meta.url)))), "scripts"),
44
47
  ];
48
+
45
49
  for (const label of [MEMORY_LABEL, AGENT_LABEL]) {
46
50
  const plistFile = `${label}.plist`;
47
51
  let templatePath = "";
52
+
48
53
  for (const dir of scriptDirs) {
49
54
  const p = resolve(dir, plistFile);
50
- if (existsSync(p)) {
51
- templatePath = p;
52
- break;
53
- }
55
+ if (existsSync(p)) { templatePath = p; break; }
54
56
  }
57
+
55
58
  if (!templatePath) {
56
- console.error(` \u2717 Template not found: ${plistFile}`);
59
+ console.error(` Template not found: ${plistFile}`);
57
60
  continue;
58
61
  }
62
+
59
63
  let content = readFileSync(templatePath, "utf-8");
60
64
  content = content.replace(/__HIVEMIND_HOME__/g, hivemindHome);
65
+
61
66
  const destPath = resolve(LAUNCH_AGENTS_DIR, plistFile);
62
67
  writeFileSync(destPath, content);
63
- try {
64
- execSync(`launchctl unload ${destPath} 2>/dev/null`);
65
- } catch {
66
- }
68
+
69
+ // Unload if already loaded, then load
70
+ try { execSync(`launchctl unload ${destPath} 2>/dev/null`); } catch {}
67
71
  execSync(`launchctl load ${destPath}`);
68
- console.log(` \u2713 ${label} installed and started`);
72
+
73
+ console.log(` ✓ ${label} installed and started`);
69
74
  }
75
+
70
76
  console.log("\n Services will auto-start on boot.\n");
71
77
  }
72
- async function uninstallServices() {
73
- console.log("\n\u2192 Uninstalling launchd services\n");
78
+
79
+ async function uninstallServices(): Promise<void> {
80
+ console.log("\n→ Uninstalling launchd services\n");
81
+
74
82
  for (const label of [AGENT_LABEL, MEMORY_LABEL]) {
75
83
  const plistPath = resolve(LAUNCH_AGENTS_DIR, `${label}.plist`);
76
84
  if (existsSync(plistPath)) {
77
- try {
78
- execSync(`launchctl unload ${plistPath} 2>/dev/null`);
79
- } catch {
80
- }
85
+ try { execSync(`launchctl unload ${plistPath} 2>/dev/null`); } catch {}
81
86
  const { unlinkSync } = await import("fs");
82
87
  unlinkSync(plistPath);
83
- console.log(` \u2713 ${label} uninstalled`);
88
+ console.log(` ${label} uninstalled`);
84
89
  } else {
85
90
  console.log(` - ${label} not installed`);
86
91
  }
87
92
  }
88
93
  console.log("");
89
94
  }
90
- function showStatus() {
91
- console.log("\n\u2192 Service status\n");
95
+
96
+ function showStatus(): void {
97
+ console.log("\n→ Service status\n");
92
98
  for (const label of [MEMORY_LABEL, AGENT_LABEL]) {
93
99
  try {
94
100
  const out = execSync(`launchctl list ${label} 2>/dev/null`, { encoding: "utf-8" });
95
101
  const pidMatch = out.match(/"PID"\s*=\s*(\d+)/);
96
102
  const pid = pidMatch ? pidMatch[1] : "unknown";
97
- console.log(` \u2713 ${label}: running (PID ${pid})`);
103
+ console.log(` ${label}: running (PID ${pid})`);
98
104
  } catch {
99
105
  console.log(` - ${label}: not running`);
100
106
  }
101
107
  }
102
108
  console.log("");
103
109
  }
104
- function showLogs(which) {
105
- const logFile = which === "memory" ? "/tmp/hivemind-memory.log" : "/tmp/hivemind-agent.log";
110
+
111
+ function showLogs(which?: string): void {
112
+ const logFile = which === "memory"
113
+ ? "/tmp/hivemind-memory.log"
114
+ : "/tmp/hivemind-agent.log";
106
115
  try {
107
116
  execSync(`tail -30 ${logFile}`, { stdio: "inherit" });
108
117
  } catch {
109
118
  console.error(`No log file at ${logFile}`);
110
119
  }
111
120
  }
112
- function printHelp() {
113
- console.log(`hivemind service \u2014 Manage launchd services
121
+
122
+ function printHelp(): void {
123
+ console.log(`hivemind service — Manage launchd services
114
124
 
115
125
  Usage: hivemind service <subcommand>
116
126
 
@@ -121,12 +131,11 @@ Subcommands:
121
131
  logs [agent|memory] Show recent logs
122
132
 
123
133
  Services:
124
- com.hivemind.memory \u2014 Memory daemon (Rust, port 3434)
125
- com.hivemind.agent \u2014 Agent runtime (Node.js, Sesame)
134
+ com.hivemind.memory Memory daemon (Rust, port 3434)
135
+ com.hivemind.agent Agent runtime (Node.js, Sesame)
126
136
  `);
127
137
  }
128
138
 
129
- export {
130
- runServiceCommand
131
- };
132
- //# sourceMappingURL=chunk-MBS5A6BZ.js.map
139
+ // Helpers for ESM
140
+ import { fileURLToPath } from "url";
141
+ import { dirname } from "path";
@@ -1,13 +1,13 @@
1
- import {
2
- startPipeline
3
- } from "./chunk-2I2O6X5D.js";
4
-
5
- // packages/cli/src/commands/start.ts
6
1
  import { resolve } from "path";
7
2
  import { existsSync } from "fs";
8
- var DEFAULT_CONFIG = "config/default.toml";
9
- async function runStartCommand(args) {
3
+ import { startPipeline } from "@hivemind/runtime";
4
+
5
+ const DEFAULT_CONFIG = "config/default.toml";
6
+
7
+ export async function runStartCommand(args: string[]): Promise<void> {
10
8
  let configPath = DEFAULT_CONFIG;
9
+
10
+ // Parse args
11
11
  for (let i = 0; i < args.length; i++) {
12
12
  if ((args[i] === "--config" || args[i] === "-c") && args[i + 1]) {
13
13
  configPath = args[++i];
@@ -20,15 +20,18 @@ async function runStartCommand(args) {
20
20
  process.exit(1);
21
21
  }
22
22
  }
23
+
23
24
  const resolved = resolve(configPath);
24
25
  if (!existsSync(resolved)) {
25
26
  console.error(`Config not found: ${resolved}`);
26
27
  process.exit(1);
27
28
  }
29
+
28
30
  await startPipeline(resolved);
29
31
  }
30
- function printHelp() {
31
- console.log(`hivemind start \u2014 Start the Hivemind agent
32
+
33
+ function printHelp(): void {
34
+ console.log(`hivemind start — Start the Hivemind agent
32
35
 
33
36
  Usage: hivemind start [options]
34
37
 
@@ -37,8 +40,3 @@ Options:
37
40
  -h, --help Show this help
38
41
  `);
39
42
  }
40
-
41
- export {
42
- runStartCommand
43
- };
44
- //# sourceMappingURL=chunk-RNK5Q5GR.js.map