@sesamespace/hivemind 0.11.3 → 0.11.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.
@@ -1,6 +1,6 @@
1
1
  // packages/cli/src/commands/service.ts
2
2
  import { resolve } from "path";
3
- import { writeFileSync, existsSync, unlinkSync, mkdirSync, readFileSync } from "fs";
3
+ import { writeFileSync, existsSync, unlinkSync, mkdirSync } from "fs";
4
4
  import { execSync } from "child_process";
5
5
  import { homedir } from "os";
6
6
  var LAUNCH_AGENTS_DIR = resolve(homedir(), "Library/LaunchAgents");
@@ -291,6 +291,7 @@ function startService() {
291
291
  }
292
292
  function showStatus() {
293
293
  console.log("\n\u2192 Service status\n");
294
+ const keepAliveServices = /* @__PURE__ */ new Set([MEMORY_LABEL, WATCHDOG_LABEL]);
294
295
  const pidFiles = {
295
296
  [AGENT_LABEL]: "/tmp/hivemind-agent.pid",
296
297
  [WATCHDOG_LABEL]: "/tmp/hivemind-watchdog.pid",
@@ -298,25 +299,32 @@ function showStatus() {
298
299
  };
299
300
  for (const label of [AGENT_LABEL, WATCHDOG_LABEL, MEMORY_LABEL]) {
300
301
  try {
301
- execSync(`launchctl list ${label} 2>/dev/null`, { encoding: "utf-8" });
302
- let pid = "unknown";
303
- const pidFile = pidFiles[label];
304
- if (existsSync(pidFile)) {
305
- const filePid = readFileSync(pidFile, "utf-8").trim();
306
- try {
307
- execSync(`ps -p ${filePid} > /dev/null 2>&1`);
308
- pid = filePid;
309
- } catch {
310
- pid = "stale";
311
- }
312
- }
313
- if (pid === "stale") {
314
- console.log(` ! ${label}: loaded but not running (stale PID file)`);
302
+ const listOutput = execSync(`launchctl list ${label} 2>/dev/null`, { encoding: "utf-8" });
303
+ const pidMatch = listOutput.match(/"PID"\s*=\s*(\d+)/);
304
+ if (pidMatch) {
305
+ console.log(` \u2713 ${label}: running (PID ${pidMatch[1]})`);
315
306
  } else {
316
- console.log(` \u2713 ${label}: running (PID ${pid})`);
307
+ const pidFile = pidFiles[label];
308
+ if (pidFile && existsSync(pidFile)) {
309
+ try {
310
+ unlinkSync(pidFile);
311
+ } catch {
312
+ }
313
+ }
314
+ if (keepAliveServices.has(label)) {
315
+ try {
316
+ const uid = execSync("id -u", { encoding: "utf-8" }).trim();
317
+ execSync(`launchctl kickstart gui/${uid}/${label} 2>/dev/null`);
318
+ console.log(` ! ${label}: was not running, kickstarted`);
319
+ } catch {
320
+ console.log(` ! ${label}: loaded but not running`);
321
+ }
322
+ } else {
323
+ console.log(` ! ${label}: loaded but not running`);
324
+ }
317
325
  }
318
326
  } catch {
319
- console.log(` - ${label}: not running`);
327
+ console.log(` - ${label}: not loaded`);
320
328
  }
321
329
  }
322
330
  try {
@@ -364,4 +372,4 @@ Services:
364
372
  export {
365
373
  runServiceCommand
366
374
  };
367
- //# sourceMappingURL=chunk-FMI7HNBT.js.map
375
+ //# sourceMappingURL=chunk-6QZDXOMW.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../packages/cli/src/commands/service.ts"],"sourcesContent":["import { resolve } from \"path\";\nimport { writeFileSync, existsSync, unlinkSync, mkdirSync, readFileSync } from \"fs\";\nimport { execSync } from \"child_process\";\nimport { homedir } from \"os\";\n\nconst LAUNCH_AGENTS_DIR = resolve(homedir(), \"Library/LaunchAgents\");\nconst AGENT_LABEL = \"com.hivemind.agent\";\nconst WATCHDOG_LABEL = \"com.hivemind.watchdog\";\nconst MEMORY_LABEL = \"com.hivemind.memory\";\nconst STOP_FLAG_FILE = \"/tmp/hivemind-agent.stopped\";\n\nfunction getHivemindHome(): string {\n return process.env.HIVEMIND_HOME || resolve(homedir(), \"hivemind\");\n}\n\nfunction getHivemindBin(): string {\n // Try to find the hivemind binary\n try {\n const which = execSync(\"which hivemind\", { encoding: \"utf-8\" }).trim();\n if (which) return which;\n } catch {}\n // Fallback to process.argv[1] (the script being run)\n return process.argv[1] || \"hivemind\";\n}\n\nfunction generateMemoryPlist(hivemindHome: string): string {\n const memoryBin = resolve(hivemindHome, \"bin\", \"hivemind-memory\");\n const dbPath = resolve(hivemindHome, \"data\", \"lancedb\");\n const pidFile = `/tmp/hivemind-memory.pid`;\n \n // Create a wrapper script that writes PID\n const wrapperScript = resolve(hivemindHome, \"bin\", \"memory-wrapper.sh\");\n const wrapperContent = `#!/bin/bash\necho $$ > ${pidFile}\nexec \"${memoryBin}\" \"$@\"\n`;\n writeFileSync(wrapperScript, wrapperContent);\n execSync(`chmod +x \"${wrapperScript}\"`);\n \n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${MEMORY_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${wrapperScript}</string>\n </array>\n <key>WorkingDirectory</key>\n <string>${hivemindHome}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PORT</key>\n <string>3434</string>\n <key>DB_PATH</key>\n <string>${dbPath}</string>\n <key>OLLAMA_URL</key>\n <string>http://localhost:11434</string>\n <key>EMBEDDING_MODEL</key>\n <string>nomic-embed-text</string>\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>StandardOutPath</key>\n <string>/tmp/hivemind-memory.log</string>\n <key>StandardErrorPath</key>\n <string>/tmp/hivemind-memory-error.log</string>\n <key>ThrottleInterval</key>\n <integer>5</integer>\n</dict>\n</plist>`;\n}\n\nfunction generateWatchdogPlist(hivemindHome: string, hivemindBin: string): string {\n const pidFile = `/tmp/hivemind-watchdog.pid`;\n \n // Create a wrapper script that writes PID\n const wrapperScript = resolve(hivemindHome, \"bin\", \"watchdog-wrapper.sh\");\n const wrapperContent = `#!/bin/bash\necho $$ > ${pidFile}\nexec \"${hivemindBin}\" watchdog \"$@\"\n`;\n writeFileSync(wrapperScript, wrapperContent);\n execSync(`chmod +x \"${wrapperScript}\"`);\n \n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${WATCHDOG_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${wrapperScript}</string>\n </array>\n <key>WorkingDirectory</key>\n <string>${hivemindHome}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>\n <key>HIVEMIND_HOME</key>\n <string>${hivemindHome}</string>\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>StandardOutPath</key>\n <string>/tmp/hivemind-watchdog.log</string>\n <key>StandardErrorPath</key>\n <string>/tmp/hivemind-watchdog-error.log</string>\n <key>ThrottleInterval</key>\n <integer>5</integer>\n</dict>\n</plist>`;\n}\n\nfunction generatePlist(hivemindHome: string, hivemindBin: string): string {\n const pidFile = `/tmp/hivemind-agent.pid`;\n \n // Create a wrapper script that writes PID\n const wrapperScript = resolve(hivemindHome, \"bin\", \"agent-wrapper.sh\");\n const wrapperContent = `#!/bin/bash\necho $$ > ${pidFile}\nexec \"${hivemindBin}\" start \"$@\"\n`;\n writeFileSync(wrapperScript, wrapperContent);\n execSync(`chmod +x \"${wrapperScript}\"`);\n \n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${AGENT_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${wrapperScript}</string>\n </array>\n <key>WorkingDirectory</key>\n <string>${hivemindHome}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>\n <key>HIVEMIND_HOME</key>\n <string>${hivemindHome}</string>\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <false/>\n <key>StandardOutPath</key>\n <string>/tmp/hivemind-agent.log</string>\n <key>StandardErrorPath</key>\n <string>/tmp/hivemind-error.log</string>\n <key>ThrottleInterval</key>\n <integer>5</integer>\n</dict>\n</plist>`;\n}\n\nexport async function runServiceCommand(args: string[]): Promise<void> {\n const subcommand = args[0];\n\n switch (subcommand) {\n case \"install\":\n await installService();\n break;\n case \"uninstall\":\n await uninstallService();\n break;\n case \"stop\":\n stopService();\n break;\n case \"start\":\n startService();\n break;\n case \"status\":\n showStatus();\n break;\n case \"logs\":\n showLogs(args[1]);\n break;\n default:\n printHelp();\n if (subcommand) {\n console.error(`Unknown subcommand: ${subcommand}`);\n process.exit(1);\n }\n break;\n }\n}\n\nasync function installService(): Promise<void> {\n const hivemindHome = getHivemindHome();\n const hivemindBin = getHivemindBin();\n const memoryBin = resolve(hivemindHome, \"bin\", \"hivemind-memory\");\n\n console.log(`\\n→ Installing launchd services for ${hivemindHome}\\n`);\n console.log(` Agent binary: ${hivemindBin}`);\n console.log(` Memory binary: ${memoryBin}`);\n\n mkdirSync(LAUNCH_AGENTS_DIR, { recursive: true });\n\n // --- Memory daemon service ---\n if (existsSync(memoryBin)) {\n const memoryPlist = generateMemoryPlist(hivemindHome);\n const memoryDest = resolve(LAUNCH_AGENTS_DIR, `${MEMORY_LABEL}.plist`);\n try { execSync(`launchctl unload ${memoryDest} 2>/dev/null`); } catch {}\n writeFileSync(memoryDest, memoryPlist);\n execSync(`launchctl load ${memoryDest}`);\n console.log(` ✓ ${MEMORY_LABEL} installed and started`);\n } else {\n console.log(` ! Memory daemon not found at ${memoryBin} — skipping`);\n console.log(` ! Run 'hivemind init' to download it`);\n }\n\n // --- Ollama service (ensure running) ---\n try {\n execSync(\"curl -sf http://localhost:11434/api/tags > /dev/null\", { stdio: \"ignore\" });\n console.log(\" ✓ Ollama already running\");\n } catch {\n try {\n execSync(\"brew services start ollama 2>/dev/null\", { stdio: \"ignore\" });\n console.log(\" ✓ Ollama started via brew services\");\n } catch {\n console.log(\" ! Ollama not running — start manually: ollama serve\");\n }\n }\n\n // --- Watchdog service ---\n const watchdogPlist = generateWatchdogPlist(hivemindHome, hivemindBin);\n const watchdogDest = resolve(LAUNCH_AGENTS_DIR, `${WATCHDOG_LABEL}.plist`);\n try { execSync(`launchctl unload ${watchdogDest} 2>/dev/null`); } catch {}\n writeFileSync(watchdogDest, watchdogPlist);\n execSync(`launchctl load ${watchdogDest}`);\n console.log(` ✓ ${WATCHDOG_LABEL} installed and started`);\n\n // --- Agent service (KeepAlive: false — watchdog manages restarts) ---\n const plistContent = generatePlist(hivemindHome, hivemindBin);\n const destPath = resolve(LAUNCH_AGENTS_DIR, `${AGENT_LABEL}.plist`);\n try { execSync(`launchctl unload ${destPath} 2>/dev/null`); } catch {}\n writeFileSync(destPath, plistContent);\n execSync(`launchctl load ${destPath}`);\n console.log(` ✓ ${AGENT_LABEL} installed and started`);\n\n console.log(\"\\n Services will auto-start on boot.\");\n console.log(\" Logs:\");\n console.log(\" Agent: /tmp/hivemind-agent.log\");\n console.log(\" Watchdog: /tmp/hivemind-watchdog.log\");\n console.log(\" Memory: /tmp/hivemind-memory.log\\n\");\n}\n\nasync function uninstallService(): Promise<void> {\n console.log(\"\\n→ Uninstalling launchd services\\n\");\n\n for (const label of [AGENT_LABEL, WATCHDOG_LABEL, MEMORY_LABEL]) {\n const plistPath = resolve(LAUNCH_AGENTS_DIR, `${label}.plist`);\n if (existsSync(plistPath)) {\n try { execSync(`launchctl unload ${plistPath} 2>/dev/null`); } catch {}\n unlinkSync(plistPath);\n console.log(` ✓ ${label} uninstalled`);\n } else {\n console.log(` - ${label} not installed`);\n }\n }\n\n // Clean up stop flag if present\n try { unlinkSync(STOP_FLAG_FILE); } catch {}\n console.log(\"\");\n}\n\nfunction stopService(): void {\n console.log(\"\\n→ Stopping agent\\n\");\n\n // Write stop flag so watchdog doesn't restart\n writeFileSync(STOP_FLAG_FILE, String(Date.now()));\n console.log(` ✓ Stop flag written (${STOP_FLAG_FILE})`);\n\n // Stop agent via launchctl\n try {\n const uid = execSync(\"id -u\", { encoding: \"utf-8\" }).trim();\n execSync(`launchctl kill SIGTERM gui/${uid}/${AGENT_LABEL} 2>/dev/null`);\n console.log(` ✓ ${AGENT_LABEL} stopped`);\n } catch {\n console.log(` - ${AGENT_LABEL} was not running`);\n }\n\n console.log(\" Watchdog will NOT restart the agent while stop flag exists.\");\n console.log(\" Use 'hivemind service start' to resume.\\n\");\n}\n\nfunction startService(): void {\n console.log(\"\\n→ Starting agent\\n\");\n\n // Remove stop flag\n try {\n unlinkSync(STOP_FLAG_FILE);\n console.log(` ✓ Stop flag removed (${STOP_FLAG_FILE})`);\n } catch {\n console.log(\" - No stop flag present\");\n }\n\n // Start agent via launchctl\n try {\n const uid = execSync(\"id -u\", { encoding: \"utf-8\" }).trim();\n execSync(`launchctl kickstart gui/${uid}/${AGENT_LABEL}`);\n console.log(` ✓ ${AGENT_LABEL} started`);\n } catch (err) {\n console.error(` ! Failed to start agent: ${(err as Error).message}`);\n }\n console.log(\"\");\n}\n\nfunction showStatus(): void {\n console.log(\"\\n→ Service status\\n\");\n \n const pidFiles: Record<string, string> = {\n [AGENT_LABEL]: \"/tmp/hivemind-agent.pid\",\n [WATCHDOG_LABEL]: \"/tmp/hivemind-watchdog.pid\",\n [MEMORY_LABEL]: \"/tmp/hivemind-memory.pid\"\n };\n \n for (const label of [AGENT_LABEL, WATCHDOG_LABEL, MEMORY_LABEL]) {\n try {\n // First check if service is loaded in launchctl\n execSync(`launchctl list ${label} 2>/dev/null`, { encoding: \"utf-8\" });\n \n // Then try to get PID from file\n let pid = \"unknown\";\n const pidFile = pidFiles[label];\n if (existsSync(pidFile)) {\n const filePid = readFileSync(pidFile, \"utf-8\").trim();\n // Verify the process is actually running\n try {\n execSync(`ps -p ${filePid} > /dev/null 2>&1`);\n pid = filePid;\n } catch {\n // PID file exists but process is dead\n pid = \"stale\";\n }\n }\n \n if (pid === \"stale\") {\n console.log(` ! ${label}: loaded but not running (stale PID file)`);\n } else {\n console.log(` ✓ ${label}: running (PID ${pid})`);\n }\n } catch {\n console.log(` - ${label}: not running`);\n }\n }\n\n // Check Ollama\n try {\n execSync(\"curl -sf http://localhost:11434/api/tags > /dev/null\", { stdio: \"ignore\" });\n console.log(\" ✓ ollama: running\");\n } catch {\n console.log(\" - ollama: not running\");\n }\n console.log(\"\");\n}\n\nfunction showLogs(which?: string): void {\n const logMap: Record<string, string> = {\n agent: \"/tmp/hivemind-agent.log\",\n error: \"/tmp/hivemind-error.log\",\n watchdog: \"/tmp/hivemind-watchdog.log\",\n memory: \"/tmp/hivemind-memory.log\",\n };\n const logFile = logMap[which || \"agent\"] || logMap.agent;\n try {\n execSync(`tail -30 ${logFile}`, { stdio: \"inherit\" });\n } catch {\n console.error(`No log file at ${logFile}`);\n }\n}\n\nfunction printHelp(): void {\n console.log(`hivemind service — Manage launchd services\n\nUsage: hivemind service <subcommand>\n\nSubcommands:\n install Install and start all launchd services (survives reboots)\n uninstall Stop and remove all launchd services\n stop Stop agent (watchdog will not restart it)\n start Start agent (removes stop flag)\n status Show service status\n logs [agent|watchdog|memory|error] Show recent logs\n\nServices:\n com.hivemind.watchdog — Watchdog daemon (health monitoring, restart/upgrade orchestration)\n com.hivemind.agent — Agent runtime (Node.js, Sesame) — managed by watchdog\n com.hivemind.memory — Memory daemon (LanceDB + Ollama embeddings)\n`);\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../packages/cli/src/commands/service.ts"],"sourcesContent":["import { resolve } from \"path\";\nimport { writeFileSync, existsSync, unlinkSync, mkdirSync, readFileSync } from \"fs\";\nimport { execSync } from \"child_process\";\nimport { homedir } from \"os\";\n\nconst LAUNCH_AGENTS_DIR = resolve(homedir(), \"Library/LaunchAgents\");\nconst AGENT_LABEL = \"com.hivemind.agent\";\nconst WATCHDOG_LABEL = \"com.hivemind.watchdog\";\nconst MEMORY_LABEL = \"com.hivemind.memory\";\nconst STOP_FLAG_FILE = \"/tmp/hivemind-agent.stopped\";\n\nfunction getHivemindHome(): string {\n return process.env.HIVEMIND_HOME || resolve(homedir(), \"hivemind\");\n}\n\nfunction getHivemindBin(): string {\n // Try to find the hivemind binary\n try {\n const which = execSync(\"which hivemind\", { encoding: \"utf-8\" }).trim();\n if (which) return which;\n } catch {}\n // Fallback to process.argv[1] (the script being run)\n return process.argv[1] || \"hivemind\";\n}\n\nfunction generateMemoryPlist(hivemindHome: string): string {\n const memoryBin = resolve(hivemindHome, \"bin\", \"hivemind-memory\");\n const dbPath = resolve(hivemindHome, \"data\", \"lancedb\");\n const pidFile = `/tmp/hivemind-memory.pid`;\n \n // Create a wrapper script that writes PID\n const wrapperScript = resolve(hivemindHome, \"bin\", \"memory-wrapper.sh\");\n const wrapperContent = `#!/bin/bash\necho $$ > ${pidFile}\nexec \"${memoryBin}\" \"$@\"\n`;\n writeFileSync(wrapperScript, wrapperContent);\n execSync(`chmod +x \"${wrapperScript}\"`);\n \n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${MEMORY_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${wrapperScript}</string>\n </array>\n <key>WorkingDirectory</key>\n <string>${hivemindHome}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PORT</key>\n <string>3434</string>\n <key>DB_PATH</key>\n <string>${dbPath}</string>\n <key>OLLAMA_URL</key>\n <string>http://localhost:11434</string>\n <key>EMBEDDING_MODEL</key>\n <string>nomic-embed-text</string>\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>StandardOutPath</key>\n <string>/tmp/hivemind-memory.log</string>\n <key>StandardErrorPath</key>\n <string>/tmp/hivemind-memory-error.log</string>\n <key>ThrottleInterval</key>\n <integer>5</integer>\n</dict>\n</plist>`;\n}\n\nfunction generateWatchdogPlist(hivemindHome: string, hivemindBin: string): string {\n const pidFile = `/tmp/hivemind-watchdog.pid`;\n \n // Create a wrapper script that writes PID\n const wrapperScript = resolve(hivemindHome, \"bin\", \"watchdog-wrapper.sh\");\n const wrapperContent = `#!/bin/bash\necho $$ > ${pidFile}\nexec \"${hivemindBin}\" watchdog \"$@\"\n`;\n writeFileSync(wrapperScript, wrapperContent);\n execSync(`chmod +x \"${wrapperScript}\"`);\n \n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${WATCHDOG_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${wrapperScript}</string>\n </array>\n <key>WorkingDirectory</key>\n <string>${hivemindHome}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>\n <key>HIVEMIND_HOME</key>\n <string>${hivemindHome}</string>\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>StandardOutPath</key>\n <string>/tmp/hivemind-watchdog.log</string>\n <key>StandardErrorPath</key>\n <string>/tmp/hivemind-watchdog-error.log</string>\n <key>ThrottleInterval</key>\n <integer>5</integer>\n</dict>\n</plist>`;\n}\n\nfunction generatePlist(hivemindHome: string, hivemindBin: string): string {\n const pidFile = `/tmp/hivemind-agent.pid`;\n \n // Create a wrapper script that writes PID\n const wrapperScript = resolve(hivemindHome, \"bin\", \"agent-wrapper.sh\");\n const wrapperContent = `#!/bin/bash\necho $$ > ${pidFile}\nexec \"${hivemindBin}\" start \"$@\"\n`;\n writeFileSync(wrapperScript, wrapperContent);\n execSync(`chmod +x \"${wrapperScript}\"`);\n \n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>${AGENT_LABEL}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${wrapperScript}</string>\n </array>\n <key>WorkingDirectory</key>\n <string>${hivemindHome}</string>\n <key>EnvironmentVariables</key>\n <dict>\n <key>PATH</key>\n <string>/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin</string>\n <key>HIVEMIND_HOME</key>\n <string>${hivemindHome}</string>\n </dict>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <false/>\n <key>StandardOutPath</key>\n <string>/tmp/hivemind-agent.log</string>\n <key>StandardErrorPath</key>\n <string>/tmp/hivemind-error.log</string>\n <key>ThrottleInterval</key>\n <integer>5</integer>\n</dict>\n</plist>`;\n}\n\nexport async function runServiceCommand(args: string[]): Promise<void> {\n const subcommand = args[0];\n\n switch (subcommand) {\n case \"install\":\n await installService();\n break;\n case \"uninstall\":\n await uninstallService();\n break;\n case \"stop\":\n stopService();\n break;\n case \"start\":\n startService();\n break;\n case \"status\":\n showStatus();\n break;\n case \"logs\":\n showLogs(args[1]);\n break;\n default:\n printHelp();\n if (subcommand) {\n console.error(`Unknown subcommand: ${subcommand}`);\n process.exit(1);\n }\n break;\n }\n}\n\nasync function installService(): Promise<void> {\n const hivemindHome = getHivemindHome();\n const hivemindBin = getHivemindBin();\n const memoryBin = resolve(hivemindHome, \"bin\", \"hivemind-memory\");\n\n console.log(`\\n→ Installing launchd services for ${hivemindHome}\\n`);\n console.log(` Agent binary: ${hivemindBin}`);\n console.log(` Memory binary: ${memoryBin}`);\n\n mkdirSync(LAUNCH_AGENTS_DIR, { recursive: true });\n\n // --- Memory daemon service ---\n if (existsSync(memoryBin)) {\n const memoryPlist = generateMemoryPlist(hivemindHome);\n const memoryDest = resolve(LAUNCH_AGENTS_DIR, `${MEMORY_LABEL}.plist`);\n try { execSync(`launchctl unload ${memoryDest} 2>/dev/null`); } catch {}\n writeFileSync(memoryDest, memoryPlist);\n execSync(`launchctl load ${memoryDest}`);\n console.log(` ✓ ${MEMORY_LABEL} installed and started`);\n } else {\n console.log(` ! Memory daemon not found at ${memoryBin} — skipping`);\n console.log(` ! Run 'hivemind init' to download it`);\n }\n\n // --- Ollama service (ensure running) ---\n try {\n execSync(\"curl -sf http://localhost:11434/api/tags > /dev/null\", { stdio: \"ignore\" });\n console.log(\" ✓ Ollama already running\");\n } catch {\n try {\n execSync(\"brew services start ollama 2>/dev/null\", { stdio: \"ignore\" });\n console.log(\" ✓ Ollama started via brew services\");\n } catch {\n console.log(\" ! Ollama not running — start manually: ollama serve\");\n }\n }\n\n // --- Watchdog service ---\n const watchdogPlist = generateWatchdogPlist(hivemindHome, hivemindBin);\n const watchdogDest = resolve(LAUNCH_AGENTS_DIR, `${WATCHDOG_LABEL}.plist`);\n try { execSync(`launchctl unload ${watchdogDest} 2>/dev/null`); } catch {}\n writeFileSync(watchdogDest, watchdogPlist);\n execSync(`launchctl load ${watchdogDest}`);\n console.log(` ✓ ${WATCHDOG_LABEL} installed and started`);\n\n // --- Agent service (KeepAlive: false — watchdog manages restarts) ---\n const plistContent = generatePlist(hivemindHome, hivemindBin);\n const destPath = resolve(LAUNCH_AGENTS_DIR, `${AGENT_LABEL}.plist`);\n try { execSync(`launchctl unload ${destPath} 2>/dev/null`); } catch {}\n writeFileSync(destPath, plistContent);\n execSync(`launchctl load ${destPath}`);\n console.log(` ✓ ${AGENT_LABEL} installed and started`);\n\n console.log(\"\\n Services will auto-start on boot.\");\n console.log(\" Logs:\");\n console.log(\" Agent: /tmp/hivemind-agent.log\");\n console.log(\" Watchdog: /tmp/hivemind-watchdog.log\");\n console.log(\" Memory: /tmp/hivemind-memory.log\\n\");\n}\n\nasync function uninstallService(): Promise<void> {\n console.log(\"\\n→ Uninstalling launchd services\\n\");\n\n for (const label of [AGENT_LABEL, WATCHDOG_LABEL, MEMORY_LABEL]) {\n const plistPath = resolve(LAUNCH_AGENTS_DIR, `${label}.plist`);\n if (existsSync(plistPath)) {\n try { execSync(`launchctl unload ${plistPath} 2>/dev/null`); } catch {}\n unlinkSync(plistPath);\n console.log(` ✓ ${label} uninstalled`);\n } else {\n console.log(` - ${label} not installed`);\n }\n }\n\n // Clean up stop flag if present\n try { unlinkSync(STOP_FLAG_FILE); } catch {}\n console.log(\"\");\n}\n\nfunction stopService(): void {\n console.log(\"\\n→ Stopping agent\\n\");\n\n // Write stop flag so watchdog doesn't restart\n writeFileSync(STOP_FLAG_FILE, String(Date.now()));\n console.log(` ✓ Stop flag written (${STOP_FLAG_FILE})`);\n\n // Stop agent via launchctl\n try {\n const uid = execSync(\"id -u\", { encoding: \"utf-8\" }).trim();\n execSync(`launchctl kill SIGTERM gui/${uid}/${AGENT_LABEL} 2>/dev/null`);\n console.log(` ✓ ${AGENT_LABEL} stopped`);\n } catch {\n console.log(` - ${AGENT_LABEL} was not running`);\n }\n\n console.log(\" Watchdog will NOT restart the agent while stop flag exists.\");\n console.log(\" Use 'hivemind service start' to resume.\\n\");\n}\n\nfunction startService(): void {\n console.log(\"\\n→ Starting agent\\n\");\n\n // Remove stop flag\n try {\n unlinkSync(STOP_FLAG_FILE);\n console.log(` ✓ Stop flag removed (${STOP_FLAG_FILE})`);\n } catch {\n console.log(\" - No stop flag present\");\n }\n\n // Start agent via launchctl\n try {\n const uid = execSync(\"id -u\", { encoding: \"utf-8\" }).trim();\n execSync(`launchctl kickstart gui/${uid}/${AGENT_LABEL}`);\n console.log(` ✓ ${AGENT_LABEL} started`);\n } catch (err) {\n console.error(` ! Failed to start agent: ${(err as Error).message}`);\n }\n console.log(\"\");\n}\n\nfunction showStatus(): void {\n console.log(\"\\n→ Service status\\n\");\n\n const keepAliveServices = new Set([MEMORY_LABEL, WATCHDOG_LABEL]);\n const pidFiles: Record<string, string> = {\n [AGENT_LABEL]: \"/tmp/hivemind-agent.pid\",\n [WATCHDOG_LABEL]: \"/tmp/hivemind-watchdog.pid\",\n [MEMORY_LABEL]: \"/tmp/hivemind-memory.pid\"\n };\n\n for (const label of [AGENT_LABEL, WATCHDOG_LABEL, MEMORY_LABEL]) {\n try {\n // Check if service is loaded and get PID from launchctl\n const listOutput = execSync(`launchctl list ${label} 2>/dev/null`, { encoding: \"utf-8\" });\n const pidMatch = listOutput.match(/\"PID\"\\s*=\\s*(\\d+)/);\n\n if (pidMatch) {\n console.log(` ✓ ${label}: running (PID ${pidMatch[1]})`);\n } else {\n // Loaded but no PID — process crashed or hasn't started\n // Clean up stale PID file if present\n const pidFile = pidFiles[label];\n if (pidFile && existsSync(pidFile)) {\n try { unlinkSync(pidFile); } catch {}\n }\n\n // Attempt kickstart for KeepAlive services (not agent — watchdog manages it)\n if (keepAliveServices.has(label)) {\n try {\n const uid = execSync(\"id -u\", { encoding: \"utf-8\" }).trim();\n execSync(`launchctl kickstart gui/${uid}/${label} 2>/dev/null`);\n console.log(` ! ${label}: was not running, kickstarted`);\n } catch {\n console.log(` ! ${label}: loaded but not running`);\n }\n } else {\n console.log(` ! ${label}: loaded but not running`);\n }\n }\n } catch {\n console.log(` - ${label}: not loaded`);\n }\n }\n\n // Check Ollama\n try {\n execSync(\"curl -sf http://localhost:11434/api/tags > /dev/null\", { stdio: \"ignore\" });\n console.log(\" ✓ ollama: running\");\n } catch {\n console.log(\" - ollama: not running\");\n }\n console.log(\"\");\n}\n\nfunction showLogs(which?: string): void {\n const logMap: Record<string, string> = {\n agent: \"/tmp/hivemind-agent.log\",\n error: \"/tmp/hivemind-error.log\",\n watchdog: \"/tmp/hivemind-watchdog.log\",\n memory: \"/tmp/hivemind-memory.log\",\n };\n const logFile = logMap[which || \"agent\"] || logMap.agent;\n try {\n execSync(`tail -30 ${logFile}`, { stdio: \"inherit\" });\n } catch {\n console.error(`No log file at ${logFile}`);\n }\n}\n\nfunction printHelp(): void {\n console.log(`hivemind service — Manage launchd services\n\nUsage: hivemind service <subcommand>\n\nSubcommands:\n install Install and start all launchd services (survives reboots)\n uninstall Stop and remove all launchd services\n stop Stop agent (watchdog will not restart it)\n start Start agent (removes stop flag)\n status Show service status\n logs [agent|watchdog|memory|error] Show recent logs\n\nServices:\n com.hivemind.watchdog — Watchdog daemon (health monitoring, restart/upgrade orchestration)\n com.hivemind.agent — Agent runtime (Node.js, Sesame) — managed by watchdog\n com.hivemind.memory — Memory daemon (LanceDB + Ollama embeddings)\n`);\n}\n"],"mappings":"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","names":[]}
@@ -5335,15 +5335,12 @@ function registerMemoryTools(registry, daemonUrl) {
5335
5335
  const context = params.context || "global";
5336
5336
  const topK = params.top_k || 10;
5337
5337
  try {
5338
- const resp = await fetch(`${daemonUrl}/api/search`, {
5339
- method: "POST",
5340
- headers: { "Content-Type": "application/json" },
5341
- body: JSON.stringify({ query, context_name: context, top_k: topK })
5342
- });
5338
+ const searchParams = new URLSearchParams({ q: query, context, limit: String(topK) });
5339
+ const resp = await fetch(`${daemonUrl}/search?${searchParams}`);
5343
5340
  if (!resp.ok) return `Memory search failed: ${resp.status}`;
5344
5341
  const data = await resp.json();
5345
- if (!data.results?.length) return `No memories found for "${query}" in context "${context}".`;
5346
- return data.results.map((r, i) => `${i + 1}. [score: ${r.score.toFixed(3)}] [${r.context_name}] [${r.role}] ${r.content.slice(0, 200)}`).join("\n");
5342
+ if (!data.episodes?.length) return `No memories found for "${query}" in context "${context}".`;
5343
+ return data.episodes.map((r, i) => `${i + 1}. [score: ${r.score.toFixed(3)}] [${r.context_name}] [${r.role}] ${r.content.slice(0, 200)}`).join("\n");
5347
5344
  } catch (err) {
5348
5345
  return `Memory daemon unreachable: ${err.message}`;
5349
5346
  }
@@ -5361,12 +5358,12 @@ function registerMemoryTools(registry, daemonUrl) {
5361
5358
  try {
5362
5359
  const healthResp = await fetch(`${daemonUrl}/health`);
5363
5360
  const health = healthResp.ok ? await healthResp.json() : { status: "unreachable" };
5364
- const ctxResp = await fetch(`${daemonUrl}/api/contexts`);
5361
+ const ctxResp = await fetch(`${daemonUrl}/contexts`);
5365
5362
  const contexts = ctxResp.ok ? (await ctxResp.json()).contexts : [];
5366
5363
  const l3Counts = {};
5367
5364
  for (const ctx of contexts) {
5368
5365
  try {
5369
- const l3Resp = await fetch(`${daemonUrl}/api/l3/${encodeURIComponent(ctx.name)}`);
5366
+ const l3Resp = await fetch(`${daemonUrl}/promotion/l3?context=${encodeURIComponent(ctx.name)}`);
5370
5367
  if (l3Resp.ok) {
5371
5368
  const l3Data = await l3Resp.json();
5372
5369
  l3Counts[ctx.name] = l3Data.entries?.length ?? 0;
@@ -5411,7 +5408,7 @@ Contexts:
5411
5408
  async (params) => {
5412
5409
  const context = params.context || "global";
5413
5410
  try {
5414
- const resp = await fetch(`${daemonUrl}/api/l3/${encodeURIComponent(context)}`);
5411
+ const resp = await fetch(`${daemonUrl}/promotion/l3?context=${encodeURIComponent(context)}`);
5415
5412
  if (!resp.ok) return `L3 query failed: ${resp.status}`;
5416
5413
  const data = await resp.json();
5417
5414
  if (!data.entries?.length) return `No L3 knowledge in context "${context}".`;
@@ -5442,15 +5439,19 @@ Contexts:
5442
5439
  const query = params.query;
5443
5440
  const topK = params.top_k || 10;
5444
5441
  try {
5445
- const resp = await fetch(`${daemonUrl}/api/search/cross-context`, {
5446
- method: "POST",
5447
- headers: { "Content-Type": "application/json" },
5448
- body: JSON.stringify({ query, top_k: topK })
5449
- });
5442
+ const crossParams = new URLSearchParams({ q: query, limit: String(topK) });
5443
+ const resp = await fetch(`${daemonUrl}/search/cross-context?${crossParams}`);
5450
5444
  if (!resp.ok) return `Cross-context search failed: ${resp.status}`;
5451
5445
  const data = await resp.json();
5452
- if (!data.results?.length) return `No memories found across any context for "${query}".`;
5453
- return data.results.map((r, i) => `${i + 1}. [${r.score.toFixed(3)}] [${r.context_name}] ${r.content.slice(0, 200)}`).join("\n");
5446
+ const flat = [];
5447
+ for (const group of data.results || []) {
5448
+ for (const ep of group.episodes) {
5449
+ flat.push({ ...ep, context_name: group.context });
5450
+ }
5451
+ }
5452
+ if (!flat.length) return `No memories found across any context for "${query}".`;
5453
+ flat.sort((a, b) => b.score - a.score);
5454
+ return flat.map((r, i) => `${i + 1}. [${r.score.toFixed(3)}] [${r.context_name}] ${r.content.slice(0, 200)}`).join("\n");
5454
5455
  } catch (err) {
5455
5456
  return `Memory daemon unreachable: ${err.message}`;
5456
5457
  }
@@ -8070,7 +8071,7 @@ ${findingText}`
8070
8071
  async function storeInMemory(contextName, topic, findings, synthesis, daemonUrl) {
8071
8072
  const storedIds = [];
8072
8073
  try {
8073
- await fetch(`${daemonUrl}/api/contexts`, {
8074
+ await fetch(`${daemonUrl}/contexts`, {
8074
8075
  method: "POST",
8075
8076
  headers: { "Content-Type": "application/json" },
8076
8077
  body: JSON.stringify({
@@ -8084,7 +8085,7 @@ async function storeInMemory(contextName, topic, findings, synthesis, daemonUrl)
8084
8085
  const content = `[Source: ${finding.source}]
8085
8086
  ${finding.keyPoints.join("\n")}`;
8086
8087
  try {
8087
- const resp = await fetch(`${daemonUrl}/api/episodes`, {
8088
+ const resp = await fetch(`${daemonUrl}/episodes`, {
8088
8089
  method: "POST",
8089
8090
  headers: { "Content-Type": "application/json" },
8090
8091
  body: JSON.stringify({
@@ -8101,7 +8102,7 @@ ${finding.keyPoints.join("\n")}`;
8101
8102
  }
8102
8103
  }
8103
8104
  try {
8104
- const resp = await fetch(`${daemonUrl}/api/episodes`, {
8105
+ const resp = await fetch(`${daemonUrl}/episodes`, {
8105
8106
  method: "POST",
8106
8107
  headers: { "Content-Type": "application/json" },
8107
8108
  body: JSON.stringify({
@@ -8118,7 +8119,7 @@ ${synthesis}`
8118
8119
  } catch {
8119
8120
  }
8120
8121
  try {
8121
- await fetch(`${daemonUrl}/api/promotion/run?context=${encodeURIComponent(contextName)}`, {
8122
+ await fetch(`${daemonUrl}/promotion/run?context=${encodeURIComponent(contextName)}`, {
8122
8123
  method: "POST"
8123
8124
  });
8124
8125
  } catch {
@@ -8265,28 +8266,30 @@ ${synthesis}${storageNote}`;
8265
8266
  const daemonUrl = config.memoryDaemonUrl;
8266
8267
  try {
8267
8268
  if (context) {
8268
- const resp2 = await fetch(`${daemonUrl}/api/search`, {
8269
- method: "POST",
8270
- headers: { "Content-Type": "application/json" },
8271
- body: JSON.stringify({ query: topic, context_name: context, top_k: 10 })
8272
- });
8269
+ const searchParams = new URLSearchParams({ q: topic, context, limit: "10" });
8270
+ const resp2 = await fetch(`${daemonUrl}/search?${searchParams}`);
8273
8271
  if (!resp2.ok) return `Memory search failed: ${resp2.status}`;
8274
8272
  const data2 = await resp2.json();
8275
- if (!data2.results?.length) return `No learned knowledge found for "${topic}" in context "${context}".`;
8276
- return data2.results.map((r, i) => `${i + 1}. [score: ${r.score.toFixed(3)}] [${r.role}]
8273
+ if (!data2.episodes?.length) return `No learned knowledge found for "${topic}" in context "${context}".`;
8274
+ return data2.episodes.map((r, i) => `${i + 1}. [score: ${r.score.toFixed(3)}] [${r.role}]
8277
8275
  ${r.content.slice(0, 500)}`).join("\n\n");
8278
8276
  }
8279
- const resp = await fetch(`${daemonUrl}/api/search/cross-context`, {
8280
- method: "POST",
8281
- headers: { "Content-Type": "application/json" },
8282
- body: JSON.stringify({ query: topic, top_k: 15 })
8283
- });
8277
+ const crossParams = new URLSearchParams({ q: topic, limit: "15" });
8278
+ const resp = await fetch(`${daemonUrl}/search/cross-context?${crossParams}`);
8284
8279
  if (!resp.ok) return `Memory cross-search failed: ${resp.status}`;
8285
8280
  const data = await resp.json();
8286
- const learnResults = data.results?.filter((r) => r.context_name.startsWith("learn-")) || [];
8281
+ const learnResults = [];
8282
+ for (const group of data.results || []) {
8283
+ if (group.context.startsWith("learn-")) {
8284
+ for (const ep of group.episodes) {
8285
+ learnResults.push({ ...ep, context_name: group.context });
8286
+ }
8287
+ }
8288
+ }
8287
8289
  if (learnResults.length === 0) {
8288
8290
  return `No previously learned knowledge found for "${topic}". Use the learn tool first.`;
8289
8291
  }
8292
+ learnResults.sort((a, b) => b.score - a.score);
8290
8293
  return learnResults.map((r, i) => `${i + 1}. [score: ${r.score.toFixed(3)}] [${r.context_name}] [${r.role}]
8291
8294
  ${r.content.slice(0, 500)}`).join("\n\n");
8292
8295
  } catch (err) {
@@ -9415,4 +9418,4 @@ smol-toml/dist/index.js:
9415
9418
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
9416
9419
  *)
9417
9420
  */
9418
- //# sourceMappingURL=chunk-OB6OXLPC.js.map
9421
+ //# sourceMappingURL=chunk-EKZ3IZU6.js.map