@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,236 +0,0 @@
1
- /**
2
- * Hive Scheduler - Pipeline Integration
3
- *
4
- * Integrates cron jobs with the Hive agent pipeline.
5
- * Converts cron jobs into system messages that flow through the agent system.
6
- */
7
-
8
- import type { CronJob, CronJobExecutionResult } from "./types";
9
- import { logger } from "../utils/logger.ts";
10
- import { getDb } from "../storage/SQLiteStorage.ts";
11
- import { buildAgentLoop } from "../agent/AgentRunner.ts";
12
- import { resolveAgentId } from "../storage/onboarding.ts";
13
- import { sendToUserChannel } from "../gateway/channel-notify.ts";
14
- import { addMessage } from "../agent/ConversationStore.ts";
15
- import { resolveBestChannel } from "../tools/cron/index.ts";
16
-
17
- const log = logger.child("SchedulerIntegration");
18
-
19
- let _scheduler: { runCleanup(): void } | null = null;
20
-
21
- export function setSchedulerForCleanup(scheduler: { runCleanup(): void }): void {
22
- _scheduler = scheduler;
23
- }
24
-
25
- /**
26
- * Execute a cron job through the agent pipeline
27
- *
28
- * This handler:
29
- * 1. Parses the job payload
30
- * 2. Builds a system message with metadata including the `task` field as instruction
31
- * 3. Routes to the target agent (or Coordinator if none specified)
32
- * 4. Executes the tool if tool_name is specified
33
- * 5. Returns the agent response
34
- */
35
- export async function executeScheduledTask(job: CronJob): Promise<CronJobExecutionResult> {
36
- log.info(`[execute] Processing job "${job.name}" (${job.id})`);
37
-
38
- try {
39
- let payload: Record<string, unknown>;
40
- try {
41
- payload = JSON.parse(job.payload);
42
- } catch (err) {
43
- log.error(`[execute] Invalid payload JSON for job "${job.id}": ${(err as Error).message}`);
44
- return { success: false, error: "Invalid payload JSON" };
45
- }
46
-
47
- const prompt = (payload.prompt || payload.message) as string | undefined;
48
- if (!prompt && !payload._internal && !job.task) {
49
- log.error(`[execute] Job "${job.id}" has no prompt, message, or task instruction`);
50
- return { success: false, error: "Missing prompt, message, or task instruction" };
51
- }
52
-
53
- if (payload._internal === true && (payload as any).action === "cleanup") {
54
- if (_scheduler) {
55
- _scheduler.runCleanup();
56
- } else {
57
- log.warn("[execute] Cleanup job fired but scheduler instance not available");
58
- }
59
- log.info("[execute] Cleanup job executed");
60
- return { success: true, response: "Cleanup completed" };
61
- }
62
-
63
- // Build message metadata
64
- const metadata = {
65
- source: "scheduler" as const,
66
- task_id: job.id,
67
- task_name: job.name,
68
- channel: job.channel,
69
- scheduled: true,
70
- tool_name: job.tool_name || undefined,
71
- };
72
-
73
- let targetAgentId: string | null = job.agent_id || null;
74
-
75
- if (!targetAgentId) {
76
- targetAgentId = resolveAgentId(null);
77
- log.debug(`[execute] No agent specified, routing to Coordinator: ${targetAgentId}`);
78
- }
79
-
80
- const db = getDb();
81
- const user = db.query("SELECT id, timezone, language FROM users LIMIT 1").get() as {
82
- id: string;
83
- timezone: string;
84
- language: string | null;
85
- } | undefined;
86
-
87
- const userTimezone = user?.timezone || "UTC";
88
- const userLanguage = user?.language || "en";
89
-
90
- const now = new Date();
91
- const dateOptions: Intl.DateTimeFormatOptions = {
92
- timeZone: userTimezone,
93
- year: "numeric",
94
- month: "long",
95
- day: "numeric",
96
- weekday: "long",
97
- };
98
- const timeOptions: Intl.DateTimeFormatOptions = {
99
- timeZone: userTimezone,
100
- hour: "2-digit",
101
- minute: "2-digit",
102
- second: "2-digit",
103
- hour12: false,
104
- };
105
-
106
- const fecha_usuario = new Intl.DateTimeFormat(userLanguage === "es" ? "es-ES" : "en-US", dateOptions).format(now);
107
- const hora_usuario = new Intl.DateTimeFormat(userLanguage === "es" ? "es-ES" : "en-US", timeOptions).format(now);
108
-
109
- // Build the full prompt with the `task` field as the primary instruction
110
- const contextPrompt = `[SCHEDULED TASK]
111
- Name: ${job.name}
112
- Instruction: ${job.task}
113
- Type: ${job.task_type}
114
- Triggered at: ${hora_usuario} on ${fecha_usuario} (${userTimezone})
115
-
116
- ${prompt || `Execute tool: ${job.tool_name}`}`;
117
-
118
- log.debug(`[execute] Sending to agent ${targetAgentId}: "${contextPrompt.slice(0, 100)}..."`);
119
-
120
- try {
121
- const agentLoop = buildAgentLoop({ mcpManager: undefined });
122
-
123
- const sessionId = `sched_${job.id}_${Date.now()}`;
124
-
125
- const agentChannel = (job.channel && job.channel !== "system")
126
- ? job.channel
127
- : resolveBestChannel(user?.id || "");
128
-
129
- const messages = [{ role: "user", content: contextPrompt }];
130
- const stream = agentLoop.stream({ messages }, {
131
- configurable: {
132
- thread_id: sessionId,
133
- agent_id: targetAgentId || undefined,
134
- channel: agentChannel,
135
- user_id: user?.id || "",
136
- system_prompt: undefined,
137
- raw_user_message: contextPrompt,
138
- },
139
- });
140
-
141
- let response = "";
142
- let hasError = false;
143
-
144
- for await (const chunk of stream) {
145
- if (chunk.agent?.messages) {
146
- const lastMsg = chunk.agent.messages[chunk.agent.messages.length - 1];
147
- if (lastMsg?.content) {
148
- response += lastMsg.content;
149
- }
150
- }
151
- if (chunk.tools?.messages) {
152
- for (const msg of chunk.tools.messages) {
153
- if (msg.content?.error) {
154
- hasError = true;
155
- response += ` [Tool error: ${JSON.stringify(msg.content)}]`;
156
- }
157
- }
158
- }
159
- }
160
-
161
- if (hasError && !response) {
162
- throw new Error("Agent execution returned errors");
163
- }
164
-
165
- log.info(`[execute] Agent response received for job "${job.name}"`);
166
-
167
- return {
168
- success: true,
169
- response: response || "Task executed successfully",
170
- };
171
- } catch (agentErr) {
172
- log.error(`[execute] Agent execution failed: ${(agentErr as Error).message}`);
173
- return {
174
- success: false,
175
- error: `Agent execution failed: ${(agentErr as Error).message}`,
176
- };
177
- }
178
- } catch (err) {
179
- log.error(`[execute] Job execution failed: ${(err as Error).message}`);
180
- return {
181
- success: false,
182
- error: (err as Error).message,
183
- };
184
- }
185
- }
186
-
187
- /**
188
- * Send notification to user's channel after job execution
189
- */
190
- export async function notifyTaskCompletion(
191
- taskId: string,
192
- taskName: string,
193
- success: boolean,
194
- response?: string,
195
- error?: string
196
- ): Promise<void> {
197
- const db = getDb();
198
-
199
- const task = db.query(
200
- "SELECT channel, agent_id FROM cron_jobs WHERE id = ?"
201
- ).get(taskId) as { channel: string; agent_id: string | null } | undefined;
202
-
203
- if (!task) {
204
- log.warn(`[notify] Job "${taskId}" not found`);
205
- return;
206
- }
207
-
208
- const userRow = db.query("SELECT id FROM users LIMIT 1").get() as { id: string } | undefined;
209
- const userId = userRow?.id || "";
210
-
211
- const explicitChannel = task.channel && task.channel !== "system" ? task.channel : undefined;
212
- const notifyChannel = resolveBestChannel(userId, explicitChannel) || "webchat";
213
-
214
- const status = success ? "✅" : "❌";
215
- const message = success
216
- ? `${status} Scheduled task "${taskName}" completed\n${response || ""}`
217
- : `${status} Scheduled task "${taskName}" failed\n${error || ""}`;
218
-
219
- log.info(`[notify] Sending notification to ${notifyChannel}: "${message.slice(0, 50)}..."`);
220
-
221
- try {
222
- addMessage(userId, "assistant", message, { channel: notifyChannel });
223
- } catch (e) {
224
- log.warn(`[notify] Failed to persist notification to DB: ${(e as Error).message}`);
225
- }
226
-
227
- await sendToUserChannel(notifyChannel, userId, message);
228
- log.info(`[notify] Notification sent to ${notifyChannel}`);
229
- }
230
-
231
- /**
232
- * Create the job execution handler for CronScheduler
233
- */
234
- export function createTaskHandler() {
235
- return executeScheduledTask;
236
- }
@@ -1,26 +0,0 @@
1
- /**
2
- * Bridge Events - WebSocket event subscription for CodeBridge
3
- *
4
- * Manages WebSocket subscriptions for real-time CodeBridge events
5
- */
6
-
7
- const bridgeSubscribers = new Set<{ send: (data: string) => void }>()
8
-
9
- export function subscribeBridge(ws: { send: (data: string) => void }) {
10
- bridgeSubscribers.add(ws)
11
- }
12
-
13
- export function unsubscribeBridge(ws: { send: (data: string) => void }) {
14
- bridgeSubscribers.delete(ws)
15
- }
16
-
17
- export function emitBridgeEvent(event: { type: string; data: any }) {
18
- const payload = JSON.stringify(event)
19
- for (const ws of bridgeSubscribers) {
20
- try {
21
- ws.send(payload)
22
- } catch {
23
- bridgeSubscribers.delete(ws)
24
- }
25
- }
26
- }
@@ -1,375 +0,0 @@
1
- /**
2
- * Canvas Tools - 7 tools + A2UI v0.9 tools
3
- *
4
- * @category canvas
5
- */
6
-
7
- import type { Tool, ToolResult } from "../types.ts";
8
- import { emitCanvas, removeCanvasComponent, type CanvasEventType } from "../../canvas/emitter.ts";
9
- import { logger } from "../../utils/logger.ts";
10
- import { canvasManager } from "../../canvas/CanvasManager.ts";
11
- import { createA2UISurfaceTool, createA2UIUpdateComponentsTool, createA2UIUpdateDataModelTool, createA2UIDeleteSurfaceTool } from "../../canvas/a2ui-tools.ts";
12
- import type { Config } from "../../config/loader.ts";
13
-
14
- const log = logger.child("canvas");
15
-
16
- // ─── Pending canvas interactions ─────────────────────────────────────────────
17
- // Simple map indexed by componentId — no session ID required.
18
- // Server calls resolveCanvasInteraction() when it receives canvas:interact.
19
-
20
- interface PendingInteraction {
21
- resolve: (data: unknown) => void;
22
- reject: (err: Error) => void;
23
- timeout: ReturnType<typeof setTimeout>;
24
- }
25
-
26
- const pendingInteractions = new Map<string, PendingInteraction>();
27
-
28
- export function resolveCanvasInteraction(componentId: string, data: unknown): boolean {
29
- const pending = pendingInteractions.get(componentId);
30
- if (!pending) return false;
31
- clearTimeout(pending.timeout);
32
- pendingInteractions.delete(componentId);
33
- pending.resolve(data);
34
- return true;
35
- }
36
-
37
- function waitForCanvasInteraction(componentId: string, timeoutMs = 300000): Promise<unknown> {
38
- return new Promise((resolve, reject) => {
39
- const timeout = setTimeout(() => {
40
- pendingInteractions.delete(componentId);
41
- reject(new Error(`Interaction timeout for ${componentId}`));
42
- }, timeoutMs);
43
- pendingInteractions.set(componentId, { resolve, reject, timeout });
44
- });
45
- }
46
-
47
- // ─── canvas_render ───────────────────────────────────────────────────────────
48
-
49
- export const canvasRenderTool: Tool = {
50
- name: "canvas_render",
51
- description: "Render a component or visualization on the canvas. Use specific types instead of always using card+markdown. Key types: chart (bar/line/area/pie graphs), table (tabular data), markdown (rich text), form (interactive form - waits for submit), button (interactive button), alert-dialog (confirm/cancel dialog), progress (progress bars), accordion, tabs, badge, card, bee-loader. Spanish: renderizar, visualizar, gráfico, diagrama, tabla, formulario",
52
- parameters: {
53
- type: "object",
54
- properties: {
55
- component: { type: "string", description: "Component type. Visualization: chart, table, markdown, card, progress, accordion, tabs, badge, separator, bee-loader. Interactive: form, button, alert-dialog. Layout: carousel, collapsible, resizable, scroll-area, tabs. Other: alert, avatar, breadcrumb, calendar, checkbox, dialog, drawer, dropdown-menu, hover-card, input, input-otp, label, menubar, navigation-menu, pagination, popover, radio-group, select, sheet, skeleton, slider, switch, textarea, toggle, toggle-group, tooltip, aspect-ratio, command, context-menu, custom" },
56
- data: { type: "object", description: "Props for the component. chart: {type:'bar'|'line'|'area'|'pie', data:[{name,...}], xKey:'name', keys:['value'], title}. table: {title, columns:[{header,key}], data:[{}]}. form: {title, fields:[{name,label,type:'text'|'email'|'number'|'textarea'|'select'|'checkbox',placeholder,options:[{value,label}]}], submitLabel}. alert-dialog: {title, description, confirmLabel, cancelLabel}. button: {label, variant:'default'|'outline'|'secondary'|'destructive'}. markdown: {content}. progress: {value:0-100}." },
57
- },
58
- required: ["component", "data"],
59
- },
60
- execute: async (params: Record<string, unknown>) => {
61
- const componentType = params.component as string;
62
- const data = params.data as Record<string, unknown>;
63
-
64
- try {
65
- const id = `render_${componentType}_${Date.now()}`;
66
- emitCanvas("canvas:render", {
67
- component: {
68
- id,
69
- type: componentType,
70
- props: data ?? {},
71
- position: { x: 0, y: 0 },
72
- size: { width: 400, height: 300 },
73
- agentId: "agent",
74
- },
75
- });
76
- return { ok: true, message: `Rendered ${componentType}.` };
77
- } catch (error) {
78
- return { ok: false, error: `Failed to render: ${(error as Error).message }` };
79
- }
80
- },
81
- };
82
-
83
- // ─── canvas_ask ──────────────────────────────────────────────────────────────
84
-
85
- export const canvasAskTool: Tool = {
86
- name: "canvas_ask",
87
- description: "Show interactive form and wait for user input. Spanish: formulario interactivo, preguntar usuario, input",
88
- parameters: {
89
- type: "object",
90
- properties: {
91
- questions: {
92
- type: "array",
93
- description: "List of questions to ask",
94
- items: {
95
- type: "object",
96
- properties: {
97
- question: { type: "string" },
98
- type: { type: "string", enum: ["text", "select", "confirm"] },
99
- options: { type: "array", items: { type: "string" } },
100
- },
101
- },
102
- },
103
- },
104
- required: ["questions"],
105
- },
106
- execute: async (params: Record<string, unknown>, config?: any) => {
107
- const questions = params.questions as any[];
108
- const userId = config?.configurable?.user_id;
109
- const threadId = config?.configurable?.thread_id;
110
- // Use threadId (session) if available, then userId, then default
111
- // This must match the WebSocket sessionId used by the frontend
112
- const sessionId = threadId ? `canvas:${threadId}` : userId ? `canvas:${userId}` : "canvas:default";
113
-
114
- // Convert questions to form fields
115
- const fields = questions.map((q, idx) => ({
116
- name: `field_${idx}`,
117
- label: q.question,
118
- type: q.type === "select" ? "select" : q.type === "confirm" ? "text" : "text",
119
- required: true,
120
- options: q.options?.map((opt: string) => ({ label: opt, value: opt })),
121
- }));
122
-
123
- const formId = `form-${Date.now()}`;
124
-
125
- try {
126
- // Render form via canvasManager
127
- await canvasManager.render(sessionId, {
128
- id: formId,
129
- type: "form",
130
- props: {
131
- title: "Input Required",
132
- fields,
133
- },
134
- });
135
-
136
- // Wait for user interaction
137
- const response = await canvasManager.waitForInteraction(sessionId, formId, 300000);
138
-
139
- return {
140
- ok: true,
141
- message: "Form submitted by user",
142
- data: response,
143
- formId,
144
- };
145
- } catch (error) {
146
- return {
147
- ok: false,
148
- error: `Form interaction failed: ${(error as Error).message}`,
149
- formId,
150
- };
151
- }
152
- },
153
- };
154
-
155
- // ─── canvas_confirm ──────────────────────────────────────────────────────────
156
-
157
- export const canvasConfirmTool: Tool = {
158
- name: "canvas_confirm",
159
- description: "Show a confirmation dialog before executing an action. Spanish: confirmar acción, diálogo, aprobar",
160
- parameters: {
161
- type: "object",
162
- properties: {
163
- message: { type: "string", description: "Confirmation message" },
164
- action: { type: "string", description: "Action to confirm" },
165
- },
166
- required: ["message", "action"],
167
- },
168
- execute: async (params: Record<string, unknown>, config?: any) => {
169
- const message = params.message as string;
170
- const action = params.action as string;
171
-
172
- const confirmId = `confirm-${Date.now()}`;
173
-
174
- emitCanvas("canvas:render", {
175
- component: {
176
- id: confirmId,
177
- type: "alert-dialog",
178
- props: { title: action, description: message, confirmLabel: "Confirmar", cancelLabel: "Cancelar" },
179
- position: { x: 0, y: 0 },
180
- size: { width: 400, height: 200 },
181
- agentId: "agent",
182
- },
183
- });
184
-
185
- try {
186
- const interactionData = await waitForCanvasInteraction(confirmId, 300000) as any;
187
- removeCanvasComponent(confirmId);
188
- const confirmed = interactionData?.confirmed === true;
189
- return { ok: true, confirmed, action, message };
190
- } catch (error) {
191
- removeCanvasComponent(confirmId);
192
- return { ok: false, confirmed: false, error: (error as Error).message };
193
- }
194
- },
195
- };
196
-
197
- // ─── canvas_show_card ────────────────────────────────────────────────────────
198
-
199
- export const canvasShowCardTool: Tool = {
200
- name: "canvas_show_card",
201
- description: "Display structured information in card format. Spanish: mostrar tarjeta, card, información estructurada",
202
- parameters: {
203
- type: "object",
204
- properties: {
205
- title: { type: "string", description: "Card title" },
206
- content: { type: "string", description: "Card content (Markdown supported)" },
207
- items: {
208
- type: "array",
209
- description: "List of key-value items",
210
- items: {
211
- type: "object",
212
- properties: {
213
- label: { type: "string" },
214
- value: { type: "string" },
215
- },
216
- },
217
- },
218
- },
219
- required: ["title"],
220
- },
221
- execute: async (params: Record<string, unknown>) => {
222
- const title = params.title as string;
223
- const content = params.content as string | undefined;
224
- const items = (params.items as Array<{ label: string; value: string }>) || [];
225
-
226
- try {
227
- const id = `card_${Date.now()}`;
228
- emitCanvas("canvas:render", {
229
- component: {
230
- id,
231
- type: "card",
232
- props: {
233
- title,
234
- children: content ?? (items.length > 0 ? items.map((item) => `**${item.label}:** ${item.value}`).join("\n") : ""),
235
- // Pass items as table rows for richer rendering
236
- items,
237
- },
238
- position: { x: 0, y: 0 },
239
- size: { width: 320, height: 200 },
240
- agentId: "agent",
241
- },
242
- });
243
- return { ok: true, message: `Card "${title}" displayed.` };
244
- } catch (error) {
245
- return { ok: false, error: `Failed to display card: ${(error as Error).message }` };
246
- }
247
- },
248
- };
249
-
250
- // ─── canvas_show_progress ────────────────────────────────────────────────────
251
-
252
- export const canvasShowProgressTool: Tool = {
253
- name: "canvas_show_progress",
254
- description: "Show progress bar or status indicator. Spanish: barra de progreso, indicador, progreso visual",
255
- parameters: {
256
- type: "object",
257
- properties: {
258
- bars: {
259
- type: "array",
260
- description: "List of progress bars",
261
- items: {
262
- type: "object",
263
- properties: {
264
- label: { type: "string" },
265
- value: { type: "number", minimum: 0, maximum: 100 },
266
- },
267
- },
268
- },
269
- },
270
- required: ["bars"],
271
- },
272
- execute: async (params: Record<string, unknown>) => {
273
- const bars = params.bars as Array<{ label: string; value: number }>;
274
-
275
- try {
276
- // Render each bar as a separate progress component
277
- for (const bar of bars) {
278
- const id = `progress_${bar.label.replace(/\s+/g, "_")}_${Date.now()}`;
279
- emitCanvas("canvas:render", {
280
- component: {
281
- id,
282
- type: "progress",
283
- props: { value: bar.value, label: bar.label },
284
- position: { x: 0, y: 0 },
285
- size: { width: 320, height: 60 },
286
- agentId: "agent",
287
- },
288
- });
289
- }
290
- return { ok: true, message: "Progress displayed." };
291
- } catch (error) {
292
- return { ok: false, error: `Failed to display progress: ${(error as Error).message }` };
293
- }
294
- },
295
- };
296
-
297
- // ─── canvas_show_list ────────────────────────────────────────────────────────
298
-
299
- export const canvasShowListTool: Tool = {
300
- name: "canvas_show_list",
301
- description: "Display key-value list information. Spanish: lista clave-valor, mostrar lista, información en lista",
302
- parameters: {
303
- type: "object",
304
- properties: {
305
- title: { type: "string", description: "List title" },
306
- items: {
307
- type: "object",
308
- description: "Key-value pairs",
309
- additionalProperties: { type: "string" },
310
- },
311
- },
312
- required: ["title", "items"],
313
- },
314
- execute: async (params: Record<string, unknown>) => {
315
- const title = params.title as string;
316
- const items = params.items as Record<string, string>;
317
-
318
- try {
319
- const id = `list_${Date.now()}`;
320
- // Render as a table with key/value columns
321
- const columns = [{ header: "Campo", key: "key" }, { header: "Valor", key: "value" }];
322
- const data = Object.entries(items).map(([key, value]) => ({ key, value }));
323
-
324
- emitCanvas("canvas:render", {
325
- component: {
326
- id,
327
- type: "table",
328
- props: { title, columns, data },
329
- position: { x: 0, y: 0 },
330
- size: { width: 400, height: 300 },
331
- agentId: "agent",
332
- },
333
- });
334
- return { ok: true, message: `List "${title}" displayed.` };
335
- } catch (error) {
336
- return { ok: false, error: `Failed to display list: ${(error as Error).message }` };
337
- }
338
- },
339
- };
340
-
341
- // ─── canvas_clear ────────────────────────────────────────────────────────────
342
-
343
- export const canvasClearTool: Tool = {
344
- name: "canvas_clear",
345
- description: "Clear current canvas content. Spanish: limpiar canvas, borrar visualización, resetear",
346
- parameters: {
347
- type: "object",
348
- properties: {},
349
- },
350
- execute: async () => {
351
- try {
352
- emitCanvas("canvas:clear", {});
353
- return { ok: true, message: "Canvas cleared." };
354
- } catch (error) {
355
- return { ok: false, error: `Failed to clear canvas: ${(error as Error).message }` };
356
- }
357
- },
358
- };
359
-
360
- export function createTools(config?: Config): Tool[] {
361
- const a2uiConfig = config ?? {} as Config;
362
- return [
363
- canvasRenderTool,
364
- canvasAskTool,
365
- canvasConfirmTool,
366
- canvasShowCardTool,
367
- canvasShowProgressTool,
368
- canvasShowListTool,
369
- canvasClearTool,
370
- createA2UISurfaceTool(a2uiConfig),
371
- createA2UIUpdateComponentsTool(a2uiConfig),
372
- createA2UIUpdateDataModelTool(a2uiConfig),
373
- createA2UIDeleteSurfaceTool(a2uiConfig),
374
- ];
375
- }