@johpaz/hive-sdk 0.1.3 → 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.
- package/CHANGELOG.md +97 -0
- package/README.md +78 -23
- package/bunfig.toml +4 -2
- package/docs/API-AGENTS.md +78 -27
- package/docs/API-CONTEXT-COMPILER.md +31 -34
- package/docs/API-TOOLS-SKILLS-CHANNELS.md +58 -22
- package/docs/HIVE-HARNESS.md +1 -1
- package/docs/INDEX.md +4 -4
- package/docs/TEMPLATE-HIVE-APP.md +10 -10
- package/package.json +9 -4
- package/packages/cli/package.json +2 -2
- package/packages/cli/src/commands/create-app.test.ts +36 -7
- package/packages/cli/src/commands/init.ts +3 -3
- package/packages/cli/src/commands/run.ts +1 -1
- package/packages/cli/src/commands/test.ts +37 -25
- package/packages/cli/src/commands/trace.ts +30 -28
- package/packages/cli/templates/hive-app/.env.example +10 -2
- package/packages/cli/templates/hive-app/README.md +103 -0
- package/packages/cli/templates/hive-app/hive.config.ts +9 -3
- package/packages/cli/templates/hive-app/src/agents/coordinator.ts +8 -1
- package/packages/cli/templates/hive-app/src/main.ts +12 -19
- package/packages/core/package.json +5 -4
- package/packages/core/src/agent/acceptance-checks.ts +166 -0
- package/packages/core/src/agent/agent-catalog.ts +348 -0
- package/packages/core/src/agent/agent-loop.ts +1373 -0
- package/packages/core/src/agent/capability-search.ts +186 -0
- package/packages/core/src/agent/catalog-selector.ts +103 -0
- package/packages/core/src/agent/{Compaction.ts → compaction.ts} +86 -63
- package/packages/core/src/agent/context-compiler.ts +689 -0
- package/packages/core/src/agent/conversation-store.ts +381 -0
- package/packages/core/src/agent/curator.ts +276 -0
- package/packages/core/src/agent/delegation-runtime.ts +241 -0
- package/packages/core/src/agent/goal-runner.ts +323 -0
- package/packages/core/src/agent/index.ts +17 -12
- package/packages/core/src/agent/llm-client.ts +266 -0
- package/packages/core/src/agent/llm-providers/anthropic.ts +264 -0
- package/packages/core/src/agent/llm-providers/deepseek.ts +8 -0
- package/packages/core/src/agent/{providers → llm-providers}/gemini.ts +98 -60
- package/packages/core/src/agent/llm-providers/groq.ts +5 -0
- package/packages/core/src/agent/llm-providers/hiveagents.ts +253 -0
- package/packages/core/src/agent/{providers → llm-providers}/interface.ts +73 -13
- package/packages/core/src/agent/llm-providers/kimi.ts +8 -0
- package/packages/core/src/agent/llm-providers/minimax.ts +13 -0
- package/packages/core/src/agent/llm-providers/mistral.ts +5 -0
- package/packages/core/src/agent/llm-providers/modelscope.ts +5 -0
- package/packages/core/src/agent/llm-providers/nvidia.ts +5 -0
- package/packages/core/src/agent/{providers → llm-providers}/ollama.ts +31 -5
- package/packages/core/src/agent/llm-providers/openai-compat-base.ts +418 -0
- package/packages/core/src/agent/llm-providers/openai.ts +5 -0
- package/packages/core/src/agent/llm-providers/opencode-go.ts +9 -0
- package/packages/core/src/agent/llm-providers/openrouter.ts +5 -0
- package/packages/core/src/agent/llm-providers/qwen.ts +5 -0
- package/packages/core/src/agent/llm-providers/z-ai.ts +5 -0
- package/packages/core/src/agent/minimal-loadout.ts +47 -0
- package/packages/core/src/agent/playbook-selector.ts +119 -0
- package/packages/core/src/agent/{PromptBuilder.ts → prompt-builder.ts} +21 -22
- package/packages/core/src/{harness → agent}/proof-packet.ts +16 -21
- package/packages/core/src/agent/providers/index.ts +35 -16
- package/packages/core/src/agent/reflector.ts +320 -0
- package/packages/core/src/agent/routing-intent.ts +22 -0
- package/packages/core/src/{harness → agent}/run-epoch.ts +4 -3
- package/packages/core/src/{harness → agent}/run-store.ts +142 -81
- package/packages/core/src/agent/{Service.ts → service.ts} +37 -26
- package/packages/core/src/agent/skill-selector.ts +374 -0
- package/packages/core/src/agent/stuck-loop.ts +209 -0
- package/packages/core/src/agent/{selectors/ToolSelector.ts → tool-selector.ts} +188 -178
- package/packages/core/src/{ace/Tracer.ts → agent/tracer.ts} +37 -27
- package/packages/core/src/api/createAgent.test.ts +139 -27
- package/packages/core/src/api/createAgent.ts +232 -44
- package/packages/core/src/artifacts/store.ts +162 -0
- package/packages/core/src/canvas/canvas-manager.ts +161 -0
- package/packages/core/src/canvas/canvas.test.ts +8 -4
- package/packages/core/src/canvas/emitter.ts +131 -80
- package/packages/core/src/canvas/index.ts +1 -3
- package/packages/core/src/channels/base.ts +9 -1
- package/packages/core/src/channels/discord.ts +5 -4
- package/packages/core/src/channels/manager.ts +122 -30
- package/packages/core/src/channels/slack.ts +5 -4
- package/packages/core/src/channels/telegram.ts +36 -6
- package/packages/core/src/channels/webchat.ts +11 -10
- package/packages/core/src/channels/whatsapp.ts +23 -7
- package/packages/core/src/config/index.ts +13 -2
- package/packages/core/src/config/loader.ts +71 -29
- package/packages/core/src/ethics/EthicsGuard.test.ts +90 -36
- package/packages/core/src/ethics/EthicsGuard.ts +51 -47
- package/packages/core/src/events/agent-bus.ts +44 -68
- package/packages/core/src/events/channel-narration.ts +150 -0
- package/packages/core/src/events/narration.ts +82 -0
- package/packages/core/src/events/tool-narration.ts +62 -0
- package/packages/core/src/gateway/delegation-groups.ts +258 -0
- package/packages/core/src/{harness → gateway}/durable-queue.ts +102 -42
- package/packages/core/src/{harness → gateway}/job-store.ts +85 -48
- package/packages/core/src/gateway/lane-queue.ts +173 -0
- package/packages/core/src/gateway/notification-inbox.ts +57 -0
- package/packages/core/src/gateway/server.ts +1 -1
- package/packages/core/src/harness/index.ts +46 -27
- package/packages/core/src/index.ts +33 -20
- package/packages/core/src/mcp/hot-reload.ts +32 -23
- package/packages/core/src/mcp/index.ts +6 -3
- package/packages/core/src/mcp/singleton.ts +1 -4
- package/packages/core/src/mcp/tool-sync.ts +138 -0
- package/packages/core/src/memory/Scratchpad.test.ts +39 -20
- package/packages/core/src/memory/Scratchpad.ts +27 -34
- package/packages/core/src/multimodal/vision-service.ts +44 -38
- package/packages/core/src/resilience/retry.ts +95 -0
- package/packages/core/src/scheduler/CronScheduler.ts +334 -287
- package/packages/core/src/scheduler/index.ts +9 -7
- package/packages/core/src/scheduler/integration.ts +46 -26
- package/packages/core/src/scheduler/scheduler.test.ts +9 -13
- package/packages/core/src/scheduler/types.ts +7 -2
- package/packages/core/src/security/Pairing.ts +1 -1
- package/packages/core/src/skills/bundled/a2ui/a2ui_dashboard/SKILL.md +176 -0
- package/packages/core/src/skills/bundled/a2ui/a2ui_form/SKILL.md +202 -0
- package/packages/core/src/skills/bundled/a2ui/a2ui_interactive/SKILL.md +206 -0
- package/packages/core/src/skills/bundled/agents/agent_spawner/SKILL.md +173 -0
- package/packages/core/src/skills/bundled/agents/memory_manager/SKILL.md +143 -0
- package/packages/core/src/skills/bundled/agents/research_and_remember/SKILL.md +139 -0
- package/packages/core/src/skills/bundled/agents/task_orchestrator/SKILL.md +98 -0
- package/packages/core/src/skills/bundled/api/api_client/SKILL.md +132 -0
- package/packages/core/src/skills/bundled/cli/cli_pipeline/SKILL.md +135 -0
- package/packages/core/src/skills/bundled/cli/cli_safe_exec/SKILL.md +125 -0
- package/packages/core/src/skills/bundled/cli/software_engineering/SKILL.md +23 -0
- package/packages/core/src/skills/bundled/cron_manager/SKILL.md +188 -0
- package/packages/core/src/skills/bundled/cron_reminder/SKILL.md +112 -0
- package/packages/core/src/skills/bundled/filesystem/file_manager/SKILL.md +118 -0
- package/packages/core/src/skills/bundled/filesystem/file_read_and_summarize/SKILL.md +109 -0
- package/packages/core/src/skills/bundled/filesystem/file_writer/SKILL.md +129 -0
- package/packages/core/src/skills/bundled/filesystem/workspace_file_operator/SKILL.md +22 -0
- package/packages/core/src/skills/bundled/office/office_document_manager/SKILL.md +262 -0
- package/packages/core/src/skills/bundled/search_knowledge/capability_discovery/SKILL.md +75 -0
- package/packages/core/src/skills/bundled/web/browser_automate/SKILL.md +120 -0
- package/packages/core/src/skills/bundled/web/browser_scrape/SKILL.md +109 -0
- package/packages/core/src/skills/bundled/web/web_monitor/SKILL.md +127 -0
- package/packages/core/src/skills/bundled/web/web_research/SKILL.md +119 -0
- package/packages/core/src/skills/bundled-data.generated.ts +731 -2678
- package/packages/core/src/skills/skills.test.ts +52 -11
- package/packages/core/src/{harness → storage}/boot-id.ts +5 -2
- package/packages/core/src/storage/bootstrap.ts +151 -0
- package/packages/core/src/storage/causal-events.ts +84 -0
- package/packages/core/src/storage/collections.ts +680 -0
- package/packages/core/src/storage/crypto.ts +205 -74
- package/packages/core/src/{harness/db-helpers.ts → storage/hive.ts} +63 -7
- package/packages/core/src/storage/hivedb.ts +61 -0
- package/packages/core/src/storage/index.ts +111 -17
- package/packages/core/src/storage/model-id.ts +53 -0
- package/packages/core/src/storage/onboarding.ts +540 -972
- package/packages/core/src/storage/reconcile.ts +238 -0
- package/packages/core/src/storage/seed.ts +572 -406
- package/packages/core/src/storage/usage.ts +285 -225
- package/packages/core/src/storage/user-email.ts +11 -0
- package/packages/core/src/swarm/AgentExecutor.ts +1 -1
- package/packages/core/src/swarm/EventBridge.ts +1 -1
- package/packages/core/src/swarm/index.ts +12 -9
- package/packages/core/src/tool-runtime/index.ts +146 -23
- package/packages/core/src/tool-runtime/tool-worker.ts +2 -2
- package/packages/core/src/tool-runtime/worker-tools.ts +27 -0
- package/packages/core/src/{canvas/a2ui-tools.ts → tools/a2ui/index.ts} +17 -8
- package/packages/core/src/tools/agents/get-available-models.ts +36 -54
- package/packages/core/src/tools/agents/index.ts +784 -292
- package/packages/core/src/tools/api/api-request.test.ts +164 -0
- package/packages/core/src/tools/api/api-request.ts +174 -0
- package/packages/core/src/tools/api/index.ts +16 -0
- package/packages/core/src/tools/cli/index.ts +4 -0
- package/packages/core/src/tools/core/index.ts +281 -112
- package/packages/core/src/tools/cron/index.ts +121 -124
- package/packages/core/src/tools/index.ts +63 -78
- package/packages/core/src/tools/office/office-escribir-xlsx.ts +3 -1
- package/packages/core/src/tools/types.ts +3 -1
- package/packages/core/src/tools/web/artifact-inspect.ts +23 -0
- package/packages/core/src/tools/web/browser-screenshot.ts +26 -5
- package/packages/core/src/tools/web/browser-service.ts +5 -0
- package/packages/core/src/tools/web/browser-type.ts +3 -8
- package/packages/core/src/tools/web/index.ts +4 -4
- package/packages/core/src/voice/index.ts +89 -63
- package/packages/core/src/workers/agent.worker.ts +2 -2
- package/packages/core/src/workers/workers.test.ts +3 -10
- package/scripts/bump-version.ts +248 -0
- package/scripts/generate-skill-bundle.ts +108 -0
- package/test/agent-loop-terminal-synthesis.test.ts +32 -0
- package/test/catalog-agents-stay-enabled.test.ts +117 -0
- package/test/causal-events.test.ts +117 -0
- package/test/compaction.test.ts +105 -0
- package/test/context-compiler.test.ts +269 -0
- package/test/curator.test.ts +130 -0
- package/test/durable-queue.test.ts +114 -0
- package/test/harness-barrel.test.ts +64 -0
- package/test/hive-helpers.test.ts +130 -0
- package/test/hivedb-search.test.ts +189 -0
- package/test/internal-turns.test.ts +166 -0
- package/test/job-idempotency.test.ts +68 -0
- package/test/job-retry-backoff.test.ts +184 -0
- package/test/job-store.test.ts +381 -0
- package/test/llm-retry.test.ts +97 -0
- package/test/memory-perf.test.ts +774 -0
- package/test/minimal-loadout.test.ts +78 -0
- package/test/model-catalog.test.ts +105 -0
- package/test/preload.ts +12 -0
- package/test/reflector.test.ts +320 -0
- package/test/retention-cap.test.ts +91 -0
- package/test/retired-capabilities-pruned.test.ts +192 -0
- package/test/run-store.test.ts +355 -0
- package/test/scratchpad.test.ts +74 -0
- package/test/secrets-durability.test.ts +119 -0
- package/test/seed-model-reseed.test.ts +155 -0
- package/test/setup-agent-seed.test.ts +264 -0
- package/test/tool-inventory.test.ts +65 -0
- package/test/tool-runtime.test.ts +258 -0
- package/test/toon.test.ts +429 -0
- package/tsconfig.json +2 -0
- package/packages/core/src/ace/Curator.ts +0 -158
- package/packages/core/src/ace/Reflector.ts +0 -200
- package/packages/core/src/ace/index.ts +0 -4
- package/packages/core/src/agent/AgentRunner.ts +0 -711
- package/packages/core/src/agent/ContextCompiler.ts +0 -567
- package/packages/core/src/agent/ContextGuard.ts +0 -91
- package/packages/core/src/agent/ConversationStore.ts +0 -254
- package/packages/core/src/agent/Hooks.ts +0 -166
- package/packages/core/src/agent/StuckLoop.ts +0 -133
- package/packages/core/src/agent/providers/LLMClient.ts +0 -149
- package/packages/core/src/agent/providers/anthropic.ts +0 -212
- package/packages/core/src/agent/providers/openai-compat.ts +0 -231
- package/packages/core/src/agent/selectors/PlaybookSelector.ts +0 -121
- package/packages/core/src/agent/selectors/SkillSelector.ts +0 -322
- package/packages/core/src/agent/selectors/index.ts +0 -6
- package/packages/core/src/auth/auth.ts +0 -121
- package/packages/core/src/auth/index.ts +0 -1
- package/packages/core/src/canvas/CanvasManager.ts +0 -390
- package/packages/core/src/canvas/canvas-tools.ts +0 -448
- package/packages/core/src/harness/collections.ts +0 -98
- package/packages/core/src/harness/goal-verifier.ts +0 -141
- package/packages/core/src/harness/harness.test.ts +0 -236
- package/packages/core/src/harness/reconcile.ts +0 -149
- package/packages/core/src/mcp/MCPToolAdapter.ts +0 -176
- package/packages/core/src/multimodal/VisionService.ts +0 -293
- package/packages/core/src/scheduler/dag/AgentExecutor.ts +0 -53
- package/packages/core/src/scheduler/dag/DAGScheduler.ts +0 -250
- package/packages/core/src/scheduler/dag/EventBridge.ts +0 -122
- package/packages/core/src/scheduler/dag/TaskGraph.ts +0 -192
- package/packages/core/src/scheduler/dag/TaskNode.ts +0 -97
- package/packages/core/src/scheduler/dag/TaskResult.ts +0 -22
- package/packages/core/src/scheduler/dag/errors.ts +0 -37
- package/packages/core/src/scheduler/dag/index.ts +0 -26
- package/packages/core/src/scheduler/dag/presets/ResearchPreset.ts +0 -97
- package/packages/core/src/scheduler/dag/strategies/ParallelStrategy.ts +0 -21
- package/packages/core/src/scheduler/dag/strategies/PriorityStrategy.ts +0 -46
- package/packages/core/src/storage/HiveDBStorage.ts +0 -64
- package/packages/core/src/storage/SQLiteStorage.ts +0 -414
- package/packages/core/src/storage/hiveSeed.ts +0 -308
- package/packages/core/src/storage/hiveStorage.test.ts +0 -38
- package/packages/core/src/storage/schema.ts +0 -689
- package/packages/core/src/storage/storage.test.ts +0 -37
- package/packages/core/src/swarm/AgentBus.ts +0 -460
- package/packages/core/src/swarm/EventBus.ts +0 -169
- package/packages/core/src/swarm/WorkerPool.ts +0 -236
- package/packages/core/src/tools/bridge-events.ts +0 -26
- package/packages/core/src/tools/canvas/index.ts +0 -375
- package/packages/core/src/tools/codebridge/index.ts +0 -342
- package/packages/core/src/tools/meeting/index.ts +0 -353
- package/packages/core/src/tools/projects/index.ts +0 -37
- package/packages/core/src/tools/projects/project-create.ts +0 -94
- package/packages/core/src/tools/projects/project-done.ts +0 -66
- package/packages/core/src/tools/projects/project-fail.ts +0 -66
- package/packages/core/src/tools/projects/project-list.ts +0 -96
- package/packages/core/src/tools/projects/project-update.ts +0 -72
- package/packages/core/src/tools/projects/task-create.ts +0 -68
- package/packages/core/src/tools/projects/task-evaluate.ts +0 -93
- package/packages/core/src/tools/projects/task-update.ts +0 -93
- package/packages/core/src/tools/voice/index.ts +0 -104
- package/packages/core/src/tools/web/api-request.test.ts +0 -170
- package/packages/core/src/tools/web/api-request.ts +0 -239
- package/test/setup-db.ts +0 -216
- /package/packages/core/src/agent/{NativeTools.ts → native-tools.ts} +0 -0
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { existsSync } from "node:fs"
|
|
2
2
|
import { fileURLToPath } from "node:url"
|
|
3
|
+
import { dirname, join } from "node:path"
|
|
3
4
|
import { availableParallelism } from "node:os"
|
|
4
5
|
import type { Config } from "../config/loader.ts"
|
|
5
6
|
import { loadConfig } from "../config/loader.ts"
|
|
@@ -15,6 +16,8 @@ export type ToolCallLike = {
|
|
|
15
16
|
export type RuntimeTool = {
|
|
16
17
|
name: string
|
|
17
18
|
execute?: (params: Record<string, unknown>, config?: any) => Promise<unknown>
|
|
19
|
+
/** Per-tool timeout (ms) override from the Tool definition. */
|
|
20
|
+
timeoutMs?: number
|
|
18
21
|
}
|
|
19
22
|
|
|
20
23
|
export type ToolRuntimeConfig = {
|
|
@@ -32,6 +35,12 @@ export type ExecuteToolBatchOptions = {
|
|
|
32
35
|
thread_id?: string
|
|
33
36
|
channel?: string
|
|
34
37
|
workspace?: string | null
|
|
38
|
+
/** The currently-running agent's own id (agent-loop.ts's opts.agentId) — read by tools that need to know who's calling them (task_delegate's parent lookup, agent_create's parent_id, bus_publish's sender). */
|
|
39
|
+
agent_id?: string
|
|
40
|
+
run_id?: string
|
|
41
|
+
turn_id?: string
|
|
42
|
+
task_id?: string
|
|
43
|
+
session_id?: string
|
|
35
44
|
}
|
|
36
45
|
hiveConfig?: Config
|
|
37
46
|
workerPool?: ToolRuntimeConfig
|
|
@@ -110,8 +119,28 @@ function resolveWorkerEntry(): string {
|
|
|
110
119
|
}
|
|
111
120
|
}
|
|
112
121
|
|
|
122
|
+
const fallbacks: string[] = []
|
|
123
|
+
const envPath = process.env.HIVE_TOOL_WORKER_PATH
|
|
124
|
+
if (envPath) fallbacks.push(envPath)
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
const execDir = dirname(process.execPath)
|
|
128
|
+
fallbacks.push(join(execDir, "tool-worker.js"))
|
|
129
|
+
fallbacks.push(join(execDir, "packages", "core", "src", "tool-runtime", "tool-worker.js"))
|
|
130
|
+
} catch {
|
|
131
|
+
// process.execPath is not available — skip execDir-based fallbacks
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
fallbacks.push("/app/tool-worker.js")
|
|
135
|
+
|
|
136
|
+
for (const filePath of fallbacks) {
|
|
137
|
+
if (existsSync(filePath)) {
|
|
138
|
+
return filePath
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
113
142
|
throw new Error(
|
|
114
|
-
`Tool worker entry not found. Tried: ${candidates.map((candidate) => fileURLToPath(candidate)).join(", ")}`
|
|
143
|
+
`Tool worker entry not found. Tried: ${[...candidates.map((candidate) => fileURLToPath(candidate)), ...fallbacks].join(", ")}`
|
|
115
144
|
)
|
|
116
145
|
}
|
|
117
146
|
|
|
@@ -139,7 +168,7 @@ function toolErrorResult(
|
|
|
139
168
|
}
|
|
140
169
|
|
|
141
170
|
const DEFAULT_MAIN_THREAD_TOOL_NAMES = new Set([
|
|
142
|
-
// These tools depend on process-local singleton state (
|
|
171
|
+
// These tools depend on process-local singleton state (HiveDB handle, live
|
|
143
172
|
// channel senders, schedulers, browser sessions, or in-memory services).
|
|
144
173
|
"search_knowledge",
|
|
145
174
|
"save_note",
|
|
@@ -155,24 +184,14 @@ const DEFAULT_MAIN_THREAD_TOOL_NAMES = new Set([
|
|
|
155
184
|
"bus_publish",
|
|
156
185
|
"bus_read",
|
|
157
186
|
"get_available_models",
|
|
158
|
-
"meeting_start",
|
|
159
|
-
"meeting_add_segment",
|
|
160
|
-
"meeting_stop",
|
|
161
|
-
"meeting_report",
|
|
162
187
|
"browser_navigate",
|
|
163
188
|
"browser_screenshot",
|
|
189
|
+
"artifact_inspect",
|
|
164
190
|
"browser_click",
|
|
165
191
|
"browser_type",
|
|
166
192
|
"browser_extract",
|
|
167
193
|
"browser_script",
|
|
168
194
|
"browser_wait",
|
|
169
|
-
"canvas_render",
|
|
170
|
-
"canvas_ask",
|
|
171
|
-
"canvas_confirm",
|
|
172
|
-
"canvas_show_card",
|
|
173
|
-
"canvas_show_progress",
|
|
174
|
-
"canvas_show_list",
|
|
175
|
-
"canvas_clear",
|
|
176
195
|
"a2ui_create_surface",
|
|
177
196
|
"a2ui_update_components",
|
|
178
197
|
"a2ui_update_data_model",
|
|
@@ -188,15 +207,14 @@ const DEFAULT_MAIN_THREAD_TOOL_NAMES = new Set([
|
|
|
188
207
|
"notify",
|
|
189
208
|
"report_progress",
|
|
190
209
|
"task_delegate",
|
|
191
|
-
"
|
|
192
|
-
"voice_transcribe",
|
|
193
|
-
"voice_speak",
|
|
210
|
+
"task_list",
|
|
194
211
|
])
|
|
195
212
|
|
|
196
213
|
async function executeInMainThread(job: {
|
|
197
214
|
toolCall: ToolCallLike
|
|
198
215
|
allTools: RuntimeTool[]
|
|
199
216
|
toolConfig: ExecuteToolBatchOptions["toolConfig"]
|
|
217
|
+
signal?: AbortSignal
|
|
200
218
|
}): Promise<unknown> {
|
|
201
219
|
const toolName = job.toolCall.function.name
|
|
202
220
|
const tool = job.allTools.find((candidate) => candidate.name === toolName)
|
|
@@ -208,16 +226,36 @@ async function executeInMainThread(job: {
|
|
|
208
226
|
const args = typeof job.toolCall.function.arguments === "string"
|
|
209
227
|
? JSON.parse(job.toolCall.function.arguments)
|
|
210
228
|
: job.toolCall.function.arguments
|
|
211
|
-
return await tool.execute((args ?? {}) as Record<string, unknown>, { configurable: job.toolConfig })
|
|
229
|
+
return await tool.execute((args ?? {}) as Record<string, unknown>, { configurable: job.toolConfig, signal: job.signal })
|
|
212
230
|
} catch (error) {
|
|
213
231
|
return toolErrorResult(toolName, (error as Error).message)
|
|
214
232
|
}
|
|
215
233
|
}
|
|
216
234
|
|
|
235
|
+
/**
|
|
236
|
+
* Bounds a single tool execution to its own timeout window (per-operation, not
|
|
237
|
+
* an aggregate turn deadline). A slow tool loses its race and yields a normal
|
|
238
|
+
* error result — the underlying promise is left to settle on its own (main-thread
|
|
239
|
+
* tools have no cross-realm handle to kill), but the caller is freed to move on.
|
|
240
|
+
*/
|
|
241
|
+
export function executeInMainThreadWithTimeout(
|
|
242
|
+
job: { toolCall: ToolCallLike; allTools: RuntimeTool[]; toolConfig: ExecuteToolBatchOptions["toolConfig"]; signal?: AbortSignal },
|
|
243
|
+
timeoutMs: number,
|
|
244
|
+
): Promise<unknown> {
|
|
245
|
+
const toolName = job.toolCall.function.name
|
|
246
|
+
return Promise.race([
|
|
247
|
+
executeInMainThread(job),
|
|
248
|
+
new Promise<unknown>((resolve) => {
|
|
249
|
+
setTimeout(() => resolve(toolErrorResult(toolName, `Tool execution timed out after ${timeoutMs}ms`)), timeoutMs)
|
|
250
|
+
}),
|
|
251
|
+
])
|
|
252
|
+
}
|
|
253
|
+
|
|
217
254
|
class ToolWorkerPool {
|
|
218
255
|
private workers: WorkerSlot[] = []
|
|
219
256
|
private queue: QueuedJob[] = []
|
|
220
257
|
private readonly maxWorkers: number
|
|
258
|
+
private disposed = false
|
|
221
259
|
|
|
222
260
|
constructor(maxWorkers: number) {
|
|
223
261
|
this.maxWorkers = Math.max(1, maxWorkers)
|
|
@@ -225,6 +263,18 @@ class ToolWorkerPool {
|
|
|
225
263
|
|
|
226
264
|
execute(job: Omit<QueuedJob, "resolve" | "settled" | "startedAt">): Promise<ToolBatchResult> {
|
|
227
265
|
return new Promise((resolve) => {
|
|
266
|
+
if (this.disposed) {
|
|
267
|
+
resolve({
|
|
268
|
+
toolCall: job.toolCall,
|
|
269
|
+
toolName: job.toolCall.function.name,
|
|
270
|
+
result: toolErrorResult(job.toolCall.function.name, "Tool runtime shut down"),
|
|
271
|
+
ok: false,
|
|
272
|
+
durationMs: 0,
|
|
273
|
+
error: { name: "AbortError", message: "Tool runtime shut down" },
|
|
274
|
+
aborted: true,
|
|
275
|
+
})
|
|
276
|
+
return
|
|
277
|
+
}
|
|
228
278
|
this.queue.push({
|
|
229
279
|
...job,
|
|
230
280
|
resolve,
|
|
@@ -272,14 +322,48 @@ class ToolWorkerPool {
|
|
|
272
322
|
}
|
|
273
323
|
|
|
274
324
|
dispose(): void {
|
|
325
|
+
this.disposed = true
|
|
326
|
+
const reason = "Tool runtime shut down"
|
|
327
|
+
|
|
328
|
+
for (const job of this.queue) {
|
|
329
|
+
if (job.settled) continue
|
|
330
|
+
job.settled = true
|
|
331
|
+
job.resolve({
|
|
332
|
+
toolCall: job.toolCall,
|
|
333
|
+
toolName: job.toolCall.function.name,
|
|
334
|
+
result: toolErrorResult(job.toolCall.function.name, reason),
|
|
335
|
+
ok: false,
|
|
336
|
+
durationMs: 0,
|
|
337
|
+
error: { name: "AbortError", message: reason },
|
|
338
|
+
aborted: true,
|
|
339
|
+
})
|
|
340
|
+
}
|
|
341
|
+
this.queue = []
|
|
342
|
+
|
|
275
343
|
for (const slot of this.workers) {
|
|
344
|
+
const job = slot.job
|
|
345
|
+
if (job && !job.settled) {
|
|
346
|
+
job.settled = true
|
|
347
|
+
if (job.timer) clearTimeout(job.timer)
|
|
348
|
+
job.resolve({
|
|
349
|
+
toolCall: job.toolCall,
|
|
350
|
+
toolName: job.toolCall.function.name,
|
|
351
|
+
result: toolErrorResult(job.toolCall.function.name, reason),
|
|
352
|
+
ok: false,
|
|
353
|
+
durationMs: Math.round(performance.now() - job.startedAt),
|
|
354
|
+
error: { name: "AbortError", message: reason },
|
|
355
|
+
aborted: true,
|
|
356
|
+
})
|
|
357
|
+
}
|
|
358
|
+
slot.job = undefined
|
|
359
|
+
slot.busy = false
|
|
276
360
|
slot.worker.terminate()
|
|
277
361
|
}
|
|
278
362
|
this.workers = []
|
|
279
|
-
this.queue = []
|
|
280
363
|
}
|
|
281
364
|
|
|
282
365
|
private drain(): void {
|
|
366
|
+
if (this.disposed) return
|
|
283
367
|
while (this.queue.length > 0) {
|
|
284
368
|
const slot = this.getIdleSlot()
|
|
285
369
|
if (!slot) return
|
|
@@ -381,6 +465,7 @@ class ToolWorkerPool {
|
|
|
381
465
|
): Promise<void> {
|
|
382
466
|
const job = slot.job
|
|
383
467
|
if (!job || job.id !== message.jobId || job.settled) return
|
|
468
|
+
const worker = slot.worker
|
|
384
469
|
|
|
385
470
|
try {
|
|
386
471
|
const result = await executeInMainThread({
|
|
@@ -394,9 +479,15 @@ class ToolWorkerPool {
|
|
|
394
479
|
allTools: job.allTools,
|
|
395
480
|
toolConfig: job.toolConfig,
|
|
396
481
|
})
|
|
397
|
-
slot.
|
|
482
|
+
if (this.disposed || slot.job !== job || job.settled || slot.worker !== worker) return
|
|
483
|
+
worker.postMessage({ type: "rpc_result", rpcId: message.rpcId, ok: true, result })
|
|
398
484
|
} catch (error) {
|
|
399
|
-
slot.
|
|
485
|
+
if (this.disposed || slot.job !== job || job.settled || slot.worker !== worker) return
|
|
486
|
+
try {
|
|
487
|
+
worker.postMessage({ type: "rpc_result", rpcId: message.rpcId, ok: false, error: serializeError(error) })
|
|
488
|
+
} catch {
|
|
489
|
+
// El worker pudo terminar entre la comprobación y el envío.
|
|
490
|
+
}
|
|
400
491
|
}
|
|
401
492
|
}
|
|
402
493
|
|
|
@@ -439,6 +530,26 @@ function resolveRuntimeConfig(config?: ToolRuntimeConfig): Required<ToolRuntimeC
|
|
|
439
530
|
}
|
|
440
531
|
}
|
|
441
532
|
|
|
533
|
+
/**
|
|
534
|
+
* Resolve the effective timeout (ms) for a single tool call.
|
|
535
|
+
* Priority: Tool.timeoutMs → config.tools.timeouts[name] → workerPool.toolTimeoutMs.
|
|
536
|
+
*/
|
|
537
|
+
function resolveToolTimeout(
|
|
538
|
+
toolName: string,
|
|
539
|
+
allTools: RuntimeTool[],
|
|
540
|
+
hiveConfig: Config,
|
|
541
|
+
baseTimeoutMs: number,
|
|
542
|
+
): number {
|
|
543
|
+
// 1. Tool definition timeoutMs (carried on the RuntimeTool via ContextTool cast)
|
|
544
|
+
const def = allTools.find((t) => t.name === toolName)
|
|
545
|
+
if (def?.timeoutMs && def.timeoutMs > 0) return def.timeoutMs
|
|
546
|
+
// 2. config.tools.timeouts[name]
|
|
547
|
+
const cfgOverride = hiveConfig?.tools?.timeouts?.[toolName]
|
|
548
|
+
if (typeof cfgOverride === "number" && cfgOverride > 0) return cfgOverride
|
|
549
|
+
// 3. base (workerPool.toolTimeoutMs)
|
|
550
|
+
return baseTimeoutMs
|
|
551
|
+
}
|
|
552
|
+
|
|
442
553
|
function getPool(maxWorkers: number): ToolWorkerPool {
|
|
443
554
|
if (!sharedPool || sharedPoolSize !== maxWorkers) {
|
|
444
555
|
sharedPool = new ToolWorkerPool(maxWorkers)
|
|
@@ -471,11 +582,18 @@ export async function executeToolBatch(options: ExecuteToolBatchOptions): Promis
|
|
|
471
582
|
const results: ToolBatchResult[] = []
|
|
472
583
|
for (const toolCall of options.toolCalls) {
|
|
473
584
|
const startedAt = performance.now()
|
|
474
|
-
const
|
|
585
|
+
const effectiveTimeout = resolveToolTimeout(
|
|
586
|
+
toolCall.function.name,
|
|
587
|
+
options.allTools,
|
|
588
|
+
hiveConfig,
|
|
589
|
+
runtimeConfig.toolTimeoutMs,
|
|
590
|
+
)
|
|
591
|
+
const result = await executeInMainThreadWithTimeout({
|
|
475
592
|
toolCall,
|
|
476
593
|
allTools: options.allTools,
|
|
477
594
|
toolConfig: options.toolConfig,
|
|
478
|
-
|
|
595
|
+
signal: options.signal,
|
|
596
|
+
}, effectiveTimeout)
|
|
479
597
|
results.push({
|
|
480
598
|
toolCall,
|
|
481
599
|
toolName: toolCall.function.name,
|
|
@@ -502,7 +620,12 @@ export async function executeToolBatch(options: ExecuteToolBatchOptions): Promis
|
|
|
502
620
|
toolConfig: options.toolConfig,
|
|
503
621
|
hiveConfig,
|
|
504
622
|
mainThreadToolNames,
|
|
505
|
-
timeoutMs:
|
|
623
|
+
timeoutMs: resolveToolTimeout(
|
|
624
|
+
toolCall.function.name,
|
|
625
|
+
options.allTools,
|
|
626
|
+
hiveConfig,
|
|
627
|
+
runtimeConfig.toolTimeoutMs,
|
|
628
|
+
),
|
|
506
629
|
})))
|
|
507
630
|
|
|
508
631
|
return results.sort((a, b) => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createWorkerTools } from "./worker-tools.ts"
|
|
2
2
|
import type { Config } from "../config/loader.ts"
|
|
3
3
|
|
|
4
4
|
type WorkerRunMessage = {
|
|
@@ -75,7 +75,7 @@ async function runTool(message: WorkerRunMessage): Promise<void> {
|
|
|
75
75
|
try {
|
|
76
76
|
const parsedArgs = parseArgs(message.args)
|
|
77
77
|
const forceMainThread = message.mainThreadToolNames.includes(message.toolName)
|
|
78
|
-
const allTools = forceMainThread ? [] :
|
|
78
|
+
const allTools = forceMainThread ? [] : createWorkerTools(message.hiveConfig)
|
|
79
79
|
const tool = allTools.find((candidate) => candidate.name === message.toolName)
|
|
80
80
|
|
|
81
81
|
const result = tool?.execute
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Config } from "../config/loader.ts"
|
|
2
|
+
import type { Tool } from "../tools/types.ts"
|
|
3
|
+
import * as filesystem from "../tools/filesystem/index.ts"
|
|
4
|
+
import { webSearchTool } from "../tools/web/web-search.ts"
|
|
5
|
+
import { webFetchTool } from "../tools/web/web-fetch.ts"
|
|
6
|
+
import * as cli from "../tools/cli/index.ts"
|
|
7
|
+
import * as office from "../tools/office/index.ts"
|
|
8
|
+
import * as api from "../tools/api/index.ts"
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Reconstruct only stateless tools inside worker realms.
|
|
12
|
+
*
|
|
13
|
+
* Importing the complete tool registry pulls process-local services (including
|
|
14
|
+
* HiveDB) into tool-worker.js even though those tools are always executed by
|
|
15
|
+
* RPC on the main thread. Keeping this registry explicit makes the worker
|
|
16
|
+
* bundle platform-neutral and prevents native bindings from leaking into it.
|
|
17
|
+
*/
|
|
18
|
+
export function createWorkerTools(_config: Config): Tool[] {
|
|
19
|
+
return [
|
|
20
|
+
...filesystem.createTools(),
|
|
21
|
+
webSearchTool,
|
|
22
|
+
webFetchTool,
|
|
23
|
+
...cli.createTools(),
|
|
24
|
+
...office.createTools(),
|
|
25
|
+
...api.createTools(),
|
|
26
|
+
]
|
|
27
|
+
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
import type { Tool } from "../
|
|
2
|
-
import type { Config } from "
|
|
3
|
-
import { canvasManager } from "
|
|
4
|
-
import { logger } from "
|
|
1
|
+
import type { Tool } from "../types.ts";
|
|
2
|
+
import type { Config } from "../../config/loader.ts";
|
|
3
|
+
import { canvasManager } from "../../canvas/canvas-manager.ts";
|
|
4
|
+
import { logger } from "../../utils/logger.ts";
|
|
5
5
|
|
|
6
6
|
export function createA2UISurfaceTool(_config: Config): Tool {
|
|
7
7
|
const log = logger.child("a2ui-surface");
|
|
8
8
|
|
|
9
9
|
return {
|
|
10
10
|
name: "a2ui_create_surface",
|
|
11
|
-
description: "Create an A2UI v0.9 surface
|
|
11
|
+
description: "Create an A2UI v0.9 surface in the user's interactive panel",
|
|
12
12
|
parameters: {
|
|
13
13
|
type: "object",
|
|
14
14
|
properties: {
|
|
@@ -58,7 +58,7 @@ export function createA2UISurfaceTool(_config: Config): Tool {
|
|
|
58
58
|
|
|
59
59
|
if (!canvasManager.isSessionConnected(sessionId)) {
|
|
60
60
|
const connected = canvasManager.getConnectedSessions();
|
|
61
|
-
log.warn(`No
|
|
61
|
+
log.warn(`No visual sessions connected. Rendering to ${sessionId} anyway. Available: ${connected.join(", ")}`);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
await canvasManager.sendA2UIMessage(sessionId, "a2ui:createSurface", {
|
|
@@ -219,7 +219,7 @@ export function createA2UIDeleteSurfaceTool(_config: Config): Tool {
|
|
|
219
219
|
|
|
220
220
|
return {
|
|
221
221
|
name: "a2ui_delete_surface",
|
|
222
|
-
description: "Delete an A2UI v0.9 surface
|
|
222
|
+
description: "Delete an A2UI v0.9 surface from the user's interactive panel",
|
|
223
223
|
parameters: {
|
|
224
224
|
type: "object",
|
|
225
225
|
properties: {
|
|
@@ -252,4 +252,13 @@ export function createA2UIDeleteSurfaceTool(_config: Config): Tool {
|
|
|
252
252
|
});
|
|
253
253
|
},
|
|
254
254
|
};
|
|
255
|
-
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export function createTools(config: Config): Tool[] {
|
|
258
|
+
return [
|
|
259
|
+
createA2UISurfaceTool(config),
|
|
260
|
+
createA2UIUpdateComponentsTool(config),
|
|
261
|
+
createA2UIUpdateDataModelTool(config),
|
|
262
|
+
createA2UIDeleteSurfaceTool(config),
|
|
263
|
+
];
|
|
264
|
+
}
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
10
|
import type { Tool } from "../types.ts";
|
|
11
|
-
import {
|
|
12
|
-
import type {
|
|
11
|
+
import { col } from "../../storage/hive.ts";
|
|
12
|
+
import type { ProviderDoc, ModelDoc } from "../../storage/collections.ts";
|
|
13
13
|
|
|
14
14
|
export const getAvailableModelsTool: Tool = {
|
|
15
15
|
name: "get_available_models",
|
|
16
|
-
description: "Obtener
|
|
16
|
+
description: "Obtener el catálogo completo de modelos de los providers configurados (con credenciales activas) para elegir el más adecuado según capacidad, contexto o costo — no solo el modelo por defecto del usuario. Sinónimos: ver modelos, listar providers, modelos disponibles, consultar modelos, provider activo, qué modelos tengo, modelos para código, modelos para chat",
|
|
17
17
|
parameters: {
|
|
18
18
|
type: "object",
|
|
19
19
|
properties: {
|
|
@@ -39,70 +39,52 @@ export const getAvailableModelsTool: Tool = {
|
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
try {
|
|
42
|
-
const
|
|
43
|
-
const
|
|
44
|
-
|
|
42
|
+
const providersCol = await col<ProviderDoc>("providers");
|
|
43
|
+
const providersById = new Map(
|
|
44
|
+
(await providersCol.scan({}))
|
|
45
|
+
.map(e => e.doc)
|
|
46
|
+
.filter(p => p.enabled && p.active)
|
|
47
|
+
.map(p => [p.id, p])
|
|
48
|
+
);
|
|
45
49
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
// Gate on the *provider* being configured (enabled + active, i.e. it has valid
|
|
51
|
+
// credentials) — not on the individual model's own `active` flag. `active` on a
|
|
52
|
+
// ModelDoc only marks the single model onboarding/voice-setup picked as the
|
|
53
|
+
// user's current default; it is not "this model is unusable". Once a provider is
|
|
54
|
+
// configured, every model under it should be visible so the caller can pick the
|
|
55
|
+
// one that actually fits the task (capability, context window, cost), instead of
|
|
56
|
+
// being stuck with whichever model happened to be flagged as the default.
|
|
57
|
+
const modelsCol = await col<ModelDoc>("models");
|
|
58
|
+
let models = (await modelsCol.scan({}))
|
|
59
|
+
.map(e => e.doc)
|
|
60
|
+
.filter(m => m.enabled && providersById.has(m.provider_id));
|
|
50
61
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
.map(p => [p.id, p.doc])
|
|
55
|
-
);
|
|
62
|
+
if (providerId) models = models.filter(m => m.provider_id === providerId);
|
|
63
|
+
if (modelType) models = models.filter(m => m.model_type === modelType);
|
|
64
|
+
if (capabilities) models = models.filter(m => (m.capabilities ?? "").includes(capabilities));
|
|
56
65
|
|
|
57
|
-
|
|
58
|
-
|
|
66
|
+
// Transformar a formato amigable
|
|
67
|
+
const result = models
|
|
59
68
|
.map(m => {
|
|
60
|
-
const provider =
|
|
61
|
-
if (!provider) return null;
|
|
69
|
+
const provider = providersById.get(m.provider_id)!;
|
|
62
70
|
return {
|
|
63
71
|
providerId: provider.id,
|
|
64
72
|
providerName: provider.name,
|
|
65
73
|
providerCategory: provider.category,
|
|
66
|
-
modelId: m.
|
|
67
|
-
modelName: m.
|
|
68
|
-
modelType: m.
|
|
69
|
-
contextWindow: m.
|
|
70
|
-
capabilities: m.
|
|
74
|
+
modelId: m.id,
|
|
75
|
+
modelName: m.name,
|
|
76
|
+
modelType: m.model_type,
|
|
77
|
+
contextWindow: m.context_window,
|
|
78
|
+
capabilities: m.capabilities ? JSON.parse(m.capabilities) : null,
|
|
79
|
+
isDefault: m.active,
|
|
71
80
|
};
|
|
72
81
|
})
|
|
73
|
-
.
|
|
74
|
-
providerId: string;
|
|
75
|
-
providerName: string;
|
|
76
|
-
providerCategory: string;
|
|
77
|
-
modelId: string;
|
|
78
|
-
modelName: string;
|
|
79
|
-
modelType: string;
|
|
80
|
-
contextWindow: number | null;
|
|
81
|
-
capabilities: string[] | null;
|
|
82
|
-
}>;
|
|
83
|
-
|
|
84
|
-
if (providerId) {
|
|
85
|
-
rows = rows.filter(r => r.providerId === providerId);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
if (modelType) {
|
|
89
|
-
rows = rows.filter(r => r.modelType === modelType);
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
if (capabilities) {
|
|
93
|
-
const cap = capabilities.toLowerCase();
|
|
94
|
-
rows = rows.filter(r => r.capabilities?.some(c => c.toLowerCase().includes(cap)));
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
rows.sort((a, b) => {
|
|
98
|
-
if (a.providerName !== b.providerName) return a.providerName.localeCompare(b.providerName);
|
|
99
|
-
return a.modelName.localeCompare(b.modelName);
|
|
100
|
-
});
|
|
82
|
+
.sort((a, b) => (Number(b.isDefault) - Number(a.isDefault)) || a.providerName.localeCompare(b.providerName) || a.modelName.localeCompare(b.modelName));
|
|
101
83
|
|
|
102
84
|
return {
|
|
103
85
|
ok: true,
|
|
104
|
-
count:
|
|
105
|
-
models:
|
|
86
|
+
count: result.length,
|
|
87
|
+
models: result,
|
|
106
88
|
};
|
|
107
89
|
} catch (error) {
|
|
108
90
|
return {
|