@sesamespace/hivemind 0.8.13 → 0.10.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 (54) hide show
  1. package/README.md +2 -1
  2. package/dist/{chunk-MLY4VFOO.js → chunk-BHCDOHSK.js} +3 -3
  3. package/dist/{chunk-PFZO67E2.js → chunk-DPLCEMEC.js} +2 -2
  4. package/dist/{chunk-HTLHMXAL.js → chunk-FBQBBAPZ.js} +2 -2
  5. package/dist/{chunk-NSTTILSN.js → chunk-FK6WYXRM.js} +79 -2
  6. package/dist/chunk-FK6WYXRM.js.map +1 -0
  7. package/dist/{chunk-LJHJGDKY.js → chunk-ICSJNKI6.js} +62 -2
  8. package/dist/chunk-ICSJNKI6.js.map +1 -0
  9. package/dist/{chunk-4Y7A25UG.js → chunk-IXBIAX76.js} +2 -2
  10. package/dist/{chunk-ZM7RK5YV.js → chunk-M3A2WRXM.js} +560 -37
  11. package/dist/chunk-M3A2WRXM.js.map +1 -0
  12. package/dist/commands/fleet.js +3 -3
  13. package/dist/commands/init.js +3 -3
  14. package/dist/commands/start.js +3 -3
  15. package/dist/commands/upgrade.js +1 -1
  16. package/dist/commands/watchdog.js +3 -3
  17. package/dist/dashboard.html +873 -131
  18. package/dist/index.js +2 -2
  19. package/dist/main.js +375 -7
  20. package/dist/main.js.map +1 -1
  21. package/dist/start.js +1 -1
  22. package/install.sh +162 -0
  23. package/package.json +24 -23
  24. package/packages/memory/Cargo.lock +6480 -0
  25. package/packages/memory/Cargo.toml +21 -0
  26. package/packages/memory/src/src/context.rs +179 -0
  27. package/packages/memory/src/src/embeddings.rs +51 -0
  28. package/packages/memory/src/src/main.rs +887 -0
  29. package/packages/memory/src/src/promotion.rs +808 -0
  30. package/packages/memory/src/src/scoring.rs +142 -0
  31. package/packages/memory/src/src/store.rs +460 -0
  32. package/packages/memory/src/src/tasks.rs +321 -0
  33. package/.pnpmrc.json +0 -1
  34. package/AUTO-DEBUG-DESIGN.md +0 -267
  35. package/DASHBOARD-PLAN.md +0 -206
  36. package/MEMORY-ENHANCEMENT-PLAN.md +0 -211
  37. package/TOOL-USE-DESIGN.md +0 -173
  38. package/dist/chunk-LJHJGDKY.js.map +0 -1
  39. package/dist/chunk-NSTTILSN.js.map +0 -1
  40. package/dist/chunk-ZM7RK5YV.js.map +0 -1
  41. package/docs/TOOL-PARITY-PLAN.md +0 -191
  42. package/src/memory/dashboard-integration.ts +0 -295
  43. package/src/memory/index.ts +0 -187
  44. package/src/memory/performance-test.ts +0 -208
  45. package/src/memory/processors/agent-sync.ts +0 -312
  46. package/src/memory/processors/command-learner.ts +0 -298
  47. package/src/memory/processors/memory-api-client.ts +0 -105
  48. package/src/memory/processors/message-flow-integration.ts +0 -168
  49. package/src/memory/processors/research-digester.ts +0 -204
  50. package/test-caitlin-access.md +0 -11
  51. /package/dist/{chunk-MLY4VFOO.js.map → chunk-BHCDOHSK.js.map} +0 -0
  52. /package/dist/{chunk-PFZO67E2.js.map → chunk-DPLCEMEC.js.map} +0 -0
  53. /package/dist/{chunk-HTLHMXAL.js.map → chunk-FBQBBAPZ.js.map} +0 -0
  54. /package/dist/{chunk-4Y7A25UG.js.map → chunk-IXBIAX76.js.map} +0 -0
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  PrimaryMemorySync,
5
5
  Watchdog,
6
6
  WorkerMemorySync
7
- } from "./chunk-4Y7A25UG.js";
7
+ } from "./chunk-IXBIAX76.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-ZM7RK5YV.js";
37
+ } from "./chunk-M3A2WRXM.js";
38
38
  import "./chunk-DGUM43GV.js";
39
39
  export {
40
40
  Agent,
package/dist/main.js CHANGED
@@ -1,26 +1,387 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  runInitCommand
4
- } from "./chunk-NSTTILSN.js";
4
+ } from "./chunk-FK6WYXRM.js";
5
5
  import {
6
6
  runStartCommand
7
- } from "./chunk-PFZO67E2.js";
7
+ } from "./chunk-DPLCEMEC.js";
8
8
  import {
9
9
  runFleetCommand
10
- } from "./chunk-HTLHMXAL.js";
10
+ } from "./chunk-FBQBBAPZ.js";
11
11
  import {
12
12
  runServiceCommand
13
13
  } from "./chunk-IJRAVHQC.js";
14
14
  import {
15
15
  runUpgradeCommand
16
- } from "./chunk-LJHJGDKY.js";
16
+ } from "./chunk-ICSJNKI6.js";
17
17
  import {
18
18
  runWatchdogCommand
19
- } from "./chunk-MLY4VFOO.js";
20
- import "./chunk-4Y7A25UG.js";
21
- import "./chunk-ZM7RK5YV.js";
19
+ } from "./chunk-BHCDOHSK.js";
20
+ import "./chunk-IXBIAX76.js";
21
+ import "./chunk-M3A2WRXM.js";
22
22
  import "./chunk-DGUM43GV.js";
23
23
 
24
+ // packages/cli/src/commands/session.ts
25
+ import { resolve } from "path";
26
+ import { existsSync, readFileSync, unlinkSync, writeFileSync } from "fs";
27
+ import { execSync } from "child_process";
28
+ import { homedir } from "os";
29
+ var MEMORY_URL = process.env.HIVEMIND_MEMORY_URL || "http://localhost:3434";
30
+ var CONTEXT = process.env.HIVEMIND_CONTEXT || "coding-sessions";
31
+ async function storeRecord(content, metadata) {
32
+ try {
33
+ const resp = await fetch(`${MEMORY_URL}/store`, {
34
+ method: "POST",
35
+ headers: { "Content-Type": "application/json" },
36
+ body: JSON.stringify({ context: CONTEXT, content, metadata })
37
+ });
38
+ return resp.ok;
39
+ } catch {
40
+ return false;
41
+ }
42
+ }
43
+ async function runSessionCommand(args2) {
44
+ const subcommand = args2[0];
45
+ switch (subcommand) {
46
+ case "ingest":
47
+ await runIngest(args2.slice(1));
48
+ break;
49
+ case "hot-start":
50
+ await runHotStart(args2.slice(1));
51
+ break;
52
+ case "setup-claude":
53
+ await runSetupClaude(args2.slice(1));
54
+ break;
55
+ default:
56
+ console.log(`hivemind session \u2014 Claude Code session memory tools
57
+
58
+ Usage: hivemind session <command>
59
+
60
+ Commands:
61
+ ingest [dir] Ingest .session-log.json from a project into hivemind memory
62
+ hot-start [dir] Generate project context guide from codebase + hivemind memory
63
+ setup-claude Install global CLAUDE.md for session logging
64
+ `);
65
+ if (subcommand) {
66
+ console.error(`Unknown subcommand: ${subcommand}`);
67
+ process.exit(1);
68
+ }
69
+ }
70
+ }
71
+ async function runIngest(args2) {
72
+ const projectDir = resolve(args2[0] || ".");
73
+ const sessionLogPath = resolve(projectDir, ".session-log.json");
74
+ if (!existsSync(sessionLogPath)) {
75
+ console.log("No .session-log.json found \u2014 nothing to ingest.");
76
+ return;
77
+ }
78
+ console.log(`Ingesting session from ${projectDir}...`);
79
+ const data = JSON.parse(readFileSync(sessionLogPath, "utf-8"));
80
+ const timestamp = data.timestamp || (/* @__PURE__ */ new Date()).toISOString();
81
+ const sessionId = `session-${Date.now()}`;
82
+ let projectName = "unknown";
83
+ let gitBranch = "unknown";
84
+ let gitHash = "unknown";
85
+ let gitDiffStat = "";
86
+ try {
87
+ projectName = execSync("basename $(git rev-parse --show-toplevel)", {
88
+ cwd: projectDir,
89
+ encoding: "utf-8"
90
+ }).trim();
91
+ } catch {
92
+ projectName = resolve(projectDir).split("/").pop() || "unknown";
93
+ }
94
+ try {
95
+ gitBranch = execSync("git rev-parse --abbrev-ref HEAD", {
96
+ cwd: projectDir,
97
+ encoding: "utf-8"
98
+ }).trim();
99
+ } catch {
100
+ }
101
+ try {
102
+ gitHash = execSync("git rev-parse --short HEAD", {
103
+ cwd: projectDir,
104
+ encoding: "utf-8"
105
+ }).trim();
106
+ } catch {
107
+ }
108
+ try {
109
+ gitDiffStat = execSync("git diff --stat HEAD~1", {
110
+ cwd: projectDir,
111
+ encoding: "utf-8"
112
+ }).trim();
113
+ } catch {
114
+ }
115
+ const baseMeta = {
116
+ type: "coding_session",
117
+ project: projectName,
118
+ session_id: sessionId,
119
+ branch: gitBranch,
120
+ commit: gitHash,
121
+ timestamp
122
+ };
123
+ let stored = 0;
124
+ if (data.summary) {
125
+ await storeRecord(
126
+ `[${projectName}] ${data.summary}`,
127
+ { ...baseMeta, record_type: "session_summary" }
128
+ );
129
+ stored++;
130
+ console.log(" \u2713 Summary stored");
131
+ }
132
+ if (data.decisions?.length) {
133
+ for (const d of data.decisions) {
134
+ let content = `[${projectName}] Decision: ${d.topic} \u2014 Chose ${d.choice} because ${d.rationale}`;
135
+ if (d.alternatives_considered?.length) {
136
+ content += ` (alternatives: ${d.alternatives_considered.join(", ")})`;
137
+ }
138
+ await storeRecord(content, { ...baseMeta, record_type: "decision", topic: d.topic });
139
+ stored++;
140
+ }
141
+ console.log(` \u2713 ${data.decisions.length} decision(s) stored`);
142
+ }
143
+ if (data.patterns?.length) {
144
+ for (const p of data.patterns) {
145
+ await storeRecord(
146
+ `[${projectName}] Pattern: ${p.pattern}`,
147
+ { ...baseMeta, record_type: "pattern", scope: p.scope || "project-wide" }
148
+ );
149
+ stored++;
150
+ }
151
+ console.log(` \u2713 ${data.patterns.length} pattern(s) stored`);
152
+ }
153
+ if (data.gotchas?.length) {
154
+ for (const g of data.gotchas) {
155
+ let content = `[${projectName}] Gotcha: ${g.issue} \u2192 Fix: ${g.resolution}`;
156
+ if (g.prevention) content += `. Prevention: ${g.prevention}`;
157
+ await storeRecord(content, { ...baseMeta, record_type: "gotcha" });
158
+ stored++;
159
+ }
160
+ console.log(` \u2713 ${data.gotchas.length} gotcha(s) stored`);
161
+ }
162
+ if (data.files_changed?.length) {
163
+ const lines = data.files_changed.map(
164
+ (f) => `- ${f.path} (${f.action}): ${f.purpose}`
165
+ );
166
+ await storeRecord(
167
+ `[${projectName}] Files changed:
168
+ ${lines.join("\n")}`,
169
+ { ...baseMeta, record_type: "file_context" }
170
+ );
171
+ stored++;
172
+ console.log(` \u2713 File context stored (${data.files_changed.length} files)`);
173
+ }
174
+ if (gitDiffStat) {
175
+ await storeRecord(
176
+ `[${projectName}] Git diff:
177
+ ${gitDiffStat}`,
178
+ { ...baseMeta, record_type: "git_diff" }
179
+ );
180
+ stored++;
181
+ console.log(" \u2713 Git diff stored");
182
+ }
183
+ unlinkSync(sessionLogPath);
184
+ console.log(`Done. ${stored} records ingested as ${sessionId}`);
185
+ }
186
+ async function runHotStart(args2) {
187
+ const projectDir = resolve(args2.find((a) => !a.startsWith("-")) || ".");
188
+ const writeMode = args2.includes("--write");
189
+ let projectRoot;
190
+ try {
191
+ projectRoot = execSync("git rev-parse --show-toplevel", {
192
+ cwd: projectDir,
193
+ encoding: "utf-8"
194
+ }).trim();
195
+ } catch {
196
+ projectRoot = resolve(projectDir);
197
+ }
198
+ const projectName = projectRoot.split("/").pop() || "unknown";
199
+ const has = (f) => existsSync(resolve(projectRoot, f));
200
+ const lines = [];
201
+ lines.push(`# Project: ${projectName}`, "");
202
+ lines.push("## Tech Stack");
203
+ const langMap = [
204
+ ["package.json", "TypeScript/JavaScript"],
205
+ ["Cargo.toml", "Rust"],
206
+ ["go.mod", "Go"],
207
+ ["requirements.txt", "Python"],
208
+ ["pyproject.toml", "Python"],
209
+ ["Gemfile", "Ruby"]
210
+ ];
211
+ const langs = [...new Set(langMap.filter(([f]) => has(f)).map(([, l]) => l))];
212
+ if (langs.length) lines.push(`- Languages: ${langs.join(", ")}`);
213
+ for (const [f, pm] of [["pnpm-lock.yaml", "pnpm"], ["yarn.lock", "yarn"], ["package-lock.json", "npm"], ["Cargo.lock", "cargo"]]) {
214
+ if (has(f)) {
215
+ lines.push(`- Package manager: ${pm}`);
216
+ break;
217
+ }
218
+ }
219
+ if (has("package.json")) {
220
+ try {
221
+ const pkg = JSON.parse(readFileSync(resolve(projectRoot, "package.json"), "utf-8"));
222
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
223
+ for (const fw of ["react", "next", "express", "fastify", "vite", "vitest", "jest", "prisma", "drizzle"]) {
224
+ if (fw in allDeps) lines.push(`- Framework: ${fw}`);
225
+ }
226
+ } catch {
227
+ }
228
+ }
229
+ lines.push("");
230
+ lines.push("## Structure", "```");
231
+ try {
232
+ const tree = execSync(
233
+ 'find . -maxdepth 2 -type d ! -path "*/node_modules*" ! -path "*/.git*" ! -path "*/target*" ! -path "*/.next*" ! -path "*/dist*" ! -path "*/__pycache__*" | sort | head -30 | sed "s|^\\./||"',
234
+ { cwd: projectRoot, encoding: "utf-8" }
235
+ ).trim();
236
+ lines.push(tree);
237
+ } catch {
238
+ }
239
+ lines.push("```", "");
240
+ lines.push("## Key Files");
241
+ for (const f of ["README.md", "CONTRIBUTING.md", "ARCHITECTURE.md", "CLAUDE.md", ".claude/settings.json"]) {
242
+ if (has(f)) lines.push(`- \`${f}\` exists`);
243
+ }
244
+ for (const f of ["src/index.ts", "src/main.ts", "src/app.ts", "index.ts", "main.ts", "src/lib.rs", "src/main.rs", "main.go"]) {
245
+ if (has(f)) lines.push(`- Entry point: \`${f}\``);
246
+ }
247
+ lines.push("");
248
+ if (has("package.json")) {
249
+ try {
250
+ const pkg = JSON.parse(readFileSync(resolve(projectRoot, "package.json"), "utf-8"));
251
+ if (pkg.scripts && Object.keys(pkg.scripts).length) {
252
+ lines.push("## Scripts (from package.json)");
253
+ for (const [k, v] of Object.entries(pkg.scripts).slice(0, 15)) {
254
+ lines.push(`- \`${k}\`: ${v}`);
255
+ }
256
+ lines.push("");
257
+ }
258
+ } catch {
259
+ }
260
+ }
261
+ lines.push("## Recent Git Activity", "```");
262
+ try {
263
+ lines.push(execSync("git log --oneline -10", { cwd: projectRoot, encoding: "utf-8" }).trim());
264
+ } catch {
265
+ lines.push("no git history");
266
+ }
267
+ lines.push("```", "");
268
+ try {
269
+ const healthRes = await fetch(`${MEMORY_URL}/health`);
270
+ if (healthRes.ok) {
271
+ lines.push("## Relevant Memories (from hivemind)", "");
272
+ for (const [label, query] of [
273
+ ["Past Decisions", `${projectName} decision`],
274
+ ["Known Gotchas", `${projectName} gotcha bug issue`],
275
+ ["Project Patterns", `${projectName} pattern convention`]
276
+ ]) {
277
+ try {
278
+ const res = await fetch(`${MEMORY_URL}/search?q=${encodeURIComponent(query)}&context=coding-sessions&limit=5`);
279
+ if (res.ok) {
280
+ const data = await res.json();
281
+ const results = (data.results || []).map((r) => r.content).filter(Boolean);
282
+ if (results.length) {
283
+ lines.push(`### ${label}`);
284
+ for (const r of results) lines.push(`- ${r}`);
285
+ lines.push("");
286
+ }
287
+ }
288
+ } catch {
289
+ }
290
+ }
291
+ }
292
+ } catch {
293
+ }
294
+ const output = lines.join("\n");
295
+ if (writeMode) {
296
+ const claudeMd = resolve(projectRoot, "CLAUDE.md");
297
+ const header = `<!-- Auto-generated by hivemind hot-start ${(/* @__PURE__ */ new Date()).toISOString()} -->`;
298
+ if (existsSync(claudeMd)) {
299
+ const existing = readFileSync(claudeMd, "utf-8");
300
+ writeFileSync(claudeMd, existing + "\n---\n" + header + "\n" + output);
301
+ console.log(`Updated ${claudeMd} with hot-start context`);
302
+ } else {
303
+ writeFileSync(claudeMd, header + "\n" + output);
304
+ console.log(`Created ${claudeMd} with hot-start context`);
305
+ }
306
+ } else {
307
+ console.log(output);
308
+ }
309
+ }
310
+ async function runSetupClaude(_args) {
311
+ const claudeDir = resolve(homedir(), ".claude");
312
+ const claudeMd = resolve(claudeDir, "CLAUDE.md");
313
+ const content = `# Claude Code \u2014 Global Instructions
314
+
315
+ ## Session Logging
316
+
317
+ Before completing any session, write a \`.session-log.json\` file in the project root with the following structure:
318
+
319
+ \`\`\`json
320
+ {
321
+ "timestamp": "<ISO-8601>",
322
+ "summary": "One paragraph describing what was done and why",
323
+ "decisions": [
324
+ {
325
+ "topic": "Short label (e.g. 'auth strategy')",
326
+ "choice": "What was chosen",
327
+ "rationale": "Why this over alternatives",
328
+ "alternatives_considered": ["alt1", "alt2"]
329
+ }
330
+ ],
331
+ "patterns": [
332
+ {
333
+ "pattern": "Description of a coding pattern or convention used/discovered",
334
+ "scope": "project-wide | file-specific | language-general"
335
+ }
336
+ ],
337
+ "gotchas": [
338
+ {
339
+ "issue": "What went wrong or was tricky",
340
+ "resolution": "How it was fixed or worked around",
341
+ "prevention": "How to avoid it next time"
342
+ }
343
+ ],
344
+ "files_changed": [
345
+ {
346
+ "path": "relative/path/to/file",
347
+ "action": "created | modified | deleted",
348
+ "purpose": "Why this file was changed"
349
+ }
350
+ ]
351
+ }
352
+ \`\`\`
353
+
354
+ Rules:
355
+ - Always create this file, even for small changes
356
+ - Omit empty arrays (e.g. if no gotchas, leave out the key)
357
+ - Be specific in decisions and gotchas \u2014 these help future sessions
358
+ - The file is gitignored and consumed by tooling, not humans
359
+ - If the session was exploratory with no changes, still log the summary and any insights
360
+ `;
361
+ if (existsSync(claudeMd)) {
362
+ const existing = readFileSync(claudeMd, "utf-8");
363
+ if (existing.includes("Session Logging")) {
364
+ console.log("CLAUDE.md already contains session logging instructions.");
365
+ return;
366
+ }
367
+ writeFileSync(claudeMd, existing + "\n" + content);
368
+ console.log(`\u2713 Appended session logging instructions to ${claudeMd}`);
369
+ } else {
370
+ writeFileSync(claudeMd, content);
371
+ console.log(`\u2713 Created ${claudeMd} with session logging instructions`);
372
+ }
373
+ const globalGitignore = resolve(homedir(), ".gitignore_global");
374
+ try {
375
+ const existing = existsSync(globalGitignore) ? readFileSync(globalGitignore, "utf-8") : "";
376
+ if (!existing.includes(".session-log.json")) {
377
+ writeFileSync(globalGitignore, existing + "\n.session-log.json\n");
378
+ execSync(`git config --global core.excludesfile "${globalGitignore}"`, { stdio: "ignore" });
379
+ console.log("\u2713 Added .session-log.json to global gitignore");
380
+ }
381
+ } catch {
382
+ }
383
+ }
384
+
24
385
  // packages/cli/src/main.ts
25
386
  var [command, ...args] = process.argv.slice(2);
26
387
  switch (command) {
@@ -60,6 +421,12 @@ switch (command) {
60
421
  process.exit(1);
61
422
  });
62
423
  break;
424
+ case "session":
425
+ runSessionCommand(args).catch((err) => {
426
+ console.error(err instanceof Error ? err.message : String(err));
427
+ process.exit(1);
428
+ });
429
+ break;
63
430
  default:
64
431
  console.log(`hivemind cli v0.3.0
65
432
 
@@ -72,6 +439,7 @@ Commands:
72
439
  upgrade Upgrade the Hivemind runtime
73
440
  service Manage launchd services (install/uninstall/stop/start/status/logs)
74
441
  fleet Manage the worker fleet
442
+ session Claude Code session memory (ingest/hot-start/setup-claude)
75
443
  `);
76
444
  if (command) {
77
445
  console.error(`Unknown command: ${command}`);
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../packages/cli/src/main.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { runFleetCommand } from \"./commands/fleet.js\";\nimport { runStartCommand } from \"./commands/start.js\";\nimport { runInitCommand } from \"./commands/init.js\";\nimport { runServiceCommand } from \"./commands/service.js\";\nimport { runUpgradeCommand } from \"./commands/upgrade.js\";\nimport { runWatchdogCommand } from \"./commands/watchdog.js\";\n\nconst [command, ...args] = process.argv.slice(2);\n\nswitch (command) {\n case \"init\":\n runInitCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n case \"start\":\n runStartCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n case \"service\":\n runServiceCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n case \"fleet\":\n runFleetCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n case \"upgrade\":\n runUpgradeCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n case \"watchdog\":\n runWatchdogCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n default:\n console.log(`hivemind cli v0.3.0\n\nUsage: hivemind <command> [args]\n\nCommands:\n init Initialize agent from Sesame API key\n start Start the Hivemind agent\n watchdog Start the watchdog daemon\n upgrade Upgrade the Hivemind runtime\n service Manage launchd services (install/uninstall/stop/start/status/logs)\n fleet Manage the worker fleet\n`);\n if (command) {\n console.error(`Unknown command: ${command}`);\n process.exit(1);\n }\n break;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AASA,IAAM,CAAC,SAAS,GAAG,IAAI,IAAI,QAAQ,KAAK,MAAM,CAAC;AAE/C,QAAQ,SAAS;AAAA,EACf,KAAK;AACH,mBAAe,IAAI,EAAE,MAAM,CAAC,QAAQ;AAClC,cAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC9D,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AACD;AAAA,EAEF,KAAK;AACH,oBAAgB,IAAI,EAAE,MAAM,CAAC,QAAQ;AACnC,cAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC9D,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AACD;AAAA,EAEF,KAAK;AACH,sBAAkB,IAAI,EAAE,MAAM,CAAC,QAAQ;AACrC,cAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC9D,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AACD;AAAA,EAEF,KAAK;AACH,oBAAgB,IAAI,EAAE,MAAM,CAAC,QAAQ;AACnC,cAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC9D,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AACD;AAAA,EAEF,KAAK;AACH,sBAAkB,IAAI,EAAE,MAAM,CAAC,QAAQ;AACrC,cAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC9D,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AACD;AAAA,EAEF,KAAK;AACH,uBAAmB,IAAI,EAAE,MAAM,CAAC,QAAQ;AACtC,cAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAC9D,cAAQ,KAAK,CAAC;AAAA,IAChB,CAAC;AACD;AAAA,EAEF;AACE,YAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAWf;AACG,QAAI,SAAS;AACX,cAAQ,MAAM,oBAAoB,OAAO,EAAE;AAC3C,cAAQ,KAAK,CAAC;AAAA,IAChB;AACA;AACJ;","names":[]}
1
+ {"version":3,"sources":["../packages/cli/src/commands/session.ts","../packages/cli/src/main.ts"],"sourcesContent":["import { resolve } from \"path\";\nimport { existsSync, readFileSync, unlinkSync, writeFileSync } from \"fs\";\nimport { execSync } from \"child_process\";\nimport { homedir } from \"os\";\n\nconst MEMORY_URL = process.env.HIVEMIND_MEMORY_URL || \"http://localhost:3434\";\nconst CONTEXT = process.env.HIVEMIND_CONTEXT || \"coding-sessions\";\n\ninterface SessionLog {\n timestamp?: string;\n summary?: string;\n decisions?: Array<{\n topic: string;\n choice: string;\n rationale: string;\n alternatives_considered?: string[];\n }>;\n patterns?: Array<{\n pattern: string;\n scope?: string;\n }>;\n gotchas?: Array<{\n issue: string;\n resolution: string;\n prevention?: string;\n }>;\n files_changed?: Array<{\n path: string;\n action: string;\n purpose: string;\n }>;\n}\n\nasync function storeRecord(content: string, metadata: Record<string, any>): Promise<boolean> {\n try {\n const resp = await fetch(`${MEMORY_URL}/store`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ context: CONTEXT, content, metadata }),\n });\n return resp.ok;\n } catch {\n return false;\n }\n}\n\nexport async function runSessionCommand(args: string[]): Promise<void> {\n const subcommand = args[0];\n\n switch (subcommand) {\n case \"ingest\":\n await runIngest(args.slice(1));\n break;\n case \"hot-start\":\n await runHotStart(args.slice(1));\n break;\n case \"setup-claude\":\n await runSetupClaude(args.slice(1));\n break;\n default:\n console.log(`hivemind session — Claude Code session memory tools\n\nUsage: hivemind session <command>\n\nCommands:\n ingest [dir] Ingest .session-log.json from a project into hivemind memory\n hot-start [dir] Generate project context guide from codebase + hivemind memory\n setup-claude Install global CLAUDE.md for session logging\n`);\n if (subcommand) {\n console.error(`Unknown subcommand: ${subcommand}`);\n process.exit(1);\n }\n }\n}\n\nasync function runIngest(args: string[]): Promise<void> {\n const projectDir = resolve(args[0] || \".\");\n const sessionLogPath = resolve(projectDir, \".session-log.json\");\n\n if (!existsSync(sessionLogPath)) {\n console.log(\"No .session-log.json found — nothing to ingest.\");\n return;\n }\n\n console.log(`Ingesting session from ${projectDir}...`);\n\n const data: SessionLog = JSON.parse(readFileSync(sessionLogPath, \"utf-8\"));\n const timestamp = data.timestamp || new Date().toISOString();\n const sessionId = `session-${Date.now()}`;\n\n // Get project name and git context\n let projectName = \"unknown\";\n let gitBranch = \"unknown\";\n let gitHash = \"unknown\";\n let gitDiffStat = \"\";\n\n try {\n projectName = execSync(\"basename $(git rev-parse --show-toplevel)\", {\n cwd: projectDir, encoding: \"utf-8\",\n }).trim();\n } catch { projectName = resolve(projectDir).split(\"/\").pop() || \"unknown\"; }\n\n try {\n gitBranch = execSync(\"git rev-parse --abbrev-ref HEAD\", {\n cwd: projectDir, encoding: \"utf-8\",\n }).trim();\n } catch {}\n\n try {\n gitHash = execSync(\"git rev-parse --short HEAD\", {\n cwd: projectDir, encoding: \"utf-8\",\n }).trim();\n } catch {}\n\n try {\n gitDiffStat = execSync(\"git diff --stat HEAD~1\", {\n cwd: projectDir, encoding: \"utf-8\",\n }).trim();\n } catch {}\n\n const baseMeta = {\n type: \"coding_session\",\n project: projectName,\n session_id: sessionId,\n branch: gitBranch,\n commit: gitHash,\n timestamp,\n };\n\n let stored = 0;\n\n // 1. Summary\n if (data.summary) {\n await storeRecord(\n `[${projectName}] ${data.summary}`,\n { ...baseMeta, record_type: \"session_summary\" },\n );\n stored++;\n console.log(\" ✓ Summary stored\");\n }\n\n // 2. Decisions\n if (data.decisions?.length) {\n for (const d of data.decisions) {\n let content = `[${projectName}] Decision: ${d.topic} — Chose ${d.choice} because ${d.rationale}`;\n if (d.alternatives_considered?.length) {\n content += ` (alternatives: ${d.alternatives_considered.join(\", \")})`;\n }\n await storeRecord(content, { ...baseMeta, record_type: \"decision\", topic: d.topic });\n stored++;\n }\n console.log(` ✓ ${data.decisions.length} decision(s) stored`);\n }\n\n // 3. Patterns\n if (data.patterns?.length) {\n for (const p of data.patterns) {\n await storeRecord(\n `[${projectName}] Pattern: ${p.pattern}`,\n { ...baseMeta, record_type: \"pattern\", scope: p.scope || \"project-wide\" },\n );\n stored++;\n }\n console.log(` ✓ ${data.patterns.length} pattern(s) stored`);\n }\n\n // 4. Gotchas\n if (data.gotchas?.length) {\n for (const g of data.gotchas) {\n let content = `[${projectName}] Gotcha: ${g.issue} → Fix: ${g.resolution}`;\n if (g.prevention) content += `. Prevention: ${g.prevention}`;\n await storeRecord(content, { ...baseMeta, record_type: \"gotcha\" });\n stored++;\n }\n console.log(` ✓ ${data.gotchas.length} gotcha(s) stored`);\n }\n\n // 5. File context\n if (data.files_changed?.length) {\n const lines = data.files_changed.map(\n (f) => `- ${f.path} (${f.action}): ${f.purpose}`,\n );\n await storeRecord(\n `[${projectName}] Files changed:\\n${lines.join(\"\\n\")}`,\n { ...baseMeta, record_type: \"file_context\" },\n );\n stored++;\n console.log(` ✓ File context stored (${data.files_changed.length} files)`);\n }\n\n // 6. Git diff\n if (gitDiffStat) {\n await storeRecord(\n `[${projectName}] Git diff:\\n${gitDiffStat}`,\n { ...baseMeta, record_type: \"git_diff\" },\n );\n stored++;\n console.log(\" ✓ Git diff stored\");\n }\n\n // Clean up\n unlinkSync(sessionLogPath);\n console.log(`Done. ${stored} records ingested as ${sessionId}`);\n}\n\nasync function runHotStart(args: string[]): Promise<void> {\n const projectDir = resolve(args.find(a => !a.startsWith(\"-\")) || \".\");\n const writeMode = args.includes(\"--write\");\n\n let projectRoot: string;\n try {\n projectRoot = execSync(\"git rev-parse --show-toplevel\", {\n cwd: projectDir, encoding: \"utf-8\",\n }).trim();\n } catch {\n projectRoot = resolve(projectDir);\n }\n const projectName = projectRoot.split(\"/\").pop() || \"unknown\";\n const has = (f: string) => existsSync(resolve(projectRoot, f));\n const lines: string[] = [];\n\n lines.push(`# Project: ${projectName}`, \"\");\n\n // Tech stack\n lines.push(\"## Tech Stack\");\n const langMap: [string, string][] = [\n [\"package.json\", \"TypeScript/JavaScript\"], [\"Cargo.toml\", \"Rust\"],\n [\"go.mod\", \"Go\"], [\"requirements.txt\", \"Python\"],\n [\"pyproject.toml\", \"Python\"], [\"Gemfile\", \"Ruby\"],\n ];\n const langs = [...new Set(langMap.filter(([f]) => has(f)).map(([, l]) => l))];\n if (langs.length) lines.push(`- Languages: ${langs.join(\", \")}`);\n\n for (const [f, pm] of [[\"pnpm-lock.yaml\", \"pnpm\"], [\"yarn.lock\", \"yarn\"], [\"package-lock.json\", \"npm\"], [\"Cargo.lock\", \"cargo\"]] as const) {\n if (has(f)) { lines.push(`- Package manager: ${pm}`); break; }\n }\n\n // Frameworks from package.json\n if (has(\"package.json\")) {\n try {\n const pkg = JSON.parse(readFileSync(resolve(projectRoot, \"package.json\"), \"utf-8\"));\n const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };\n for (const fw of [\"react\", \"next\", \"express\", \"fastify\", \"vite\", \"vitest\", \"jest\", \"prisma\", \"drizzle\"]) {\n if (fw in allDeps) lines.push(`- Framework: ${fw}`);\n }\n } catch {}\n }\n lines.push(\"\");\n\n // Structure\n lines.push(\"## Structure\", \"```\");\n try {\n const tree = execSync(\n 'find . -maxdepth 2 -type d ' +\n '! -path \"*/node_modules*\" ! -path \"*/.git*\" ! -path \"*/target*\" ' +\n '! -path \"*/.next*\" ! -path \"*/dist*\" ! -path \"*/__pycache__*\" ' +\n '| sort | head -30 | sed \"s|^\\\\./||\"',\n { cwd: projectRoot, encoding: \"utf-8\" },\n ).trim();\n lines.push(tree);\n } catch {}\n lines.push(\"```\", \"\");\n\n // Key files\n lines.push(\"## Key Files\");\n for (const f of [\"README.md\", \"CONTRIBUTING.md\", \"ARCHITECTURE.md\", \"CLAUDE.md\", \".claude/settings.json\"]) {\n if (has(f)) lines.push(`- \\`${f}\\` exists`);\n }\n for (const f of [\"src/index.ts\", \"src/main.ts\", \"src/app.ts\", \"index.ts\", \"main.ts\", \"src/lib.rs\", \"src/main.rs\", \"main.go\"]) {\n if (has(f)) lines.push(`- Entry point: \\`${f}\\``);\n }\n lines.push(\"\");\n\n // Scripts from package.json\n if (has(\"package.json\")) {\n try {\n const pkg = JSON.parse(readFileSync(resolve(projectRoot, \"package.json\"), \"utf-8\"));\n if (pkg.scripts && Object.keys(pkg.scripts).length) {\n lines.push(\"## Scripts (from package.json)\");\n for (const [k, v] of Object.entries(pkg.scripts).slice(0, 15)) {\n lines.push(`- \\`${k}\\`: ${v}`);\n }\n lines.push(\"\");\n }\n } catch {}\n }\n\n // Git context\n lines.push(\"## Recent Git Activity\", \"```\");\n try {\n lines.push(execSync(\"git log --oneline -10\", { cwd: projectRoot, encoding: \"utf-8\" }).trim());\n } catch {\n lines.push(\"no git history\");\n }\n lines.push(\"```\", \"\");\n\n // Hivemind memory\n try {\n const healthRes = await fetch(`${MEMORY_URL}/health`);\n if (healthRes.ok) {\n lines.push(\"## Relevant Memories (from hivemind)\", \"\");\n\n for (const [label, query] of [\n [\"Past Decisions\", `${projectName} decision`],\n [\"Known Gotchas\", `${projectName} gotcha bug issue`],\n [\"Project Patterns\", `${projectName} pattern convention`],\n ] as const) {\n try {\n const res = await fetch(`${MEMORY_URL}/search?q=${encodeURIComponent(query)}&context=coding-sessions&limit=5`);\n if (res.ok) {\n const data = await res.json() as any;\n const results = (data.results || []).map((r: any) => r.content).filter(Boolean);\n if (results.length) {\n lines.push(`### ${label}`);\n for (const r of results) lines.push(`- ${r}`);\n lines.push(\"\");\n }\n }\n } catch {}\n }\n }\n } catch {}\n\n // Output\n const output = lines.join(\"\\n\");\n\n if (writeMode) {\n const claudeMd = resolve(projectRoot, \"CLAUDE.md\");\n const header = `<!-- Auto-generated by hivemind hot-start ${new Date().toISOString()} -->`;\n if (existsSync(claudeMd)) {\n const existing = readFileSync(claudeMd, \"utf-8\");\n writeFileSync(claudeMd, existing + \"\\n---\\n\" + header + \"\\n\" + output);\n console.log(`Updated ${claudeMd} with hot-start context`);\n } else {\n writeFileSync(claudeMd, header + \"\\n\" + output);\n console.log(`Created ${claudeMd} with hot-start context`);\n }\n } else {\n console.log(output);\n }\n}\n\nasync function runSetupClaude(_args: string[]): Promise<void> {\n const claudeDir = resolve(homedir(), \".claude\");\n const claudeMd = resolve(claudeDir, \"CLAUDE.md\");\n\n const content = `# Claude Code — Global Instructions\n\n## Session Logging\n\nBefore completing any session, write a \\`.session-log.json\\` file in the project root with the following structure:\n\n\\`\\`\\`json\n{\n \"timestamp\": \"<ISO-8601>\",\n \"summary\": \"One paragraph describing what was done and why\",\n \"decisions\": [\n {\n \"topic\": \"Short label (e.g. 'auth strategy')\",\n \"choice\": \"What was chosen\",\n \"rationale\": \"Why this over alternatives\",\n \"alternatives_considered\": [\"alt1\", \"alt2\"]\n }\n ],\n \"patterns\": [\n {\n \"pattern\": \"Description of a coding pattern or convention used/discovered\",\n \"scope\": \"project-wide | file-specific | language-general\"\n }\n ],\n \"gotchas\": [\n {\n \"issue\": \"What went wrong or was tricky\",\n \"resolution\": \"How it was fixed or worked around\",\n \"prevention\": \"How to avoid it next time\"\n }\n ],\n \"files_changed\": [\n {\n \"path\": \"relative/path/to/file\",\n \"action\": \"created | modified | deleted\",\n \"purpose\": \"Why this file was changed\"\n }\n ]\n}\n\\`\\`\\`\n\nRules:\n- Always create this file, even for small changes\n- Omit empty arrays (e.g. if no gotchas, leave out the key)\n- Be specific in decisions and gotchas — these help future sessions\n- The file is gitignored and consumed by tooling, not humans\n- If the session was exploratory with no changes, still log the summary and any insights\n`;\n\n if (existsSync(claudeMd)) {\n const existing = readFileSync(claudeMd, \"utf-8\");\n if (existing.includes(\"Session Logging\")) {\n console.log(\"CLAUDE.md already contains session logging instructions.\");\n return;\n }\n // Append\n writeFileSync(claudeMd, existing + \"\\n\" + content);\n console.log(`✓ Appended session logging instructions to ${claudeMd}`);\n } else {\n writeFileSync(claudeMd, content);\n console.log(`✓ Created ${claudeMd} with session logging instructions`);\n }\n\n // Also add .session-log.json to global gitignore\n const globalGitignore = resolve(homedir(), \".gitignore_global\");\n try {\n const existing = existsSync(globalGitignore) ? readFileSync(globalGitignore, \"utf-8\") : \"\";\n if (!existing.includes(\".session-log.json\")) {\n writeFileSync(globalGitignore, existing + \"\\n.session-log.json\\n\");\n execSync(`git config --global core.excludesfile \"${globalGitignore}\"`, { stdio: \"ignore\" });\n console.log(\"✓ Added .session-log.json to global gitignore\");\n }\n } catch {}\n}\n","#!/usr/bin/env node\n\nimport { runFleetCommand } from \"./commands/fleet.js\";\nimport { runStartCommand } from \"./commands/start.js\";\nimport { runInitCommand } from \"./commands/init.js\";\nimport { runServiceCommand } from \"./commands/service.js\";\nimport { runUpgradeCommand } from \"./commands/upgrade.js\";\nimport { runWatchdogCommand } from \"./commands/watchdog.js\";\nimport { runSessionCommand } from \"./commands/session.js\";\n\nconst [command, ...args] = process.argv.slice(2);\n\nswitch (command) {\n case \"init\":\n runInitCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n case \"start\":\n runStartCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n case \"service\":\n runServiceCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n case \"fleet\":\n runFleetCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n case \"upgrade\":\n runUpgradeCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n case \"watchdog\":\n runWatchdogCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n case \"session\":\n runSessionCommand(args).catch((err) => {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n });\n break;\n\n default:\n console.log(`hivemind cli v0.3.0\n\nUsage: hivemind <command> [args]\n\nCommands:\n init Initialize agent from Sesame API key\n start Start the Hivemind agent\n watchdog Start the watchdog daemon\n upgrade Upgrade the Hivemind runtime\n service Manage launchd services (install/uninstall/stop/start/status/logs)\n fleet Manage the worker fleet\n session Claude Code session memory (ingest/hot-start/setup-claude)\n`);\n if (command) {\n console.error(`Unknown command: ${command}`);\n process.exit(1);\n }\n break;\n}\n"],"mappings":"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","names":["args"]}
package/dist/start.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  loadConfig,
4
4
  startPipeline,
5
5
  startWorker
6
- } from "./chunk-ZM7RK5YV.js";
6
+ } from "./chunk-M3A2WRXM.js";
7
7
  import "./chunk-DGUM43GV.js";
8
8
 
9
9
  // packages/runtime/src/start.ts
package/install.sh ADDED
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ # Hivemind — One-shot install for macOS
5
+ # Usage: curl -sL api.sesame.space/api/v1/hivemind/install | bash -s -- <sesame-api-key>
6
+
7
+ # --- Handle curl-pipe-bash stdin issue ---
8
+ # When piped from curl, stdin is the script itself. We need stdin for interactive prompts.
9
+ # Self-extract: download to temp, re-exec from disk with /dev/tty as stdin.
10
+ if [ -z "${HIVEMIND_INSTALL_REEXEC:-}" ]; then
11
+ TMPSCRIPT="$(mktemp /tmp/hivemind-install.XXXXXX)"
12
+ # If we're being piped, cat has already consumed stdin — use $0 or re-download
13
+ cat > "$TMPSCRIPT" < /dev/stdin 2>/dev/null || cp "$0" "$TMPSCRIPT" 2>/dev/null || true
14
+ # If the temp file is empty or too small, we're running from disk already
15
+ if [ -s "$TMPSCRIPT" ] && [ "$(wc -c < "$TMPSCRIPT")" -gt 100 ]; then
16
+ chmod +x "$TMPSCRIPT"
17
+ HIVEMIND_INSTALL_REEXEC=1 exec bash "$TMPSCRIPT" "$@" < /dev/tty
18
+ fi
19
+ rm -f "$TMPSCRIPT"
20
+ fi
21
+
22
+ BOLD='\033[1m'
23
+ GREEN='\033[0;32m'
24
+ YELLOW='\033[0;33m'
25
+ RED='\033[0;31m'
26
+ NC='\033[0m'
27
+
28
+ info() { echo -e "${GREEN}[✓]${NC} $1"; }
29
+ warn() { echo -e "${YELLOW}[!]${NC} $1"; }
30
+ err() { echo -e "${RED}[✗]${NC} $1"; }
31
+ step() { echo -e "\n${BOLD}→ $1${NC}"; }
32
+
33
+ HIVEMIND_HOME="${HIVEMIND_HOME:-$HOME/hivemind}"
34
+
35
+ echo -e "${BOLD}"
36
+ echo " ╦ ╦╦╦ ╦╔═╗╔╦╗╦╔╗╔╔╦╗"
37
+ echo " ╠═╣║╚╗╔╝║╣ ║║║║║║║ ║║"
38
+ echo " ╩ ╩╩ ╚╝ ╚═╝╩ ╩╩╝╚╝═╩╝"
39
+ echo -e "${NC}"
40
+ echo " Agent Runtime Installer"
41
+ echo ""
42
+
43
+ # --- 1. System dependencies ---
44
+ step "Checking system dependencies"
45
+
46
+ # Homebrew
47
+ if ! command -v brew &>/dev/null; then
48
+ warn "Homebrew not found — installing..."
49
+ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
50
+ eval "$(/opt/homebrew/bin/brew shellenv)"
51
+ else
52
+ info "Homebrew found"
53
+ fi
54
+
55
+ # Node.js
56
+ if ! command -v node &>/dev/null; then
57
+ warn "Node.js not found — installing via brew..."
58
+ brew install node
59
+ else
60
+ NODE_VER=$(node -v | sed 's/v//' | cut -d. -f1)
61
+ if [ "$NODE_VER" -lt 20 ]; then
62
+ warn "Node.js v${NODE_VER} too old (need ≥20) — upgrading..."
63
+ brew upgrade node
64
+ else
65
+ info "Node.js $(node -v)"
66
+ fi
67
+ fi
68
+
69
+ # Rust (for memory daemon)
70
+ if ! command -v cargo &>/dev/null; then
71
+ warn "Rust not found — installing..."
72
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path
73
+ source "$HOME/.cargo/env"
74
+ else
75
+ info "Rust $(cargo --version | cut -d' ' -f2)"
76
+ fi
77
+
78
+ # --- 2. Install hivemind via npm ---
79
+ step "Installing @sesamespace/hivemind"
80
+ npm install -g @sesamespace/hivemind
81
+ info "Hivemind CLI installed: $(which hivemind)"
82
+
83
+ # --- 2b. Install Playwright (for browse tool) ---
84
+ step "Installing Playwright"
85
+ if npx playwright --version &>/dev/null 2>&1; then
86
+ info "Playwright already available"
87
+ else
88
+ npm install -g playwright
89
+ info "Playwright installed"
90
+ fi
91
+ # Install Chromium browser (required for headless browsing)
92
+ npx playwright install chromium 2>/dev/null && info "Playwright Chromium installed" || warn "Playwright Chromium install failed — browse tool may not work"
93
+
94
+ # --- 2c. Build memory daemon ---
95
+ step "Building memory daemon"
96
+ if [ -f "${HIVEMIND_HOME}/bin/hivemind-memory" ]; then
97
+ info "Memory daemon already built"
98
+ else
99
+ # Check if we have the source
100
+ NPM_GLOBAL="$(npm root -g)"
101
+ MEMORY_SRC="${NPM_GLOBAL}/@sesamespace/hivemind/packages/memory"
102
+
103
+ if [ -d "$MEMORY_SRC" ] && [ -f "$MEMORY_SRC/Cargo.toml" ]; then
104
+ info "Building from source..."
105
+ cd "$MEMORY_SRC"
106
+ cargo build --release
107
+ mkdir -p "${HIVEMIND_HOME}/bin"
108
+ cp target/release/hivemind-memory "${HIVEMIND_HOME}/bin/"
109
+ info "Memory daemon built successfully"
110
+ else
111
+ warn "Memory daemon source not found — skipping build"
112
+ warn "Run 'hivemind build-memory' after installation to compile"
113
+ fi
114
+ fi
115
+
116
+ # --- 3. Set up HIVEMIND_HOME ---
117
+ step "Setting up ${HIVEMIND_HOME}"
118
+ mkdir -p "${HIVEMIND_HOME}/config"
119
+
120
+ # Copy default config
121
+ NPM_GLOBAL="$(npm root -g)"
122
+ DEFAULT_CONFIG="${NPM_GLOBAL}/@sesamespace/hivemind/config/default.toml"
123
+ if [ -f "$DEFAULT_CONFIG" ]; then
124
+ cp "$DEFAULT_CONFIG" "${HIVEMIND_HOME}/config/default.toml"
125
+ info "Copied default config"
126
+ else
127
+ warn "Default config not found at ${DEFAULT_CONFIG} — skipping"
128
+ fi
129
+
130
+ # --- 4. Initialize agent ---
131
+ step "Initializing agent"
132
+
133
+ SESAME_KEY="${1:-${SESAME_API_KEY:-}}"
134
+ if [ -z "$SESAME_KEY" ]; then
135
+ read -rp " Sesame API key: " SESAME_KEY
136
+ fi
137
+
138
+ if [ -z "$SESAME_KEY" ]; then
139
+ err "Sesame API key is required"
140
+ exit 1
141
+ fi
142
+
143
+ export HIVEMIND_HOME
144
+ hivemind init "$SESAME_KEY" --non-interactive
145
+
146
+ # --- 5. Install launchd service ---
147
+ step "Installing launchd service"
148
+ hivemind service install
149
+
150
+ # --- Done ---
151
+ echo ""
152
+ echo -e "${GREEN}${BOLD} ✓ Hivemind installed successfully!${NC}"
153
+ echo ""
154
+ echo " Home: ${HIVEMIND_HOME}"
155
+ echo " Config: ${HIVEMIND_HOME}/config/"
156
+ echo " Logs: /tmp/hivemind-agent.log, /tmp/hivemind-watchdog.log"
157
+ echo ""
158
+ echo " Commands:"
159
+ echo " hivemind service status — Check service"
160
+ echo " hivemind service logs — View logs"
161
+ echo " hivemind upgrade — Update to latest"
162
+ echo ""