@johpaz/hive-sdk 0.1.6 → 0.2.0

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 (185) hide show
  1. package/CHANGELOG.md +135 -0
  2. package/README.md +11 -1
  3. package/package.json +18 -2
  4. package/packages/core/src/agent/acceptance-checks.ts +9 -9
  5. package/packages/core/src/agent/agent-catalog.ts +3 -3
  6. package/packages/core/src/agent/agent-loop.ts +115 -26
  7. package/packages/core/src/agent/capability-search.ts +2 -2
  8. package/packages/core/src/agent/catalog-selector.ts +4 -4
  9. package/packages/core/src/agent/compaction.ts +10 -9
  10. package/packages/core/src/agent/context-compiler.ts +58 -34
  11. package/packages/core/src/agent/conversation-store.ts +31 -7
  12. package/packages/core/src/agent/curator.ts +4 -4
  13. package/packages/core/src/agent/delegation-runtime.ts +5 -5
  14. package/packages/core/src/agent/goal-runner.ts +9 -9
  15. package/packages/core/src/agent/index.ts +1 -0
  16. package/packages/core/src/agent/llm-client.ts +98 -37
  17. package/packages/core/src/agent/llm-providers/anthropic.ts +4 -4
  18. package/packages/core/src/agent/llm-providers/deepseek.ts +1 -1
  19. package/packages/core/src/agent/llm-providers/gemini.ts +4 -4
  20. package/packages/core/src/agent/llm-providers/groq.ts +1 -1
  21. package/packages/core/src/agent/llm-providers/hiveagents.ts +3 -3
  22. package/packages/core/src/agent/llm-providers/interface.ts +2 -2
  23. package/packages/core/src/agent/llm-providers/kimi.ts +1 -1
  24. package/packages/core/src/agent/llm-providers/minimax.ts +1 -1
  25. package/packages/core/src/agent/llm-providers/mistral.ts +1 -1
  26. package/packages/core/src/agent/llm-providers/modelscope.ts +1 -1
  27. package/packages/core/src/agent/llm-providers/nvidia.ts +1 -1
  28. package/packages/core/src/agent/llm-providers/ollama.ts +4 -4
  29. package/packages/core/src/agent/llm-providers/openai-compat-base.ts +9 -5
  30. package/packages/core/src/agent/llm-providers/openai.ts +1 -1
  31. package/packages/core/src/agent/llm-providers/opencode-go.ts +1 -1
  32. package/packages/core/src/agent/llm-providers/openrouter.ts +1 -1
  33. package/packages/core/src/agent/llm-providers/qwen.ts +1 -1
  34. package/packages/core/src/agent/llm-providers/z-ai.ts +1 -1
  35. package/packages/core/src/agent/mcp-result-normalizer.ts +192 -0
  36. package/packages/core/src/agent/playbook-selector.ts +4 -4
  37. package/packages/core/src/agent/prompt-builder.ts +5 -5
  38. package/packages/core/src/agent/proof-packet.ts +5 -5
  39. package/packages/core/src/agent/providers/index.ts +4 -4
  40. package/packages/core/src/agent/realtime-providers/gemini-live.ts +238 -0
  41. package/packages/core/src/agent/realtime-providers/index.ts +29 -0
  42. package/packages/core/src/agent/realtime-providers/interface.ts +108 -0
  43. package/packages/core/src/agent/reflector.ts +6 -6
  44. package/packages/core/src/agent/run-store.ts +8 -8
  45. package/packages/core/src/agent/service.ts +10 -10
  46. package/packages/core/src/agent/skill-selector.ts +6 -6
  47. package/packages/core/src/agent/thread-id.ts +71 -0
  48. package/packages/core/src/agent/thread-store.ts +250 -0
  49. package/packages/core/src/agent/tool-selector.ts +7 -5
  50. package/packages/core/src/agent/tracer.ts +5 -5
  51. package/packages/core/src/api/createAgent.ts +1 -1
  52. package/packages/core/src/artifacts/store.ts +84 -3
  53. package/packages/core/src/canvas/emitter.ts +2 -2
  54. package/packages/core/src/channels/telegram.ts +1 -1
  55. package/packages/core/src/channels/webchat.ts +1 -1
  56. package/packages/core/src/config/loader.ts +14 -5
  57. package/packages/core/src/events/agent-bus.ts +3 -3
  58. package/packages/core/src/events/channel-narration.ts +3 -3
  59. package/packages/core/src/events/event-bus.ts +1 -1
  60. package/packages/core/src/events/narration.ts +3 -3
  61. package/packages/core/src/gateway/delegation-groups.ts +4 -4
  62. package/packages/core/src/gateway/durable-queue.ts +5 -5
  63. package/packages/core/src/gateway/job-store.ts +5 -5
  64. package/packages/core/src/gateway/notification-inbox.ts +2 -2
  65. package/packages/core/src/gateway/server.ts +2 -2
  66. package/packages/core/src/mcp/MCPClient.ts +3 -3
  67. package/packages/core/src/mcp/hot-reload.ts +5 -5
  68. package/packages/core/src/mcp/tool-sync.ts +5 -5
  69. package/packages/core/src/mcp/transports/index.ts +2 -2
  70. package/packages/core/src/mcp/transports/sse.ts +1 -1
  71. package/packages/core/src/models/index.ts +36 -0
  72. package/packages/core/src/multimodal/index.ts +2 -2
  73. package/packages/core/src/multimodal/vision-service.ts +6 -6
  74. package/packages/core/src/plugins/loader.ts +4 -1
  75. package/packages/core/src/resilience/circuit-breaker.ts +16 -5
  76. package/packages/core/src/resilience/retry.ts +1 -1
  77. package/packages/core/src/scheduler/CronScheduler.ts +6 -6
  78. package/packages/core/src/scheduler/integration.ts +9 -9
  79. package/packages/core/src/sessions/index.ts +266 -0
  80. package/packages/core/src/storage/bootstrap.ts +34 -8
  81. package/packages/core/src/storage/causal-events.ts +1 -1
  82. package/packages/core/src/storage/collections.ts +32 -1
  83. package/packages/core/src/storage/crypto.ts +16 -2
  84. package/packages/core/src/storage/hive.ts +1 -1
  85. package/packages/core/src/storage/hivedb.ts +10 -1
  86. package/packages/core/src/storage/onboarding.ts +6 -6
  87. package/packages/core/src/storage/reconcile.ts +5 -5
  88. package/packages/core/src/storage/seed.ts +103 -13
  89. package/packages/core/src/storage/usage.ts +3 -3
  90. package/packages/core/src/swarm/AgentExecutor.ts +2 -2
  91. package/packages/core/src/swarm/Coordinator.ts +8 -8
  92. package/packages/core/src/swarm/EventBridge.ts +2 -2
  93. package/packages/core/src/swarm/RoleSwarm.ts +234 -0
  94. package/packages/core/src/swarm/TaskGraph.ts +2 -2
  95. package/packages/core/src/swarm/index.ts +7 -0
  96. package/packages/core/src/swarm/presets/HiveLearnPreset.ts +2 -2
  97. package/packages/core/src/swarm/presets/ResearchPreset.ts +2 -2
  98. package/packages/core/src/swarm/strategies/ParallelStrategy.ts +1 -1
  99. package/packages/core/src/swarm/strategies/PriorityStrategy.ts +3 -3
  100. package/packages/core/src/tools/ToolExecutor.ts +7 -3
  101. package/packages/core/src/tools/core/index.ts +2 -2
  102. package/packages/core/src/tools/cron/index.ts +4 -4
  103. package/packages/core/src/tools/web/artifact-inspect.ts +2 -2
  104. package/packages/core/src/tools/web/artifact-read.ts +162 -0
  105. package/packages/core/src/tools/web/browser-backend.ts +141 -44
  106. package/packages/core/src/tools/web/browser-click.ts +2 -2
  107. package/packages/core/src/tools/web/browser-extract.ts +2 -2
  108. package/packages/core/src/tools/web/browser-navigate.ts +2 -2
  109. package/packages/core/src/tools/web/browser-screenshot.ts +12 -5
  110. package/packages/core/src/tools/web/browser-script.ts +2 -2
  111. package/packages/core/src/tools/web/browser-service.ts +63 -384
  112. package/packages/core/src/tools/web/browser-session.ts +125 -0
  113. package/packages/core/src/tools/web/browser-type.ts +2 -2
  114. package/packages/core/src/tools/web/browser-wait.ts +2 -2
  115. package/packages/core/src/tools/web/computer-use.ts +553 -0
  116. package/packages/core/src/tools/web/index.ts +8 -1
  117. package/packages/core/src/tools/web/webview-backend.ts +460 -21
  118. package/packages/core/src/utils/index.ts +1 -0
  119. package/packages/core/src/utils/logger.ts +12 -4
  120. package/packages/core/src/utils/redact-binary.ts +17 -0
  121. package/packages/core/src/utils/toon.ts +1 -1
  122. package/packages/core/src/voice/index.ts +6 -6
  123. package/bun.lock +0 -859
  124. package/bunfig.toml +0 -9
  125. package/docs/API-AGENTS.md +0 -367
  126. package/docs/API-CONTEXT-COMPILER.md +0 -249
  127. package/docs/API-DAG-SCHEDULER.md +0 -273
  128. package/docs/API-TOOLS-SKILLS-CHANNELS.md +0 -446
  129. package/docs/API-WORKERS-EVENTS.md +0 -299
  130. package/docs/HIVE-HARNESS.md +0 -113
  131. package/docs/INDEX.md +0 -190
  132. package/docs/TEMPLATE-HIVE-APP.md +0 -360
  133. package/packages/cli/package.json +0 -17
  134. package/packages/cli/src/commands/create-app.test.ts +0 -180
  135. package/packages/core/package.json +0 -70
  136. package/packages/core/src/api/createAgent.test.ts +0 -160
  137. package/packages/core/src/canvas/canvas.test.ts +0 -36
  138. package/packages/core/src/channels/channels.test.ts +0 -18
  139. package/packages/core/src/ethics/EthicsGuard.test.ts +0 -108
  140. package/packages/core/src/gateway/gateway.test.ts +0 -38
  141. package/packages/core/src/memory/Scratchpad.test.ts +0 -68
  142. package/packages/core/src/scheduler/scheduler.test.ts +0 -15
  143. package/packages/core/src/skills/skills.test.ts +0 -62
  144. package/packages/core/src/swarm/swarm.test.ts +0 -24
  145. package/packages/core/src/tool-runtime/tool-runtime.test.ts +0 -99
  146. package/packages/core/src/tools/ToolRegistry.test.ts +0 -98
  147. package/packages/core/src/tools/api/api-request.test.ts +0 -164
  148. package/packages/core/src/tools/web/browser-service.test.ts +0 -83
  149. package/packages/core/src/workers/workers.test.ts +0 -41
  150. package/scripts/bump-version.ts +0 -248
  151. package/scripts/generate-skill-bundle.ts +0 -108
  152. package/test/acceptance-checks.test.ts +0 -403
  153. package/test/agent-loop-terminal-synthesis.test.ts +0 -32
  154. package/test/browser-backend.test.ts +0 -308
  155. package/test/catalog-agents-stay-enabled.test.ts +0 -117
  156. package/test/causal-events.test.ts +0 -117
  157. package/test/compaction.test.ts +0 -105
  158. package/test/context-compiler.test.ts +0 -269
  159. package/test/curator.test.ts +0 -130
  160. package/test/durable-queue.test.ts +0 -114
  161. package/test/harness-barrel.test.ts +0 -64
  162. package/test/hive-helpers.test.ts +0 -130
  163. package/test/hivedb-search.test.ts +0 -189
  164. package/test/internal-turns.test.ts +0 -166
  165. package/test/job-idempotency.test.ts +0 -68
  166. package/test/job-retry-backoff.test.ts +0 -184
  167. package/test/job-store.test.ts +0 -381
  168. package/test/llm-retry.test.ts +0 -97
  169. package/test/memory-perf.test.ts +0 -774
  170. package/test/minimal-loadout.test.ts +0 -78
  171. package/test/model-catalog.test.ts +0 -105
  172. package/test/preload.ts +0 -12
  173. package/test/reflector.test.ts +0 -320
  174. package/test/retention-cap.test.ts +0 -91
  175. package/test/retired-capabilities-pruned.test.ts +0 -192
  176. package/test/run-store.test.ts +0 -355
  177. package/test/scratchpad.test.ts +0 -74
  178. package/test/secrets-durability.test.ts +0 -119
  179. package/test/seed-model-reseed.test.ts +0 -155
  180. package/test/setup-agent-seed.test.ts +0 -264
  181. package/test/tool-inventory.test.ts +0 -65
  182. package/test/tool-runtime.test.ts +0 -258
  183. package/test/tool-selector-runtime-tools.test.ts +0 -117
  184. package/test/toon.test.ts +0 -429
  185. package/tsconfig.json +0 -42
@@ -1,258 +0,0 @@
1
- import { afterEach, describe, expect, it } from "bun:test"
2
- import { executeToolBatch, shutdownToolRuntime, type RuntimeTool, type ToolCallLike } from "../packages/core/src/tool-runtime/index.ts"
3
- import { loadConfig } from "../packages/core/src/config/loader.ts"
4
-
5
- const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms))
6
-
7
- function toolCall(id: string, name: string, args: unknown = {}): ToolCallLike {
8
- return {
9
- id,
10
- function: {
11
- name,
12
- arguments: JSON.stringify(args),
13
- },
14
- }
15
- }
16
-
17
- describe("tool runtime worker pool", () => {
18
- afterEach(() => {
19
- shutdownToolRuntime()
20
- })
21
-
22
- it("runs multiple tools in parallel through worker scheduling", async () => {
23
- const tools: RuntimeTool[] = ["slow_a", "slow_b", "slow_c"].map((name) => ({
24
- name,
25
- execute: async () => {
26
- await delay(120)
27
- return { name }
28
- },
29
- }))
30
-
31
- const startedAt = performance.now()
32
- const results = await executeToolBatch({
33
- toolCalls: [
34
- toolCall("1", "slow_a"),
35
- toolCall("2", "slow_b"),
36
- toolCall("3", "slow_c"),
37
- ],
38
- allTools: tools,
39
- toolConfig: {},
40
- hiveConfig: loadConfig(),
41
- workerPool: { enabled: true, maxWorkers: 3, toolTimeoutMs: 1000, parallelToolCalls: true },
42
- })
43
- const elapsed = performance.now() - startedAt
44
-
45
- expect(results.map((result) => (result.result as any).name)).toEqual(["slow_a", "slow_b", "slow_c"])
46
- expect(elapsed).toBeLessThan(260)
47
- })
48
-
49
- it("preserves input order when tools complete out of order", async () => {
50
- const tools: RuntimeTool[] = [
51
- { name: "first", execute: async () => { await delay(120); return { value: 1 } } },
52
- { name: "second", execute: async () => { await delay(20); return { value: 2 } } },
53
- { name: "third", execute: async () => { await delay(60); return { value: 3 } } },
54
- ]
55
-
56
- const results = await executeToolBatch({
57
- toolCalls: [toolCall("1", "first"), toolCall("2", "second"), toolCall("3", "third")],
58
- allTools: tools,
59
- toolConfig: {},
60
- hiveConfig: loadConfig(),
61
- workerPool: { enabled: true, maxWorkers: 3, toolTimeoutMs: 1000, parallelToolCalls: true },
62
- })
63
-
64
- expect(results.map((result) => result.toolName)).toEqual(["first", "second", "third"])
65
- expect(results.map((result) => (result.result as any).value)).toEqual([1, 2, 3])
66
- })
67
-
68
- it("isolates tool errors without cancelling sibling tools", async () => {
69
- const tools: RuntimeTool[] = [
70
- { name: "ok", execute: async () => ({ ok: true }) },
71
- { name: "fail", execute: async () => { throw new Error("boom") } },
72
- { name: "also_ok", execute: async () => ({ ok: "also" }) },
73
- ]
74
-
75
- const results = await executeToolBatch({
76
- toolCalls: [toolCall("1", "ok"), toolCall("2", "fail"), toolCall("3", "also_ok")],
77
- allTools: tools,
78
- toolConfig: {},
79
- hiveConfig: loadConfig(),
80
- workerPool: { enabled: true, maxWorkers: 3, toolTimeoutMs: 1000, parallelToolCalls: true },
81
- })
82
-
83
- expect(results[0].ok).toBe(true)
84
- expect(results[1].ok).toBe(false)
85
- expect((results[1].result as any).error).toBe(true)
86
- expect((results[1].result as any).message).toContain("boom")
87
- expect(results[2].ok).toBe(true)
88
- })
89
-
90
- it("routes non-reconstructible tools through main-thread RPC", async () => {
91
- let executedInMainThread = false
92
- const tools: RuntimeTool[] = [
93
- {
94
- name: "ExampleServer__live_tool",
95
- execute: async (params) => {
96
- executedInMainThread = true
97
- return { echoed: params.value }
98
- },
99
- },
100
- {
101
- name: "other_rpc_tool",
102
- execute: async () => ({ ok: true }),
103
- },
104
- ]
105
-
106
- const results = await executeToolBatch({
107
- toolCalls: [
108
- toolCall("1", "ExampleServer__live_tool", { value: "ok" }),
109
- toolCall("2", "other_rpc_tool"),
110
- ],
111
- allTools: tools,
112
- toolConfig: {},
113
- hiveConfig: loadConfig(),
114
- workerPool: { enabled: true, maxWorkers: 1, toolTimeoutMs: 1000, parallelToolCalls: true },
115
- })
116
-
117
- expect(executedInMainThread).toBe(true)
118
- expect(results[0].ok).toBe(true)
119
- expect(results[0].result).toEqual({ echoed: "ok" })
120
- })
121
-
122
- it("settles in-flight RPC work when the runtime shuts down", async () => {
123
- const tools: RuntimeTool[] = [
124
- {
125
- name: "ExampleServer__slow_live_tool",
126
- execute: async () => {
127
- await delay(100)
128
- return { late: true }
129
- },
130
- },
131
- { name: "other_rpc_tool", execute: async () => ({ ok: true }) },
132
- ]
133
-
134
- const pending = executeToolBatch({
135
- toolCalls: [
136
- toolCall("1", "ExampleServer__slow_live_tool"),
137
- toolCall("2", "other_rpc_tool"),
138
- ],
139
- allTools: tools,
140
- toolConfig: {},
141
- hiveConfig: loadConfig(),
142
- workerPool: { enabled: true, maxWorkers: 1, toolTimeoutMs: 1000, parallelToolCalls: true },
143
- })
144
-
145
- await delay(20)
146
- shutdownToolRuntime()
147
-
148
- const results = await pending
149
- expect(results.every((result) => result.aborted)).toBe(true)
150
- })
151
-
152
- it("routes singleton-backed native tools through main-thread RPC", async () => {
153
- const executed = new Set<string>()
154
- const tools: RuntimeTool[] = [
155
- "search_knowledge",
156
- "save_note",
157
- "memory_write",
158
- "task_status",
159
- "project_create",
160
- ].map((name) => ({
161
- name,
162
- execute: async () => {
163
- executed.add(name)
164
- return { name, mainThread: true }
165
- },
166
- }))
167
-
168
- const results = await executeToolBatch({
169
- toolCalls: [
170
- toolCall("1", "search_knowledge", { query: "A2UI" }),
171
- toolCall("2", "save_note", { key: "k", value: "v" }),
172
- toolCall("3", "memory_write", { key: "m", value: "v" }),
173
- toolCall("4", "task_status", { task_id: "t1" }),
174
- toolCall("5", "project_create", { name: "release" }),
175
- ],
176
- allTools: tools,
177
- toolConfig: {},
178
- hiveConfig: loadConfig(),
179
- workerPool: { enabled: true, maxWorkers: 2, toolTimeoutMs: 1000, parallelToolCalls: true },
180
- })
181
-
182
- expect(results.every((result) => result.ok)).toBe(true)
183
- expect(executed).toEqual(new Set(["search_knowledge", "save_note", "memory_write", "task_status", "project_create"]))
184
- expect(results.map((result) => (result.result as any).mainThread)).toEqual([true, true, true, true, true])
185
- })
186
-
187
- it("marks timed out tools and keeps completed tools", async () => {
188
- const tools: RuntimeTool[] = [
189
- { name: "fast", execute: async () => ({ done: true }) },
190
- { name: "timeout", execute: async () => { await delay(400); return { late: true } } },
191
- ]
192
-
193
- const results = await executeToolBatch({
194
- toolCalls: [toolCall("1", "fast"), toolCall("2", "timeout")],
195
- allTools: tools,
196
- toolConfig: {},
197
- hiveConfig: loadConfig(),
198
- workerPool: { enabled: true, maxWorkers: 2, toolTimeoutMs: 150, parallelToolCalls: true },
199
- })
200
-
201
- expect(results[0].ok).toBe(true)
202
- expect(results[1].ok).toBe(false)
203
- expect(results[1].timedOut).toBe(true)
204
- expect((results[1].result as any).error).toBe(true)
205
- })
206
-
207
- it("marks queued and running work as aborted", async () => {
208
- const controller = new AbortController()
209
- const tools: RuntimeTool[] = [
210
- { name: "slow_one", execute: async () => { await delay(200); return { done: 1 } } },
211
- { name: "slow_two", execute: async () => { await delay(200); return { done: 2 } } },
212
- ]
213
-
214
- setTimeout(() => controller.abort(), 30)
215
-
216
- const results = await executeToolBatch({
217
- toolCalls: [toolCall("1", "slow_one"), toolCall("2", "slow_two")],
218
- allTools: tools,
219
- toolConfig: {},
220
- hiveConfig: loadConfig(),
221
- workerPool: { enabled: true, maxWorkers: 1, toolTimeoutMs: 1000, parallelToolCalls: true },
222
- signal: controller.signal,
223
- })
224
-
225
- expect(results.every((result) => result.aborted)).toBe(true)
226
- expect(results.map((result) => result.toolName)).toEqual(["slow_one", "slow_two"])
227
- })
228
-
229
- it("passes toolConfig (including agent_id) through to a single tool call's config.configurable", async () => {
230
- // Single tool call → always the serial/main-thread path (executeToolBatch's
231
- // `toolCalls.length <= 1` branch) — exactly what task_delegate/agent_create/
232
- // bus_publish go through. Regression test for a real bug: toolConfig never
233
- // included agent_id, so config.configurable.agent_id was always undefined
234
- // inside every tool's execute() (task_delegate's parent-agent lookup always
235
- // failed as a result — see agent-loop.ts's toolConfig construction).
236
- let seenConfigurable: Record<string, unknown> | undefined;
237
- const tools: RuntimeTool[] = [
238
- {
239
- name: "whoami",
240
- execute: async (_params, config) => {
241
- seenConfigurable = config?.configurable;
242
- return { ok: true };
243
- },
244
- },
245
- ];
246
-
247
- await executeToolBatch({
248
- toolCalls: [toolCall("1", "whoami")],
249
- allTools: tools,
250
- toolConfig: { agent_id: "bee-coordinator", user_id: "u1", thread_id: "t1", channel: "webchat", workspace: "/tmp/ws" },
251
- hiveConfig: loadConfig(),
252
- });
253
-
254
- expect(seenConfigurable?.agent_id).toBe("bee-coordinator");
255
- expect(seenConfigurable?.user_id).toBe("u1");
256
- expect(seenConfigurable?.workspace).toBe("/tmp/ws");
257
- })
258
- })
@@ -1,117 +0,0 @@
1
- /**
2
- * tool-selector — las tools que sólo viven en la colección `tools`.
3
- *
4
- * `syncToolCatalogToIndex` construye el índice BM25 con CORE_TOOL_CATALOG **más**
5
- * las filas de la colección. `selectTools`, en cambio, resolvía los hits contra
6
- * `fullToolList`, que por defecto es sólo CORE_TOOL_CATALOG. Una tool registrada
7
- * en runtime podía salir primera en la búsqueda y aun así no llegar nunca al
8
- * modelo: el hit se descartaba en silencio, sin log ni error.
9
- *
10
- * Acá no se notaba porque todas las tools de hive están en el catálogo estático.
11
- * Se detectó en el SDK, donde las apps declaran tools con `defineTool`.
12
- *
13
- * Usa HIVE_DB_PATH=":memory:".
14
- */
15
-
16
- process.env.HIVE_DB_PATH = ":memory:";
17
-
18
- import { describe, test, expect, beforeEach, afterEach } from "bun:test";
19
- import { closeHiveDb } from "../packages/core/src/storage/hivedb";
20
- import { ensureHiveDb } from "../packages/core/src/storage/bootstrap";
21
- import { col } from "../packages/core/src/storage/hive";
22
- import type { ToolDoc } from "../packages/core/src/storage/collections";
23
- import { selectTools, syncToolCatalogToIndex } from "../packages/core/src/agent/tool-selector";
24
-
25
- /** Nombre y vocabulario deliberadamente ajenos al catálogo estático. */
26
- const RUNTIME_TOOL = "consultar_inventario_ferreteria";
27
- const QUERY = "necesito consultar el inventario de la ferretería";
28
-
29
- async function registerRuntimeTool(overrides: Partial<ToolDoc> = {}): Promise<void> {
30
- const tools = await col<ToolDoc>("tools");
31
- await tools.put(RUNTIME_TOOL, {
32
- id: RUNTIME_TOOL,
33
- name: RUNTIME_TOOL,
34
- description: "Consulta el inventario de la ferretería: stock, existencias y precios de artículos",
35
- category: "core",
36
- enabled: true,
37
- active: true,
38
- created_at: Date.now(),
39
- updated_at: Date.now(),
40
- ...overrides,
41
- });
42
- }
43
-
44
- beforeEach(async () => {
45
- closeHiveDb();
46
- await ensureHiveDb();
47
- });
48
-
49
- afterEach(() => {
50
- closeHiveDb();
51
- });
52
-
53
- describe("selectTools con tools registradas en runtime", () => {
54
- test("una tool que sólo está en la colección llega al modelo", async () => {
55
- await registerRuntimeTool();
56
- await syncToolCatalogToIndex();
57
-
58
- const selected = await selectTools(QUERY);
59
-
60
- expect(selected.map((t) => t.name)).toContain(RUNTIME_TOOL);
61
- });
62
-
63
- test("conserva la descripción de la fila — es lo que el modelo lee para decidir", async () => {
64
- await registerRuntimeTool();
65
- await syncToolCatalogToIndex();
66
-
67
- const tool = (await selectTools(QUERY)).find((t) => t.name === RUNTIME_TOOL);
68
-
69
- expect(tool?.description).toContain("inventario de la ferretería");
70
- });
71
-
72
- test("una tool deshabilitada no se ofrece aunque esté indexada", async () => {
73
- // El índice se construye desde la colección sin mirar `enabled`, así que la
74
- // única defensa es el filtro al resolver el hit.
75
- await registerRuntimeTool({ enabled: false });
76
- await syncToolCatalogToIndex();
77
-
78
- const selected = await selectTools(QUERY);
79
-
80
- expect(selected.map((t) => t.name)).not.toContain(RUNTIME_TOOL);
81
- });
82
-
83
- test("una tool inactiva tampoco se ofrece", async () => {
84
- await registerRuntimeTool({ active: false });
85
- await syncToolCatalogToIndex();
86
-
87
- const selected = await selectTools(QUERY);
88
-
89
- expect(selected.map((t) => t.name)).not.toContain(RUNTIME_TOOL);
90
- });
91
-
92
- test("un hit sin fila en la colección se descarta sin romper la selección", async () => {
93
- // El índice puede quedar con basura de una tool borrada; el resto del
94
- // loadout tiene que seguir funcionando.
95
- await registerRuntimeTool();
96
- await syncToolCatalogToIndex();
97
- await (await col<ToolDoc>("tools")).delete(RUNTIME_TOOL);
98
-
99
- const selected = await selectTools(QUERY);
100
-
101
- expect(selected.map((t) => t.name)).not.toContain(RUNTIME_TOOL);
102
- expect(Array.isArray(selected)).toBe(true);
103
- });
104
-
105
- test("no rompe la resolución de las tools del catálogo estático", async () => {
106
- await registerRuntimeTool();
107
- await syncToolCatalogToIndex();
108
-
109
- const selected = await selectTools("buscá en la web información sobre tarifas de envío");
110
-
111
- expect(selected.length).toBeGreaterThan(0);
112
- for (const tool of selected) {
113
- expect(tool.name).toBeString();
114
- expect(tool.description).toBeString();
115
- }
116
- });
117
- });