@johpaz/hive-sdk 0.1.6 → 0.3.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.
- package/CHANGELOG.md +441 -0
- package/README.md +21 -3
- package/package.json +27 -5
- package/packages/core/src/agent/acceptance-checks.ts +9 -9
- package/packages/core/src/agent/agent-catalog.ts +82 -25
- package/packages/core/src/agent/agent-loop.ts +115 -26
- package/packages/core/src/agent/capability-search.ts +2 -2
- package/packages/core/src/agent/catalog-selector.ts +4 -4
- package/packages/core/src/agent/compaction.ts +30 -10
- package/packages/core/src/agent/context-compiler.ts +63 -36
- package/packages/core/src/agent/conversation-store.ts +167 -9
- package/packages/core/src/agent/curator.ts +16 -7
- package/packages/core/src/agent/delegation-runtime.ts +5 -5
- package/packages/core/src/agent/goal-runner.ts +9 -9
- package/packages/core/src/agent/index.ts +1 -0
- package/packages/core/src/agent/llm-client.ts +98 -37
- package/packages/core/src/agent/llm-providers/anthropic.ts +4 -4
- package/packages/core/src/agent/llm-providers/deepseek.ts +1 -1
- package/packages/core/src/agent/llm-providers/gemini.ts +4 -4
- package/packages/core/src/agent/llm-providers/groq.ts +1 -1
- package/packages/core/src/agent/llm-providers/hiveagents.ts +3 -3
- package/packages/core/src/agent/llm-providers/interface.ts +2 -2
- package/packages/core/src/agent/llm-providers/kimi.ts +1 -1
- package/packages/core/src/agent/llm-providers/minimax.ts +1 -1
- package/packages/core/src/agent/llm-providers/mistral.ts +1 -1
- package/packages/core/src/agent/llm-providers/modelscope.ts +1 -1
- package/packages/core/src/agent/llm-providers/nvidia.ts +40 -1
- package/packages/core/src/agent/llm-providers/ollama.ts +4 -4
- package/packages/core/src/agent/llm-providers/openai-compat-base.ts +47 -7
- package/packages/core/src/agent/llm-providers/openai.ts +1 -1
- package/packages/core/src/agent/llm-providers/opencode-go.ts +1 -1
- package/packages/core/src/agent/llm-providers/openrouter.ts +1 -1
- package/packages/core/src/agent/llm-providers/qwen.ts +1 -1
- package/packages/core/src/agent/llm-providers/z-ai.ts +1 -1
- package/packages/core/src/agent/mcp-result-normalizer.ts +192 -0
- package/packages/core/src/agent/playbook-selector.ts +22 -7
- package/packages/core/src/agent/prompt-builder.ts +5 -5
- package/packages/core/src/agent/proof-packet.ts +5 -5
- package/packages/core/src/agent/providers/index.ts +39 -4
- package/packages/core/src/agent/realtime-providers/gemini-live.ts +238 -0
- package/packages/core/src/agent/realtime-providers/index.ts +29 -0
- package/packages/core/src/agent/realtime-providers/interface.ts +108 -0
- package/packages/core/src/agent/reflector.ts +38 -15
- package/packages/core/src/agent/run-store.ts +8 -8
- package/packages/core/src/agent/service.ts +10 -10
- package/packages/core/src/agent/skill-selector.ts +6 -6
- package/packages/core/src/agent/thread-id.ts +71 -0
- package/packages/core/src/agent/thread-store.ts +293 -0
- package/packages/core/src/agent/tool-selector.ts +9 -5
- package/packages/core/src/agent/tracer.ts +5 -5
- package/packages/core/src/api/createAgent.ts +67 -2
- package/packages/core/src/artifacts/index.ts +15 -0
- package/packages/core/src/artifacts/store.ts +161 -5
- package/packages/core/src/canvas/emitter.ts +2 -2
- package/packages/core/src/canvas/index.ts +9 -0
- package/packages/core/src/channels/telegram.ts +1 -1
- package/packages/core/src/channels/webchat.ts +1 -1
- package/packages/core/src/config/loader.ts +14 -5
- package/packages/core/src/ethics/EthicsGuard.ts +7 -1
- package/packages/core/src/events/agent-bus.ts +3 -3
- package/packages/core/src/events/channel-narration.ts +3 -3
- package/packages/core/src/events/event-bus.ts +1 -1
- package/packages/core/src/events/index.ts +18 -0
- package/packages/core/src/events/narration.ts +3 -3
- package/packages/core/src/events/tool-narration.ts +4 -0
- package/packages/core/src/gateway/channel-notify.ts +103 -6
- package/packages/core/src/gateway/delegation-groups.ts +4 -4
- package/packages/core/src/gateway/durable-queue.ts +18 -6
- package/packages/core/src/gateway/index.ts +3 -0
- package/packages/core/src/gateway/job-store.ts +11 -5
- package/packages/core/src/gateway/notification-inbox.ts +2 -2
- package/packages/core/src/gateway/server.ts +2 -2
- package/packages/core/src/harness/executors.ts +493 -0
- package/packages/core/src/harness/index.ts +12 -2
- package/packages/core/src/hooks/index.ts +203 -0
- package/packages/core/src/images/index.ts +161 -0
- package/packages/core/src/index.ts +1 -0
- package/packages/core/src/mcp/MCPClient.ts +3 -3
- package/packages/core/src/mcp/hot-reload.ts +5 -5
- package/packages/core/src/mcp/tool-sync.ts +5 -5
- package/packages/core/src/mcp/transports/index.ts +2 -2
- package/packages/core/src/mcp/transports/sse.ts +1 -1
- package/packages/core/src/models/index.ts +36 -0
- package/packages/core/src/multimodal/index.ts +2 -2
- package/packages/core/src/multimodal/vision-service.ts +51 -19
- package/packages/core/src/plugins/loader.ts +4 -1
- package/packages/core/src/resilience/circuit-breaker.ts +16 -5
- package/packages/core/src/resilience/index.ts +13 -0
- package/packages/core/src/resilience/retry.ts +1 -1
- package/packages/core/src/scheduler/CronScheduler.ts +54 -27
- package/packages/core/src/scheduler/cron/expression.ts +165 -0
- package/packages/core/src/scheduler/cron/index.ts +10 -0
- package/packages/core/src/scheduler/cron/job.ts +339 -0
- package/packages/core/src/scheduler/cron/next-run.ts +121 -0
- package/packages/core/src/scheduler/cron/zoned-time.ts +138 -0
- package/packages/core/src/scheduler/index.ts +21 -3
- package/packages/core/src/scheduler/integration.ts +25 -14
- package/packages/core/src/scheduler/types.ts +3 -18
- package/packages/core/src/services/agents.ts +268 -0
- package/packages/core/src/services/cron.ts +257 -0
- package/packages/core/src/services/endpoints.ts +289 -0
- package/packages/core/src/services/ethics.ts +107 -0
- package/packages/core/src/services/images.ts +212 -0
- package/packages/core/src/services/index.ts +112 -0
- package/packages/core/src/services/mcp.ts +201 -0
- package/packages/core/src/services/memory.ts +133 -0
- package/packages/core/src/services/models.ts +179 -0
- package/packages/core/src/services/providers.ts +152 -0
- package/packages/core/src/services/setup.ts +222 -0
- package/packages/core/src/services/skills.ts +241 -0
- package/packages/core/src/services/swarms.ts +307 -0
- package/packages/core/src/services/tools.ts +106 -0
- package/packages/core/src/sessions/index.ts +268 -0
- package/packages/core/src/sessions/resolve.ts +108 -0
- package/packages/core/src/skills/SkillLoader.ts +8 -1
- package/packages/core/src/skills/bundled/artifacts/artifact_reader/SKILL.md +105 -0
- package/packages/core/src/skills/bundled/cron_manager/SKILL.md +21 -11
- package/packages/core/src/skills/bundled/images/image_editor/SKILL.md +120 -0
- package/packages/core/src/skills/bundled/web/browser_automate/SKILL.md +12 -3
- package/packages/core/src/skills/bundled/web/browser_scrape/SKILL.md +22 -7
- package/packages/core/src/skills/bundled-data.generated.ts +110 -12
- package/packages/core/src/storage/bootstrap.ts +107 -12
- package/packages/core/src/storage/causal-events.ts +1 -1
- package/packages/core/src/storage/collections.ts +138 -2
- package/packages/core/src/storage/crypto.ts +35 -4
- package/packages/core/src/storage/hive.ts +1 -1
- package/packages/core/src/storage/hivedb.ts +10 -1
- package/packages/core/src/storage/index.ts +2 -1
- package/packages/core/src/storage/onboarding.ts +61 -45
- package/packages/core/src/storage/reconcile.ts +11 -6
- package/packages/core/src/storage/seed.ts +191 -23
- package/packages/core/src/storage/usage.ts +3 -3
- package/packages/core/src/swarm/AgentExecutor.ts +2 -2
- package/packages/core/src/swarm/Coordinator.ts +8 -8
- package/packages/core/src/swarm/EventBridge.ts +2 -2
- package/packages/core/src/swarm/RoleSwarm.ts +234 -0
- package/packages/core/src/swarm/TaskGraph.ts +2 -2
- package/packages/core/src/swarm/index.ts +7 -0
- package/packages/core/src/swarm/presets/HiveLearnPreset.ts +2 -2
- package/packages/core/src/swarm/presets/ResearchPreset.ts +2 -2
- package/packages/core/src/swarm/strategies/ParallelStrategy.ts +1 -1
- package/packages/core/src/swarm/strategies/PriorityStrategy.ts +3 -3
- package/packages/core/src/swarm/types.ts +3 -18
- package/packages/core/src/tool-runtime/embedded-worker.generated.ts +21 -0
- package/packages/core/src/tool-runtime/index.ts +129 -14
- package/packages/core/src/tools/ToolExecutor.ts +7 -3
- package/packages/core/src/tools/agents/index.ts +18 -60
- package/packages/core/src/tools/cli/index.ts +55 -0
- package/packages/core/src/tools/core/index.ts +52 -4
- package/packages/core/src/tools/cron/index.ts +8 -8
- package/packages/core/src/tools/images/index.ts +130 -0
- package/packages/core/src/tools/index.ts +14 -1
- package/packages/core/src/tools/office/office-escribir-xlsx.ts +2 -1
- package/packages/core/src/tools/office/office-leer-xlsx.ts +2 -1
- package/packages/core/src/tools/office/xlsx-loader.ts +19 -0
- package/packages/core/src/tools/web/artifact-inspect.ts +2 -2
- package/packages/core/src/tools/web/artifact-read.ts +162 -0
- package/packages/core/src/tools/web/browser-backend.ts +141 -44
- package/packages/core/src/tools/web/browser-click.ts +2 -2
- package/packages/core/src/tools/web/browser-extract.ts +2 -2
- package/packages/core/src/tools/web/browser-navigate.ts +2 -2
- package/packages/core/src/tools/web/browser-screenshot.ts +12 -5
- package/packages/core/src/tools/web/browser-script.ts +2 -2
- package/packages/core/src/tools/web/browser-service.ts +63 -384
- package/packages/core/src/tools/web/browser-session.ts +125 -0
- package/packages/core/src/tools/web/browser-type.ts +2 -2
- package/packages/core/src/tools/web/browser-wait.ts +2 -2
- package/packages/core/src/tools/web/computer-use.ts +553 -0
- package/packages/core/src/tools/web/index.ts +8 -1
- package/packages/core/src/tools/web/webview-backend.ts +460 -21
- package/packages/core/src/utils/index.ts +1 -0
- package/packages/core/src/utils/logger.ts +12 -4
- package/packages/core/src/utils/redact-binary.ts +17 -0
- package/packages/core/src/utils/toon.ts +1 -1
- package/packages/core/src/voice/index.ts +6 -6
- package/bun.lock +0 -859
- package/bunfig.toml +0 -9
- package/docs/API-AGENTS.md +0 -367
- package/docs/API-CONTEXT-COMPILER.md +0 -249
- package/docs/API-DAG-SCHEDULER.md +0 -273
- package/docs/API-TOOLS-SKILLS-CHANNELS.md +0 -446
- package/docs/API-WORKERS-EVENTS.md +0 -299
- package/docs/HIVE-HARNESS.md +0 -113
- package/docs/INDEX.md +0 -190
- package/docs/TEMPLATE-HIVE-APP.md +0 -360
- package/packages/cli/package.json +0 -17
- package/packages/cli/src/commands/create-app.test.ts +0 -180
- package/packages/core/package.json +0 -70
- package/packages/core/src/api/createAgent.test.ts +0 -160
- package/packages/core/src/canvas/canvas.test.ts +0 -36
- package/packages/core/src/channels/channels.test.ts +0 -18
- package/packages/core/src/ethics/EthicsGuard.test.ts +0 -108
- package/packages/core/src/gateway/gateway.test.ts +0 -38
- package/packages/core/src/memory/Scratchpad.test.ts +0 -68
- package/packages/core/src/scheduler/scheduler.test.ts +0 -15
- package/packages/core/src/skills/skills.test.ts +0 -62
- package/packages/core/src/swarm/swarm.test.ts +0 -24
- package/packages/core/src/tool-runtime/tool-runtime.test.ts +0 -99
- package/packages/core/src/tools/ToolRegistry.test.ts +0 -98
- package/packages/core/src/tools/api/api-request.test.ts +0 -164
- package/packages/core/src/tools/web/browser-service.test.ts +0 -83
- package/packages/core/src/workers/workers.test.ts +0 -41
- package/scripts/bump-version.ts +0 -248
- package/scripts/generate-skill-bundle.ts +0 -108
- package/test/acceptance-checks.test.ts +0 -403
- package/test/agent-loop-terminal-synthesis.test.ts +0 -32
- package/test/browser-backend.test.ts +0 -308
- package/test/catalog-agents-stay-enabled.test.ts +0 -117
- package/test/causal-events.test.ts +0 -117
- package/test/compaction.test.ts +0 -105
- package/test/context-compiler.test.ts +0 -269
- package/test/curator.test.ts +0 -130
- package/test/durable-queue.test.ts +0 -114
- package/test/harness-barrel.test.ts +0 -64
- package/test/hive-helpers.test.ts +0 -130
- package/test/hivedb-search.test.ts +0 -189
- package/test/internal-turns.test.ts +0 -166
- package/test/job-idempotency.test.ts +0 -68
- package/test/job-retry-backoff.test.ts +0 -184
- package/test/job-store.test.ts +0 -381
- package/test/llm-retry.test.ts +0 -97
- package/test/memory-perf.test.ts +0 -774
- package/test/minimal-loadout.test.ts +0 -78
- package/test/model-catalog.test.ts +0 -105
- package/test/preload.ts +0 -12
- package/test/reflector.test.ts +0 -320
- package/test/retention-cap.test.ts +0 -91
- package/test/retired-capabilities-pruned.test.ts +0 -192
- package/test/run-store.test.ts +0 -355
- package/test/scratchpad.test.ts +0 -74
- package/test/secrets-durability.test.ts +0 -119
- package/test/seed-model-reseed.test.ts +0 -155
- package/test/setup-agent-seed.test.ts +0 -264
- package/test/tool-inventory.test.ts +0 -65
- package/test/tool-runtime.test.ts +0 -258
- package/test/tool-selector-runtime-tools.test.ts +0 -117
- package/test/toon.test.ts +0 -429
- package/tsconfig.json +0 -42
|
@@ -21,27 +21,28 @@
|
|
|
21
21
|
* TODOS los datos se formatean en TOON para ahorro de tokens.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { col, fromIndexable } from "../storage/hive"
|
|
25
|
-
import type { AgentDoc, ModelDoc } from "../storage/collections"
|
|
26
|
-
import { logger } from "../utils/logger"
|
|
27
|
-
import type { LLMMessage, LLMToolDef, ContentPart } from "./llm-client"
|
|
24
|
+
import { col, fromIndexable } from "../storage/hive.ts"
|
|
25
|
+
import type { AgentDoc, ModelDoc } from "../storage/collections.ts"
|
|
26
|
+
import { logger } from "../utils/logger.ts"
|
|
27
|
+
import type { LLMMessage, LLMToolDef, ContentPart } from "./llm-client.ts"
|
|
28
28
|
import type { MCPClientManager } from "../mcp/index.ts"
|
|
29
|
-
import { syncToolCatalogToIndex, mcpToolFullName } from "./tool-selector"
|
|
30
|
-
import { syncSkillsToIndex, getMinimalSkills, selectSkills, getSkillByName, type SkillDescriptor } from "./skill-selector"
|
|
31
|
-
import { syncPlaybookToIndex, selectPlaybookRules } from "./playbook-selector"
|
|
32
|
-
import { getRecentMessages, getSummary, getScratchpad, toAPIMessages } from "./conversation-store"
|
|
33
|
-
import { formatContext, estimateTokens } from "../utils/toon"
|
|
34
|
-
import { buildSystemPromptWithProjects } from "./prompt-builder"
|
|
29
|
+
import { syncToolCatalogToIndex, mcpToolFullName } from "./tool-selector.ts"
|
|
30
|
+
import { syncSkillsToIndex, getMinimalSkills, selectSkills, getSkillByName, type SkillDescriptor } from "./skill-selector.ts"
|
|
31
|
+
import { syncPlaybookToIndex, selectPlaybookRules } from "./playbook-selector.ts"
|
|
32
|
+
import { getRecentMessages, getSummary, getScratchpad, toAPIMessages, inflateRecentImages } from "./conversation-store.ts"
|
|
33
|
+
import { formatContext, estimateTokens } from "../utils/toon.ts"
|
|
34
|
+
import { buildSystemPromptWithProjects } from "./prompt-builder.ts"
|
|
35
35
|
import { createAllTools } from "../tools/index.ts"
|
|
36
|
-
import { resolveUserId } from "../storage/onboarding"
|
|
37
|
-
import { getMCPManager as getSingletonMCPManager } from "../mcp/singleton"
|
|
38
|
-
import { syncMCPToolsToDB, syncMCPToolsToIndex } from "../mcp/tool-sync"
|
|
39
|
-
import { getUserDate, getUserTime } from "../utils/date"
|
|
40
|
-
import { loadConfig } from "../config/loader"
|
|
41
|
-
import { getHiveDb } from "../storage/hivedb"
|
|
42
|
-
import { listCatalogAgents, renderAgentRoutingCatalog } from "./catalog-selector"
|
|
43
|
-
import { expandToolAllowlist } from "./delegation-runtime"
|
|
44
|
-
import { MINIMAL_TOOLS } from "./minimal-loadout"
|
|
36
|
+
import { resolveUserId } from "../storage/onboarding.ts"
|
|
37
|
+
import { getMCPManager as getSingletonMCPManager } from "../mcp/singleton.ts"
|
|
38
|
+
import { syncMCPToolsToDB, syncMCPToolsToIndex } from "../mcp/tool-sync.ts"
|
|
39
|
+
import { getUserDate, getUserTime } from "../utils/date.ts"
|
|
40
|
+
import { loadConfig } from "../config/loader.ts"
|
|
41
|
+
import { getHiveDb } from "../storage/hivedb.ts"
|
|
42
|
+
import { listCatalogAgents, renderAgentRoutingCatalog } from "./catalog-selector.ts"
|
|
43
|
+
import { expandToolAllowlist } from "./delegation-runtime.ts"
|
|
44
|
+
import { MINIMAL_TOOLS } from "./minimal-loadout.ts"
|
|
45
|
+
import { normalizeMcpResult } from "./mcp-result-normalizer.ts"
|
|
45
46
|
|
|
46
47
|
const log = logger.child("context-compiler")
|
|
47
48
|
|
|
@@ -238,7 +239,7 @@ export async function compileContext(opts: {
|
|
|
238
239
|
|
|
239
240
|
if (effectiveMcpManager) {
|
|
240
241
|
try {
|
|
241
|
-
const mcpServersCol = await col<import("../storage/collections").McpServerDoc>("mcpServers")
|
|
242
|
+
const mcpServersCol = await col<import("../storage/collections.ts").McpServerDoc>("mcpServers")
|
|
242
243
|
const assignedMcpIds = new Set<string>([
|
|
243
244
|
...(agent.mcp_server_ids_json ? JSON.parse(agent.mcp_server_ids_json) : []),
|
|
244
245
|
...(agent.active_mcp_json ? JSON.parse(agent.active_mcp_json) : []),
|
|
@@ -293,10 +294,20 @@ export async function compileContext(opts: {
|
|
|
293
294
|
name: fullName,
|
|
294
295
|
description: mcpTool.description || `Tool from ${server.name}`,
|
|
295
296
|
parameters: mcpTool.inputSchema || { type: "object", properties: {} },
|
|
296
|
-
execute: async (params: Record<string, unknown>) => {
|
|
297
|
+
execute: async (params: Record<string, unknown>, config?: { configurable?: Record<string, unknown> }) => {
|
|
297
298
|
// Return raw JS value — agent-loop will TOON-encode via formatToolResult.
|
|
298
299
|
// Never pre-stringify here: formatToolResult(string) double-encodes.
|
|
299
|
-
|
|
300
|
+
const raw = await effectiveMcpManager.callTool(resolvedServerKey, mcpTool.name, params)
|
|
301
|
+
// MCP results can carry base64 image/audio/blob content blocks —
|
|
302
|
+
// normalize those into artifact_ref pointers so a large binary
|
|
303
|
+
// result never gets serialized whole into the LLM context (see
|
|
304
|
+
// mcp-result-normalizer.ts for the incident this prevents).
|
|
305
|
+
const configurable = config?.configurable ?? {}
|
|
306
|
+
return await normalizeMcpResult(raw, {
|
|
307
|
+
userId: configurable.user_id ? String(configurable.user_id) : undefined,
|
|
308
|
+
runId: configurable.run_id ? String(configurable.run_id) : null,
|
|
309
|
+
taskId: configurable.task_id ? String(configurable.task_id) : null,
|
|
310
|
+
})
|
|
300
311
|
},
|
|
301
312
|
})
|
|
302
313
|
|
|
@@ -352,17 +363,30 @@ export async function compileContext(opts: {
|
|
|
352
363
|
// Only native minimal tools in LLM context
|
|
353
364
|
// MCP tools are discovered dynamically via search_knowledge(type="mcp")
|
|
354
365
|
let filteredNativeTools: ContextTool[] = nativeTools.filter(t => MINIMAL_TOOLS.has(t.name))
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
366
|
+
|
|
367
|
+
// La lista blanca se aplica a `allTools`, no sólo al prompt inicial. Filtrar
|
|
368
|
+
// únicamente el loadout de arranque no restringe nada: `search_knowledge`
|
|
369
|
+
// busca contra el índice completo y agent-loop.ts inyecta lo que encuentre
|
|
370
|
+
// resolviéndolo contra `allTools`, así que un agente restringido llegaba
|
|
371
|
+
// igual a cualquier tool nativa por descubrimiento dinámico. Sacarla de
|
|
372
|
+
// `allTools` la vuelve irresoluble: se puede encontrar en el índice, pero no
|
|
373
|
+
// se puede cargar ni llamar.
|
|
374
|
+
//
|
|
375
|
+
// Antes esto dependía de `isCatalogAgent`, y los agentes creados por el
|
|
376
|
+
// usuario —que son los que un host multi-tenant define— quedaban sin límite.
|
|
377
|
+
// Ahora depende de que el agente declare una lista: el coordinador, que no
|
|
378
|
+
// declara ninguna, conserva el descubrimiento abierto.
|
|
379
|
+
const declaredAllowlist = agent.tool_allowlist_json
|
|
380
|
+
? expandToolAllowlist(
|
|
381
|
+
JSON.parse(agent.tool_allowlist_json),
|
|
382
|
+
nativeTools.map((tool) => tool.name),
|
|
365
383
|
)
|
|
384
|
+
: agent.tools_json
|
|
385
|
+
? (JSON.parse(agent.tools_json) as string[])
|
|
386
|
+
: null
|
|
387
|
+
|
|
388
|
+
if (declaredAllowlist) {
|
|
389
|
+
const allowedNames = new Set<string>(declaredAllowlist)
|
|
366
390
|
filteredNativeTools = nativeTools.filter((tool) => allowedNames.has(tool.name))
|
|
367
391
|
allTools = [...filteredNativeTools, ...mcpToolExecutors]
|
|
368
392
|
}
|
|
@@ -494,7 +518,10 @@ export async function compileContext(opts: {
|
|
|
494
518
|
// or — on a context-overflow retry that keeps only the LAST system message
|
|
495
519
|
// (openai-compat-base.ts) — silently replaces the real prompt. The summary
|
|
496
520
|
// lives in `systemPrompt` instead (see conversationSummarySection below).
|
|
497
|
-
|
|
521
|
+
// En el historial las imágenes son referencias, para no reenviarlas enteras en
|
|
522
|
+
// cada turno. Las de los últimos mensajes se vuelven a poner en línea: el
|
|
523
|
+
// modelo todavía puede necesitar mirarlas, y una referencia no se mira.
|
|
524
|
+
const messages: LLMMessage[] = await inflateRecentImages(toAPIMessages(recentMessages))
|
|
498
525
|
|
|
499
526
|
// [STEP-10] STRATEGY 4: ISOLATE — Build context based on agent role
|
|
500
527
|
log.info(`[context-compiler] [STEP-10] Building system prompt...`)
|
|
@@ -508,7 +535,7 @@ export async function compileContext(opts: {
|
|
|
508
535
|
}
|
|
509
536
|
|
|
510
537
|
// [STEP-10b] Inject current date/time (ENTORNO ACTUAL)
|
|
511
|
-
const usersCol = await col<import("../storage/collections").UserDoc>("users")
|
|
538
|
+
const usersCol = await col<import("../storage/collections.ts").UserDoc>("users")
|
|
512
539
|
const userRow = await usersCol.get(userId)
|
|
513
540
|
const userTimezone = userRow?.doc.timezone || "UTC"
|
|
514
541
|
const now = new Date()
|
|
@@ -538,7 +565,7 @@ export async function compileContext(opts: {
|
|
|
538
565
|
: Array.isArray(playbookInput)
|
|
539
566
|
? playbookInput.filter((part) => part.type === "text").map((part) => (part as any).text).join("\n")
|
|
540
567
|
: String(playbookInput)
|
|
541
|
-
const playbookRules = (await selectPlaybookRules(playbookText)).filter((rule) => {
|
|
568
|
+
const playbookRules = (await selectPlaybookRules(playbookText, userId)).filter((rule) => {
|
|
542
569
|
if (!rule.applicable_to || !rule.applicable_to.includes("agent:")) return true
|
|
543
570
|
return isCatalogAgent ? rule.applicable_to.includes(`agent:${agent.id}`) : false
|
|
544
571
|
})
|
|
@@ -585,7 +612,7 @@ export async function compileContext(opts: {
|
|
|
585
612
|
.filter((line): line is string => !!line)
|
|
586
613
|
|
|
587
614
|
if (causalLines.length > 0) {
|
|
588
|
-
systemPrompt += `\n\n# CAUSAL CONTEXT (decisiones y tool calls de este turno, previos a la compactación —
|
|
615
|
+
systemPrompt += `\n\n# CAUSAL CONTEXT (decisiones y tool calls de este turno, previos a la compactación — prioriza la conversación actual; úsalo solo para no repetir algo que ya funcionó o ya falló)\n${causalLines.join("\n")}\n`
|
|
589
616
|
log.info(`[context-compiler] [STEP-9d] ✅ Injected ${causalLines.length} causal context item(s)`)
|
|
590
617
|
}
|
|
591
618
|
} catch (err) {
|
|
@@ -5,12 +5,13 @@
|
|
|
5
5
|
* Also manages: summaries and scratchpad, both HiveDB document collections.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { col, nextId, bumpRollup } from "../storage/hive"
|
|
9
|
-
import { getHiveDb } from "../storage/hivedb"
|
|
10
|
-
import { logger } from "../utils/logger"
|
|
11
|
-
import type { LLMMessage, ContentPart } from "./llm-client"
|
|
12
|
-
import { estimateTokens } from "../utils/toon"
|
|
13
|
-
import type { ConversationDoc, SummaryDoc, MessageSource } from "../storage/collections"
|
|
8
|
+
import { col, nextId, bumpRollup } from "../storage/hive.ts"
|
|
9
|
+
import { getHiveDb } from "../storage/hivedb.ts"
|
|
10
|
+
import { logger } from "../utils/logger.ts"
|
|
11
|
+
import type { LLMMessage, ContentPart } from "./llm-client.ts"
|
|
12
|
+
import { estimateTokens } from "../utils/toon.ts"
|
|
13
|
+
import type { ConversationDoc, SummaryDoc, MessageSource } from "../storage/collections.ts"
|
|
14
|
+
import { touchThread } from "./thread-store.ts"
|
|
14
15
|
|
|
15
16
|
const log = logger.child("conv-store")
|
|
16
17
|
|
|
@@ -45,13 +46,26 @@ export interface StoredMessage {
|
|
|
45
46
|
// stays clean and the wording can evolve without a migration.
|
|
46
47
|
|
|
47
48
|
export const INTERNAL_SOURCES: ReadonlySet<string> =
|
|
48
|
-
new Set(["task_complete", "delegation_summary", "legacy_internal"])
|
|
49
|
+
new Set(["task_complete", "delegation_summary", "legacy_internal", "realtime_chat"])
|
|
49
50
|
|
|
50
51
|
export function isInternalSource(source: string | null | undefined): boolean {
|
|
51
52
|
return !!source && INTERNAL_SOURCES.has(source)
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
export function formatInternalEvent(source: string, content: string): string {
|
|
56
|
+
// La charla hablada sí salió del usuario, pero la sesión de voz ya la
|
|
57
|
+
// respondió: es contexto, no trabajo por hacer. Sin esta distinción el
|
|
58
|
+
// coordinador leía cada frase suelta de una llamada como un pedido nuevo y
|
|
59
|
+
// delegaba una tarea por cada una.
|
|
60
|
+
if (source === "realtime_chat") {
|
|
61
|
+
return `<hive:voice_context>\n` +
|
|
62
|
+
`Fragmento de una conversación hablada que la voz de Hive YA respondió en el momento. ` +
|
|
63
|
+
`Es contexto de lo que vinieron hablando, NO un pedido pendiente: no ejecutes ni delegues nada por esto. ` +
|
|
64
|
+
`El trabajo real llega siempre como un mensaje aparte y explícito.\n\n` +
|
|
65
|
+
`${content}\n` +
|
|
66
|
+
`</hive:voice_context>`
|
|
67
|
+
}
|
|
68
|
+
|
|
55
69
|
return `<hive:internal_event source="${source}">\n` +
|
|
56
70
|
`Evento interno del sistema — NO es un mensaje del usuario. No lo cites literalmente, no expongas IDs internos (task_id, worker_id) ni JSON crudo. Respondé al usuario de forma natural y breve.\n\n` +
|
|
57
71
|
`${content}\n` +
|
|
@@ -97,6 +111,66 @@ export function getRecentMessageCount(windowMs = 5 * 60_000): number {
|
|
|
97
111
|
return recentMessageTimestamps.length
|
|
98
112
|
}
|
|
99
113
|
|
|
114
|
+
/** El threadId es `${userId}/${canal}/${peer}`, así que el dueño ya está ahí. */
|
|
115
|
+
async function resolveOwnerId(threadId: string): Promise<string> {
|
|
116
|
+
const { parseThreadId } = await import("./thread-id.ts")
|
|
117
|
+
return parseThreadId(threadId)?.userId ?? threadId
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Cuánto ocupa una imagen en la ventana de contexto.
|
|
122
|
+
*
|
|
123
|
+
* Los proveedores cobran por área, no por bytes: la fórmula es la de los
|
|
124
|
+
* modelos de visión más comunes (~750 px² por token). Es una estimación, pero
|
|
125
|
+
* cualquier estimación es infinitamente mejor que la anterior, que era cero: la
|
|
126
|
+
* compactación creía que un hilo con diez fotos ocupaba lo que ocupa su texto,
|
|
127
|
+
* y no se disparaba hasta que el proveedor rechazaba el turno.
|
|
128
|
+
*/
|
|
129
|
+
export function estimateImageTokens(width?: number | null, height?: number | null): number {
|
|
130
|
+
if (!width || !height) return 1_500; // desconocida: el promedio de una foto
|
|
131
|
+
return Math.ceil((width * height) / 750);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Cambia las imágenes en línea por referencias a un artefacto.
|
|
136
|
+
*
|
|
137
|
+
* El base64 se guardaba entero en `content_multimodal` y `toAPIMessages` lo
|
|
138
|
+
* devolvía al modelo **en cada turno siguiente**: cinco fotos en una
|
|
139
|
+
* conversación eran cinco fotos reenviadas una y otra vez. Guardar el archivo y
|
|
140
|
+
* dejar una referencia corta ese crecimiento de raíz.
|
|
141
|
+
*
|
|
142
|
+
* La imagen no se pierde: `inflateRecentImages` la vuelve a poner en línea para
|
|
143
|
+
* los últimos turnos, que es donde el modelo todavía puede necesitar mirarla.
|
|
144
|
+
*/
|
|
145
|
+
async function imagesToRefs(content: ContentPart[], userId: string): Promise<ContentPart[]> {
|
|
146
|
+
const { createArtifact } = await import("../artifacts/store.ts")
|
|
147
|
+
const out: ContentPart[] = []
|
|
148
|
+
|
|
149
|
+
for (const part of content) {
|
|
150
|
+
if (part.type !== "image_base64") { out.push(part); continue }
|
|
151
|
+
try {
|
|
152
|
+
const bytes = Uint8Array.from(Buffer.from((part as { base64: string }).base64, "base64"))
|
|
153
|
+
const mimeType = (part as { mimeType?: string }).mimeType || "image/jpeg"
|
|
154
|
+
// Si no se puede medir, no es una imagen. Guardarla igual crearía un
|
|
155
|
+
// artefacto de tipo "image" con basura adentro, que aparecería en la
|
|
156
|
+
// galería del usuario; es mejor dejarla como venía.
|
|
157
|
+
const { measureImage } = await import("../images/index.ts")
|
|
158
|
+
const meta = await measureImage(bytes)
|
|
159
|
+
|
|
160
|
+
const art = await createArtifact({
|
|
161
|
+
bytes, mimeType, kind: "image", userId,
|
|
162
|
+
width: meta.width, height: meta.height, expiresAt: null,
|
|
163
|
+
})
|
|
164
|
+
out.push({ type: "artifact_ref", artifact_id: art.id, mime_type: mimeType, width: meta.width, height: meta.height } as unknown as ContentPart)
|
|
165
|
+
} catch {
|
|
166
|
+
// No es una imagen medible, o no se pudo guardar: viaja como venía.
|
|
167
|
+
// Perderla sería peor que no optimizarla.
|
|
168
|
+
out.push(part)
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return out
|
|
172
|
+
}
|
|
173
|
+
|
|
100
174
|
export async function addMessage(
|
|
101
175
|
threadId: string,
|
|
102
176
|
role: StoredMessage["role"],
|
|
@@ -107,6 +181,8 @@ export async function addMessage(
|
|
|
107
181
|
tool_call_id?: string
|
|
108
182
|
reasoning_content?: string
|
|
109
183
|
source?: MessageSource
|
|
184
|
+
/** Dueño de los artefactos que se creen para este mensaje (imágenes). */
|
|
185
|
+
userId?: string
|
|
110
186
|
}
|
|
111
187
|
): Promise<number> {
|
|
112
188
|
// Handle multimodal content by extracting text for the content column
|
|
@@ -116,7 +192,12 @@ export async function addMessage(
|
|
|
116
192
|
? content.filter(p => p.type === "text").map(p => (p as any).text).join("\n")
|
|
117
193
|
: String(content)
|
|
118
194
|
|
|
119
|
-
|
|
195
|
+
// Las imágenes se guardan como archivo y en el historial queda una
|
|
196
|
+
// referencia: el base64 entero se reenviaba al modelo en cada turno.
|
|
197
|
+
const partes = Array.isArray(content)
|
|
198
|
+
? await imagesToRefs(content, opts?.userId ?? (await resolveOwnerId(threadId)))
|
|
199
|
+
: null
|
|
200
|
+
const content_multimodal = partes ? JSON.stringify(partes) : null
|
|
120
201
|
const tool_calls_json = opts?.tool_calls ? JSON.stringify(opts.tool_calls) : null
|
|
121
202
|
|
|
122
203
|
const paddedSeq = await nextId(`conversations:${threadId}`)
|
|
@@ -136,7 +217,19 @@ export async function addMessage(
|
|
|
136
217
|
reasoning_content: opts?.reasoning_content ?? null,
|
|
137
218
|
source: opts?.source ?? "message",
|
|
138
219
|
// Estimate tokens: content + tool_calls JSON
|
|
139
|
-
|
|
220
|
+
// Las imágenes cuentan: antes sumaban cero y la compactación creía que un
|
|
221
|
+
// hilo lleno de fotos ocupaba lo que ocupa su texto.
|
|
222
|
+
token_count: Math.max(
|
|
223
|
+
1,
|
|
224
|
+
estimateTokens(textContent) +
|
|
225
|
+
estimateTokens(tool_calls_json ?? "") +
|
|
226
|
+
(partes ?? []).reduce((n, p) => {
|
|
227
|
+
const q = p as { type: string; width?: number | null; height?: number | null }
|
|
228
|
+
return q.type === "artifact_ref" || q.type === "image_base64" || q.type === "image_url"
|
|
229
|
+
? n + estimateImageTokens(q.width, q.height)
|
|
230
|
+
: n
|
|
231
|
+
}, 0),
|
|
232
|
+
),
|
|
140
233
|
created_at: now,
|
|
141
234
|
updated_at: now,
|
|
142
235
|
}, { expectedVersion: 0 })
|
|
@@ -146,6 +239,16 @@ export async function addMessage(
|
|
|
146
239
|
bumpRollup("activityRollups", hour, { messageCount: 1 }).catch(() => {})
|
|
147
240
|
recentMessageTimestamps.push(now)
|
|
148
241
|
|
|
242
|
+
// Igual de opcional: el registro de conversaciones es el catálogo que alimenta la
|
|
243
|
+
// lista de la web (título, orden, contador). Se actualiza acá y no en cada llamador
|
|
244
|
+
// para que todo camino que escriba un mensaje —canales, webchat, API, voz— lo
|
|
245
|
+
// mantenga al día sin repetir la llamada.
|
|
246
|
+
touchThread(threadId, {
|
|
247
|
+
role,
|
|
248
|
+
text: textContent,
|
|
249
|
+
internal: isInternalSource(opts?.source),
|
|
250
|
+
}).catch(() => {})
|
|
251
|
+
|
|
149
252
|
return seq
|
|
150
253
|
}
|
|
151
254
|
|
|
@@ -228,6 +331,61 @@ export async function getMessagesAfter(threadId: string, afterId: number): Promi
|
|
|
228
331
|
|
|
229
332
|
// ─── Convert stored messages → LLMMessage array ───────────────────────────────
|
|
230
333
|
|
|
334
|
+
/**
|
|
335
|
+
* Cuántos mensajes del final conservan sus imágenes en línea.
|
|
336
|
+
*
|
|
337
|
+
* Mismo criterio que `clearOldToolResults` (compaction.ts), que ya poda
|
|
338
|
+
* resultados viejos y deja intactos los recientes. Es el compromiso: el modelo
|
|
339
|
+
* puede volver a mirar una imagen de hace un rato —"¿qué decía la factura?"—
|
|
340
|
+
* sin que una conversación larga arrastre todas las fotos para siempre.
|
|
341
|
+
*/
|
|
342
|
+
export const KEEP_IMAGES_LAST_N = 6
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Vuelve a poner en línea las imágenes de los últimos mensajes.
|
|
346
|
+
*
|
|
347
|
+
* En el historial las imágenes son referencias (ver `imagesToRefs`), que no
|
|
348
|
+
* ocupan contexto pero tampoco se pueden mirar: un modelo de visión no ve una
|
|
349
|
+
* foto desde un id. Para los últimos `keepLastN` mensajes se leen del disco y
|
|
350
|
+
* se devuelven como base64; los anteriores quedan como referencia, con sus
|
|
351
|
+
* dimensiones, para que el modelo sepa que hubo una imagen y cuál.
|
|
352
|
+
*/
|
|
353
|
+
export async function inflateRecentImages(
|
|
354
|
+
messages: LLMMessage[],
|
|
355
|
+
keepLastN = KEEP_IMAGES_LAST_N,
|
|
356
|
+
): Promise<LLMMessage[]> {
|
|
357
|
+
const desde = Math.max(0, messages.length - keepLastN)
|
|
358
|
+
const tieneRefs = messages.slice(desde).some((m) =>
|
|
359
|
+
Array.isArray(m.content) && m.content.some((p) => (p as { type?: string }).type === "artifact_ref"))
|
|
360
|
+
if (!tieneRefs) return messages
|
|
361
|
+
|
|
362
|
+
const { readArtifactBytes } = await import("../artifacts/store.ts")
|
|
363
|
+
|
|
364
|
+
return Promise.all(messages.map(async (msg, i) => {
|
|
365
|
+
if (i < desde || !Array.isArray(msg.content)) return msg
|
|
366
|
+
|
|
367
|
+
const partes = await Promise.all(msg.content.map(async (part) => {
|
|
368
|
+
const p = part as { type: string; artifact_id?: string; mime_type?: string }
|
|
369
|
+
if (p.type !== "artifact_ref" || !p.artifact_id) return part
|
|
370
|
+
if (!String(p.mime_type ?? "").startsWith("image/")) return part
|
|
371
|
+
|
|
372
|
+
try {
|
|
373
|
+
const datos = await readArtifactBytes(p.artifact_id)
|
|
374
|
+
if (!datos) return part // caducó o se borró: queda la referencia
|
|
375
|
+
return {
|
|
376
|
+
type: "image_base64",
|
|
377
|
+
base64: Buffer.from(datos.bytes).toString("base64"),
|
|
378
|
+
mimeType: datos.mimeType,
|
|
379
|
+
} as unknown as ContentPart
|
|
380
|
+
} catch {
|
|
381
|
+
return part
|
|
382
|
+
}
|
|
383
|
+
}))
|
|
384
|
+
|
|
385
|
+
return { ...msg, content: partes }
|
|
386
|
+
}))
|
|
387
|
+
}
|
|
388
|
+
|
|
231
389
|
export function toAPIMessages(rows: StoredMessage[]): LLMMessage[] {
|
|
232
390
|
return rows.map((r) => {
|
|
233
391
|
let content: string | ContentPart[] = r.content
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
* (id="curator:lastReflection") instead of SQL's MAX(source_reflection_id).
|
|
14
14
|
*/
|
|
15
15
|
|
|
16
|
-
import { logger } from "../utils/logger"
|
|
17
|
-
import { col, nextId, toIndexable, fromIndexable } from "../storage/hive"
|
|
16
|
+
import { logger } from "../utils/logger.ts"
|
|
17
|
+
import { col, nextId, toIndexable, fromIndexable } from "../storage/hive.ts"
|
|
18
18
|
import type {
|
|
19
19
|
ReflectionDoc,
|
|
20
20
|
PlaybookDoc,
|
|
@@ -22,7 +22,7 @@ import type {
|
|
|
22
22
|
CursorDoc,
|
|
23
23
|
AgentProposalDoc,
|
|
24
24
|
TraceDoc,
|
|
25
|
-
} from "../storage/collections"
|
|
25
|
+
} from "../storage/collections.ts"
|
|
26
26
|
|
|
27
27
|
const log = logger.child("curator")
|
|
28
28
|
|
|
@@ -149,7 +149,7 @@ async function curateAgentStructure(): Promise<void> {
|
|
|
149
149
|
})
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
const { syncCatalogAgentsToIndex } = await import("./catalog-selector")
|
|
152
|
+
const { syncCatalogAgentsToIndex } = await import("./catalog-selector.ts")
|
|
153
153
|
await syncCatalogAgentsToIndex()
|
|
154
154
|
}
|
|
155
155
|
|
|
@@ -201,7 +201,13 @@ async function processReflection(
|
|
|
201
201
|
|
|
202
202
|
// Check if a similar rule already exists (fuzzy check by first 60 chars)
|
|
203
203
|
const prefix = reflection.description.substring(0, 60)
|
|
204
|
-
|
|
204
|
+
// La deduplicación también va por usuario: si dos personas producen la misma
|
|
205
|
+
// observación, son dos reglas. Buscando sólo por texto, lo aprendido de la
|
|
206
|
+
// segunda reforzaría la regla de la primera y la haría pesar más en un
|
|
207
|
+
// playbook que no es suyo.
|
|
208
|
+
const existing = allPlaybook.find(
|
|
209
|
+
e => e.doc.active && e.doc.user_id === reflection.user_id && e.doc.rule.startsWith(prefix)
|
|
210
|
+
)
|
|
205
211
|
|
|
206
212
|
if (existing) {
|
|
207
213
|
// Reinforce existing rule
|
|
@@ -216,6 +222,7 @@ async function processReflection(
|
|
|
216
222
|
id,
|
|
217
223
|
rule: reflection.description,
|
|
218
224
|
category,
|
|
225
|
+
user_id: reflection.user_id,
|
|
219
226
|
applicable_to: applicableTo,
|
|
220
227
|
helpful_count: 1,
|
|
221
228
|
harmful_count: 0,
|
|
@@ -224,7 +231,7 @@ async function processReflection(
|
|
|
224
231
|
created_at: now,
|
|
225
232
|
updated_at: now,
|
|
226
233
|
}, { expectedVersion: 0 })
|
|
227
|
-
allPlaybook.push({ id, version: 1, doc: { id, rule: reflection.description, category, applicable_to: applicableTo, helpful_count: 1, harmful_count: 0, active: true, source_reflection_id: toIndexable(reflection.id), created_at: now, updated_at: now } })
|
|
234
|
+
allPlaybook.push({ id, version: 1, doc: { id, rule: reflection.description, category, user_id: reflection.user_id, applicable_to: applicableTo, helpful_count: 1, harmful_count: 0, active: true, source_reflection_id: toIndexable(reflection.id), created_at: now, updated_at: now } })
|
|
228
235
|
}
|
|
229
236
|
|
|
230
237
|
function mapInsightTypeToCategory(
|
|
@@ -248,12 +255,13 @@ async function addOrUpdateRule(
|
|
|
248
255
|
opts: {
|
|
249
256
|
rule: string
|
|
250
257
|
category: string
|
|
258
|
+
user_id: string
|
|
251
259
|
applicable_to: string | null
|
|
252
260
|
sourceReflectionId: string | null
|
|
253
261
|
}
|
|
254
262
|
): Promise<void> {
|
|
255
263
|
const prefix = opts.rule.substring(0, 60)
|
|
256
|
-
const existing = allPlaybook.find(e => e.doc.rule.startsWith(prefix))
|
|
264
|
+
const existing = allPlaybook.find(e => e.doc.user_id === opts.user_id && e.doc.rule.startsWith(prefix))
|
|
257
265
|
|
|
258
266
|
if (existing) {
|
|
259
267
|
await playbookCol.put(existing.id, { ...existing.doc, helpful_count: existing.doc.helpful_count + 1, updated_at: Date.now() }, { expectedVersion: existing.version })
|
|
@@ -264,6 +272,7 @@ async function addOrUpdateRule(
|
|
|
264
272
|
id,
|
|
265
273
|
rule: opts.rule,
|
|
266
274
|
category: opts.category as PlaybookDoc["category"],
|
|
275
|
+
user_id: opts.user_id,
|
|
267
276
|
applicable_to: opts.applicable_to,
|
|
268
277
|
helpful_count: 1,
|
|
269
278
|
harmful_count: 0,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { col, toIndexable, fromIndexable, updateDoc } from "../storage/hive";
|
|
1
|
+
import { col, toIndexable, fromIndexable, updateDoc } from "../storage/hive.ts";
|
|
2
2
|
import type {
|
|
3
3
|
AgentDoc,
|
|
4
4
|
McpServerDoc,
|
|
@@ -6,11 +6,11 @@ import type {
|
|
|
6
6
|
ProviderDoc,
|
|
7
7
|
SkillDoc,
|
|
8
8
|
AgentModelOverride,
|
|
9
|
-
} from "../storage/collections";
|
|
10
|
-
import { createAllTools } from "../tools";
|
|
11
|
-
import { loadConfig } from "../config/loader";
|
|
9
|
+
} from "../storage/collections.ts";
|
|
10
|
+
import { createAllTools } from "../tools/index.ts";
|
|
11
|
+
import { loadConfig } from "../config/loader.ts";
|
|
12
12
|
import type { MCPClientManager } from "../mcp/index.ts";
|
|
13
|
-
import { logger } from "../utils/logger";
|
|
13
|
+
import { logger } from "../utils/logger.ts";
|
|
14
14
|
|
|
15
15
|
const log = logger.child("delegation-runtime");
|
|
16
16
|
const MCP_IDLE_TTL_MS = 2 * 60_000;
|
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
* entire run (not per-turn). This prevents endless loops.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import { logger } from "../utils/logger";
|
|
18
|
-
import { callLLM, type LLMMessage } from "./llm-client";
|
|
19
|
-
import { createRun, type AcceptanceCriterion } from "./run-store";
|
|
20
|
-
import { clearOldToolResults } from "./compaction";
|
|
21
|
-
import { loadConfig } from "../config/loader";
|
|
17
|
+
import { logger } from "../utils/logger.ts";
|
|
18
|
+
import { callLLM, type LLMMessage } from "./llm-client.ts";
|
|
19
|
+
import { createRun, type AcceptanceCriterion } from "./run-store.ts";
|
|
20
|
+
import { clearOldToolResults } from "./compaction.ts";
|
|
21
|
+
import { loadConfig } from "../config/loader.ts";
|
|
22
22
|
import { getDurableQueue } from "../gateway/durable-queue.ts";
|
|
23
|
-
import { recordLLMUsage } from "./tracer";
|
|
23
|
+
import { recordLLMUsage } from "./tracer.ts";
|
|
24
24
|
|
|
25
|
-
export type { AcceptanceCriterion } from "./run-store";
|
|
25
|
+
export type { AcceptanceCriterion } from "./run-store.ts";
|
|
26
26
|
|
|
27
27
|
export interface AcceptanceResult {
|
|
28
28
|
id: string;
|
|
@@ -126,8 +126,8 @@ export async function runGoal(opts: GoalRunOptions): Promise<GoalRunResult> {
|
|
|
126
126
|
/** Runs a deterministic goal_check_tool, no LLM involved. */
|
|
127
127
|
async function runDeterministicCheck(checkTool: string, goal: string): Promise<{ met: boolean; reason: string } | null> {
|
|
128
128
|
try {
|
|
129
|
-
const { executeToolBatch } = await import("../tool-runtime");
|
|
130
|
-
const { createAllTools } = await import("../tools/index");
|
|
129
|
+
const { executeToolBatch } = await import("../tool-runtime/index.ts");
|
|
130
|
+
const { createAllTools } = await import("../tools/index.ts");
|
|
131
131
|
const allTools = createAllTools(loadConfig());
|
|
132
132
|
const toolDef = allTools.find((t) => t.name === checkTool);
|
|
133
133
|
if (!toolDef) {
|