@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,448 +0,0 @@
|
|
|
1
|
-
import type { Tool } from "../agent/NativeTools.ts";
|
|
2
|
-
import type { Config } from "../config/loader.ts";
|
|
3
|
-
import { canvasManager } from "./CanvasManager.ts";
|
|
4
|
-
import { logger } from "../utils/logger.ts";
|
|
5
|
-
|
|
6
|
-
export function createCanvasRenderTool(_config: Config): Tool {
|
|
7
|
-
const log = logger.child("canvas-render");
|
|
8
|
-
|
|
9
|
-
return {
|
|
10
|
-
name: "canvas_render",
|
|
11
|
-
description: "Render a component on the user's canvas",
|
|
12
|
-
parameters: {
|
|
13
|
-
type: "object",
|
|
14
|
-
properties: {
|
|
15
|
-
sessionId: {
|
|
16
|
-
type: "string",
|
|
17
|
-
description: "Session ID to render to (auto-resolved from user context if omitted)",
|
|
18
|
-
},
|
|
19
|
-
component: {
|
|
20
|
-
type: "object",
|
|
21
|
-
properties: {
|
|
22
|
-
id: {
|
|
23
|
-
type: "string",
|
|
24
|
-
description: "Unique component ID",
|
|
25
|
-
},
|
|
26
|
-
type: {
|
|
27
|
-
type: "string",
|
|
28
|
-
enum: ["button", "form", "chart", "table", "markdown", "text", "image"],
|
|
29
|
-
description: "Component type",
|
|
30
|
-
},
|
|
31
|
-
props: {
|
|
32
|
-
type: "object",
|
|
33
|
-
description: "Component properties",
|
|
34
|
-
},
|
|
35
|
-
span: {
|
|
36
|
-
type: "string",
|
|
37
|
-
enum: ["full", "half"],
|
|
38
|
-
description: "Width span: 'full' for full-width component, 'half' for half width. Default: single column",
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
required: ["id", "type", "props"],
|
|
42
|
-
},
|
|
43
|
-
},
|
|
44
|
-
required: ["component"],
|
|
45
|
-
},
|
|
46
|
-
execute: async (params: Record<string, unknown>, config?: any) => {
|
|
47
|
-
const userId = config?.configurable?.user_id;
|
|
48
|
-
const rawSessionId = params.sessionId as string;
|
|
49
|
-
const sessionId = rawSessionId
|
|
50
|
-
? (rawSessionId.startsWith("canvas:") ? rawSessionId : `canvas:${rawSessionId}`)
|
|
51
|
-
: (userId ? `canvas:${userId}` : (() => { throw new Error("No session or user ID provided"); })());
|
|
52
|
-
const component = params.component as {
|
|
53
|
-
id: string;
|
|
54
|
-
type: "button" | "form" | "chart" | "table" | "markdown" | "text" | "image" | "card" | "progress" | "list" | "confirm";
|
|
55
|
-
props: Record<string, unknown>;
|
|
56
|
-
span?: "full" | "half";
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
log.debug(`Rendering component ${component.id} to session ${sessionId}`);
|
|
60
|
-
|
|
61
|
-
// Check if session is connected, if not try to render to any available session
|
|
62
|
-
if (!canvasManager.isSessionConnected(sessionId)) {
|
|
63
|
-
const connectedSessions = canvasManager.getConnectedSessions();
|
|
64
|
-
if (connectedSessions.length > 0) {
|
|
65
|
-
log.warn(`Session ${sessionId} not connected, using first available: ${connectedSessions[0]}`);
|
|
66
|
-
} else {
|
|
67
|
-
log.warn(`No canvas sessions connected. Rendering to ${sessionId} anyway.`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
await canvasManager.render(sessionId, {
|
|
72
|
-
id: component.id,
|
|
73
|
-
type: component.type as any,
|
|
74
|
-
props: component.props,
|
|
75
|
-
span: component.span,
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
return {
|
|
79
|
-
success: true,
|
|
80
|
-
componentId: component.id,
|
|
81
|
-
sessionId,
|
|
82
|
-
};
|
|
83
|
-
},
|
|
84
|
-
};
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export function createCanvasAskTool(_config: Config): Tool {
|
|
88
|
-
const log = logger.child("canvas-ask");
|
|
89
|
-
|
|
90
|
-
return {
|
|
91
|
-
name: "canvas_ask",
|
|
92
|
-
description: "Display a form and wait for user response",
|
|
93
|
-
parameters: {
|
|
94
|
-
type: "object",
|
|
95
|
-
properties: {
|
|
96
|
-
sessionId: {
|
|
97
|
-
type: "string",
|
|
98
|
-
description: "Session ID",
|
|
99
|
-
},
|
|
100
|
-
title: {
|
|
101
|
-
type: "string",
|
|
102
|
-
description: "Form title",
|
|
103
|
-
},
|
|
104
|
-
fields: {
|
|
105
|
-
type: "array",
|
|
106
|
-
items: {
|
|
107
|
-
type: "object",
|
|
108
|
-
properties: {
|
|
109
|
-
name: { type: "string" },
|
|
110
|
-
label: { type: "string" },
|
|
111
|
-
type: { type: "string", enum: ["text", "email", "textarea", "select"] },
|
|
112
|
-
required: { type: "boolean" },
|
|
113
|
-
options: {
|
|
114
|
-
type: "array",
|
|
115
|
-
items: {
|
|
116
|
-
type: "object",
|
|
117
|
-
properties: {
|
|
118
|
-
label: { type: "string" },
|
|
119
|
-
value: { type: "string" },
|
|
120
|
-
},
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
},
|
|
124
|
-
required: ["name", "label", "type"],
|
|
125
|
-
},
|
|
126
|
-
description: "Form fields",
|
|
127
|
-
},
|
|
128
|
-
timeout: {
|
|
129
|
-
type: "number",
|
|
130
|
-
description: "Timeout in milliseconds (default: 300000)",
|
|
131
|
-
},
|
|
132
|
-
},
|
|
133
|
-
required: ["fields"],
|
|
134
|
-
},
|
|
135
|
-
execute: async (params: Record<string, unknown>, config?: any) => {
|
|
136
|
-
const userId = config?.configurable?.user_id;
|
|
137
|
-
const rawSessionId = params.sessionId as string;
|
|
138
|
-
const sessionId = rawSessionId
|
|
139
|
-
? (rawSessionId.startsWith("canvas:") ? rawSessionId : `canvas:${rawSessionId}`)
|
|
140
|
-
: (userId ? `canvas:${userId}` : (() => { throw new Error("No session or user ID provided"); })());
|
|
141
|
-
const title = (params.title as string) ?? "Form";
|
|
142
|
-
const fields = params.fields as Array<{
|
|
143
|
-
name: string;
|
|
144
|
-
label: string;
|
|
145
|
-
type: string;
|
|
146
|
-
required?: boolean;
|
|
147
|
-
options?: Array<{ label: string; value: string }>;
|
|
148
|
-
}>;
|
|
149
|
-
const timeout = (params.timeout as number) ?? 300000;
|
|
150
|
-
|
|
151
|
-
const formId = `form-${Date.now()}`;
|
|
152
|
-
|
|
153
|
-
log.debug(`Asking user via form ${formId}`);
|
|
154
|
-
|
|
155
|
-
await canvasManager.render(sessionId, {
|
|
156
|
-
id: formId,
|
|
157
|
-
type: "form",
|
|
158
|
-
props: { title, fields },
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
try {
|
|
162
|
-
const response = await canvasManager.waitForInteraction(sessionId, formId, timeout);
|
|
163
|
-
|
|
164
|
-
return {
|
|
165
|
-
success: true,
|
|
166
|
-
formId,
|
|
167
|
-
data: response,
|
|
168
|
-
};
|
|
169
|
-
} catch (error) {
|
|
170
|
-
return {
|
|
171
|
-
success: false,
|
|
172
|
-
formId,
|
|
173
|
-
error: (error as Error).message,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
export function createCanvasClearTool(_config: Config): Tool {
|
|
181
|
-
const log = logger.child("canvas-clear");
|
|
182
|
-
|
|
183
|
-
return {
|
|
184
|
-
name: "canvas_clear",
|
|
185
|
-
description: "Clear the canvas for a session",
|
|
186
|
-
parameters: {
|
|
187
|
-
type: "object",
|
|
188
|
-
properties: {
|
|
189
|
-
sessionId: {
|
|
190
|
-
type: "string",
|
|
191
|
-
description: "Session ID to clear",
|
|
192
|
-
},
|
|
193
|
-
},
|
|
194
|
-
required: [],
|
|
195
|
-
},
|
|
196
|
-
execute: async (params: Record<string, unknown>, config?: any) => {
|
|
197
|
-
const userId = config?.configurable?.user_id;
|
|
198
|
-
const rawSessionId = params.sessionId as string;
|
|
199
|
-
const sessionId = rawSessionId
|
|
200
|
-
? (rawSessionId.startsWith("canvas:") ? rawSessionId : `canvas:${rawSessionId}`)
|
|
201
|
-
: (userId ? `canvas:${userId}` : (() => { throw new Error("No session or user ID provided"); })());
|
|
202
|
-
|
|
203
|
-
log.debug(`Clearing canvas for session ${sessionId}`);
|
|
204
|
-
|
|
205
|
-
await canvasManager.clear(sessionId);
|
|
206
|
-
|
|
207
|
-
return { success: true, sessionId };
|
|
208
|
-
},
|
|
209
|
-
};
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
export function createCanvasTools(config: Config): Tool[] {
|
|
213
|
-
return [
|
|
214
|
-
createCanvasRenderTool(config),
|
|
215
|
-
createCanvasAskTool(config),
|
|
216
|
-
createCanvasClearTool(config),
|
|
217
|
-
createCanvasCardTool(config),
|
|
218
|
-
createCanvasProgressTool(config),
|
|
219
|
-
createCanvasListTool(config),
|
|
220
|
-
createCanvasConfirmTool(config),
|
|
221
|
-
];
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
225
|
-
// Extended Canvas Tools for A2UI
|
|
226
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
227
|
-
|
|
228
|
-
export function createCanvasCardTool(_config: Config): Tool {
|
|
229
|
-
const log = logger.child("canvas-card");
|
|
230
|
-
|
|
231
|
-
return {
|
|
232
|
-
name: "canvas_show_card",
|
|
233
|
-
description: "Display a card with labeled items (useful for showing status, summaries)",
|
|
234
|
-
parameters: {
|
|
235
|
-
type: "object",
|
|
236
|
-
properties: {
|
|
237
|
-
sessionId: { type: "string", description: "Session ID" },
|
|
238
|
-
title: { type: "string", description: "Card title" },
|
|
239
|
-
items: {
|
|
240
|
-
type: "array",
|
|
241
|
-
items: {
|
|
242
|
-
type: "object",
|
|
243
|
-
properties: {
|
|
244
|
-
label: { type: "string" },
|
|
245
|
-
value: { type: "string" },
|
|
246
|
-
variant: { type: "string", enum: ["default", "success", "warning", "danger"] },
|
|
247
|
-
},
|
|
248
|
-
},
|
|
249
|
-
},
|
|
250
|
-
actions: {
|
|
251
|
-
type: "array",
|
|
252
|
-
items: {
|
|
253
|
-
type: "object",
|
|
254
|
-
properties: {
|
|
255
|
-
id: { type: "string" },
|
|
256
|
-
label: { type: "string" },
|
|
257
|
-
variant: { type: "string", enum: ["primary", "secondary", "danger", "success"] },
|
|
258
|
-
},
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
span: {
|
|
262
|
-
type: "string",
|
|
263
|
-
enum: ["full", "half"],
|
|
264
|
-
description: "Width span: 'full' for full-width card, 'half' for half width. Default: single column",
|
|
265
|
-
},
|
|
266
|
-
},
|
|
267
|
-
required: ["items"],
|
|
268
|
-
},
|
|
269
|
-
execute: async (params: Record<string, unknown>, config?: any) => {
|
|
270
|
-
const userId = config?.configurable?.user_id;
|
|
271
|
-
const rawSessionId = params.sessionId as string;
|
|
272
|
-
const sessionId = rawSessionId
|
|
273
|
-
? (rawSessionId.startsWith("canvas:") ? rawSessionId : `canvas:${rawSessionId}`)
|
|
274
|
-
: (userId ? `canvas:${userId}` : (() => { throw new Error("No session or user ID provided"); })());
|
|
275
|
-
const title = (params.title as string) ?? "Information";
|
|
276
|
-
const items = (params.items as Array<{ label: string; value: string; variant?: string }>) ?? [];
|
|
277
|
-
const actions = (params.actions as Array<{ id: string; label: string; variant?: string }>) ?? [];
|
|
278
|
-
const span = params.span as "full" | "half" | undefined;
|
|
279
|
-
|
|
280
|
-
const cardId = `card-${Date.now()}`;
|
|
281
|
-
|
|
282
|
-
await canvasManager.render(sessionId, {
|
|
283
|
-
id: cardId,
|
|
284
|
-
type: "card",
|
|
285
|
-
props: { title, items, actions },
|
|
286
|
-
span,
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
return { success: true, cardId, sessionId };
|
|
290
|
-
},
|
|
291
|
-
};
|
|
292
|
-
}
|
|
293
|
-
|
|
294
|
-
export function createCanvasProgressTool(_config: Config): Tool {
|
|
295
|
-
const log = logger.child("canvas-progress");
|
|
296
|
-
|
|
297
|
-
return {
|
|
298
|
-
name: "canvas_show_progress",
|
|
299
|
-
description: "Display progress bars for tasks (useful for multi-step operations)",
|
|
300
|
-
parameters: {
|
|
301
|
-
type: "object",
|
|
302
|
-
properties: {
|
|
303
|
-
sessionId: { type: "string", description: "Session ID" },
|
|
304
|
-
tasks: {
|
|
305
|
-
type: "array",
|
|
306
|
-
items: {
|
|
307
|
-
type: "object",
|
|
308
|
-
properties: {
|
|
309
|
-
id: { type: "string" },
|
|
310
|
-
name: { type: "string" },
|
|
311
|
-
progress: { type: "number" },
|
|
312
|
-
status: { type: "string", enum: ["pending", "running", "completed", "error"] },
|
|
313
|
-
},
|
|
314
|
-
},
|
|
315
|
-
},
|
|
316
|
-
span: {
|
|
317
|
-
type: "string",
|
|
318
|
-
enum: ["full", "half"],
|
|
319
|
-
description: "Width span: 'full' for full-width, 'half' for half width. Default: single column",
|
|
320
|
-
},
|
|
321
|
-
},
|
|
322
|
-
required: ["tasks"],
|
|
323
|
-
},
|
|
324
|
-
execute: async (params: Record<string, unknown>, config?: any) => {
|
|
325
|
-
const userId = config?.configurable?.user_id;
|
|
326
|
-
const rawSessionId = params.sessionId as string;
|
|
327
|
-
const sessionId = rawSessionId
|
|
328
|
-
? (rawSessionId.startsWith("canvas:") ? rawSessionId : `canvas:${rawSessionId}`)
|
|
329
|
-
: (userId ? `canvas:${userId}` : (() => { throw new Error("No session or user ID provided"); })());
|
|
330
|
-
const tasks = (params.tasks as Array<{ id: string; name: string; progress: number; status?: string }>) ?? [];
|
|
331
|
-
const span = params.span as "full" | "half" | undefined;
|
|
332
|
-
|
|
333
|
-
const progressId = `progress-${Date.now()}`;
|
|
334
|
-
|
|
335
|
-
await canvasManager.render(sessionId, {
|
|
336
|
-
id: progressId,
|
|
337
|
-
type: "progress",
|
|
338
|
-
props: { tasks },
|
|
339
|
-
span,
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
return { success: true, progressId, sessionId };
|
|
343
|
-
},
|
|
344
|
-
};
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
export function createCanvasListTool(_config: Config): Tool {
|
|
348
|
-
const log = logger.child("canvas-list");
|
|
349
|
-
|
|
350
|
-
return {
|
|
351
|
-
name: "canvas_show_list",
|
|
352
|
-
description: "Display a list of key-value pairs (useful for configuration display)",
|
|
353
|
-
parameters: {
|
|
354
|
-
type: "object",
|
|
355
|
-
properties: {
|
|
356
|
-
sessionId: { type: "string", description: "Session ID" },
|
|
357
|
-
title: { type: "string", description: "List title" },
|
|
358
|
-
items: {
|
|
359
|
-
type: "array",
|
|
360
|
-
items: {
|
|
361
|
-
type: "object",
|
|
362
|
-
properties: {
|
|
363
|
-
key: { type: "string" },
|
|
364
|
-
value: { type: "string" },
|
|
365
|
-
},
|
|
366
|
-
},
|
|
367
|
-
},
|
|
368
|
-
span: {
|
|
369
|
-
type: "string",
|
|
370
|
-
enum: ["full", "half"],
|
|
371
|
-
description: "Width span: 'full' for full-width, 'half' for half width. Default: single column",
|
|
372
|
-
},
|
|
373
|
-
},
|
|
374
|
-
required: ["items"],
|
|
375
|
-
},
|
|
376
|
-
execute: async (params: Record<string, unknown>, config?: any) => {
|
|
377
|
-
const userId = config?.configurable?.user_id;
|
|
378
|
-
const rawSessionId = params.sessionId as string;
|
|
379
|
-
const sessionId = rawSessionId
|
|
380
|
-
? (rawSessionId.startsWith("canvas:") ? rawSessionId : `canvas:${rawSessionId}`)
|
|
381
|
-
: (userId ? `canvas:${userId}` : (() => { throw new Error("No session or user ID provided"); })());
|
|
382
|
-
const title = (params.title as string) ?? "Details";
|
|
383
|
-
const items = (params.items as Array<{ key: string; value: string }>) ?? [];
|
|
384
|
-
const span = params.span as "full" | "half" | undefined;
|
|
385
|
-
|
|
386
|
-
const listId = `list-${Date.now()}`;
|
|
387
|
-
|
|
388
|
-
await canvasManager.render(sessionId, {
|
|
389
|
-
id: listId,
|
|
390
|
-
type: "list",
|
|
391
|
-
props: { title, items },
|
|
392
|
-
span,
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
return { success: true, listId, sessionId };
|
|
396
|
-
},
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
export function createCanvasConfirmTool(_config: Config): Tool {
|
|
401
|
-
const log = logger.child("canvas-confirm");
|
|
402
|
-
|
|
403
|
-
return {
|
|
404
|
-
name: "canvas_confirm",
|
|
405
|
-
description: "Show a confirmation dialog and wait for user response",
|
|
406
|
-
parameters: {
|
|
407
|
-
type: "object",
|
|
408
|
-
properties: {
|
|
409
|
-
sessionId: { type: "string", description: "Session ID" },
|
|
410
|
-
title: { type: "string", description: "Dialog title" },
|
|
411
|
-
message: { type: "string", description: "Confirmation message" },
|
|
412
|
-
confirmLabel: { type: "string", description: "Confirm button label" },
|
|
413
|
-
cancelLabel: { type: "string", description: "Cancel button label" },
|
|
414
|
-
danger: { type: "boolean", description: "Show as dangerous action" },
|
|
415
|
-
timeout: { type: "number", description: "Timeout in ms (default: 60000)" },
|
|
416
|
-
},
|
|
417
|
-
required: ["message"],
|
|
418
|
-
},
|
|
419
|
-
execute: async (params: Record<string, unknown>, config?: any) => {
|
|
420
|
-
const userId = config?.configurable?.user_id;
|
|
421
|
-
const rawSessionId = params.sessionId as string;
|
|
422
|
-
const sessionId = rawSessionId
|
|
423
|
-
? (rawSessionId.startsWith("canvas:") ? rawSessionId : `canvas:${rawSessionId}`)
|
|
424
|
-
: (userId ? `canvas:${userId}` : (() => { throw new Error("No session or user ID provided"); })());
|
|
425
|
-
const title = (params.title as string) ?? "Confirm";
|
|
426
|
-
const message = params.message as string;
|
|
427
|
-
const confirmLabel = (params.confirmLabel as string) ?? "Confirm";
|
|
428
|
-
const cancelLabel = (params.cancelLabel as string) ?? "Cancel";
|
|
429
|
-
const danger = (params.danger as boolean) ?? false;
|
|
430
|
-
const timeout = (params.timeout as number) ?? 60000;
|
|
431
|
-
|
|
432
|
-
const confirmId = `confirm-${Date.now()}`;
|
|
433
|
-
|
|
434
|
-
await canvasManager.render(sessionId, {
|
|
435
|
-
id: confirmId,
|
|
436
|
-
type: "confirm",
|
|
437
|
-
props: { title, message, confirmLabel, cancelLabel, danger },
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
try {
|
|
441
|
-
const response = await canvasManager.waitForInteraction(sessionId, confirmId, timeout);
|
|
442
|
-
return { success: true, confirmed: response === true, confirmId, sessionId };
|
|
443
|
-
} catch (error) {
|
|
444
|
-
return { success: false, confirmed: false, confirmId, error: (error as Error).message, sessionId };
|
|
445
|
-
}
|
|
446
|
-
},
|
|
447
|
-
};
|
|
448
|
-
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Document shapes for the harness's HiveDB collections. Ported from `hive`'s
|
|
3
|
-
* durable-task harness, generalized for SDK consumers: `JobDoc.type` and
|
|
4
|
-
* `HarnessRunDoc.kind` are plain strings (not a fixed union) so a host app
|
|
5
|
-
* (hive-cloud, a custom hive-sdk app, etc.) can define its own job/run
|
|
6
|
-
* vocabulary and register executors for it via `registerExecutor()`.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
export interface HarnessRunDoc {
|
|
10
|
-
id: string
|
|
11
|
-
thread_id: string
|
|
12
|
-
agent_id: string
|
|
13
|
-
user_id: string
|
|
14
|
-
channel: string | null
|
|
15
|
-
/** Host-defined run kind, e.g. "chat" | "worker" | "goal". */
|
|
16
|
-
kind: string
|
|
17
|
-
status: "running" | "completed" | "failed" | "interrupted" | "aborted"
|
|
18
|
-
|
|
19
|
-
iterations_used: number
|
|
20
|
-
max_iterations: number
|
|
21
|
-
turns_used: number
|
|
22
|
-
max_turns: number | null
|
|
23
|
-
tokens_used: number
|
|
24
|
-
max_tokens: number | null
|
|
25
|
-
|
|
26
|
-
goal: string | null
|
|
27
|
-
goal_check_tool: string | null
|
|
28
|
-
goal_attempts: number
|
|
29
|
-
|
|
30
|
-
state_json: string
|
|
31
|
-
state_bytes: number
|
|
32
|
-
pending_tool_calls_json: string | null
|
|
33
|
-
checkpointed_at: number
|
|
34
|
-
|
|
35
|
-
boot_id: string
|
|
36
|
-
lease_expires_at: number
|
|
37
|
-
resume_policy: "resume" | "mark_interrupted" | "discard"
|
|
38
|
-
|
|
39
|
-
/** Whole-job acceptance criteria (harness-engineering "proof" concept): JSON array of AcceptanceCriterion. */
|
|
40
|
-
acceptance_json: string | null
|
|
41
|
-
/** Fixed-worker epoch recorded at run creation: RunEpoch JSON. */
|
|
42
|
-
epoch_json: string | null
|
|
43
|
-
|
|
44
|
-
error: string | null
|
|
45
|
-
created_at: number
|
|
46
|
-
updated_at: number
|
|
47
|
-
finished_at: number | null
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface JobDoc {
|
|
51
|
-
id: string
|
|
52
|
-
lane: string
|
|
53
|
-
/** Host-defined job type, e.g. "chat_turn" | "worker_task" | "goal_run". */
|
|
54
|
-
type: string
|
|
55
|
-
status: "pending" | "running" | "completed" | "failed" | "cancelled" | "interrupted"
|
|
56
|
-
priority: number
|
|
57
|
-
payload_json: string
|
|
58
|
-
run_id: string
|
|
59
|
-
attempts: number
|
|
60
|
-
max_attempts: number
|
|
61
|
-
not_before: number
|
|
62
|
-
boot_id: string | null
|
|
63
|
-
lease_expires_at: number | null
|
|
64
|
-
result_json: string | null
|
|
65
|
-
error: string | null
|
|
66
|
-
created_at: number
|
|
67
|
-
started_at: number | null
|
|
68
|
-
finished_at: number | null
|
|
69
|
-
/** Logical-failure retries (executor returned {ok:false, retryable:true}). Separate from `attempts` (crash/lease-expiry only). */
|
|
70
|
-
retry_count: number
|
|
71
|
-
/** Error from the most recent logical-failure retry; `error` stays null until the job is terminal. */
|
|
72
|
-
last_error: string | null
|
|
73
|
-
/** `toIndexable`-encoded — sentinel when unset. Client-supplied dedup key for job creation. */
|
|
74
|
-
idempotency_key: string
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Compressed evidence artifact for a completed run — the "proof packet"
|
|
79
|
-
* concept from harness-engineering's proof/verification practice: what was
|
|
80
|
-
* intended, what was checked, what evidence backs the verdict, known limits.
|
|
81
|
-
*/
|
|
82
|
-
export interface ProofPacketDoc {
|
|
83
|
-
id: string
|
|
84
|
-
run_id: string
|
|
85
|
-
agent_id: string
|
|
86
|
-
intended_outcome: string
|
|
87
|
-
/** Per-acceptance-criterion verdicts: [{id, description, met, evidence}]. */
|
|
88
|
-
acceptance_results_json: string
|
|
89
|
-
/** Names of checks executed (tool ids, LLM verifier, etc). */
|
|
90
|
-
checks_run_json: string
|
|
91
|
-
/** Free-form evidence snippets backing the verdict (tool outputs, verifier reasons). */
|
|
92
|
-
evidence_json: string
|
|
93
|
-
known_limits: string | null
|
|
94
|
-
/** Fixed-worker epoch this run executed under — copied from HarnessRunDoc.epoch_json. */
|
|
95
|
-
epoch_json: string | null
|
|
96
|
-
met: boolean
|
|
97
|
-
created_at: number
|
|
98
|
-
}
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* goal-verifier — verify whether a goal/acceptance-criterion has been met.
|
|
3
|
-
* Ported from `hive`'s agent/goal-runner.ts#verifyGoal, decoupled from
|
|
4
|
-
* `hive`'s goal-run orchestration loop (that's host-app specific — see
|
|
5
|
-
* `harness/collections.ts` doc comment). This module only answers "was it
|
|
6
|
-
* met", using either a caller-provided deterministic check tool or an LLM
|
|
7
|
-
* verifier.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { logger } from "../utils/logger";
|
|
11
|
-
import { callLLM, type LLMMessage, type LLMCallOptions } from "../agent/providers/LLMClient";
|
|
12
|
-
import type { AcceptanceCriterion } from "./run-store";
|
|
13
|
-
|
|
14
|
-
type ProviderConfig = Pick<LLMCallOptions, "provider" | "model" | "apiKey" | "baseUrl" | "numCtx" | "numGpu">;
|
|
15
|
-
|
|
16
|
-
const log = logger.child("harness:goal-verifier");
|
|
17
|
-
|
|
18
|
-
export interface AcceptanceResult {
|
|
19
|
-
id: string;
|
|
20
|
-
description: string;
|
|
21
|
-
met: boolean;
|
|
22
|
-
evidence: string;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export interface GoalVerdict {
|
|
26
|
-
met: boolean;
|
|
27
|
-
reason: string;
|
|
28
|
-
acceptanceResults?: AcceptanceResult[];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Runs a caller-provided check tool and interprets its result (boolean, or
|
|
33
|
-
* an object/string with a `met` field). The harness has no built-in tool
|
|
34
|
-
* registry — the host app resolves `checkTool` to a callable.
|
|
35
|
-
*/
|
|
36
|
-
export type CheckToolRunner = (checkTool: string, args: { goal: string }) => Promise<unknown>;
|
|
37
|
-
|
|
38
|
-
export interface VerifyGoalOptions {
|
|
39
|
-
goal: string;
|
|
40
|
-
checkTool?: string | null;
|
|
41
|
-
messages: LLMMessage[];
|
|
42
|
-
providerCfg: ProviderConfig;
|
|
43
|
-
/** Required when any criterion (or the top-level goal) specifies `checkTool`. */
|
|
44
|
-
runCheckTool?: CheckToolRunner;
|
|
45
|
-
acceptance?: AcceptanceCriterion[] | null;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Verify whether a goal has been met using either a deterministic check
|
|
50
|
-
* tool (via `runCheckTool`) or an LLM verifier. When `acceptance` criteria
|
|
51
|
-
* are supplied, each is verified independently and the overall verdict is
|
|
52
|
-
* the conjunction of all of them — the top-level `goal`/`checkTool` are
|
|
53
|
-
* ignored in that case.
|
|
54
|
-
*/
|
|
55
|
-
export async function verifyGoal(opts: VerifyGoalOptions): Promise<GoalVerdict> {
|
|
56
|
-
const { goal, checkTool, messages, providerCfg, runCheckTool, acceptance } = opts;
|
|
57
|
-
|
|
58
|
-
if (acceptance && acceptance.length > 0) {
|
|
59
|
-
const results: AcceptanceResult[] = [];
|
|
60
|
-
for (const criterion of acceptance) {
|
|
61
|
-
const verdict = await verifyGoal({
|
|
62
|
-
goal: criterion.description,
|
|
63
|
-
checkTool: criterion.checkTool,
|
|
64
|
-
messages,
|
|
65
|
-
providerCfg,
|
|
66
|
-
runCheckTool,
|
|
67
|
-
});
|
|
68
|
-
results.push({ id: criterion.id, description: criterion.description, met: verdict.met, evidence: verdict.reason });
|
|
69
|
-
}
|
|
70
|
-
const met = results.every((r) => r.met);
|
|
71
|
-
const reason = results.map((r) => `${r.met ? "✅" : "❌"} ${r.description}: ${r.evidence}`).join("\n");
|
|
72
|
-
return { met, reason, acceptanceResults: results };
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
if (checkTool) {
|
|
76
|
-
if (!runCheckTool) {
|
|
77
|
-
log.warn(`[verifyGoal] Check tool "${checkTool}" requested but no runCheckTool was provided — falling back to LLM verifier`);
|
|
78
|
-
} else {
|
|
79
|
-
try {
|
|
80
|
-
const result = await runCheckTool(checkTool, { goal });
|
|
81
|
-
return interpretCheckResult(result);
|
|
82
|
-
} catch (err) {
|
|
83
|
-
log.warn(`[verifyGoal] Check tool "${checkTool}" failed: ${(err as Error).message}`);
|
|
84
|
-
// Fall through to LLM verifier
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
try {
|
|
90
|
-
const verificationMessages: LLMMessage[] = [
|
|
91
|
-
...messages,
|
|
92
|
-
{
|
|
93
|
-
role: "user",
|
|
94
|
-
content: `Evaluá si el siguiente objetivo ha sido cumplido basándote en la conversación anterior.\n\nObjetivo: "${goal}"\n\nRespondé en JSON:\n{"met": true/false, "reason": "explicación breve"}`,
|
|
95
|
-
},
|
|
96
|
-
];
|
|
97
|
-
|
|
98
|
-
const response = await callLLM({ ...providerCfg, messages: verificationMessages, tools: undefined });
|
|
99
|
-
|
|
100
|
-
const content = response.content?.trim() || "";
|
|
101
|
-
const jsonMatch = content.match(/\{[^}]*\}/);
|
|
102
|
-
if (jsonMatch) {
|
|
103
|
-
const parsed = JSON.parse(jsonMatch[0]);
|
|
104
|
-
return { met: !!parsed.met, reason: parsed.reason || "No reason provided" };
|
|
105
|
-
}
|
|
106
|
-
return { met: false, reason: "Could not parse verification response" };
|
|
107
|
-
} catch (err) {
|
|
108
|
-
log.warn(`[verifyGoal] LLM verification failed: ${(err as Error).message}`);
|
|
109
|
-
return { met: false, reason: `Verification error: ${(err as Error).message}` };
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
/**
|
|
114
|
-
* Interpret a check tool's result strictly: an object with a boolean `met`,
|
|
115
|
-
* a bare boolean, or a JSON string with `met` — anything else is not met.
|
|
116
|
-
*/
|
|
117
|
-
function interpretCheckResult(raw: unknown): { met: boolean; reason: string } {
|
|
118
|
-
if (typeof raw === "boolean") {
|
|
119
|
-
return { met: raw, reason: raw ? "Check tool returned true" : "Check tool returned false" };
|
|
120
|
-
}
|
|
121
|
-
if (raw && typeof raw === "object" && "met" in (raw as Record<string, unknown>)) {
|
|
122
|
-
const obj = raw as { met: unknown; reason?: unknown };
|
|
123
|
-
return { met: obj.met === true, reason: typeof obj.reason === "string" ? obj.reason : `Check tool met=${obj.met === true}` };
|
|
124
|
-
}
|
|
125
|
-
if (typeof raw === "string") {
|
|
126
|
-
const trimmed = raw.trim();
|
|
127
|
-
if (trimmed === "true" || trimmed === "false") {
|
|
128
|
-
return { met: trimmed === "true", reason: `Check tool returned "${trimmed}"` };
|
|
129
|
-
}
|
|
130
|
-
try {
|
|
131
|
-
const parsed = JSON.parse(trimmed);
|
|
132
|
-
if (parsed && typeof parsed === "object" && "met" in parsed) {
|
|
133
|
-
return { met: parsed.met === true, reason: typeof parsed.reason === "string" ? parsed.reason : `Check tool met=${parsed.met === true}` };
|
|
134
|
-
}
|
|
135
|
-
if (typeof parsed === "boolean") {
|
|
136
|
-
return { met: parsed, reason: `Check tool returned ${parsed}` };
|
|
137
|
-
}
|
|
138
|
-
} catch { /* not JSON */ }
|
|
139
|
-
}
|
|
140
|
-
return { met: false, reason: "Check tool result had no interpretable met/true signal" };
|
|
141
|
-
}
|