@johpaz/hive-sdk 0.1.4 → 0.1.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.
Files changed (272) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/README.md +78 -23
  3. package/bunfig.toml +4 -2
  4. package/docs/API-AGENTS.md +78 -27
  5. package/docs/API-CONTEXT-COMPILER.md +31 -34
  6. package/docs/API-TOOLS-SKILLS-CHANNELS.md +58 -22
  7. package/docs/HIVE-HARNESS.md +1 -1
  8. package/docs/INDEX.md +4 -4
  9. package/docs/TEMPLATE-HIVE-APP.md +10 -10
  10. package/package.json +9 -4
  11. package/packages/cli/package.json +2 -2
  12. package/packages/cli/src/commands/create-app.test.ts +36 -7
  13. package/packages/cli/src/commands/init.ts +3 -3
  14. package/packages/cli/src/commands/run.ts +1 -1
  15. package/packages/cli/src/commands/test.ts +37 -25
  16. package/packages/cli/src/commands/trace.ts +30 -28
  17. package/packages/cli/templates/hive-app/.env.example +10 -2
  18. package/packages/cli/templates/hive-app/README.md +103 -0
  19. package/packages/cli/templates/hive-app/hive.config.ts +9 -3
  20. package/packages/cli/templates/hive-app/src/agents/coordinator.ts +8 -1
  21. package/packages/cli/templates/hive-app/src/main.ts +12 -19
  22. package/packages/core/package.json +5 -4
  23. package/packages/core/src/agent/acceptance-checks.ts +166 -0
  24. package/packages/core/src/agent/agent-catalog.ts +348 -0
  25. package/packages/core/src/agent/agent-loop.ts +1373 -0
  26. package/packages/core/src/agent/capability-search.ts +186 -0
  27. package/packages/core/src/agent/catalog-selector.ts +103 -0
  28. package/packages/core/src/agent/{Compaction.ts → compaction.ts} +86 -63
  29. package/packages/core/src/agent/context-compiler.ts +689 -0
  30. package/packages/core/src/agent/conversation-store.ts +381 -0
  31. package/packages/core/src/agent/curator.ts +276 -0
  32. package/packages/core/src/agent/delegation-runtime.ts +241 -0
  33. package/packages/core/src/agent/goal-runner.ts +323 -0
  34. package/packages/core/src/agent/index.ts +17 -12
  35. package/packages/core/src/agent/llm-client.ts +266 -0
  36. package/packages/core/src/agent/llm-providers/anthropic.ts +264 -0
  37. package/packages/core/src/agent/llm-providers/deepseek.ts +8 -0
  38. package/packages/core/src/agent/{providers → llm-providers}/gemini.ts +98 -60
  39. package/packages/core/src/agent/llm-providers/groq.ts +5 -0
  40. package/packages/core/src/agent/llm-providers/hiveagents.ts +253 -0
  41. package/packages/core/src/agent/{providers → llm-providers}/interface.ts +73 -13
  42. package/packages/core/src/agent/llm-providers/kimi.ts +8 -0
  43. package/packages/core/src/agent/llm-providers/minimax.ts +13 -0
  44. package/packages/core/src/agent/llm-providers/mistral.ts +5 -0
  45. package/packages/core/src/agent/llm-providers/modelscope.ts +5 -0
  46. package/packages/core/src/agent/llm-providers/nvidia.ts +5 -0
  47. package/packages/core/src/agent/{providers → llm-providers}/ollama.ts +31 -5
  48. package/packages/core/src/agent/llm-providers/openai-compat-base.ts +418 -0
  49. package/packages/core/src/agent/llm-providers/openai.ts +5 -0
  50. package/packages/core/src/agent/llm-providers/opencode-go.ts +9 -0
  51. package/packages/core/src/agent/llm-providers/openrouter.ts +5 -0
  52. package/packages/core/src/agent/llm-providers/qwen.ts +5 -0
  53. package/packages/core/src/agent/llm-providers/z-ai.ts +5 -0
  54. package/packages/core/src/agent/minimal-loadout.ts +47 -0
  55. package/packages/core/src/agent/playbook-selector.ts +119 -0
  56. package/packages/core/src/agent/{PromptBuilder.ts → prompt-builder.ts} +21 -22
  57. package/packages/core/src/{harness → agent}/proof-packet.ts +16 -21
  58. package/packages/core/src/agent/providers/index.ts +35 -16
  59. package/packages/core/src/agent/reflector.ts +320 -0
  60. package/packages/core/src/agent/routing-intent.ts +22 -0
  61. package/packages/core/src/{harness → agent}/run-epoch.ts +4 -3
  62. package/packages/core/src/{harness → agent}/run-store.ts +142 -81
  63. package/packages/core/src/agent/{Service.ts → service.ts} +37 -26
  64. package/packages/core/src/agent/skill-selector.ts +374 -0
  65. package/packages/core/src/agent/stuck-loop.ts +209 -0
  66. package/packages/core/src/agent/{selectors/ToolSelector.ts → tool-selector.ts} +188 -178
  67. package/packages/core/src/{ace/Tracer.ts → agent/tracer.ts} +37 -27
  68. package/packages/core/src/api/createAgent.test.ts +139 -27
  69. package/packages/core/src/api/createAgent.ts +232 -44
  70. package/packages/core/src/artifacts/store.ts +162 -0
  71. package/packages/core/src/canvas/canvas-manager.ts +161 -0
  72. package/packages/core/src/canvas/canvas.test.ts +8 -4
  73. package/packages/core/src/canvas/emitter.ts +131 -80
  74. package/packages/core/src/canvas/index.ts +1 -3
  75. package/packages/core/src/channels/base.ts +9 -1
  76. package/packages/core/src/channels/discord.ts +5 -4
  77. package/packages/core/src/channels/manager.ts +122 -30
  78. package/packages/core/src/channels/slack.ts +5 -4
  79. package/packages/core/src/channels/telegram.ts +36 -6
  80. package/packages/core/src/channels/webchat.ts +11 -10
  81. package/packages/core/src/channels/whatsapp.ts +23 -7
  82. package/packages/core/src/config/index.ts +13 -2
  83. package/packages/core/src/config/loader.ts +71 -29
  84. package/packages/core/src/ethics/EthicsGuard.test.ts +90 -36
  85. package/packages/core/src/ethics/EthicsGuard.ts +51 -47
  86. package/packages/core/src/events/agent-bus.ts +44 -68
  87. package/packages/core/src/events/channel-narration.ts +150 -0
  88. package/packages/core/src/events/narration.ts +82 -0
  89. package/packages/core/src/events/tool-narration.ts +62 -0
  90. package/packages/core/src/gateway/delegation-groups.ts +258 -0
  91. package/packages/core/src/{harness → gateway}/durable-queue.ts +102 -42
  92. package/packages/core/src/{harness → gateway}/job-store.ts +85 -48
  93. package/packages/core/src/gateway/lane-queue.ts +173 -0
  94. package/packages/core/src/gateway/notification-inbox.ts +57 -0
  95. package/packages/core/src/gateway/server.ts +1 -1
  96. package/packages/core/src/harness/index.ts +46 -27
  97. package/packages/core/src/index.ts +33 -27
  98. package/packages/core/src/mcp/hot-reload.ts +32 -23
  99. package/packages/core/src/mcp/index.ts +6 -3
  100. package/packages/core/src/mcp/singleton.ts +1 -4
  101. package/packages/core/src/mcp/tool-sync.ts +138 -0
  102. package/packages/core/src/memory/Scratchpad.test.ts +39 -20
  103. package/packages/core/src/memory/Scratchpad.ts +27 -34
  104. package/packages/core/src/multimodal/vision-service.ts +44 -38
  105. package/packages/core/src/resilience/retry.ts +95 -0
  106. package/packages/core/src/scheduler/CronScheduler.ts +334 -287
  107. package/packages/core/src/scheduler/index.ts +9 -7
  108. package/packages/core/src/scheduler/integration.ts +46 -26
  109. package/packages/core/src/scheduler/scheduler.test.ts +9 -13
  110. package/packages/core/src/scheduler/types.ts +7 -2
  111. package/packages/core/src/security/Pairing.ts +1 -1
  112. package/packages/core/src/skills/bundled/a2ui/a2ui_dashboard/SKILL.md +176 -0
  113. package/packages/core/src/skills/bundled/a2ui/a2ui_form/SKILL.md +202 -0
  114. package/packages/core/src/skills/bundled/a2ui/a2ui_interactive/SKILL.md +206 -0
  115. package/packages/core/src/skills/bundled/agents/agent_spawner/SKILL.md +173 -0
  116. package/packages/core/src/skills/bundled/agents/memory_manager/SKILL.md +143 -0
  117. package/packages/core/src/skills/bundled/agents/research_and_remember/SKILL.md +139 -0
  118. package/packages/core/src/skills/bundled/agents/task_orchestrator/SKILL.md +98 -0
  119. package/packages/core/src/skills/bundled/api/api_client/SKILL.md +132 -0
  120. package/packages/core/src/skills/bundled/cli/cli_pipeline/SKILL.md +135 -0
  121. package/packages/core/src/skills/bundled/cli/cli_safe_exec/SKILL.md +125 -0
  122. package/packages/core/src/skills/bundled/cli/software_engineering/SKILL.md +23 -0
  123. package/packages/core/src/skills/bundled/cron_manager/SKILL.md +188 -0
  124. package/packages/core/src/skills/bundled/cron_reminder/SKILL.md +112 -0
  125. package/packages/core/src/skills/bundled/filesystem/file_manager/SKILL.md +118 -0
  126. package/packages/core/src/skills/bundled/filesystem/file_read_and_summarize/SKILL.md +109 -0
  127. package/packages/core/src/skills/bundled/filesystem/file_writer/SKILL.md +129 -0
  128. package/packages/core/src/skills/bundled/filesystem/workspace_file_operator/SKILL.md +22 -0
  129. package/packages/core/src/skills/bundled/office/office_document_manager/SKILL.md +262 -0
  130. package/packages/core/src/skills/bundled/search_knowledge/capability_discovery/SKILL.md +75 -0
  131. package/packages/core/src/skills/bundled/web/browser_automate/SKILL.md +120 -0
  132. package/packages/core/src/skills/bundled/web/browser_scrape/SKILL.md +109 -0
  133. package/packages/core/src/skills/bundled/web/web_monitor/SKILL.md +127 -0
  134. package/packages/core/src/skills/bundled/web/web_research/SKILL.md +119 -0
  135. package/packages/core/src/skills/bundled-data.generated.ts +731 -2678
  136. package/packages/core/src/skills/skills.test.ts +52 -11
  137. package/packages/core/src/{harness → storage}/boot-id.ts +5 -2
  138. package/packages/core/src/storage/bootstrap.ts +151 -0
  139. package/packages/core/src/storage/causal-events.ts +84 -0
  140. package/packages/core/src/storage/collections.ts +680 -0
  141. package/packages/core/src/storage/crypto.ts +205 -74
  142. package/packages/core/src/{harness/db-helpers.ts → storage/hive.ts} +63 -7
  143. package/packages/core/src/storage/hivedb.ts +61 -0
  144. package/packages/core/src/storage/index.ts +111 -18
  145. package/packages/core/src/storage/model-id.ts +53 -0
  146. package/packages/core/src/storage/onboarding.ts +540 -972
  147. package/packages/core/src/storage/reconcile.ts +238 -0
  148. package/packages/core/src/storage/seed.ts +572 -406
  149. package/packages/core/src/storage/usage.ts +285 -225
  150. package/packages/core/src/storage/user-email.ts +11 -0
  151. package/packages/core/src/swarm/AgentExecutor.ts +1 -1
  152. package/packages/core/src/swarm/EventBridge.ts +1 -1
  153. package/packages/core/src/swarm/index.ts +12 -9
  154. package/packages/core/src/tool-runtime/index.ts +146 -23
  155. package/packages/core/src/tool-runtime/tool-worker.ts +2 -2
  156. package/packages/core/src/tool-runtime/worker-tools.ts +27 -0
  157. package/packages/core/src/{canvas/a2ui-tools.ts → tools/a2ui/index.ts} +17 -8
  158. package/packages/core/src/tools/agents/get-available-models.ts +36 -54
  159. package/packages/core/src/tools/agents/index.ts +784 -292
  160. package/packages/core/src/tools/api/api-request.test.ts +164 -0
  161. package/packages/core/src/tools/api/api-request.ts +174 -0
  162. package/packages/core/src/tools/api/index.ts +16 -0
  163. package/packages/core/src/tools/cli/index.ts +4 -0
  164. package/packages/core/src/tools/core/index.ts +281 -112
  165. package/packages/core/src/tools/cron/index.ts +121 -124
  166. package/packages/core/src/tools/index.ts +63 -78
  167. package/packages/core/src/tools/office/office-escribir-xlsx.ts +3 -1
  168. package/packages/core/src/tools/types.ts +3 -1
  169. package/packages/core/src/tools/web/artifact-inspect.ts +23 -0
  170. package/packages/core/src/tools/web/browser-screenshot.ts +26 -5
  171. package/packages/core/src/tools/web/browser-service.ts +5 -0
  172. package/packages/core/src/tools/web/browser-type.ts +3 -8
  173. package/packages/core/src/tools/web/index.ts +4 -4
  174. package/packages/core/src/voice/index.ts +89 -63
  175. package/packages/core/src/workers/agent.worker.ts +2 -2
  176. package/packages/core/src/workers/workers.test.ts +3 -10
  177. package/scripts/bump-version.ts +248 -0
  178. package/scripts/generate-skill-bundle.ts +108 -0
  179. package/test/agent-loop-terminal-synthesis.test.ts +32 -0
  180. package/test/catalog-agents-stay-enabled.test.ts +117 -0
  181. package/test/causal-events.test.ts +117 -0
  182. package/test/compaction.test.ts +105 -0
  183. package/test/context-compiler.test.ts +269 -0
  184. package/test/curator.test.ts +130 -0
  185. package/test/durable-queue.test.ts +114 -0
  186. package/test/harness-barrel.test.ts +64 -0
  187. package/test/hive-helpers.test.ts +130 -0
  188. package/test/hivedb-search.test.ts +189 -0
  189. package/test/internal-turns.test.ts +166 -0
  190. package/test/job-idempotency.test.ts +68 -0
  191. package/test/job-retry-backoff.test.ts +184 -0
  192. package/test/job-store.test.ts +381 -0
  193. package/test/llm-retry.test.ts +97 -0
  194. package/test/memory-perf.test.ts +774 -0
  195. package/test/minimal-loadout.test.ts +78 -0
  196. package/test/model-catalog.test.ts +105 -0
  197. package/test/preload.ts +12 -0
  198. package/test/reflector.test.ts +320 -0
  199. package/test/retention-cap.test.ts +91 -0
  200. package/test/retired-capabilities-pruned.test.ts +192 -0
  201. package/test/run-store.test.ts +355 -0
  202. package/test/scratchpad.test.ts +74 -0
  203. package/test/secrets-durability.test.ts +119 -0
  204. package/test/seed-model-reseed.test.ts +155 -0
  205. package/test/setup-agent-seed.test.ts +264 -0
  206. package/test/tool-inventory.test.ts +65 -0
  207. package/test/tool-runtime.test.ts +258 -0
  208. package/test/toon.test.ts +429 -0
  209. package/tsconfig.json +2 -0
  210. package/packages/core/src/ace/Curator.ts +0 -158
  211. package/packages/core/src/ace/Reflector.ts +0 -200
  212. package/packages/core/src/ace/index.ts +0 -4
  213. package/packages/core/src/agent/AgentRunner.ts +0 -711
  214. package/packages/core/src/agent/ContextCompiler.ts +0 -567
  215. package/packages/core/src/agent/ContextGuard.ts +0 -91
  216. package/packages/core/src/agent/ConversationStore.ts +0 -254
  217. package/packages/core/src/agent/Hooks.ts +0 -166
  218. package/packages/core/src/agent/StuckLoop.ts +0 -133
  219. package/packages/core/src/agent/providers/LLMClient.ts +0 -149
  220. package/packages/core/src/agent/providers/anthropic.ts +0 -212
  221. package/packages/core/src/agent/providers/openai-compat.ts +0 -231
  222. package/packages/core/src/agent/selectors/PlaybookSelector.ts +0 -121
  223. package/packages/core/src/agent/selectors/SkillSelector.ts +0 -322
  224. package/packages/core/src/agent/selectors/index.ts +0 -6
  225. package/packages/core/src/auth/auth.ts +0 -121
  226. package/packages/core/src/auth/index.ts +0 -1
  227. package/packages/core/src/canvas/CanvasManager.ts +0 -390
  228. package/packages/core/src/canvas/canvas-tools.ts +0 -448
  229. package/packages/core/src/harness/collections.ts +0 -98
  230. package/packages/core/src/harness/goal-verifier.ts +0 -141
  231. package/packages/core/src/harness/harness.test.ts +0 -236
  232. package/packages/core/src/harness/reconcile.ts +0 -149
  233. package/packages/core/src/mcp/MCPToolAdapter.ts +0 -176
  234. package/packages/core/src/multimodal/VisionService.ts +0 -293
  235. package/packages/core/src/scheduler/dag/AgentExecutor.ts +0 -53
  236. package/packages/core/src/scheduler/dag/DAGScheduler.ts +0 -250
  237. package/packages/core/src/scheduler/dag/EventBridge.ts +0 -122
  238. package/packages/core/src/scheduler/dag/TaskGraph.ts +0 -192
  239. package/packages/core/src/scheduler/dag/TaskNode.ts +0 -97
  240. package/packages/core/src/scheduler/dag/TaskResult.ts +0 -22
  241. package/packages/core/src/scheduler/dag/errors.ts +0 -37
  242. package/packages/core/src/scheduler/dag/index.ts +0 -26
  243. package/packages/core/src/scheduler/dag/presets/ResearchPreset.ts +0 -97
  244. package/packages/core/src/scheduler/dag/strategies/ParallelStrategy.ts +0 -21
  245. package/packages/core/src/scheduler/dag/strategies/PriorityStrategy.ts +0 -46
  246. package/packages/core/src/storage/HiveDBStorage.ts +0 -64
  247. package/packages/core/src/storage/SQLiteStorage.ts +0 -414
  248. package/packages/core/src/storage/hiveSeed.ts +0 -308
  249. package/packages/core/src/storage/hiveStorage.test.ts +0 -38
  250. package/packages/core/src/storage/schema.ts +0 -689
  251. package/packages/core/src/storage/storage.test.ts +0 -37
  252. package/packages/core/src/swarm/AgentBus.ts +0 -460
  253. package/packages/core/src/swarm/EventBus.ts +0 -169
  254. package/packages/core/src/swarm/WorkerPool.ts +0 -236
  255. package/packages/core/src/tools/bridge-events.ts +0 -26
  256. package/packages/core/src/tools/canvas/index.ts +0 -375
  257. package/packages/core/src/tools/codebridge/index.ts +0 -342
  258. package/packages/core/src/tools/meeting/index.ts +0 -353
  259. package/packages/core/src/tools/projects/index.ts +0 -37
  260. package/packages/core/src/tools/projects/project-create.ts +0 -94
  261. package/packages/core/src/tools/projects/project-done.ts +0 -66
  262. package/packages/core/src/tools/projects/project-fail.ts +0 -66
  263. package/packages/core/src/tools/projects/project-list.ts +0 -96
  264. package/packages/core/src/tools/projects/project-update.ts +0 -72
  265. package/packages/core/src/tools/projects/task-create.ts +0 -68
  266. package/packages/core/src/tools/projects/task-evaluate.ts +0 -93
  267. package/packages/core/src/tools/projects/task-update.ts +0 -93
  268. package/packages/core/src/tools/voice/index.ts +0 -104
  269. package/packages/core/src/tools/web/api-request.test.ts +0 -170
  270. package/packages/core/src/tools/web/api-request.ts +0 -239
  271. package/test/setup-db.ts +0 -216
  272. /package/packages/core/src/agent/{NativeTools.ts → native-tools.ts} +0 -0
@@ -1,342 +0,0 @@
1
- /**
2
- * CodeBridge Tools - 3 tools
3
- *
4
- * @category codebridge
5
- */
6
-
7
- import type { Tool } from "../types.ts";
8
- import { logger } from "../../utils/logger.ts";
9
- import { emitBridgeEvent } from "../bridge-events.ts";
10
-
11
- const log = logger.child("codebridge");
12
- const CODE_BRIDGE_PORT = parseInt(process.env.CODE_BRIDGE_PORT ?? "18791", 10);
13
- const CODE_BRIDGE_URL = `ws://localhost:${CODE_BRIDGE_PORT}/ws`;
14
- const CODE_BRIDGE_BASE = `http://localhost:${CODE_BRIDGE_PORT}`;
15
-
16
- // ─── codebridge_launch ───────────────────────────────────────────────────────
17
-
18
- export const codebridgeLaunchTool: Tool = {
19
- name: "codebridge_launch",
20
- description: "Launch an external coding CLI subagent (Claude Code, Qwen CLI, Gemini CLI, OpenCode CLI) to execute a coding task locally. Spanish: lanzar agente de código, iniciar Claude Code, Qwen CLI, Gemini CLI, OpenCode, subagente externo de programación",
21
- parameters: {
22
- type: "object",
23
- properties: {
24
- cli: {
25
- type: "string",
26
- enum: ["qwen", "claude", "opencode", "gemini"],
27
- description: "CLI command to run (alias: agent)",
28
- },
29
- agent: {
30
- type: "string",
31
- enum: ["qwen", "claude", "opencode", "gemini"],
32
- description: "Alias for cli (deprecated, use cli instead)",
33
- },
34
- prompt: {
35
- type: "string",
36
- description: "The prompt/task for the subagent",
37
- },
38
- role: {
39
- type: "string",
40
- enum: ["architecture", "development", "testing", "documentation"],
41
- description: "Role of the subagent",
42
- },
43
- timeoutSeconds: {
44
- type: "number",
45
- description: "Timeout in seconds (default: 600)",
46
- },
47
- },
48
- required: ["prompt"],
49
- },
50
- execute: async (params: Record<string, unknown>) => {
51
- // Support both 'cli' and 'agent' (deprecated alias)
52
- const cli = (params.cli as string) ?? (params.agent as string);
53
- const prompt = params.prompt as string;
54
- const role = (params.role as string) ?? "development";
55
- const timeoutSeconds = (params.timeoutSeconds as number) ?? 600;
56
-
57
- if (!cli) {
58
- log.error(`[codebridge_launch] ❌ Error: falta parámetro 'cli' o 'agent'`);
59
- return {
60
- ok: false,
61
- error: "Missing required parameter: 'cli' or 'agent'. Use: codebridge_launch({ cli: 'qwen', prompt: '...' })",
62
- };
63
- }
64
-
65
- if (!prompt) {
66
- log.error(`[codebridge_launch] ❌ Error: falta parámetro 'prompt'`);
67
- return {
68
- ok: false,
69
- error: "Missing required parameter: 'prompt'. Use: codebridge_launch({ cli: 'qwen', prompt: '...' })",
70
- };
71
- }
72
-
73
- log.info(`[codebridge_launch] Iniciando subagente ${cli} para rol: ${role}`);
74
- log.info(`[codebridge_launch] Code Bridge URL: ${CODE_BRIDGE_URL}`);
75
- log.info(`[codebridge_launch] Code Bridge Base: ${CODE_BRIDGE_BASE}`);
76
-
77
- try {
78
- // Check if Code Bridge is available
79
- log.info(`[codebridge_launch] Verificando disponibilidad de Code Bridge...`);
80
- const controller = new AbortController();
81
- const timeout = setTimeout(() => controller.abort(), 1000);
82
- const response = await fetch(`${CODE_BRIDGE_BASE}/health`, { signal: controller.signal });
83
- clearTimeout(timeout);
84
-
85
- if (!response.ok) {
86
- log.error(`[codebridge_launch] Code Bridge respondió con estado ${response.status}`);
87
- return {
88
- ok: false,
89
- error: "Code Bridge not available. Start with: bun run packages/code-bridge/src/index.ts",
90
- };
91
- }
92
-
93
- log.info(`[codebridge_launch] ✅ Code Bridge disponible`);
94
-
95
- // Launch via WebSocket
96
- log.info(`[codebridge_launch] Conectando WebSocket a ${CODE_BRIDGE_URL}...`);
97
- const ws = new WebSocket(CODE_BRIDGE_URL);
98
- const taskId = `task_${Date.now()}`;
99
- log.info(`[codebridge_launch] Task ID generado: ${taskId}`);
100
-
101
- return new Promise((resolve) => {
102
- let resolved = false;
103
- let timeoutHandle: ReturnType<typeof setTimeout>;
104
-
105
- const done = () => {
106
- clearTimeout(timeoutHandle);
107
- ws.close();
108
- };
109
-
110
- ws.onopen = () => {
111
- log.info(`[codebridge_launch] ✅ WebSocket conectado`);
112
- log.info(`[codebridge_launch] Enviando comando launch para task ${taskId}...`);
113
- log.info(`[codebridge_launch] Parámetros: cli=${cli}, prompt=${prompt?.substring(0, 50)}..., role=${role}, timeout=${timeoutSeconds}`);
114
-
115
- const launchCmd = {
116
- cmd: "launch",
117
- taskId,
118
- config: { role, cli, timeoutSeconds },
119
- prompt,
120
- };
121
-
122
- log.info(`[codebridge_launch] Comando JSON: ${JSON.stringify(launchCmd, null, 2).substring(0, 200)}...`);
123
- ws.send(JSON.stringify(launchCmd));
124
- };
125
-
126
- ws.onmessage = (event) => {
127
- let data: any;
128
- try { data = JSON.parse(event.data as string); } catch { return; }
129
-
130
- log.info(`[codebridge_launch] 📩 WebSocket message: ${data.type}`, data.taskId ? `task: ${data.taskId}` : "");
131
-
132
- if (data.type === "ack" && !resolved) {
133
- resolved = true;
134
- clearTimeout(timeoutHandle);
135
- log.info(`[codebridge_launch] ✅ Launch ACK recibido - PID: ${data.pid}`);
136
- emitBridgeEvent({ type: "bridge:cmd_start", data: { processId: taskId, command: cli, name: role } });
137
- resolve({
138
- ok: true,
139
- taskId,
140
- pid: data.pid,
141
- message: `Launched ${cli} with PID ${data.pid}`,
142
- });
143
- // Keep WS open to relay subsequent events
144
- return;
145
- }
146
-
147
- if (data.taskId !== taskId) return;
148
-
149
- if (data.type === "agent:output") {
150
- emitBridgeEvent({ type: "bridge:cmd_output", data: { processId: taskId, chunk: data.chunk, stream: data.stream ?? "stdout" } });
151
- } else if (data.type === "agent:finished") {
152
- log.info(`[codebridge_launch] ✅ Agente finalizado - Exit code: ${data.exitCode ?? 0}`);
153
- emitBridgeEvent({ type: "bridge:cmd_done", data: { processId: taskId, exitCode: data.exitCode ?? 0, success: true } });
154
- done();
155
- } else if (data.type === "agent:error") {
156
- log.error(`[codebridge_launch] ❌ Error del agente: ${data.message}`);
157
- emitBridgeEvent({ type: "bridge:cmd_error", data: { processId: taskId, message: data.message } });
158
- done();
159
- } else if (data.type === "agent:cancelled") {
160
- log.warn(`[codebridge_launch] ⚠️ Agente cancelado`);
161
- emitBridgeEvent({ type: "bridge:cmd_done", data: { processId: taskId, exitCode: -1, success: false } });
162
- done();
163
- }
164
- };
165
-
166
- ws.onerror = () => {
167
- log.error(`[codebridge_launch] ❌ Error de WebSocket`);
168
- if (!resolved) {
169
- resolved = true;
170
- clearTimeout(timeoutHandle);
171
- resolve({ ok: false, error: "Failed to connect to Code Bridge" });
172
- }
173
- };
174
-
175
- timeoutHandle = setTimeout(() => {
176
- if (!resolved) {
177
- log.error(`[codebridge_launch] ⏱️ Timeout esperando respuesta de Code Bridge`);
178
- resolved = true;
179
- ws.close();
180
- resolve({ ok: false, error: "Timeout connecting to Code Bridge" });
181
- }
182
- }, 5000);
183
- });
184
- } catch (error) {
185
- log.error(`[codebridge_launch] ❌ Error fatal: ${(error as Error).message}`);
186
- return {
187
- ok: false,
188
- error: `Failed to launch: ${(error as Error).message}`,
189
- };
190
- }
191
- },
192
- };
193
-
194
- // ─── codebridge_status ───────────────────────────────────────────────────────
195
-
196
- export const codebridgeStatusTool: Tool = {
197
- name: "codebridge_status",
198
- description: "Check the status and output of a running CodeBridge subagent. Spanish: estado agente de código, verificar Claude Code, progreso subagente externo",
199
- parameters: {
200
- type: "object",
201
- properties: {
202
- taskId: {
203
- type: "string",
204
- description: "Task ID to check status for",
205
- },
206
- },
207
- required: ["taskId"],
208
- },
209
- execute: async (params: Record<string, unknown>) => {
210
- const taskId = params.taskId as string;
211
-
212
- try {
213
- const response = await fetch(`${CODE_BRIDGE_BASE}/status/${taskId}`);
214
-
215
- if (!response.ok) {
216
- return { ok: false, error: `Task not found: ${taskId}` };
217
- }
218
-
219
- const data = await response.json();
220
- return { ok: true, ...data };
221
- } catch (error) {
222
- return {
223
- ok: false,
224
- error: `Failed to get status: ${(error as Error).message}`,
225
- };
226
- }
227
- },
228
- };
229
-
230
- // ─── codebridge_cancel ───────────────────────────────────────────────────────
231
-
232
- export const codebridgeCancelTool: Tool = {
233
- name: "codebridge_cancel",
234
- description: "Cancel and terminate a running CodeBridge subagent process. Spanish: cancelar agente de código, detener Claude Code, terminar subagente externo",
235
- parameters: {
236
- type: "object",
237
- properties: {
238
- taskId: {
239
- type: "string",
240
- description: "Task ID to cancel",
241
- },
242
- },
243
- required: ["taskId"],
244
- },
245
- execute: async (params: Record<string, unknown>) => {
246
- const taskId = params.taskId as string;
247
-
248
- try {
249
- const response = await fetch(`${CODE_BRIDGE_BASE}/cancel/${taskId}`, { method: "POST" });
250
-
251
- if (!response.ok) {
252
- return { ok: false, error: `Failed to cancel: ${taskId}` };
253
- }
254
-
255
- return { ok: true, taskId, message: "Task cancelled." };
256
- } catch (error) {
257
- return {
258
- ok: false,
259
- error: `Failed to cancel: ${(error as Error).message}`,
260
- };
261
- }
262
- },
263
- };
264
-
265
- // ─── codebridge_feedback ───────────────────────────────────────────────────────
266
-
267
- export const codebridgeFeedbackTool: Tool = {
268
- name: "codebridge_feedback",
269
- description: "Send feedback or additional instructions to a running CodeBridge subagent. Use for course correction, clarifications, or iterative improvements during long-running code tasks. Spanish: enviar feedback, corregir rumbo, aclaraciones, mejoras iterativas",
270
- parameters: {
271
- type: "object",
272
- properties: {
273
- taskId: {
274
- type: "string",
275
- description: "Task ID to send feedback to",
276
- },
277
- feedback: {
278
- type: "string",
279
- description: "Feedback message or additional instructions for the running agent",
280
- },
281
- },
282
- required: ["taskId", "feedback"],
283
- },
284
- execute: async (params: Record<string, unknown>) => {
285
- const taskId = params.taskId as string;
286
- const feedback = params.feedback as string;
287
-
288
- try {
289
- const ws = new WebSocket(CODE_BRIDGE_URL);
290
-
291
- return new Promise((resolve) => {
292
- ws.onopen = () => {
293
- ws.send(JSON.stringify({
294
- cmd: "feedback",
295
- taskId,
296
- feedback,
297
- }));
298
- };
299
-
300
- ws.onmessage = (event) => {
301
- try {
302
- const data = JSON.parse(event.data);
303
- if (data.type === "feedback:ack") {
304
- resolve({
305
- ok: data.delivered,
306
- taskId,
307
- delivered: data.delivered,
308
- reason: data.reason,
309
- message: data.delivered
310
- ? "Feedback delivered to running agent"
311
- : `Feedback not delivered: ${data.reason}`,
312
- });
313
- }
314
- } catch {
315
- resolve({ ok: false, error: "Failed to parse feedback response" });
316
- }
317
- ws.close();
318
- };
319
-
320
- ws.onerror = () => {
321
- resolve({ ok: false, error: "WebSocket error" });
322
- ws.close();
323
- };
324
-
325
- // Timeout after 5 seconds
326
- setTimeout(() => {
327
- resolve({ ok: false, error: "Feedback timeout" });
328
- ws.close();
329
- }, 5000);
330
- });
331
- } catch (error) {
332
- return {
333
- ok: false,
334
- error: `Failed to send feedback: ${(error as Error).message}`,
335
- };
336
- }
337
- },
338
- };
339
-
340
- export function createTools(): Tool[] {
341
- return [codebridgeLaunchTool, codebridgeStatusTool, codebridgeCancelTool, codebridgeFeedbackTool];
342
- }
@@ -1,353 +0,0 @@
1
- /**
2
- * Meeting Tools - 4 tools para transcripción de reuniones
3
- *
4
- * @category meeting
5
- */
6
-
7
- import type { Tool } from "../types.ts";
8
- import { getHiveDB } from "../../storage/HiveDBStorage.ts";
9
- import { voiceService, type AudioInput } from "../../voice/index.ts";
10
- import { logger } from "../../utils/logger.ts";
11
-
12
- const log = logger.child("meeting");
13
-
14
- interface MeetingSession {
15
- id: string;
16
- title: string;
17
- status: string;
18
- sttModel: string;
19
- startedAt: number;
20
- stoppedAt?: number;
21
- }
22
-
23
- interface MeetingSegment {
24
- sessionId: string;
25
- seq: number;
26
- speaker?: string;
27
- text: string;
28
- durationMs?: number;
29
- createdAt: number;
30
- }
31
-
32
- // ─── meeting_start ───────────────────────────────────────────────────────────
33
-
34
- export const meetingStartTool: Tool = {
35
- name: "meeting_start",
36
- description:
37
- "Inicia una sesión de transcripción de reunión en tiempo real. | Start a real-time meeting transcription session.",
38
- parameters: {
39
- type: "object",
40
- properties: {
41
- title: {
42
- type: "string",
43
- description: "Título de la reunión (default: 'Reunión sin título')",
44
- },
45
- stt_model: {
46
- type: "string",
47
- description:
48
- "Modelo STT a usar: 'whisper-large-v3-turbo' (default), 'whisper-large-v3', 'whisper-1'",
49
- },
50
- },
51
- required: [],
52
- },
53
- execute: async (params) => {
54
- const title = (params.title as string) || "Reunión sin título";
55
- const sttModel =
56
- (params.stt_model as string) || "whisper-large-v3-turbo";
57
-
58
- try {
59
- const db = await getHiveDB();
60
- const sessionsCol = db.collection<MeetingSession>("meeting_sessions");
61
- const id = crypto.randomUUID();
62
- const session: MeetingSession = {
63
- id,
64
- title,
65
- status: "active",
66
- sttModel,
67
- startedAt: Math.floor(Date.now() / 1000),
68
- };
69
- await sessionsCol.put(id, session);
70
-
71
- log.info(`Meeting session started: ${id} — "${title}"`);
72
-
73
- return {
74
- ok: true,
75
- session_id: id,
76
- title,
77
- status: session.status,
78
- stt_model: sttModel,
79
- message: `✅ Sesión de reunión iniciada. ID: ${id}\nTítulo: "${title}"\nModelo STT: ${sttModel}`,
80
- };
81
- } catch (error) {
82
- log.error(`meeting_start error: ${(error as Error).message}`);
83
- return { ok: false, error: `Error al iniciar la sesión: ${(error as Error).message}` };
84
- }
85
- },
86
- };
87
-
88
- // ─── meeting_add_segment ─────────────────────────────────────────────────────
89
-
90
- export const meetingAddSegmentTool: Tool = {
91
- name: "meeting_add_segment",
92
- description:
93
- "Transcribe un chunk de audio y lo agrega a la sesión de reunión activa. | Transcribe an audio chunk and add it to the active meeting session.",
94
- parameters: {
95
- type: "object",
96
- properties: {
97
- session_id: {
98
- type: "string",
99
- description: "ID de la sesión de reunión activa",
100
- },
101
- audio_base64: {
102
- type: "string",
103
- description: "Audio codificado en base64 (webm, ogg, mp3)",
104
- },
105
- speaker: {
106
- type: "string",
107
- description: "Etiqueta del hablante (opcional, ej: 'Ana', 'Speaker 1')",
108
- },
109
- mime_type: {
110
- type: "string",
111
- description: "Tipo MIME del audio (default: 'audio/webm')",
112
- },
113
- },
114
- required: ["session_id", "audio_base64"],
115
- },
116
- execute: async (params) => {
117
- const sessionId = params.session_id as string;
118
- const audioBase64 = params.audio_base64 as string;
119
- const speaker = (params.speaker as string) || undefined;
120
- const mimeType = (params.mime_type as string) || "audio/webm";
121
-
122
- try {
123
- const db = await getHiveDB();
124
- const sessionsCol = db.collection<MeetingSession>("meeting_sessions");
125
- const segmentsCol = db.collection<MeetingSegment>("meeting_segments");
126
-
127
- const sessionEntry = await sessionsCol.get(sessionId);
128
- if (!sessionEntry) {
129
- return { ok: false, error: `Sesión ${sessionId} no encontrada.` };
130
- }
131
- const session = sessionEntry.doc;
132
- if (session.status !== "active") {
133
- return {
134
- ok: false,
135
- error: `La sesión está ${session.status}. Solo se pueden agregar segmentos a sesiones activas.`,
136
- };
137
- }
138
-
139
- const audioInput: AudioInput = {
140
- type: "base64",
141
- data: audioBase64,
142
- mimeType,
143
- };
144
-
145
- let transcription: string;
146
- try {
147
- transcription = await voiceService.transcribe(audioInput, session.sttModel);
148
- } catch (transcribeError) {
149
- return {
150
- ok: false,
151
- error: `Error de transcripción: ${(transcribeError as Error).message}`,
152
- };
153
- }
154
-
155
- const entries = await segmentsCol.scan();
156
- const seq = entries
157
- .filter(e => e.doc.sessionId === sessionId)
158
- .reduce((max, e) => Math.max(max, e.doc.seq), -1) + 1;
159
-
160
- const segmentId = `${sessionId}:${seq}`;
161
- await segmentsCol.put(segmentId, {
162
- sessionId,
163
- seq,
164
- speaker,
165
- text: transcription,
166
- createdAt: Math.floor(Date.now() / 1000),
167
- });
168
-
169
- log.info(`Segment ${seq} added to session ${sessionId}: "${transcription.substring(0, 60)}..."`);
170
-
171
- return {
172
- ok: true,
173
- seq,
174
- speaker: speaker || null,
175
- text: transcription,
176
- message: speaker ? `[${speaker}]: ${transcription}` : transcription,
177
- };
178
- } catch (error) {
179
- log.error(`meeting_add_segment error: ${(error as Error).message}`);
180
- return {
181
- ok: false,
182
- error: `Error al agregar segmento: ${(error as Error).message}`,
183
- };
184
- }
185
- },
186
- };
187
-
188
- // ─── meeting_stop ────────────────────────────────────────────────────────────
189
-
190
- export const meetingStopTool: Tool = {
191
- name: "meeting_stop",
192
- description:
193
- "Detiene una sesión de transcripción de reunión. | Stop an active meeting transcription session.",
194
- parameters: {
195
- type: "object",
196
- properties: {
197
- session_id: {
198
- type: "string",
199
- description: "ID de la sesión de reunión a detener",
200
- },
201
- },
202
- required: ["session_id"],
203
- },
204
- execute: async (params) => {
205
- const sessionId = params.session_id as string;
206
-
207
- try {
208
- const db = await getHiveDB();
209
- const sessionsCol = db.collection<MeetingSession>("meeting_sessions");
210
- const segmentsCol = db.collection<MeetingSegment>("meeting_segments");
211
-
212
- const sessionEntry = await sessionsCol.get(sessionId);
213
- if (!sessionEntry) {
214
- return { ok: false, error: `Sesión ${sessionId} no encontrada.` };
215
- }
216
- const session = sessionEntry.doc;
217
- if (session.status === "stopped" || session.status === "report_ready") {
218
- return {
219
- ok: true,
220
- session_id: sessionId,
221
- message: `La sesión ya estaba detenida (status: ${session.status}).`,
222
- };
223
- }
224
-
225
- const stoppedAt = Math.floor(Date.now() / 1000);
226
- await sessionsCol.put(sessionId, { ...session, status: "stopped", stoppedAt });
227
-
228
- const entries = await segmentsCol.scan();
229
- const count = entries.filter(e => e.doc.sessionId === sessionId).length;
230
-
231
- log.info(`Meeting session stopped: ${sessionId} — ${count} segments`);
232
-
233
- return {
234
- ok: true,
235
- session_id: sessionId,
236
- title: session.title,
237
- segment_count: count,
238
- message: `⏹️ Sesión "${session.title}" detenida.\n${count} segmentos transcritos.\n\nPuedes pedir el reporte con: "Genera el reporte de la reunión ${sessionId}"`,
239
- };
240
- } catch (error) {
241
- log.error(`meeting_stop error: ${(error as Error).message}`);
242
- return { ok: false, error: `Error al detener la sesión: ${(error as Error).message}` };
243
- }
244
- },
245
- };
246
-
247
- // ─── meeting_report ──────────────────────────────────────────────────────────
248
-
249
- export const meetingReportTool: Tool = {
250
- name: "meeting_report",
251
- description:
252
- "Obtiene el transcript completo de una sesión de reunión para que el agente genere el informe gerencial. | Get the full transcript of a meeting session so the agent can generate the managerial report.",
253
- parameters: {
254
- type: "object",
255
- properties: {
256
- session_id: {
257
- type: "string",
258
- description: "ID de la sesión de reunión",
259
- },
260
- },
261
- required: ["session_id"],
262
- },
263
- execute: async (params) => {
264
- const sessionId = params.session_id as string;
265
-
266
- try {
267
- const db = await getHiveDB();
268
- const sessionsCol = db.collection<MeetingSession>("meeting_sessions");
269
- const segmentsCol = db.collection<MeetingSegment>("meeting_segments");
270
-
271
- const sessionEntry = await sessionsCol.get(sessionId);
272
- if (!sessionEntry) {
273
- return { ok: false, error: `Sesión ${sessionId} no encontrada.` };
274
- }
275
- const session = sessionEntry.doc;
276
-
277
- const entries = await segmentsCol.scan();
278
- const segments = entries
279
- .filter(e => e.doc.sessionId === sessionId)
280
- .map(e => e.doc)
281
- .sort((a, b) => a.seq - b.seq);
282
-
283
- if (segments.length === 0) {
284
- return {
285
- ok: false,
286
- error: "La sesión no tiene segmentos transcritos. No se puede generar el reporte.",
287
- };
288
- }
289
-
290
- const transcript = segments
291
- .map((s) => (s.speaker ? `[${s.speaker}]: ${s.text}` : s.text))
292
- .join("\n");
293
-
294
- const durationSec = session.stoppedAt
295
- ? session.stoppedAt - session.startedAt
296
- : Math.floor(Date.now() / 1000) - session.startedAt;
297
- const durationMin = Math.floor(durationSec / 60);
298
- const durationSecRem = durationSec % 60;
299
-
300
- return {
301
- ok: true,
302
- session_id: session.id,
303
- title: session.title,
304
- status: session.status,
305
- duration: `${durationMin}m ${durationSecRem}s`,
306
- segment_count: segments.length,
307
- transcript,
308
- instructions: `Con el transcript anterior, genera un INFORME GERENCIAL en español con estas secciones:
309
-
310
- ## Informe de Reunión: ${session.title}
311
-
312
- ### 1. Resumen Ejecutivo
313
- (3-5 oraciones que capturen la esencia de la reunión)
314
-
315
- ### 2. Participantes Detectados
316
- (Lista de nombres o roles mencionados en el transcript)
317
-
318
- ### 3. Decisiones Tomadas
319
- (Lista numerada de cada decisión concreta)
320
-
321
- ### 4. Action Items
322
- | Qué | Quién | Cuándo |
323
- |-----|-------|--------|
324
- (Tabla con todas las tareas asignadas)
325
-
326
- ### 5. Próximos Pasos
327
- (Lista de acciones inmediatas)
328
-
329
- ### 6. Temas de Seguimiento
330
- (Puntos que quedaron pendientes o requieren más discusión)
331
-
332
- Luego llama a office_escribir_docx para guardar el reporte como documento Word.`,
333
- };
334
- } catch (error) {
335
- log.error(`meeting_report error: ${(error as Error).message}`);
336
- return {
337
- ok: false,
338
- error: `Error al obtener el reporte: ${(error as Error).message}`,
339
- };
340
- }
341
- },
342
- };
343
-
344
- // ─── Registry ────────────────────────────────────────────────────────────────
345
-
346
- export function createTools(): Tool[] {
347
- return [
348
- meetingStartTool,
349
- meetingAddSegmentTool,
350
- meetingStopTool,
351
- meetingReportTool,
352
- ];
353
- }