@sesamespace/hivemind 0.5.4 → 0.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/.github/workflows/memory-release.yml +89 -0
  2. package/config/default.toml +12 -0
  3. package/dist/{chunk-YHRGEWAZ.js → chunk-4U4GKI3X.js} +121 -34
  4. package/dist/chunk-4U4GKI3X.js.map +1 -0
  5. package/{packages/cli/src/commands/start.ts → dist/chunk-62S2NGMN.js} +39 -38
  6. package/dist/chunk-62S2NGMN.js.map +1 -0
  7. package/dist/{chunk-CGSXJVSS.js → chunk-7RTJSPMX.js} +2 -2
  8. package/dist/chunk-IJRAVHQC.js +327 -0
  9. package/dist/chunk-IJRAVHQC.js.map +1 -0
  10. package/dist/{chunk-MHDLSAJ3.js → chunk-JXLLCKMG.js} +102 -5
  11. package/dist/chunk-JXLLCKMG.js.map +1 -0
  12. package/dist/{chunk-SJI2KAIN.js → chunk-LJHJGDKY.js} +8 -2
  13. package/dist/chunk-LJHJGDKY.js.map +1 -0
  14. package/dist/{chunk-LNV373IF.js → chunk-LSOEUOTO.js} +2 -2
  15. package/dist/{chunk-S3RVZBPZ.js → chunk-PFN3BITA.js} +322 -2
  16. package/dist/chunk-PFN3BITA.js.map +1 -0
  17. package/dist/commands/fleet.js +3 -3
  18. package/dist/commands/init.js +1 -1
  19. package/dist/commands/service.js +1 -1
  20. package/dist/commands/start.js +3 -3
  21. package/dist/commands/upgrade.js +1 -1
  22. package/dist/commands/watchdog.js +10 -0
  23. package/dist/commands/watchdog.js.map +1 -0
  24. package/dist/index.js +6 -2
  25. package/dist/main.js +22 -12
  26. package/dist/main.js.map +1 -1
  27. package/dist/start.js +1 -1
  28. package/package.json +4 -3
  29. package/PLANNING.md +0 -383
  30. package/TASKS.md +0 -60
  31. package/dist/chunk-MHDLSAJ3.js.map +0 -1
  32. package/dist/chunk-PPQGQHXJ.js +0 -151
  33. package/dist/chunk-PPQGQHXJ.js.map +0 -1
  34. package/dist/chunk-S3RVZBPZ.js.map +0 -1
  35. package/dist/chunk-SJI2KAIN.js.map +0 -1
  36. package/dist/chunk-YHRGEWAZ.js.map +0 -1
  37. package/install.sh +0 -120
  38. package/npm-package.json +0 -26
  39. package/packages/cli/package.json +0 -23
  40. package/packages/cli/src/commands/fleet.ts +0 -206
  41. package/packages/cli/src/commands/init.ts +0 -252
  42. package/packages/cli/src/commands/service.ts +0 -159
  43. package/packages/cli/src/commands/upgrade.ts +0 -158
  44. package/packages/cli/src/main.ts +0 -64
  45. package/packages/cli/tsconfig.json +0 -8
  46. package/packages/memory/Cargo.lock +0 -6480
  47. package/packages/memory/Cargo.toml +0 -21
  48. package/packages/memory/src/context.rs +0 -179
  49. package/packages/memory/src/embeddings.rs +0 -51
  50. package/packages/memory/src/main.rs +0 -626
  51. package/packages/memory/src/promotion.rs +0 -637
  52. package/packages/memory/src/scoring.rs +0 -131
  53. package/packages/memory/src/store.rs +0 -460
  54. package/packages/memory/src/tasks.rs +0 -321
  55. package/packages/runtime/package.json +0 -24
  56. package/packages/runtime/src/__tests__/fleet-integration.test.ts +0 -235
  57. package/packages/runtime/src/__tests__/fleet.test.ts +0 -207
  58. package/packages/runtime/src/__tests__/integration.test.ts +0 -434
  59. package/packages/runtime/src/agent.ts +0 -255
  60. package/packages/runtime/src/config.ts +0 -130
  61. package/packages/runtime/src/context.ts +0 -192
  62. package/packages/runtime/src/fleet/fleet-manager.ts +0 -399
  63. package/packages/runtime/src/fleet/memory-sync.ts +0 -362
  64. package/packages/runtime/src/fleet/primary-client.ts +0 -285
  65. package/packages/runtime/src/fleet/worker-protocol.ts +0 -158
  66. package/packages/runtime/src/fleet/worker-server.ts +0 -246
  67. package/packages/runtime/src/index.ts +0 -57
  68. package/packages/runtime/src/llm-client.ts +0 -65
  69. package/packages/runtime/src/memory-client.ts +0 -309
  70. package/packages/runtime/src/pipeline.ts +0 -187
  71. package/packages/runtime/src/prompt.ts +0 -173
  72. package/packages/runtime/src/sesame.ts +0 -226
  73. package/packages/runtime/src/start.ts +0 -20
  74. package/packages/runtime/src/task-engine.ts +0 -113
  75. package/packages/runtime/src/worker.ts +0 -339
  76. package/packages/runtime/tsconfig.json +0 -8
  77. package/pnpm-workspace.yaml +0 -2
  78. package/run-aidan.sh +0 -23
  79. package/scripts/bootstrap.sh +0 -196
  80. package/scripts/build-npm.sh +0 -92
  81. package/scripts/com.hivemind.agent.plist +0 -44
  82. package/scripts/com.hivemind.memory.plist +0 -31
  83. package/tsconfig.json +0 -22
  84. package/tsup.config.ts +0 -27
  85. /package/dist/{chunk-CGSXJVSS.js.map → chunk-7RTJSPMX.js.map} +0 -0
  86. /package/dist/{chunk-LNV373IF.js.map → chunk-LSOEUOTO.js.map} +0 -0
@@ -0,0 +1,89 @@
1
+ name: Build Memory Daemon
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ workflow_dispatch:
8
+ inputs:
9
+ tag:
10
+ description: "Release tag (e.g. v0.5.5)"
11
+ required: false
12
+
13
+ jobs:
14
+ build:
15
+ strategy:
16
+ matrix:
17
+ include:
18
+ - target: aarch64-apple-darwin
19
+ os: macos-14
20
+ artifact: hivemind-memory-darwin-arm64
21
+ - target: x86_64-apple-darwin
22
+ os: macos-13
23
+ artifact: hivemind-memory-darwin-x64
24
+
25
+ runs-on: ${{ matrix.os }}
26
+
27
+ steps:
28
+ - uses: actions/checkout@v4
29
+
30
+ - name: Install Rust
31
+ uses: dtolnay/rust-toolchain@stable
32
+ with:
33
+ targets: ${{ matrix.target }}
34
+
35
+ - name: Cache cargo
36
+ uses: actions/cache@v4
37
+ with:
38
+ path: |
39
+ ~/.cargo/registry
40
+ ~/.cargo/git
41
+ packages/memory/target
42
+ key: ${{ matrix.target }}-cargo-${{ hashFiles('packages/memory/Cargo.lock') }}
43
+ restore-keys: ${{ matrix.target }}-cargo-
44
+
45
+ - name: Build
46
+ working-directory: packages/memory
47
+ run: |
48
+ cargo build --release --target ${{ matrix.target }}
49
+ cp target/${{ matrix.target }}/release/hivemind-memory ${{ matrix.artifact }}
50
+ chmod +x ${{ matrix.artifact }}
51
+
52
+ - name: Upload artifact
53
+ uses: actions/upload-artifact@v4
54
+ with:
55
+ name: ${{ matrix.artifact }}
56
+ path: packages/memory/${{ matrix.artifact }}
57
+
58
+ release:
59
+ needs: build
60
+ runs-on: ubuntu-latest
61
+ permissions:
62
+ contents: write
63
+
64
+ steps:
65
+ - name: Download artifacts
66
+ uses: actions/download-artifact@v4
67
+ with:
68
+ path: artifacts
69
+
70
+ - name: Determine tag
71
+ id: tag
72
+ run: |
73
+ if [ "${{ github.event_name }}" = "push" ]; then
74
+ echo "tag=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
75
+ elif [ -n "${{ github.event.inputs.tag }}" ]; then
76
+ echo "tag=${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
77
+ else
78
+ echo "tag=dev-$(date +%Y%m%d-%H%M%S)" >> $GITHUB_OUTPUT
79
+ fi
80
+
81
+ - name: Create release
82
+ uses: softprops/action-gh-release@v2
83
+ with:
84
+ tag_name: ${{ steps.tag.outputs.tag }}
85
+ name: "Hivemind ${{ steps.tag.outputs.tag }}"
86
+ files: |
87
+ artifacts/hivemind-memory-darwin-arm64/hivemind-memory-darwin-arm64
88
+ artifacts/hivemind-memory-darwin-x64/hivemind-memory-darwin-x64
89
+ generate_release_notes: true
@@ -28,6 +28,18 @@ api_key = "" # Set via SESAME_API_KEY env var or hivemind setup
28
28
  help = "hivemind-help" # Peer support and knowledge transfer
29
29
  # Add more default channels here as needed
30
30
 
31
+ # Watchdog (sentinel) — monitors agent health and handles restarts/upgrades
32
+ [sentinel]
33
+ poll_interval_ms = 5000
34
+ health_timeout_ms = 3000
35
+ max_restart_attempts = 5
36
+ backoff_base_ms = 5000
37
+ backoff_max_ms = 300000
38
+ agent_startup_grace_ms = 15000
39
+ health_port = 9484
40
+ pid_file = "/tmp/hivemind-agent.pid"
41
+ stop_flag_file = "/tmp/hivemind-agent.stopped"
42
+
31
43
  # Worker mode — set enabled = true to run as a fleet worker
32
44
  [worker]
33
45
  enabled = false
@@ -1483,6 +1483,19 @@ function defaultWorkerConfig() {
1483
1483
  status_report_interval_ms: 15e3
1484
1484
  };
1485
1485
  }
1486
+ function defaultSentinelConfig() {
1487
+ return {
1488
+ poll_interval_ms: 5e3,
1489
+ health_timeout_ms: 3e3,
1490
+ max_restart_attempts: 5,
1491
+ backoff_base_ms: 5e3,
1492
+ backoff_max_ms: 3e5,
1493
+ agent_startup_grace_ms: 15e3,
1494
+ health_port: 9484,
1495
+ pid_file: "/tmp/hivemind-agent.pid",
1496
+ stop_flag_file: "/tmp/hivemind-agent.stopped"
1497
+ };
1498
+ }
1486
1499
  function deepMerge(target, source) {
1487
1500
  const result = { ...target };
1488
1501
  for (const key of Object.keys(source)) {
@@ -1532,6 +1545,22 @@ function loadConfig(path) {
1532
1545
  if (!parsed.worker) parsed.worker = defaultWorkerConfig();
1533
1546
  parsed.worker.worker_id = process.env.WORKER_ID;
1534
1547
  }
1548
+ if (process.env.SENTINEL_POLL_INTERVAL_MS) {
1549
+ if (!parsed.sentinel) parsed.sentinel = defaultSentinelConfig();
1550
+ parsed.sentinel.poll_interval_ms = parseInt(process.env.SENTINEL_POLL_INTERVAL_MS, 10);
1551
+ }
1552
+ if (process.env.SENTINEL_HEALTH_PORT) {
1553
+ if (!parsed.sentinel) parsed.sentinel = defaultSentinelConfig();
1554
+ parsed.sentinel.health_port = parseInt(process.env.SENTINEL_HEALTH_PORT, 10);
1555
+ }
1556
+ if (process.env.SENTINEL_PID_FILE) {
1557
+ if (!parsed.sentinel) parsed.sentinel = defaultSentinelConfig();
1558
+ parsed.sentinel.pid_file = process.env.SENTINEL_PID_FILE;
1559
+ }
1560
+ if (process.env.SENTINEL_STOP_FLAG_FILE) {
1561
+ if (!parsed.sentinel) parsed.sentinel = defaultSentinelConfig();
1562
+ parsed.sentinel.stop_flag_file = process.env.SENTINEL_STOP_FLAG_FILE;
1563
+ }
1535
1564
  if (parsed.agent.workspace && !parsed.agent.workspace.startsWith("/")) {
1536
1565
  const configDir2 = dirname(path);
1537
1566
  parsed.agent.workspace = resolve2(configDir2, "..", parsed.agent.workspace);
@@ -1555,6 +1584,7 @@ var SesameClient2 = class {
1555
1584
  sdk;
1556
1585
  messageHandler = null;
1557
1586
  upgradeHandler = null;
1587
+ restartHandler = null;
1558
1588
  agentId = null;
1559
1589
  channels = /* @__PURE__ */ new Map();
1560
1590
  typingIntervals = /* @__PURE__ */ new Map();
@@ -1572,6 +1602,9 @@ var SesameClient2 = class {
1572
1602
  onUpgrade(handler) {
1573
1603
  this.upgradeHandler = handler;
1574
1604
  }
1605
+ onRestart(handler) {
1606
+ this.restartHandler = handler;
1607
+ }
1575
1608
  async connect() {
1576
1609
  const manifest = await this.sdk.getManifest();
1577
1610
  this.agentId = manifest.agent.id;
@@ -1593,6 +1626,15 @@ var SesameClient2 = class {
1593
1626
  });
1594
1627
  }
1595
1628
  });
1629
+ this.sdk.on("restart.request", (event) => {
1630
+ console.log(`[sesame] Restart requested by ${event.requestedBy}`);
1631
+ if (this.restartHandler) {
1632
+ this.restartHandler({
1633
+ requestedBy: event.requestedBy,
1634
+ requestId: event.requestId
1635
+ });
1636
+ }
1637
+ });
1596
1638
  this.sdk.on("control", (event) => {
1597
1639
  console.log(`[sesame] Control event: ${event.action}`, event.payload);
1598
1640
  });
@@ -1695,16 +1737,79 @@ var SesameClient2 = class {
1695
1737
  };
1696
1738
 
1697
1739
  // packages/runtime/src/pipeline.ts
1698
- import { execSync } from "child_process";
1740
+ import { createServer } from "http";
1741
+
1742
+ // packages/runtime/src/health.ts
1743
+ var HEALTH_PORT = 9484;
1744
+ var HEALTH_PATH = "/health";
1745
+
1746
+ // packages/runtime/src/pipeline.ts
1747
+ import { readFileSync as readFileSync4, writeFileSync, unlinkSync } from "fs";
1748
+ import { resolve as resolve4, dirname as dirname3 } from "path";
1749
+ import { fileURLToPath as fileURLToPath2 } from "url";
1750
+ var PACKAGE_VERSION = "unknown";
1751
+ try {
1752
+ const __dirname = dirname3(fileURLToPath2(import.meta.url));
1753
+ const pkg = JSON.parse(readFileSync4(resolve4(__dirname, "../package.json"), "utf-8"));
1754
+ PACKAGE_VERSION = pkg.version ?? "unknown";
1755
+ } catch {
1756
+ }
1757
+ var sesameConnected = false;
1758
+ var memoryConnected = false;
1759
+ var startTime = Date.now();
1760
+ function startHealthServer(port) {
1761
+ const server = createServer((req, res) => {
1762
+ if (req.method === "GET" && req.url === HEALTH_PATH) {
1763
+ const status = {
1764
+ status: sesameConnected ? "ok" : "degraded",
1765
+ pid: process.pid,
1766
+ uptime_s: Math.floor((Date.now() - startTime) / 1e3),
1767
+ sesame_connected: sesameConnected,
1768
+ memory_connected: memoryConnected,
1769
+ version: PACKAGE_VERSION
1770
+ };
1771
+ res.writeHead(200, { "Content-Type": "application/json" });
1772
+ res.end(JSON.stringify(status));
1773
+ } else {
1774
+ res.writeHead(404);
1775
+ res.end();
1776
+ }
1777
+ });
1778
+ server.listen(port, "127.0.0.1", () => {
1779
+ console.log(`[hivemind] Health endpoint listening on http://127.0.0.1:${port}${HEALTH_PATH}`);
1780
+ });
1781
+ return server;
1782
+ }
1783
+ function writePidFile(path) {
1784
+ writeFileSync(path, String(process.pid));
1785
+ console.log(`[hivemind] PID file written: ${path}`);
1786
+ }
1787
+ function cleanupPidFile(path) {
1788
+ try {
1789
+ unlinkSync(path);
1790
+ } catch {
1791
+ }
1792
+ }
1699
1793
  async function startPipeline(configPath) {
1700
1794
  const config = loadConfig(configPath);
1795
+ const sentinel = config.sentinel ?? defaultSentinelConfig();
1796
+ const healthPort = sentinel.health_port || HEALTH_PORT;
1797
+ const pidFile = sentinel.pid_file;
1701
1798
  console.log(`[hivemind] Starting ${config.agent.name} (pid ${process.pid})`);
1799
+ writePidFile(pidFile);
1800
+ const healthServer = startHealthServer(healthPort);
1801
+ const cleanupOnExit = () => {
1802
+ cleanupPidFile(pidFile);
1803
+ healthServer.close();
1804
+ };
1805
+ process.on("exit", cleanupOnExit);
1702
1806
  const memory = new MemoryClient(config.memory);
1703
1807
  const memoryOk = await memory.healthCheck();
1704
1808
  if (!memoryOk) {
1705
1809
  console.warn("[hivemind] Memory daemon unreachable at", config.memory.daemon_url);
1706
1810
  console.warn("[hivemind] Continuing without persistent memory \u2014 episodes will not be stored");
1707
1811
  } else {
1812
+ memoryConnected = true;
1708
1813
  console.log("[hivemind] Memory daemon connected");
1709
1814
  }
1710
1815
  const agent = new Agent(config);
@@ -1735,27 +1840,6 @@ async function startSesameLoop(config, agent) {
1735
1840
  };
1736
1841
  process.on("SIGTERM", () => shutdown("SIGTERM"));
1737
1842
  process.on("SIGINT", () => shutdown("SIGINT"));
1738
- sesame.onUpgrade(async (req) => {
1739
- console.log(`[hivemind] Upgrade requested: ${req.packageName}@${req.targetVersion} (by ${req.requestedBy})`);
1740
- sesame.updatePresence("working", { detail: `Upgrading to ${req.targetVersion}`, emoji: "\u2B06\uFE0F" });
1741
- try {
1742
- const target = req.targetVersion === "latest" ? req.packageName : `${req.packageName}@${req.targetVersion}`;
1743
- console.log(`[hivemind] Running: npm install -g ${target}`);
1744
- execSync(`npm install -g ${target}`, { stdio: "inherit", timeout: 12e4 });
1745
- console.log("[hivemind] Package updated successfully");
1746
- console.log(`[hivemind] Upgrade to ${req.targetVersion} complete. Restarting...`);
1747
- sesame.updatePresence("working", { detail: "Restarting after upgrade", emoji: "\u{1F504}" });
1748
- try {
1749
- execSync("launchctl kickstart -k gui/$(id -u)/com.hivemind.agent", { timeout: 1e4 });
1750
- } catch {
1751
- console.log("[hivemind] Exiting for restart...");
1752
- process.exit(0);
1753
- }
1754
- } catch (err) {
1755
- console.error(`[hivemind] Upgrade failed: ${err.message}`);
1756
- sesame.updatePresence("online", { detail: "Upgrade failed", emoji: "\u274C" });
1757
- }
1758
- });
1759
1843
  sesame.onMessage(async (msg) => {
1760
1844
  if (shuttingDown) return;
1761
1845
  console.log(`[sesame] ${msg.author.handle} (${msg.channelKind}): ${msg.content}`);
@@ -1781,6 +1865,7 @@ async function startSesameLoop(config, agent) {
1781
1865
  }
1782
1866
  });
1783
1867
  await sesame.connect();
1868
+ sesameConnected = true;
1784
1869
  console.log("[hivemind] Listening for Sesame messages");
1785
1870
  await new Promise(() => {
1786
1871
  });
@@ -1829,13 +1914,13 @@ ${response.content}
1829
1914
  console.error("Error:", err.message);
1830
1915
  }
1831
1916
  });
1832
- return new Promise((resolve4) => {
1833
- rl.on("close", resolve4);
1917
+ return new Promise((resolve5) => {
1918
+ rl.on("close", resolve5);
1834
1919
  });
1835
1920
  }
1836
1921
 
1837
1922
  // packages/runtime/src/fleet/worker-server.ts
1838
- import { createServer } from "http";
1923
+ import { createServer as createServer2 } from "http";
1839
1924
  var WorkerServer = class {
1840
1925
  server = null;
1841
1926
  workerId;
@@ -1859,20 +1944,20 @@ var WorkerServer = class {
1859
1944
  }
1860
1945
  /** Start listening. */
1861
1946
  async start() {
1862
- return new Promise((resolve4, reject) => {
1863
- this.server = createServer((req, res) => this.handleRequest(req, res));
1947
+ return new Promise((resolve5, reject) => {
1948
+ this.server = createServer2((req, res) => this.handleRequest(req, res));
1864
1949
  this.server.on("error", reject);
1865
- this.server.listen(this.port, () => resolve4());
1950
+ this.server.listen(this.port, () => resolve5());
1866
1951
  });
1867
1952
  }
1868
1953
  /** Stop the server. */
1869
1954
  async stop() {
1870
- return new Promise((resolve4) => {
1955
+ return new Promise((resolve5) => {
1871
1956
  if (!this.server) {
1872
- resolve4();
1957
+ resolve5();
1873
1958
  return;
1874
1959
  }
1875
- this.server.close(() => resolve4());
1960
+ this.server.close(() => resolve5());
1876
1961
  });
1877
1962
  }
1878
1963
  getPort() {
@@ -1995,10 +2080,10 @@ var WorkerServer = class {
1995
2080
  }
1996
2081
  };
1997
2082
  function readBody(req) {
1998
- return new Promise((resolve4, reject) => {
2083
+ return new Promise((resolve5, reject) => {
1999
2084
  const chunks = [];
2000
2085
  req.on("data", (chunk) => chunks.push(chunk));
2001
- req.on("end", () => resolve4(Buffer.concat(chunks).toString("utf-8")));
2086
+ req.on("end", () => resolve5(Buffer.concat(chunks).toString("utf-8")));
2002
2087
  req.on("error", reject);
2003
2088
  });
2004
2089
  }
@@ -2272,8 +2357,10 @@ export {
2272
2357
  buildSystemPrompt,
2273
2358
  buildMessages,
2274
2359
  Agent,
2360
+ defaultSentinelConfig,
2275
2361
  loadConfig,
2276
2362
  SesameClient2 as SesameClient,
2363
+ HEALTH_PATH,
2277
2364
  startPipeline,
2278
2365
  PRIMARY_ROUTES,
2279
2366
  WORKER_ROUTES,
@@ -2323,4 +2410,4 @@ smol-toml/dist/index.js:
2323
2410
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2324
2411
  *)
2325
2412
  */
2326
- //# sourceMappingURL=chunk-YHRGEWAZ.js.map
2413
+ //# sourceMappingURL=chunk-4U4GKI3X.js.map