@johpaz/hive-sdk 0.1.4 → 0.1.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +129 -0
- package/README.md +78 -23
- package/bun.lock +55 -29
- 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 +17 -12
- 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 +13 -12
- package/packages/core/src/agent/acceptance-checks.ts +172 -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 +76 -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 -27
- 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 -18
- 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-backend.ts +129 -0
- package/packages/core/src/tools/web/browser-screenshot.ts +26 -5
- package/packages/core/src/tools/web/browser-service.ts +80 -35
- 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/tools/web/webview-backend.ts +412 -0
- 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/acceptance-checks.test.ts +403 -0
- package/test/agent-loop-terminal-synthesis.test.ts +32 -0
- package/test/browser-backend.test.ts +308 -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/tool-selector-runtime-tools.test.ts +117 -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
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { Tool } from "../types";
|
|
2
|
+
import { inspectArtifact } from "../../artifacts/store";
|
|
3
|
+
|
|
4
|
+
export const artifactInspectTool: Tool = {
|
|
5
|
+
name: "artifact_inspect",
|
|
6
|
+
description: "Inspect managed artifact metadata, integrity, MIME type and dimensions without returning or modifying its binary content.",
|
|
7
|
+
parameters: {
|
|
8
|
+
type: "object",
|
|
9
|
+
properties: {
|
|
10
|
+
artifactId: {
|
|
11
|
+
type: "string",
|
|
12
|
+
description: "Managed artifact identifier returned by a Hive tool.",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
required: ["artifactId"],
|
|
16
|
+
},
|
|
17
|
+
execute: async (params, config) => {
|
|
18
|
+
const artifactId = String(params.artifactId ?? "").trim();
|
|
19
|
+
if (!artifactId) return { ok: false, error: "artifactId is required" };
|
|
20
|
+
const userId = config?.configurable?.user_id as string | undefined;
|
|
21
|
+
return inspectArtifact(artifactId, { userId });
|
|
22
|
+
},
|
|
23
|
+
};
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BrowserBackend — el contrato que consumen las browser tools.
|
|
3
|
+
*
|
|
4
|
+
* Hay dos implementaciones con perfiles opuestos:
|
|
5
|
+
*
|
|
6
|
+
* - `AgentBrowserBackend` (browser-service.ts): habla con el CLI de
|
|
7
|
+
* agent-browser por subproceso. Maneja Chrome de verdad, corre headless y
|
|
8
|
+
* por lo tanto sirve en Docker y en un servidor sin display. El costo es
|
|
9
|
+
* un `Bun.spawn` por operación —medido en ~68 ms de piso— más una
|
|
10
|
+
* instalación diferida de ~75 MB y la descarga de Chrome.
|
|
11
|
+
*
|
|
12
|
+
* - `WebViewBackend` (webview-backend.ts): usa `Bun.WebView`, in-process.
|
|
13
|
+
* Sin instalación, sin subprocesos, ~0.25 ms por `evaluate`. Necesita un
|
|
14
|
+
* entorno gráfico (WebKitGTK en Linux, WebKit del sistema en macOS), así
|
|
15
|
+
* que no sirve headless.
|
|
16
|
+
*
|
|
17
|
+
* El default sigue siendo agent-browser: es el único de los dos que funciona
|
|
18
|
+
* donde suele correr el gateway. WebView se elige explícitamente.
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export interface ScreenshotOptions {
|
|
22
|
+
encoding?: "blob" | "buffer" | "base64" | "shmem";
|
|
23
|
+
format?: "png" | "jpeg" | "webp";
|
|
24
|
+
quality?: number;
|
|
25
|
+
clip?: { x: number; y: number; width: number; height: number; scale: number };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface SnapshotOptions {
|
|
29
|
+
/** Colapsa nodos sin nombre accesible y recorta el texto largo. Default: true. */
|
|
30
|
+
compact?: boolean;
|
|
31
|
+
/** Profundidad máxima del árbol. */
|
|
32
|
+
depth?: number;
|
|
33
|
+
/** Sólo elementos accionables (links, botones, inputs...). */
|
|
34
|
+
interactiveOnly?: boolean;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* La superficie que las tools de `tools/web/` realmente usan. Se mantuvo
|
|
39
|
+
* deliberadamente chica: cualquier método que se agregue acá hay que
|
|
40
|
+
* implementarlo en los dos backends.
|
|
41
|
+
*/
|
|
42
|
+
export interface BrowserBackend {
|
|
43
|
+
readonly url: string;
|
|
44
|
+
readonly title: string;
|
|
45
|
+
readonly loading: boolean;
|
|
46
|
+
|
|
47
|
+
navigate(url: string): Promise<void>;
|
|
48
|
+
evaluate<T = unknown>(script: string): Promise<T>;
|
|
49
|
+
screenshot(options?: ScreenshotOptions): Promise<string>;
|
|
50
|
+
/** Árbol de accesibilidad en texto — lo que ve el modelo en vez del HTML crudo. */
|
|
51
|
+
snapshot(options?: SnapshotOptions): Promise<string>;
|
|
52
|
+
click(selector: string, options?: Record<string, unknown>): Promise<void>;
|
|
53
|
+
type(text: string): Promise<void>;
|
|
54
|
+
typeIn(selector: string, text: string): Promise<void>;
|
|
55
|
+
fill(selector: string, text: string): Promise<void>;
|
|
56
|
+
press(key: string, options?: { modifiers?: string[] }): Promise<void>;
|
|
57
|
+
scroll(dx: number, dy: number): Promise<void>;
|
|
58
|
+
scrollTo(selector: string, options?: { behavior?: "smooth" | "instant" }): Promise<void>;
|
|
59
|
+
back(): Promise<void>;
|
|
60
|
+
forward(): Promise<void>;
|
|
61
|
+
reload(): Promise<void>;
|
|
62
|
+
resize(width: number, height: number): Promise<void>;
|
|
63
|
+
/** Captura de un elemento puntual; el backend puede recortar sobre el viewport. */
|
|
64
|
+
screenshotElement(selector: string): Promise<string>;
|
|
65
|
+
close(): void;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type BrowserBackendKind = "agent-browser" | "webview";
|
|
69
|
+
|
|
70
|
+
/** `auto` resuelve a webview si el runtime lo soporta; si no, agent-browser. */
|
|
71
|
+
export type BrowserBackendPreference = BrowserBackendKind | "auto";
|
|
72
|
+
|
|
73
|
+
/** Motor que usa `Bun.WebView` por debajo. */
|
|
74
|
+
export type WebViewEngine = "webkit" | "chrome";
|
|
75
|
+
|
|
76
|
+
const CHROME_PATHS = [
|
|
77
|
+
"/usr/bin/google-chrome",
|
|
78
|
+
"/usr/bin/google-chrome-stable",
|
|
79
|
+
"/usr/bin/chromium",
|
|
80
|
+
"/usr/bin/chromium-browser",
|
|
81
|
+
"/snap/bin/chromium",
|
|
82
|
+
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome",
|
|
83
|
+
"/Applications/Chromium.app/Contents/MacOS/Chromium",
|
|
84
|
+
"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe",
|
|
85
|
+
"C:\\Program Files (x86)\\Google\\Chrome\\Application\\chrome.exe",
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
/** Chrome instalado en el sistema — `Bun.WebView` con motor chrome lo necesita. */
|
|
89
|
+
export function findChrome(): string | null {
|
|
90
|
+
if (process.env.BUN_CHROME_PATH) return process.env.BUN_CHROME_PATH;
|
|
91
|
+
const { existsSync } = require("node:fs") as typeof import("node:fs");
|
|
92
|
+
for (const candidate of CHROME_PATHS) {
|
|
93
|
+
if (existsSync(candidate)) return candidate;
|
|
94
|
+
}
|
|
95
|
+
// Último recurso: lo que esté en el PATH del usuario.
|
|
96
|
+
const home = process.env.HOME;
|
|
97
|
+
if (home) {
|
|
98
|
+
for (const name of ["google-chrome", "chromium"]) {
|
|
99
|
+
const local = `${home}/.local/bin/${name}`;
|
|
100
|
+
if (existsSync(local)) return local;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Motor a usar. WebKit no tiene dependencias externas pero sólo existe en macOS;
|
|
108
|
+
* Chrome corre headless en cualquier lado —incluido Docker— siempre que el
|
|
109
|
+
* binario esté instalado.
|
|
110
|
+
*/
|
|
111
|
+
export function resolveWebViewEngine(): WebViewEngine | null {
|
|
112
|
+
if (process.platform === "darwin") return "webkit";
|
|
113
|
+
return findChrome() ? "chrome" : null;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/** `Bun.WebView` existe desde Bun 1.3; además hace falta un motor utilizable. */
|
|
117
|
+
export function isWebViewSupported(): boolean {
|
|
118
|
+
if (typeof (globalThis as { Bun?: { WebView?: unknown } }).Bun?.WebView !== "function") return false;
|
|
119
|
+
return resolveWebViewEngine() !== null;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function resolveBackendKind(
|
|
123
|
+
preference: BrowserBackendPreference | undefined,
|
|
124
|
+
): BrowserBackendKind {
|
|
125
|
+
const wanted = process.env.HIVE_BROWSER_BACKEND ?? preference ?? "agent-browser";
|
|
126
|
+
if (wanted === "webview") return "webview";
|
|
127
|
+
if (wanted === "auto") return isWebViewSupported() ? "webview" : "agent-browser";
|
|
128
|
+
return "agent-browser";
|
|
129
|
+
}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import type { Tool } from "../types.ts";
|
|
10
10
|
import { logger } from "../../utils/logger.ts";
|
|
11
11
|
import { getBrowserService, screenshotElement } from "./browser-service.ts";
|
|
12
|
+
import { createArtifact } from "../../artifacts/store.ts";
|
|
12
13
|
|
|
13
14
|
const log = logger.child("browser-screenshot");
|
|
14
15
|
|
|
@@ -53,7 +54,7 @@ export const browserScreenshotTool: Tool = {
|
|
|
53
54
|
},
|
|
54
55
|
required: [],
|
|
55
56
|
},
|
|
56
|
-
execute: async (params: Record<string, unknown
|
|
57
|
+
execute: async (params: Record<string, unknown>, config?: any) => {
|
|
57
58
|
const url = params.url as string | undefined;
|
|
58
59
|
const fullPage = (params.fullPage as boolean) ?? false;
|
|
59
60
|
const selector = params.selector as string | undefined;
|
|
@@ -99,14 +100,34 @@ export const browserScreenshotTool: Tool = {
|
|
|
99
100
|
}
|
|
100
101
|
|
|
101
102
|
const currentUrl = view.url;
|
|
102
|
-
|
|
103
|
+
const bytes = Buffer.from(screenshot, "base64");
|
|
104
|
+
const effectiveFormat = selector ? "png" : format;
|
|
105
|
+
const mimeType = effectiveFormat === "png" ? "image/png" : "image/jpeg";
|
|
106
|
+
const configurable = config?.configurable ?? {};
|
|
107
|
+
const artifact = await createArtifact({
|
|
108
|
+
bytes,
|
|
109
|
+
mimeType,
|
|
110
|
+
kind: "browser_screenshot",
|
|
111
|
+
userId: String(configurable.user_id ?? ""),
|
|
112
|
+
runId: configurable.run_id ? String(configurable.run_id) : null,
|
|
113
|
+
taskId: configurable.task_id ? String(configurable.task_id) : null,
|
|
114
|
+
rootDir: configurable.artifact_dir ? String(configurable.artifact_dir) : undefined,
|
|
115
|
+
width,
|
|
116
|
+
height,
|
|
117
|
+
});
|
|
118
|
+
log.info(`Screenshot stored as artifact ${artifact.id} (${artifact.size} bytes, ${mimeType})`);
|
|
103
119
|
|
|
104
120
|
return {
|
|
105
121
|
ok: true,
|
|
106
122
|
url: currentUrl,
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
123
|
+
artifact_id: artifact.id,
|
|
124
|
+
kind: artifact.kind,
|
|
125
|
+
mime_type: artifact.mime_type,
|
|
126
|
+
size: artifact.size,
|
|
127
|
+
sha256: artifact.sha256,
|
|
128
|
+
status: artifact.status,
|
|
129
|
+
expires_at: artifact.expires_at,
|
|
130
|
+
format: effectiveFormat,
|
|
110
131
|
fullPage,
|
|
111
132
|
selector,
|
|
112
133
|
viewport: { width, height },
|
|
@@ -1,11 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* BrowserService —
|
|
2
|
+
* BrowserService — automatización de navegador, con backend intercambiable.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* `AgentBrowserBackend` (este archivo) habla con el CLI de agent-browser por
|
|
5
|
+
* subproceso: maneja Chrome de verdad y corre headless, así que es el único que
|
|
6
|
+
* sirve en Docker o en un servidor sin display. Por eso sigue siendo el default.
|
|
7
|
+
*
|
|
8
|
+
* `WebViewBackend` (webview-backend.ts) usa `Bun.WebView` in-process — sin
|
|
9
|
+
* instalación ni subprocesos, mucho más rápido — pero necesita entorno gráfico.
|
|
10
|
+
* Se elige con `tools.browser.backend` o `HIVE_BROWSER_BACKEND`.
|
|
11
|
+
*
|
|
12
|
+
* Flujo del backend por CLI:
|
|
5
13
|
* 1. Detecta si agent-browser está instalado (lazy install en primer uso).
|
|
6
14
|
* 2. Ejecuta comandos via CLI con --json para output estructurado.
|
|
7
15
|
* 3. El daemon de agent-browser maneja Chrome internamente via CDP.
|
|
8
|
-
* 4. Las herramientas de browser usan AgentBrowserView (API compatible con CDPClient).
|
|
9
16
|
*/
|
|
10
17
|
|
|
11
18
|
import { logger } from "../../utils/logger.ts";
|
|
@@ -13,6 +20,13 @@ import type { Config } from "../../config/loader.ts";
|
|
|
13
20
|
import { existsSync, mkdirSync, readFileSync, rmSync } from "fs";
|
|
14
21
|
import { homedir, tmpdir } from "os";
|
|
15
22
|
import { dirname, join, resolve } from "path";
|
|
23
|
+
import {
|
|
24
|
+
resolveBackendKind,
|
|
25
|
+
type BrowserBackend,
|
|
26
|
+
type BrowserBackendKind,
|
|
27
|
+
type ScreenshotOptions,
|
|
28
|
+
type SnapshotOptions,
|
|
29
|
+
} from "./browser-backend.ts";
|
|
16
30
|
|
|
17
31
|
const log = logger.child("browser-service");
|
|
18
32
|
|
|
@@ -117,7 +131,7 @@ async function ensureChromeInstalled(): Promise<void> {
|
|
|
117
131
|
|
|
118
132
|
// ─── AgentBrowserView (API compatible con CDPClient) ──────────────────────────
|
|
119
133
|
|
|
120
|
-
export class AgentBrowserView {
|
|
134
|
+
export class AgentBrowserView implements BrowserBackend {
|
|
121
135
|
private sessionName: string;
|
|
122
136
|
private _url = "";
|
|
123
137
|
|
|
@@ -162,12 +176,7 @@ export class AgentBrowserView {
|
|
|
162
176
|
return res.data?.result as T;
|
|
163
177
|
}
|
|
164
178
|
|
|
165
|
-
async screenshot(options?: {
|
|
166
|
-
encoding?: "blob" | "buffer" | "base64" | "shmem";
|
|
167
|
-
format?: "png" | "jpeg" | "webp";
|
|
168
|
-
quality?: number;
|
|
169
|
-
clip?: { x: number; y: number; width: number; height: number; scale: number };
|
|
170
|
-
}): Promise<string> {
|
|
179
|
+
async screenshot(options?: ScreenshotOptions): Promise<string> {
|
|
171
180
|
// Build args
|
|
172
181
|
const args: string[] = ["screenshot"];
|
|
173
182
|
|
|
@@ -178,6 +187,11 @@ export class AgentBrowserView {
|
|
|
178
187
|
args.push("--screenshot-quality", String(options.quality));
|
|
179
188
|
}
|
|
180
189
|
|
|
190
|
+
// If clip/selector is provided, agent-browser screenshot accepts a positional selector
|
|
191
|
+
// For element screenshots, we can pass a selector as first positional arg
|
|
192
|
+
// But we don't have selector in options here — the old CDPClient didn't use it either
|
|
193
|
+
// screenshotElement helper handles element-specific screenshots
|
|
194
|
+
|
|
181
195
|
const res = await this.run(args);
|
|
182
196
|
if (!res.success) throw new Error(res.error || "screenshot failed");
|
|
183
197
|
|
|
@@ -259,8 +273,21 @@ export class AgentBrowserView {
|
|
|
259
273
|
if (!res.success) throw new Error(res.error || "resize failed");
|
|
260
274
|
}
|
|
261
275
|
|
|
276
|
+
/** Screenshot recortado a un elemento — agent-browser acepta el selector posicional. */
|
|
277
|
+
async screenshotElement(selector: string): Promise<string> {
|
|
278
|
+
const res = await this.run(["screenshot", selector]);
|
|
279
|
+
if (!res.success) throw new Error(res.error || `screenshot failed: ${selector}`);
|
|
280
|
+
|
|
281
|
+
const path = res.data?.path as string;
|
|
282
|
+
if (!path) throw new Error("screenshot did not return a path");
|
|
283
|
+
|
|
284
|
+
const base64 = Buffer.from(readFileSync(path)).toString("base64");
|
|
285
|
+
try { rmSync(path); } catch { /* ignore */ }
|
|
286
|
+
return base64;
|
|
287
|
+
}
|
|
288
|
+
|
|
262
289
|
/** Capture accessibility tree snapshot (compact, AI-optimized). ~200-600 chars vs ~3000+ innerText. */
|
|
263
|
-
async snapshot(options?:
|
|
290
|
+
async snapshot(options?: SnapshotOptions): Promise<string> {
|
|
264
291
|
const args = ["snapshot"];
|
|
265
292
|
if (options?.compact !== false) args.push("-c");
|
|
266
293
|
if (options?.depth) args.push("-d", String(options.depth));
|
|
@@ -321,11 +348,17 @@ export type LaunchSpec = { kind: "remote"; cdpUrl: string };
|
|
|
321
348
|
|
|
322
349
|
// ─── BrowserService (singleton) ───────────────────────────────────────────────
|
|
323
350
|
|
|
324
|
-
|
|
351
|
+
/** Alias histórico: las tools sólo dependen del contrato, no de la implementación. */
|
|
352
|
+
export type BrowserView = BrowserBackend;
|
|
353
|
+
|
|
354
|
+
/** Re-export para que quien importe el servicio no tenga que conocer el módulo del contrato. */
|
|
355
|
+
export type { BrowserBackend, BrowserBackendKind } from "./browser-backend.ts";
|
|
356
|
+
export { isWebViewSupported, resolveBackendKind } from "./browser-backend.ts";
|
|
325
357
|
|
|
326
|
-
let _client:
|
|
358
|
+
let _client: BrowserBackend | null = null;
|
|
327
359
|
let _available = false;
|
|
328
360
|
let _launching = false;
|
|
361
|
+
let _kind: BrowserBackendKind = "agent-browser";
|
|
329
362
|
|
|
330
363
|
export class BrowserService {
|
|
331
364
|
private static instance: BrowserService | null = null;
|
|
@@ -352,6 +385,17 @@ export class BrowserService {
|
|
|
352
385
|
return false;
|
|
353
386
|
}
|
|
354
387
|
|
|
388
|
+
_kind = resolveBackendKind(b?.backend);
|
|
389
|
+
|
|
390
|
+
if (_kind === "webview") {
|
|
391
|
+
// No hay nada que instalar ni que descargar: el WebView se crea al primer
|
|
392
|
+
// uso. Si el entorno no lo soporta, ensureView() falla ahí y el servicio
|
|
393
|
+
// queda no disponible, igual que cuando agent-browser no arranca.
|
|
394
|
+
_available = true;
|
|
395
|
+
log.info("✅ Backend de navegador: Bun.WebView (in-process, sin Chrome)");
|
|
396
|
+
return true;
|
|
397
|
+
}
|
|
398
|
+
|
|
355
399
|
const installed = await isAgentBrowserInstalled();
|
|
356
400
|
|
|
357
401
|
if (!installed) {
|
|
@@ -387,8 +431,13 @@ export class BrowserService {
|
|
|
387
431
|
}
|
|
388
432
|
_launching = true;
|
|
389
433
|
try {
|
|
390
|
-
|
|
391
|
-
|
|
434
|
+
if (_kind === "webview") {
|
|
435
|
+
const { WebViewBackend } = await import("./webview-backend.ts");
|
|
436
|
+
_client = new WebViewBackend({ show: this.config.tools?.browser?.headless === false });
|
|
437
|
+
} else {
|
|
438
|
+
const sessionName = this.config.tools?.browser?.sessionName ?? DEFAULT_SESSION_NAME;
|
|
439
|
+
_client = new AgentBrowserView(sessionName);
|
|
440
|
+
}
|
|
392
441
|
log.info("✅ Browser abierto — el usuario verá las acciones del agente");
|
|
393
442
|
return true;
|
|
394
443
|
} catch (err) {
|
|
@@ -401,20 +450,25 @@ export class BrowserService {
|
|
|
401
450
|
}
|
|
402
451
|
}
|
|
403
452
|
|
|
404
|
-
async getView(): Promise<
|
|
453
|
+
async getView(): Promise<BrowserBackend | null> {
|
|
405
454
|
if (!_available) return null;
|
|
406
455
|
await this._ensureLaunched();
|
|
407
456
|
return _client;
|
|
408
457
|
}
|
|
409
458
|
|
|
410
|
-
getViewSync():
|
|
459
|
+
getViewSync(): BrowserBackend | null {
|
|
411
460
|
return _client;
|
|
412
461
|
}
|
|
413
462
|
|
|
414
|
-
async getPage(): Promise<
|
|
463
|
+
async getPage(): Promise<BrowserBackend | null> {
|
|
415
464
|
return this.getView();
|
|
416
465
|
}
|
|
417
466
|
|
|
467
|
+
/** Qué backend quedó activo — lo reporta `hive doctor` y los tests. */
|
|
468
|
+
getBackendKind(): BrowserBackendKind {
|
|
469
|
+
return _kind;
|
|
470
|
+
}
|
|
471
|
+
|
|
418
472
|
isAvailable(): boolean {
|
|
419
473
|
return _available;
|
|
420
474
|
}
|
|
@@ -423,8 +477,8 @@ export class BrowserService {
|
|
|
423
477
|
return _available && _client !== null;
|
|
424
478
|
}
|
|
425
479
|
|
|
426
|
-
getInfo(): { running: boolean } {
|
|
427
|
-
return { running: this.isRunning() };
|
|
480
|
+
getInfo(): { running: boolean; backend: BrowserBackendKind } {
|
|
481
|
+
return { running: this.isRunning(), backend: _kind };
|
|
428
482
|
}
|
|
429
483
|
|
|
430
484
|
async stop(): Promise<void> {
|
|
@@ -457,7 +511,7 @@ export function getBrowserService(): BrowserService | null {
|
|
|
457
511
|
// ─── Helpers (misma API que antes) ───────────────────────────────────────────
|
|
458
512
|
|
|
459
513
|
export async function waitForSelector(
|
|
460
|
-
view:
|
|
514
|
+
view: BrowserBackend,
|
|
461
515
|
selector: string,
|
|
462
516
|
timeout = 30000
|
|
463
517
|
): Promise<void> {
|
|
@@ -471,7 +525,7 @@ export async function waitForSelector(
|
|
|
471
525
|
}
|
|
472
526
|
|
|
473
527
|
export async function waitForCondition(
|
|
474
|
-
view:
|
|
528
|
+
view: BrowserBackend,
|
|
475
529
|
expression: string,
|
|
476
530
|
timeout = 30000
|
|
477
531
|
): Promise<void> {
|
|
@@ -485,19 +539,10 @@ export async function waitForCondition(
|
|
|
485
539
|
}
|
|
486
540
|
|
|
487
541
|
export async function screenshotElement(
|
|
488
|
-
view:
|
|
542
|
+
view: BrowserBackend,
|
|
489
543
|
selector: string
|
|
490
544
|
): Promise<string> {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
const path = res.data?.path as string;
|
|
495
|
-
if (!path) throw new Error("screenshot did not return a path");
|
|
496
|
-
|
|
497
|
-
const data = readFileSync(path);
|
|
498
|
-
const base64 = Buffer.from(data).toString("base64");
|
|
499
|
-
|
|
500
|
-
try { rmSync(path); } catch { /* ignore */ }
|
|
501
|
-
|
|
502
|
-
return base64;
|
|
545
|
+
// Antes esto hacía `(view as any).run([...])`, atándose a la implementación por
|
|
546
|
+
// CLI: con dos backends el recorte es responsabilidad de cada uno.
|
|
547
|
+
return view.screenshotElement(selector);
|
|
503
548
|
}
|
|
@@ -68,17 +68,12 @@ export const browserTypeTool: Tool = {
|
|
|
68
68
|
await Bun.sleep(500);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
// click(selector) waits for actionability then focuses the element
|
|
72
|
-
await view.click(selector, { timeout });
|
|
73
|
-
|
|
74
71
|
if (clear) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
await view.
|
|
72
|
+
await (view as any).fill(selector, text);
|
|
73
|
+
} else {
|
|
74
|
+
await (view as any).typeIn(selector, text);
|
|
78
75
|
}
|
|
79
76
|
|
|
80
|
-
await view.type(text);
|
|
81
|
-
|
|
82
77
|
const currentUrl = view.url;
|
|
83
78
|
log.info(`Type successful: "${text.substring(0, 50)}${text.length > 50 ? "..." : ""}" into ${selector}`);
|
|
84
79
|
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Web Tools - Browser automation + Web utilities
|
|
3
3
|
*
|
|
4
|
-
* Browser tools use
|
|
4
|
+
* Browser tools use agent-browser (Rust CLI, auto-managed).
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { Tool } from "../types.ts";
|
|
8
8
|
import { webSearchTool } from "./web-search.ts";
|
|
9
9
|
import { webFetchTool } from "./web-fetch.ts";
|
|
10
|
-
import { apiRequestTool } from "./api-request.ts";
|
|
11
10
|
import { browserNavigateTool } from "./browser-navigate.ts";
|
|
12
11
|
import { browserScreenshotTool } from "./browser-screenshot.ts";
|
|
13
12
|
import { browserClickTool } from "./browser-click.ts";
|
|
@@ -15,12 +14,12 @@ import { browserTypeTool } from "./browser-type.ts";
|
|
|
15
14
|
import { browserExtractTool } from "./browser-extract.ts";
|
|
16
15
|
import { browserScriptTool } from "./browser-script.ts";
|
|
17
16
|
import { browserWaitTool } from "./browser-wait.ts";
|
|
17
|
+
import { artifactInspectTool } from "./artifact-inspect.ts";
|
|
18
18
|
|
|
19
19
|
export function createTools(): Tool[] {
|
|
20
20
|
return [
|
|
21
21
|
webSearchTool,
|
|
22
22
|
webFetchTool,
|
|
23
|
-
apiRequestTool,
|
|
24
23
|
browserNavigateTool,
|
|
25
24
|
browserScreenshotTool,
|
|
26
25
|
browserClickTool,
|
|
@@ -28,12 +27,12 @@ export function createTools(): Tool[] {
|
|
|
28
27
|
browserExtractTool,
|
|
29
28
|
browserScriptTool,
|
|
30
29
|
browserWaitTool,
|
|
30
|
+
artifactInspectTool,
|
|
31
31
|
];
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
export * from "./web-search.ts";
|
|
35
35
|
export * from "./web-fetch.ts";
|
|
36
|
-
export * from "./api-request.ts";
|
|
37
36
|
export * from "./browser-navigate.ts";
|
|
38
37
|
export * from "./browser-screenshot.ts";
|
|
39
38
|
export * from "./browser-click.ts";
|
|
@@ -42,3 +41,4 @@ export * from "./browser-extract.ts";
|
|
|
42
41
|
export * from "./browser-script.ts";
|
|
43
42
|
export * from "./browser-wait.ts";
|
|
44
43
|
export * from "./browser-service.ts";
|
|
44
|
+
export * from "./artifact-inspect.ts";
|