@johpaz/hive-sdk 0.1.4 → 0.1.6

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 (278) hide show
  1. package/CHANGELOG.md +129 -0
  2. package/README.md +78 -23
  3. package/bun.lock +55 -29
  4. package/bunfig.toml +4 -2
  5. package/docs/API-AGENTS.md +78 -27
  6. package/docs/API-CONTEXT-COMPILER.md +31 -34
  7. package/docs/API-TOOLS-SKILLS-CHANNELS.md +58 -22
  8. package/docs/HIVE-HARNESS.md +1 -1
  9. package/docs/INDEX.md +4 -4
  10. package/docs/TEMPLATE-HIVE-APP.md +10 -10
  11. package/package.json +17 -12
  12. package/packages/cli/package.json +2 -2
  13. package/packages/cli/src/commands/create-app.test.ts +36 -7
  14. package/packages/cli/src/commands/init.ts +3 -3
  15. package/packages/cli/src/commands/run.ts +1 -1
  16. package/packages/cli/src/commands/test.ts +37 -25
  17. package/packages/cli/src/commands/trace.ts +30 -28
  18. package/packages/cli/templates/hive-app/.env.example +10 -2
  19. package/packages/cli/templates/hive-app/README.md +103 -0
  20. package/packages/cli/templates/hive-app/hive.config.ts +9 -3
  21. package/packages/cli/templates/hive-app/src/agents/coordinator.ts +8 -1
  22. package/packages/cli/templates/hive-app/src/main.ts +12 -19
  23. package/packages/core/package.json +13 -12
  24. package/packages/core/src/agent/acceptance-checks.ts +172 -0
  25. package/packages/core/src/agent/agent-catalog.ts +348 -0
  26. package/packages/core/src/agent/agent-loop.ts +1373 -0
  27. package/packages/core/src/agent/capability-search.ts +186 -0
  28. package/packages/core/src/agent/catalog-selector.ts +103 -0
  29. package/packages/core/src/agent/{Compaction.ts → compaction.ts} +86 -63
  30. package/packages/core/src/agent/context-compiler.ts +689 -0
  31. package/packages/core/src/agent/conversation-store.ts +381 -0
  32. package/packages/core/src/agent/curator.ts +276 -0
  33. package/packages/core/src/agent/delegation-runtime.ts +241 -0
  34. package/packages/core/src/agent/goal-runner.ts +323 -0
  35. package/packages/core/src/agent/index.ts +17 -12
  36. package/packages/core/src/agent/llm-client.ts +266 -0
  37. package/packages/core/src/agent/llm-providers/anthropic.ts +264 -0
  38. package/packages/core/src/agent/llm-providers/deepseek.ts +8 -0
  39. package/packages/core/src/agent/{providers → llm-providers}/gemini.ts +98 -60
  40. package/packages/core/src/agent/llm-providers/groq.ts +5 -0
  41. package/packages/core/src/agent/llm-providers/hiveagents.ts +253 -0
  42. package/packages/core/src/agent/{providers → llm-providers}/interface.ts +73 -13
  43. package/packages/core/src/agent/llm-providers/kimi.ts +8 -0
  44. package/packages/core/src/agent/llm-providers/minimax.ts +13 -0
  45. package/packages/core/src/agent/llm-providers/mistral.ts +5 -0
  46. package/packages/core/src/agent/llm-providers/modelscope.ts +5 -0
  47. package/packages/core/src/agent/llm-providers/nvidia.ts +5 -0
  48. package/packages/core/src/agent/{providers → llm-providers}/ollama.ts +31 -5
  49. package/packages/core/src/agent/llm-providers/openai-compat-base.ts +418 -0
  50. package/packages/core/src/agent/llm-providers/openai.ts +5 -0
  51. package/packages/core/src/agent/llm-providers/opencode-go.ts +9 -0
  52. package/packages/core/src/agent/llm-providers/openrouter.ts +5 -0
  53. package/packages/core/src/agent/llm-providers/qwen.ts +5 -0
  54. package/packages/core/src/agent/llm-providers/z-ai.ts +5 -0
  55. package/packages/core/src/agent/minimal-loadout.ts +47 -0
  56. package/packages/core/src/agent/playbook-selector.ts +119 -0
  57. package/packages/core/src/agent/{PromptBuilder.ts → prompt-builder.ts} +21 -22
  58. package/packages/core/src/{harness → agent}/proof-packet.ts +16 -21
  59. package/packages/core/src/agent/providers/index.ts +35 -16
  60. package/packages/core/src/agent/reflector.ts +320 -0
  61. package/packages/core/src/agent/routing-intent.ts +22 -0
  62. package/packages/core/src/{harness → agent}/run-epoch.ts +4 -3
  63. package/packages/core/src/{harness → agent}/run-store.ts +142 -81
  64. package/packages/core/src/agent/{Service.ts → service.ts} +37 -26
  65. package/packages/core/src/agent/skill-selector.ts +374 -0
  66. package/packages/core/src/agent/stuck-loop.ts +209 -0
  67. package/packages/core/src/agent/{selectors/ToolSelector.ts → tool-selector.ts} +188 -178
  68. package/packages/core/src/{ace/Tracer.ts → agent/tracer.ts} +37 -27
  69. package/packages/core/src/api/createAgent.test.ts +139 -27
  70. package/packages/core/src/api/createAgent.ts +232 -44
  71. package/packages/core/src/artifacts/store.ts +162 -0
  72. package/packages/core/src/canvas/canvas-manager.ts +161 -0
  73. package/packages/core/src/canvas/canvas.test.ts +8 -4
  74. package/packages/core/src/canvas/emitter.ts +131 -80
  75. package/packages/core/src/canvas/index.ts +1 -3
  76. package/packages/core/src/channels/base.ts +9 -1
  77. package/packages/core/src/channels/discord.ts +5 -4
  78. package/packages/core/src/channels/manager.ts +122 -30
  79. package/packages/core/src/channels/slack.ts +5 -4
  80. package/packages/core/src/channels/telegram.ts +36 -6
  81. package/packages/core/src/channels/webchat.ts +11 -10
  82. package/packages/core/src/channels/whatsapp.ts +23 -7
  83. package/packages/core/src/config/index.ts +13 -2
  84. package/packages/core/src/config/loader.ts +76 -29
  85. package/packages/core/src/ethics/EthicsGuard.test.ts +90 -36
  86. package/packages/core/src/ethics/EthicsGuard.ts +51 -47
  87. package/packages/core/src/events/agent-bus.ts +44 -68
  88. package/packages/core/src/events/channel-narration.ts +150 -0
  89. package/packages/core/src/events/narration.ts +82 -0
  90. package/packages/core/src/events/tool-narration.ts +62 -0
  91. package/packages/core/src/gateway/delegation-groups.ts +258 -0
  92. package/packages/core/src/{harness → gateway}/durable-queue.ts +102 -42
  93. package/packages/core/src/{harness → gateway}/job-store.ts +85 -48
  94. package/packages/core/src/gateway/lane-queue.ts +173 -0
  95. package/packages/core/src/gateway/notification-inbox.ts +57 -0
  96. package/packages/core/src/gateway/server.ts +1 -1
  97. package/packages/core/src/harness/index.ts +46 -27
  98. package/packages/core/src/index.ts +33 -27
  99. package/packages/core/src/mcp/hot-reload.ts +32 -23
  100. package/packages/core/src/mcp/index.ts +6 -3
  101. package/packages/core/src/mcp/singleton.ts +1 -4
  102. package/packages/core/src/mcp/tool-sync.ts +138 -0
  103. package/packages/core/src/memory/Scratchpad.test.ts +39 -20
  104. package/packages/core/src/memory/Scratchpad.ts +27 -34
  105. package/packages/core/src/multimodal/vision-service.ts +44 -38
  106. package/packages/core/src/resilience/retry.ts +95 -0
  107. package/packages/core/src/scheduler/CronScheduler.ts +334 -287
  108. package/packages/core/src/scheduler/index.ts +9 -7
  109. package/packages/core/src/scheduler/integration.ts +46 -26
  110. package/packages/core/src/scheduler/scheduler.test.ts +9 -13
  111. package/packages/core/src/scheduler/types.ts +7 -2
  112. package/packages/core/src/security/Pairing.ts +1 -1
  113. package/packages/core/src/skills/bundled/a2ui/a2ui_dashboard/SKILL.md +176 -0
  114. package/packages/core/src/skills/bundled/a2ui/a2ui_form/SKILL.md +202 -0
  115. package/packages/core/src/skills/bundled/a2ui/a2ui_interactive/SKILL.md +206 -0
  116. package/packages/core/src/skills/bundled/agents/agent_spawner/SKILL.md +173 -0
  117. package/packages/core/src/skills/bundled/agents/memory_manager/SKILL.md +143 -0
  118. package/packages/core/src/skills/bundled/agents/research_and_remember/SKILL.md +139 -0
  119. package/packages/core/src/skills/bundled/agents/task_orchestrator/SKILL.md +98 -0
  120. package/packages/core/src/skills/bundled/api/api_client/SKILL.md +132 -0
  121. package/packages/core/src/skills/bundled/cli/cli_pipeline/SKILL.md +135 -0
  122. package/packages/core/src/skills/bundled/cli/cli_safe_exec/SKILL.md +125 -0
  123. package/packages/core/src/skills/bundled/cli/software_engineering/SKILL.md +23 -0
  124. package/packages/core/src/skills/bundled/cron_manager/SKILL.md +188 -0
  125. package/packages/core/src/skills/bundled/cron_reminder/SKILL.md +112 -0
  126. package/packages/core/src/skills/bundled/filesystem/file_manager/SKILL.md +118 -0
  127. package/packages/core/src/skills/bundled/filesystem/file_read_and_summarize/SKILL.md +109 -0
  128. package/packages/core/src/skills/bundled/filesystem/file_writer/SKILL.md +129 -0
  129. package/packages/core/src/skills/bundled/filesystem/workspace_file_operator/SKILL.md +22 -0
  130. package/packages/core/src/skills/bundled/office/office_document_manager/SKILL.md +262 -0
  131. package/packages/core/src/skills/bundled/search_knowledge/capability_discovery/SKILL.md +75 -0
  132. package/packages/core/src/skills/bundled/web/browser_automate/SKILL.md +120 -0
  133. package/packages/core/src/skills/bundled/web/browser_scrape/SKILL.md +109 -0
  134. package/packages/core/src/skills/bundled/web/web_monitor/SKILL.md +127 -0
  135. package/packages/core/src/skills/bundled/web/web_research/SKILL.md +119 -0
  136. package/packages/core/src/skills/bundled-data.generated.ts +731 -2678
  137. package/packages/core/src/skills/skills.test.ts +52 -11
  138. package/packages/core/src/{harness → storage}/boot-id.ts +5 -2
  139. package/packages/core/src/storage/bootstrap.ts +151 -0
  140. package/packages/core/src/storage/causal-events.ts +84 -0
  141. package/packages/core/src/storage/collections.ts +680 -0
  142. package/packages/core/src/storage/crypto.ts +205 -74
  143. package/packages/core/src/{harness/db-helpers.ts → storage/hive.ts} +63 -7
  144. package/packages/core/src/storage/hivedb.ts +61 -0
  145. package/packages/core/src/storage/index.ts +111 -18
  146. package/packages/core/src/storage/model-id.ts +53 -0
  147. package/packages/core/src/storage/onboarding.ts +540 -972
  148. package/packages/core/src/storage/reconcile.ts +238 -0
  149. package/packages/core/src/storage/seed.ts +572 -406
  150. package/packages/core/src/storage/usage.ts +285 -225
  151. package/packages/core/src/storage/user-email.ts +11 -0
  152. package/packages/core/src/swarm/AgentExecutor.ts +1 -1
  153. package/packages/core/src/swarm/EventBridge.ts +1 -1
  154. package/packages/core/src/swarm/index.ts +12 -9
  155. package/packages/core/src/tool-runtime/index.ts +146 -23
  156. package/packages/core/src/tool-runtime/tool-worker.ts +2 -2
  157. package/packages/core/src/tool-runtime/worker-tools.ts +27 -0
  158. package/packages/core/src/{canvas/a2ui-tools.ts → tools/a2ui/index.ts} +17 -8
  159. package/packages/core/src/tools/agents/get-available-models.ts +36 -54
  160. package/packages/core/src/tools/agents/index.ts +784 -292
  161. package/packages/core/src/tools/api/api-request.test.ts +164 -0
  162. package/packages/core/src/tools/api/api-request.ts +174 -0
  163. package/packages/core/src/tools/api/index.ts +16 -0
  164. package/packages/core/src/tools/cli/index.ts +4 -0
  165. package/packages/core/src/tools/core/index.ts +281 -112
  166. package/packages/core/src/tools/cron/index.ts +121 -124
  167. package/packages/core/src/tools/index.ts +63 -78
  168. package/packages/core/src/tools/office/office-escribir-xlsx.ts +3 -1
  169. package/packages/core/src/tools/types.ts +3 -1
  170. package/packages/core/src/tools/web/artifact-inspect.ts +23 -0
  171. package/packages/core/src/tools/web/browser-backend.ts +129 -0
  172. package/packages/core/src/tools/web/browser-screenshot.ts +26 -5
  173. package/packages/core/src/tools/web/browser-service.ts +80 -35
  174. package/packages/core/src/tools/web/browser-type.ts +3 -8
  175. package/packages/core/src/tools/web/index.ts +4 -4
  176. package/packages/core/src/tools/web/webview-backend.ts +412 -0
  177. package/packages/core/src/voice/index.ts +89 -63
  178. package/packages/core/src/workers/agent.worker.ts +2 -2
  179. package/packages/core/src/workers/workers.test.ts +3 -10
  180. package/scripts/bump-version.ts +248 -0
  181. package/scripts/generate-skill-bundle.ts +108 -0
  182. package/test/acceptance-checks.test.ts +403 -0
  183. package/test/agent-loop-terminal-synthesis.test.ts +32 -0
  184. package/test/browser-backend.test.ts +308 -0
  185. package/test/catalog-agents-stay-enabled.test.ts +117 -0
  186. package/test/causal-events.test.ts +117 -0
  187. package/test/compaction.test.ts +105 -0
  188. package/test/context-compiler.test.ts +269 -0
  189. package/test/curator.test.ts +130 -0
  190. package/test/durable-queue.test.ts +114 -0
  191. package/test/harness-barrel.test.ts +64 -0
  192. package/test/hive-helpers.test.ts +130 -0
  193. package/test/hivedb-search.test.ts +189 -0
  194. package/test/internal-turns.test.ts +166 -0
  195. package/test/job-idempotency.test.ts +68 -0
  196. package/test/job-retry-backoff.test.ts +184 -0
  197. package/test/job-store.test.ts +381 -0
  198. package/test/llm-retry.test.ts +97 -0
  199. package/test/memory-perf.test.ts +774 -0
  200. package/test/minimal-loadout.test.ts +78 -0
  201. package/test/model-catalog.test.ts +105 -0
  202. package/test/preload.ts +12 -0
  203. package/test/reflector.test.ts +320 -0
  204. package/test/retention-cap.test.ts +91 -0
  205. package/test/retired-capabilities-pruned.test.ts +192 -0
  206. package/test/run-store.test.ts +355 -0
  207. package/test/scratchpad.test.ts +74 -0
  208. package/test/secrets-durability.test.ts +119 -0
  209. package/test/seed-model-reseed.test.ts +155 -0
  210. package/test/setup-agent-seed.test.ts +264 -0
  211. package/test/tool-inventory.test.ts +65 -0
  212. package/test/tool-runtime.test.ts +258 -0
  213. package/test/tool-selector-runtime-tools.test.ts +117 -0
  214. package/test/toon.test.ts +429 -0
  215. package/tsconfig.json +2 -0
  216. package/packages/core/src/ace/Curator.ts +0 -158
  217. package/packages/core/src/ace/Reflector.ts +0 -200
  218. package/packages/core/src/ace/index.ts +0 -4
  219. package/packages/core/src/agent/AgentRunner.ts +0 -711
  220. package/packages/core/src/agent/ContextCompiler.ts +0 -567
  221. package/packages/core/src/agent/ContextGuard.ts +0 -91
  222. package/packages/core/src/agent/ConversationStore.ts +0 -254
  223. package/packages/core/src/agent/Hooks.ts +0 -166
  224. package/packages/core/src/agent/StuckLoop.ts +0 -133
  225. package/packages/core/src/agent/providers/LLMClient.ts +0 -149
  226. package/packages/core/src/agent/providers/anthropic.ts +0 -212
  227. package/packages/core/src/agent/providers/openai-compat.ts +0 -231
  228. package/packages/core/src/agent/selectors/PlaybookSelector.ts +0 -121
  229. package/packages/core/src/agent/selectors/SkillSelector.ts +0 -322
  230. package/packages/core/src/agent/selectors/index.ts +0 -6
  231. package/packages/core/src/auth/auth.ts +0 -121
  232. package/packages/core/src/auth/index.ts +0 -1
  233. package/packages/core/src/canvas/CanvasManager.ts +0 -390
  234. package/packages/core/src/canvas/canvas-tools.ts +0 -448
  235. package/packages/core/src/harness/collections.ts +0 -98
  236. package/packages/core/src/harness/goal-verifier.ts +0 -141
  237. package/packages/core/src/harness/harness.test.ts +0 -236
  238. package/packages/core/src/harness/reconcile.ts +0 -149
  239. package/packages/core/src/mcp/MCPToolAdapter.ts +0 -176
  240. package/packages/core/src/multimodal/VisionService.ts +0 -293
  241. package/packages/core/src/scheduler/dag/AgentExecutor.ts +0 -53
  242. package/packages/core/src/scheduler/dag/DAGScheduler.ts +0 -250
  243. package/packages/core/src/scheduler/dag/EventBridge.ts +0 -122
  244. package/packages/core/src/scheduler/dag/TaskGraph.ts +0 -192
  245. package/packages/core/src/scheduler/dag/TaskNode.ts +0 -97
  246. package/packages/core/src/scheduler/dag/TaskResult.ts +0 -22
  247. package/packages/core/src/scheduler/dag/errors.ts +0 -37
  248. package/packages/core/src/scheduler/dag/index.ts +0 -26
  249. package/packages/core/src/scheduler/dag/presets/ResearchPreset.ts +0 -97
  250. package/packages/core/src/scheduler/dag/strategies/ParallelStrategy.ts +0 -21
  251. package/packages/core/src/scheduler/dag/strategies/PriorityStrategy.ts +0 -46
  252. package/packages/core/src/storage/HiveDBStorage.ts +0 -64
  253. package/packages/core/src/storage/SQLiteStorage.ts +0 -414
  254. package/packages/core/src/storage/hiveSeed.ts +0 -308
  255. package/packages/core/src/storage/hiveStorage.test.ts +0 -38
  256. package/packages/core/src/storage/schema.ts +0 -689
  257. package/packages/core/src/storage/storage.test.ts +0 -37
  258. package/packages/core/src/swarm/AgentBus.ts +0 -460
  259. package/packages/core/src/swarm/EventBus.ts +0 -169
  260. package/packages/core/src/swarm/WorkerPool.ts +0 -236
  261. package/packages/core/src/tools/bridge-events.ts +0 -26
  262. package/packages/core/src/tools/canvas/index.ts +0 -375
  263. package/packages/core/src/tools/codebridge/index.ts +0 -342
  264. package/packages/core/src/tools/meeting/index.ts +0 -353
  265. package/packages/core/src/tools/projects/index.ts +0 -37
  266. package/packages/core/src/tools/projects/project-create.ts +0 -94
  267. package/packages/core/src/tools/projects/project-done.ts +0 -66
  268. package/packages/core/src/tools/projects/project-fail.ts +0 -66
  269. package/packages/core/src/tools/projects/project-list.ts +0 -96
  270. package/packages/core/src/tools/projects/project-update.ts +0 -72
  271. package/packages/core/src/tools/projects/task-create.ts +0 -68
  272. package/packages/core/src/tools/projects/task-evaluate.ts +0 -93
  273. package/packages/core/src/tools/projects/task-update.ts +0 -93
  274. package/packages/core/src/tools/voice/index.ts +0 -104
  275. package/packages/core/src/tools/web/api-request.test.ts +0 -170
  276. package/packages/core/src/tools/web/api-request.ts +0 -239
  277. package/test/setup-db.ts +0 -216
  278. /package/packages/core/src/agent/{NativeTools.ts → native-tools.ts} +0 -0
@@ -1,21 +1,62 @@
1
+ /**
2
+ * El catálogo de skills bundled se genera desde los SKILL.md de `skills/bundled/`
3
+ * con `bun run skills:bundle`. Hasta 0.1.5 el SDK traía 44 skills copiadas a
4
+ * mano, 21 de las cuales invocaban tools que ya no existen (`voice_*`,
5
+ * `meeting_transcription`, `canvas_*`, `code_*`, `project_*`): el selector se
6
+ * las podía ofrecer al modelo y la ejecución moría sin ejecutor.
7
+ */
8
+
1
9
  import { describe, it, expect } from "bun:test";
2
10
  import { BUNDLED_SKILLS_DATA } from "./bundled-data.generated.ts";
11
+ import { createAllTools } from "../tools/index.ts";
12
+ import { loadConfig } from "../config/loader.ts";
3
13
 
4
14
  describe("Bundled skills", () => {
5
- it("includes web_browser_research skill", () => {
6
- const skill = BUNDLED_SKILLS_DATA.find((s) => s.name === "web_browser_research");
7
- expect(skill).toBeDefined();
8
- expect(skill?.category).toBe("web");
9
- expect(skill?.tools).toContain("web_search");
10
- expect(skill?.tools).toContain("browser_navigate");
11
- expect(skill?.tools).toContain("browser_extract");
12
- expect(skill?.triggers.length).toBeGreaterThan(0);
13
- });
14
-
15
- it("includes existing web and browser skills", () => {
15
+ it("incluye las skills web y de browser", () => {
16
16
  const names = BUNDLED_SKILLS_DATA.map((s) => s.name);
17
17
  expect(names).toContain("web_research");
18
18
  expect(names).toContain("browser_scrape");
19
19
  expect(names).toContain("browser_automate");
20
20
  });
21
+
22
+ it("no arrastra las skills retiradas", () => {
23
+ const names = BUNDLED_SKILLS_DATA.map((s) => s.name);
24
+ for (const retired of [
25
+ "web_browser_research",
26
+ "voice_input",
27
+ "voice_output",
28
+ "voice_assistant",
29
+ "meeting_transcription",
30
+ "canvas_report",
31
+ "canvas_dashboard",
32
+ "code_review",
33
+ "code_generate",
34
+ "project_planner",
35
+ "busqueda_fts5",
36
+ "ai_coder",
37
+ "data_analyst",
38
+ ]) {
39
+ expect(names, `la skill retirada "${retired}" volvió al bundle`).not.toContain(retired);
40
+ }
41
+ });
42
+
43
+ it("cada skill declara sólo tools que existen en el registry", async () => {
44
+ const available = new Set(createAllTools(await loadConfig()).map((t) => t.name));
45
+
46
+ const dangling = BUNDLED_SKILLS_DATA.flatMap((skill) =>
47
+ (skill.tools ?? [])
48
+ .filter((tool) => !available.has(tool))
49
+ .map((tool) => `${skill.name} → ${tool}`)
50
+ );
51
+
52
+ expect(dangling, `skills apuntando a tools inexistentes:\n${dangling.join("\n")}`).toEqual([]);
53
+ });
54
+
55
+ it("toda skill tiene nombre, descripción y categoría", () => {
56
+ for (const skill of BUNDLED_SKILLS_DATA) {
57
+ expect(skill.name, "skill sin nombre").toBeTruthy();
58
+ expect(skill.description, `${skill.name} sin descripción`).toBeTruthy();
59
+ expect(skill.category, `${skill.name} sin categoría`).toBeTruthy();
60
+ }
61
+ });
21
62
  });
@@ -1,7 +1,10 @@
1
1
  /**
2
2
  * boot-id — a unique id generated on every process start so that durable
3
- * leases (harness runs / jobs) can detect which rows belong to a dead
3
+ * leases (agentRuns / jobQueue) can detect which rows belong to a dead
4
4
  * process after a crash/restart.
5
+ *
6
+ * The id is a short hex string; it is stable for the lifetime of the
7
+ * process and can be passed to {@link reconcileOnBoot}.
5
8
  */
6
9
 
7
10
  import { randomBytes } from "node:crypto";
@@ -17,4 +20,4 @@ export function getBootId(): string {
17
20
 
18
21
  export function resetBootId(): void {
19
22
  currentBootId = null;
20
- }
23
+ }
@@ -0,0 +1,151 @@
1
+ /**
2
+ * HiveDB bootstrap — replaces initializeDatabase() + seedAllData() +
3
+ * runStartupMigrations().
4
+ *
5
+ * A brand-new install never has legacy SQLite data to migrate, so there is
6
+ * no version-gated migration list: ensureHiveDb() just makes sure every
7
+ * collection's secondary indexes exist (idempotent, safe every boot) and
8
+ * that the static catalogs are (re)seeded from their canonical source
9
+ * (SEED_DATA / SkillLoader) — same "reseed every boot so code changes
10
+ * always take effect" behavior `seedAllData()` had, just via `put()`
11
+ * instead of `DELETE`+`INSERT`.
12
+ */
13
+
14
+ import { getHiveDb } from "./hivedb";
15
+ import { col } from "./hive";
16
+ import { seedAllData } from "./seed";
17
+ import { ensureSecretsBackend } from "./crypto";
18
+
19
+ interface IndexSpec {
20
+ collection: string;
21
+ field: string;
22
+ unique?: boolean;
23
+ }
24
+
25
+ /**
26
+ * Every equality index used by `findBy()` across the codebase. Grouped by
27
+ * the migration stage that introduces the collection; kept in one place so
28
+ * a missing index is a loud error (`findBy` throws) rather than a silent
29
+ * empty result.
30
+ */
31
+ const INDEXES: IndexSpec[] = [
32
+ // Stage 1 — identity/config core
33
+ { collection: "models", field: "provider_id" },
34
+ { collection: "models", field: "model_type" },
35
+ { collection: "agents", field: "user_id" },
36
+ { collection: "agents", field: "model_id" },
37
+ { collection: "agents", field: "parent_id" },
38
+ { collection: "agents", field: "role" },
39
+ { collection: "agents", field: "status" },
40
+ { collection: "agents", field: "source" },
41
+ // Stage 2 — catalog
42
+ { collection: "channels", field: "user_id" },
43
+ { collection: "channels", field: "type" },
44
+ { collection: "skills", field: "category" },
45
+ { collection: "skills", field: "active" },
46
+ { collection: "tools", field: "category" },
47
+ { collection: "tools", field: "active" },
48
+ { collection: "ethics", field: "active" },
49
+ { collection: "mcpTools", field: "server_id" },
50
+ { collection: "mcpTools", field: "active" },
51
+ // Stage 3 — auth/identity
52
+ { collection: "userChannels", field: "channel" },
53
+ { collection: "refreshTokens", field: "token_hash", unique: true },
54
+ { collection: "refreshTokens", field: "user_id" },
55
+ { collection: "notifications", field: "user_id" },
56
+ { collection: "notifications", field: "channel" },
57
+ // Stage 4 — chat/ACE
58
+ { collection: "traces", field: "thread_id" },
59
+ { collection: "traces", field: "agent_id" },
60
+ { collection: "traces", field: "success" },
61
+ { collection: "playbook", field: "active" },
62
+ { collection: "playbook", field: "category" },
63
+ // Stage 5 — scheduler
64
+ { collection: "cronJobs", field: "status" },
65
+ { collection: "cronJobs", field: "task_type" },
66
+ { collection: "cronJobs", field: "agent_id" },
67
+ { collection: "agentRuns", field: "status" },
68
+ { collection: "agentRuns", field: "thread_id" },
69
+ { collection: "agentRuns", field: "agent_id" },
70
+ { collection: "agentRuns", field: "kind" },
71
+ { collection: "agentRuns", field: "catalog_agent_id" },
72
+ { collection: "jobQueue", field: "status" },
73
+ { collection: "jobQueue", field: "lane" },
74
+ { collection: "jobQueue", field: "type" },
75
+ { collection: "jobQueue", field: "run_id" },
76
+ { collection: "jobQueue", field: "idempotency_key" },
77
+ { collection: "proofPackets", field: "run_id" },
78
+ { collection: "proofPackets", field: "agent_id" },
79
+ { collection: "proofPackets", field: "catalog_agent_id" },
80
+ { collection: "artifacts", field: "run_id" },
81
+ { collection: "artifacts", field: "task_id" },
82
+ { collection: "artifacts", field: "user_id" },
83
+ { collection: "artifacts", field: "status" },
84
+ { collection: "agentProposals", field: "agent_id" },
85
+ { collection: "agentProposals", field: "status" },
86
+ { collection: "agentProposals", field: "type" },
87
+ // Stage 6 — orchestration
88
+ { collection: "tasks", field: "agent_id" },
89
+ { collection: "tasks", field: "status" },
90
+ { collection: "tasks", field: "catalog_agent_id" },
91
+ { collection: "tasks", field: "delegation_group_id" },
92
+ { collection: "delegationGroups", field: "turn_id", unique: true },
93
+ { collection: "delegationGroups", field: "thread_id" },
94
+ { collection: "delegationGroups", field: "status" },
95
+ { collection: "agentBusMessages", field: "to_worker_id" },
96
+ { collection: "agentBusMessages", field: "from_worker_id" },
97
+ { collection: "agentBusMessages", field: "event_type" },
98
+ { collection: "narrationEvents", field: "turn_id" },
99
+ { collection: "narrationEvents", field: "thread_id" },
100
+ { collection: "narrationEvents", field: "user_id" },
101
+ { collection: "narrationEvents", field: "kind" },
102
+ // Stage 7 — meeting
103
+ { collection: "meetingSessions", field: "user_id" },
104
+ { collection: "meetingSessions", field: "status" },
105
+ ];
106
+
107
+ async function ensureIndexes(): Promise<void> {
108
+ for (const spec of INDEXES) {
109
+ const c = await col(spec.collection);
110
+ await c.createIndex(spec.field, { unique: spec.unique });
111
+ }
112
+ }
113
+
114
+ /**
115
+ * Seeds the static catalogs (tools, skills, providers, models, mcp servers,
116
+ * channels, ethics, ACE playbook) from their canonical source every boot —
117
+ * same "reseed every boot so code changes always take effect" behavior the
118
+ * old SQLite seedAllData() had. Fully idempotent: uses putIfAbsent for
119
+ * user-toggleable fields (enabled/active) and doesn't touch `users`, so it's
120
+ * safe to call unconditionally before any onboarding has happened.
121
+ */
122
+ async function ensureSeedData(): Promise<void> {
123
+ await seedAllData();
124
+ }
125
+
126
+ let bootstrapped = false;
127
+
128
+ /**
129
+ * Idempotent entry point: opens the database, ensures indexes, reseeds the
130
+ * static catalogs, and records the schema version. Safe to call on every
131
+ * gateway boot.
132
+ */
133
+ export async function ensureHiveDb(): Promise<void> {
134
+ await getHiveDb();
135
+ await ensureIndexes();
136
+ // Mint the master key before anything can save an API key, so a fresh
137
+ // install is durable from the first keystroke rather than after a restart
138
+ // has already dropped the secret.
139
+ ensureSecretsBackend();
140
+ await ensureSeedData();
141
+
142
+ const meta = await col<{ value: number }>("meta");
143
+ const existing = await meta.get("schemaVersion");
144
+ if (!existing) await meta.put("schemaVersion", { value: 1 }, { expectedVersion: 0 });
145
+
146
+ bootstrapped = true;
147
+ }
148
+
149
+ export function isBootstrapped(): boolean {
150
+ return bootstrapped;
151
+ }
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Live-tail wrapper over HiveDB's G9 causal event log (subscribe()/events()).
3
+ *
4
+ * Read-side, separate from agent-loop.ts's write-side appendCausalEvent()
5
+ * (module-private there, write-only). This is the read/watch counterpart,
6
+ * co-located with the DB singleton accessor.
7
+ */
8
+
9
+ import { getHiveDb } from "./hivedb"
10
+ import type { Event, EventPattern } from "@johpaz/hive-db"
11
+
12
+ export type { Event as CausalEvent, EventPattern as CausalEventPattern }
13
+
14
+ /**
15
+ * Live-tail causal events matching `pattern`. Forward-only: only events
16
+ * appended AFTER this call resolves are delivered. hive-db's subscribe()/
17
+ * events() are a pure in-process pub/sub (see hiveBD's reactive.rs — a
18
+ * DashMap of subscribers, dispatched right after the durable write, with no
19
+ * backing read of the log on subscribe) — there is no historical replay.
20
+ * Combine with causalThread()/read(seq) if backfill is ever needed.
21
+ *
22
+ * Note: `pattern.kind` matches exactly one kind at a time, not an OR of
23
+ * several — call watchCausalEvents() once per kind if you need more than one.
24
+ *
25
+ * Process constraint (confirmed by testing): getHiveDb() opens the database
26
+ * exclusively — there is no shared/read-only mode, so this can only be
27
+ * called from within the SAME process as whatever else has the DB open
28
+ * (e.g. embedded inside the gateway). A separate process (like the `hive
29
+ * causal watch` CLI) calling this while a `hive` gateway is already running
30
+ * against the same DB fails fast with an "already open" error.
31
+ */
32
+ export async function watchCausalEvents(
33
+ pattern: EventPattern
34
+ ): Promise<AsyncIterable<Event> & { close(): void }> {
35
+ const db = await getHiveDb()
36
+ return db.events(pattern)
37
+ }
38
+
39
+ /** One-line human-readable summary of a causal event, keyed by its kindTag. */
40
+ export function formatCausalEvent(event: Event): string {
41
+ let payload: Record<string, unknown> = {}
42
+ try {
43
+ payload = JSON.parse(event.payload)
44
+ } catch {
45
+ // Malformed payload — still print seq/kind/agent/stream below.
46
+ }
47
+
48
+ const streamShort = event.streamId.slice(0, 8)
49
+ const header = `[${event.seq}] ${kindIcon(event.kindTag)} ${event.kindTag.padEnd(16)} agent=${event.agentId} stream=${streamShort}…`
50
+
51
+ switch (event.kindTag) {
52
+ case "IntentLogged":
53
+ return `${header} "${truncate(String(payload.intent ?? ""), 120)}"`
54
+ case "StateTransition":
55
+ return `${header} "${truncate(String(payload.description ?? ""), 120)}"`
56
+ case "ToolCall": {
57
+ const outcome = payload.outcome
58
+ const outcomeStr =
59
+ outcome === "Ok" ? "ok"
60
+ : outcome === "Timeout" ? "TIMEOUT"
61
+ : (outcome && typeof outcome === "object" && "Err" in (outcome as object))
62
+ ? `ERR: ${(outcome as { Err: string }).Err}`
63
+ : String(outcome)
64
+ const latency = payload.latency_ms !== undefined ? `${payload.latency_ms}ms` : "?ms"
65
+ return `${header} tool=${payload.tool} ${latency} ${outcomeStr}`
66
+ }
67
+ default:
68
+ return `${header} ${truncate(JSON.stringify(payload), 120)}`
69
+ }
70
+ }
71
+
72
+ function kindIcon(kindTag: string): string {
73
+ switch (kindTag) {
74
+ case "IntentLogged": return "🎯"
75
+ case "StateTransition": return "🔀"
76
+ case "ToolCall": return "🔧"
77
+ case "LearningProposal": return "📄"
78
+ default: return "•"
79
+ }
80
+ }
81
+
82
+ function truncate(s: string, max: number): string {
83
+ return s.length > max ? s.slice(0, max) + "…" : s
84
+ }