@johpaz/hive-sdk 0.4.4 → 0.4.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 +20 -4
- package/README.md +48 -7
- package/SECURITY.md +17 -0
- package/docs/API-AGENTS.md +430 -0
- package/docs/API-ARTIFACTS.md +55 -0
- package/docs/API-CONTEXT-COMPILER.md +285 -0
- package/docs/API-CRON.md +188 -0
- package/docs/API-DAG-SCHEDULER.md +291 -0
- package/docs/API-HOOKS.md +147 -0
- package/docs/API-RESILIENCE.md +45 -0
- package/docs/API-SERVICES.md +458 -0
- package/docs/API-SESSIONS.md +146 -0
- package/docs/API-TOOLS-SKILLS-CHANNELS.md +499 -0
- package/docs/API-WORKERS-EVENTS.md +311 -0
- package/docs/HIVE-HARNESS.md +232 -0
- package/docs/INDEX.md +198 -0
- package/docs/SECURITY-GUARDRAILS.md +87 -0
- package/docs/TEMPLATE-HIVE-APP.md +360 -0
- package/docs/UPGRADING.md +65 -0
- package/docs/assets/logoblack.png +0 -0
- package/docs/assets/logocolor-dark.png +0 -0
- package/docs/assets/logocolorbg.png +0 -0
- package/docs/plans/2026-09-05-office-dependency-hardening-design.md +28 -0
- package/docs/plans/2026-09-06-dependency-audit-remediation-design.md +25 -0
- package/docs/plans/2026-09-06-pptx-image-size-remediation-design.md +54 -0
- package/docs/plans/2026-09-06-typescript7-bun142-documentation-design.md +48 -0
- package/package.json +5 -4
- package/packages/core/src/agent/llm-providers/hiveagents.ts +2 -2
- package/packages/core/src/agent/providers/index.ts +17 -1
- package/packages/core/src/api/createAgent.ts +4 -2
- package/packages/core/src/gateway/server.ts +1 -1
- package/packages/core/src/mcp/transports/sse.ts +11 -3
- package/packages/core/src/mcp/transports/websocket.ts +11 -9
- package/packages/core/src/tool-runtime/tool-worker.ts +3 -1
- package/packages/core/src/tools/office/office-escribir-pptx.ts +3 -1
- package/packages/core/src/vendor/pptxgenjs/LICENSE +21 -0
- package/packages/core/src/vendor/pptxgenjs/README.md +17 -0
- package/packages/core/src/vendor/pptxgenjs/pptxgen.es.d.ts +17 -0
- package/packages/core/src/vendor/pptxgenjs/pptxgen.es.js +7368 -0
- package/packages/core/src/voice/index.ts +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
## Sin publicar
|
|
4
4
|
|
|
5
|
+
### Plataforma y seguridad
|
|
6
|
+
|
|
7
|
+
- Runtime mínimo actualizado a **Bun 1.4.2** en `engines`, CI, publicación y
|
|
8
|
+
aplicaciones generadas.
|
|
9
|
+
- Compilador actualizado a **TypeScript 7.0.2**. Se adaptaron las fronteras de
|
|
10
|
+
streams SSE, opciones WebSocket de Bun y memoria de audio a los tipos nuevos,
|
|
11
|
+
sin desactivar el chequeo.
|
|
12
|
+
- Corregidas las alertas altas de PDF.js y SheetJS; los lectores Office ahora
|
|
13
|
+
limitan tamaño, páginas, hojas, filas y tiempo de procesamiento, y PDF.js
|
|
14
|
+
desactiva scripting y evaluación dinámica.
|
|
15
|
+
- Eliminada la cadena vulnerable `pptxgenjs > image-size`. Hive conserva sólo
|
|
16
|
+
el artefacto ESM oficial necesario para PPTX de texto, con licencia,
|
|
17
|
+
procedencia, hash y una prueba funcional del OOXML generado.
|
|
18
|
+
- Añadidas las guías `docs/UPGRADING.md` y
|
|
19
|
+
`docs/SECURITY-GUARDRAILS.md` para operación y auditoría.
|
|
20
|
+
|
|
5
21
|
### Corregido
|
|
6
22
|
|
|
7
23
|
- **`browser_scrape` extraía con una tool que no ve lo que el navegador
|
|
@@ -103,9 +119,9 @@
|
|
|
103
119
|
runtime. `cron-parser` además ni siquiera se importaba: estaba declarada en
|
|
104
120
|
los dos `package.json` y se la bajaba todo el que instalara el SDK.
|
|
105
121
|
|
|
106
|
-
`Bun.cron()` **no** sirve como reemplazo —
|
|
122
|
+
`Bun.cron()` **no** sirve como reemplazo —reevaluado contra Bun 1.4.2—:
|
|
107
123
|
acepta sólo 5 campos, rechaza una fecha ISO como patrón (que es como se
|
|
108
|
-
agendan los jobs `one_shot`),
|
|
124
|
+
agendan los jobs `one_shot`), no acepta una zona distinta por job, y su handle
|
|
109
125
|
no expone la próxima corrida, de donde sale `next_run_at` y con lo que se
|
|
110
126
|
detectan las corridas perdidas al arrancar. Tampoco tiene equivalente de
|
|
111
127
|
`protect`, `maxRuns`, `interval`, `startAt`/`stopAt` ni `domAndDow`, todos
|
|
@@ -227,7 +243,7 @@
|
|
|
227
243
|
de una browser tool. Una versión flotante bajada de npm en runtime, en
|
|
228
244
|
producción. Eso ya no existe.
|
|
229
245
|
|
|
230
|
-
Requisitos ahora: un Chromium instalado (o `BUN_CHROME_PATH`) y **Bun ≥ 1.4**,
|
|
246
|
+
Requisitos ahora: un Chromium instalado (o `BUN_CHROME_PATH`) y **Bun ≥ 1.4.2**,
|
|
231
247
|
declarado en `engines`. La clave de config `tools.browser.backend` sobrevive:
|
|
232
248
|
`"agent-browser"` se acepta, avisa una vez y usa el WebView, así que las
|
|
233
249
|
configuraciones viejas no se rompen.
|
|
@@ -242,7 +258,7 @@
|
|
|
242
258
|
—clic por coordenadas, escribir, navegar— cuando no hay un selector CSS
|
|
243
259
|
estable (canvas, UIs generadas, visores embebidos).
|
|
244
260
|
|
|
245
|
-
- CI actualizado a **Bun 1.4.
|
|
261
|
+
- CI actualizado a **Bun 1.4.2**, alineado con `hive`.
|
|
246
262
|
|
|
247
263
|
### Quitado
|
|
248
264
|
|
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ bun add @johpaz/hive-sdk
|
|
|
18
18
|
|
|
19
19
|
- **Agentes**: ciclo ReAct nativo con checkpoint durable, 16 providers LLM y descubrimiento de tools/skills por búsqueda BM25.
|
|
20
20
|
- **Catálogo**: 18 providers y 110 modelos sembrados, cada uno con su precio por millón de tokens — una sola fuente de verdad para el costo.
|
|
21
|
-
- **Tools**: 60 tools incluidas — filesystem, web search, browser automation (`Bun.WebView`), APIs (`api_request`), a2ui, office, cron, delegación.
|
|
21
|
+
- **Tools**: 60 tools incluidas — filesystem, web search, browser automation (`Bun.WebView`), APIs (`api_request`), a2ui, office, cron, delegación. Las de office validan la entrada antes de parsear (PDF 25 MiB, XLSX 15 MiB, 200 páginas, 50 hojas, 10 000 filas por hoja, 30 s de tope) y devuelven un error de tool en vez de truncar en silencio — importa cuando el archivo lo sube un tercero. Ver [SECURITY-GUARDRAILS.md](./docs/SECURITY-GUARDRAILS.md).
|
|
22
22
|
- **Skills**: 23 workflows bundled, más los tuyos con `defineSkill` y `SkillLoader`.
|
|
23
23
|
- **Canales**: Telegram, Discord, WhatsApp, Slack y WebChat con `ChannelManager`.
|
|
24
24
|
- **Swarm**: orquestación multi-agente con `DAGScheduler`, `TaskGraph` y `WorkerPool`.
|
|
@@ -38,12 +38,39 @@ mismo CRUD que usan las tools, en funciones tipadas.
|
|
|
38
38
|
|
|
39
39
|
## Instalación
|
|
40
40
|
|
|
41
|
-
> **Requiere Bun.** El paquete se publica como TypeScript y usa APIs de Bun
|
|
41
|
+
> **Requiere Bun 1.4.2 o posterior y TypeScript 7.0.2.** El paquete se publica como TypeScript y usa APIs de Bun
|
|
42
42
|
> (`Bun.secrets`, `Bun.spawn`, Workers) en 18 archivos del core, así que no
|
|
43
43
|
> corre sobre Node aunque se le apliquen los flags de type-stripping. Si tu
|
|
44
44
|
> backend es Node, hoy la vía es un proceso Bun aparte; el build a JS que
|
|
45
45
|
> levantaría esa restricción todavía no existe.
|
|
46
46
|
|
|
47
|
+
### Compilar el SDK desde tu proyecto
|
|
48
|
+
|
|
49
|
+
Como el paquete se publica **en TypeScript**, tu `tsc` no lee declaraciones ya
|
|
50
|
+
validadas: recompila el código del SDK con **tu** configuración. Eso significa que
|
|
51
|
+
`skipLibCheck` no ayuda —sólo salta archivos `.d.ts`, y acá son `.ts` de verdad— y
|
|
52
|
+
que una config más estricta que la del SDK puede sacar errores en código que no
|
|
53
|
+
escribiste.
|
|
54
|
+
|
|
55
|
+
El SDK se mantiene compilable en los dos entornos de tipos que importan:
|
|
56
|
+
|
|
57
|
+
| entorno | `lib` | `types` | `strict` | errores |
|
|
58
|
+
|---|---|---|---|---|
|
|
59
|
+
| el del SDK | `ESNext, DOM, DOM.Iterable` | — | `false` | 0 |
|
|
60
|
+
| servidor (Bun) | `ES2022` | `["bun"]` | `true` | 0 |
|
|
61
|
+
|
|
62
|
+
Para lograrlo, el core no usa alias que sólo existen en la lib DOM
|
|
63
|
+
(`RequestInfo`, `HeadersInit`, `BlobPart`): las uniones van escritas. Si tu
|
|
64
|
+
proyecto es un backend, no necesitás agregar `DOM` a tu `lib` para consumirlo
|
|
65
|
+
—y no conviene, porque `BufferSource` y `BlobPart` de DOM chocan con
|
|
66
|
+
`Uint8Array` y `Buffer` de Node en tu propio código.
|
|
67
|
+
|
|
68
|
+
Los `*.test.ts` no se publican, así que nada de la suite entra en tu typecheck.
|
|
69
|
+
|
|
70
|
+
Para actualizar un proyecto existente, consulta [UPGRADING.md](./docs/UPGRADING.md).
|
|
71
|
+
Los límites de entrada y controles de runtime están inventariados en
|
|
72
|
+
[SECURITY-GUARDRAILS.md](./docs/SECURITY-GUARDRAILS.md).
|
|
73
|
+
|
|
47
74
|
```bash
|
|
48
75
|
# Instalar globalmente para el CLI
|
|
49
76
|
bun install -g @johpaz/hive-sdk
|
|
@@ -159,10 +186,15 @@ console.log(`Gateway at http://127.0.0.1:18790`);
|
|
|
159
186
|
HIVE_HOME=~/.hive # Directorio de datos (HiveDB vive en <HIVE_HOME>/data)
|
|
160
187
|
HIVE_DB_PATH= # Ruta explícita de la base; ":memory:" para efímera
|
|
161
188
|
HIVE_HOST=127.0.0.1 # Gateway host
|
|
162
|
-
HIVE_PORT=18790 # Gateway port
|
|
189
|
+
HIVE_PORT=18790 # Gateway port (inválido → avisa y usa el default)
|
|
163
190
|
LOG_LEVEL=info # debug | info | warn | error
|
|
164
191
|
```
|
|
165
192
|
|
|
193
|
+
Desde Bun 1.4 `Bun.serve` lanza `RangeError` con un puerto fuera de `[0, 65535]`
|
|
194
|
+
o con `NaN` —lo que devuelve `parseInt("no-es-un-numero")`— en vez de recortarlo,
|
|
195
|
+
así que un `HIVE_PORT` mal escrito tumbaba el arranque con una excepción sin
|
|
196
|
+
capturar. El SDK lo resuelve con `resolvePort`: avisa y sigue con el default.
|
|
197
|
+
|
|
166
198
|
La API key de cada provider se guarda cifrada en la base. Como alternativa, el
|
|
167
199
|
SDK cae a `<PROVIDER>_API_KEY` del entorno, en mayúsculas y con el id del
|
|
168
200
|
provider tal cual:
|
|
@@ -179,15 +211,24 @@ OPENROUTER_API_KEY=sk-or-...
|
|
|
179
211
|
## Tests
|
|
180
212
|
|
|
181
213
|
```bash
|
|
182
|
-
#
|
|
214
|
+
# Toda la suite
|
|
183
215
|
bun test
|
|
184
216
|
|
|
185
|
-
#
|
|
217
|
+
# Repartida entre procesos, uno por núcleo
|
|
218
|
+
bun test --parallel
|
|
219
|
+
|
|
220
|
+
# Timeout extendido
|
|
186
221
|
bun test --timeout 60000
|
|
187
222
|
```
|
|
188
223
|
|
|
224
|
+
`--parallel` (Bun 1.4) reparte los archivos entre procesos e implica
|
|
225
|
+
`--isolate`, un global nuevo por archivo. Medido en este repo: **48 s → 18 s**,
|
|
226
|
+
con resultados idénticos. Es lo que corre CI; en local `bun test` a secas sigue
|
|
227
|
+
siendo secuencial, que da una salida más legible cuando estás sobre un archivo.
|
|
228
|
+
|
|
189
229
|
La suite usa una base efímera (`HIVE_DB_PATH=":memory:"`, fijado en
|
|
190
|
-
`test/preload.ts`) para no escribir en la del usuario.
|
|
230
|
+
`test/preload.ts`) para no escribir en la del usuario. El `preload` sigue
|
|
231
|
+
corriendo por archivo bajo `--isolate`.
|
|
191
232
|
|
|
192
233
|
## Publicar
|
|
193
234
|
|
|
@@ -230,4 +271,4 @@ npm view @johpaz/hive-sdk dist-tags # verificar después del release
|
|
|
230
271
|
|
|
231
272
|
---
|
|
232
273
|
|
|
233
|
-
*Hive SDK v0.4.
|
|
274
|
+
*Hive SDK v0.4.5 — MIT*
|
package/SECURITY.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Security policy
|
|
2
|
+
|
|
3
|
+
Los controles de entrada, dependencias, runtime y publicación están
|
|
4
|
+
documentados en [`docs/SECURITY-GUARDRAILS.md`](docs/SECURITY-GUARDRAILS.md).
|
|
5
|
+
|
|
6
|
+
## Vendored security-sensitive dependencies
|
|
7
|
+
|
|
8
|
+
### PptxGenJS 4.0.1 ESM
|
|
9
|
+
|
|
10
|
+
Hive vendors the official PptxGenJS 4.0.1 ESM artifact for the text-only
|
|
11
|
+
`office_escribir_pptx` tool. The upstream npm package declares the vulnerable
|
|
12
|
+
`image-size` package even though its ESM artifact does not import it. Vendoring
|
|
13
|
+
that artifact removes `image-size` from Hive's installable dependency graph.
|
|
14
|
+
|
|
15
|
+
The vendored copy, license, provenance, and update instructions live in
|
|
16
|
+
`packages/core/src/vendor/pptxgenjs/`. Do not expose PPTX image input without a
|
|
17
|
+
new security review.
|
|
@@ -0,0 +1,430 @@
|
|
|
1
|
+
# API Reference — Agentes
|
|
2
|
+
|
|
3
|
+
## Índice
|
|
4
|
+
|
|
5
|
+
1. [createAgent](#createagent)
|
|
6
|
+
2. [AgentLoop](#agentloop)
|
|
7
|
+
3. [Tool Selector](#tool-selector)
|
|
8
|
+
4. [Skill Selector](#skill-selector)
|
|
9
|
+
5. [LLM Providers](#llm-providers)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## createAgent
|
|
14
|
+
|
|
15
|
+
Función de alto nivel para crear y ejecutar agentes.
|
|
16
|
+
|
|
17
|
+
### Firma
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { createAgent } from "@johpaz/hive-sdk";
|
|
21
|
+
|
|
22
|
+
const agent = await createAgent(config: AgentConfig): Promise<Agent>
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### AgentConfig
|
|
26
|
+
|
|
27
|
+
```typescript
|
|
28
|
+
interface AgentConfig {
|
|
29
|
+
name: string;
|
|
30
|
+
model?: string; // id tal como lo nombra su dueño, ej. "claude-opus-5"
|
|
31
|
+
provider?: Provider; // cualquiera de los 16 del catálogo
|
|
32
|
+
systemPrompt?: string;
|
|
33
|
+
tools?: ToolDefinition[]; // Tools custom
|
|
34
|
+
skills?: SkillDefinition[]; // Skills custom
|
|
35
|
+
mcpServers?: Record<string, { // Servidores MCP
|
|
36
|
+
command?: string; // STDIO transport
|
|
37
|
+
url?: string; // SSE transport
|
|
38
|
+
args?: string[];
|
|
39
|
+
env?: Record<string, string>;
|
|
40
|
+
}>;
|
|
41
|
+
maxIterations?: number;
|
|
42
|
+
workspace?: string;
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
La config **se persiste en la fila del agente**, que es de donde el loop resuelve
|
|
47
|
+
provider y modelo en cada turno. Consecuencias que conviene tener presentes:
|
|
48
|
+
|
|
49
|
+
- `model` exige `provider`: el mismo modelo lo sirven varios providers y la clave
|
|
50
|
+
del catálogo depende de cuál. Sin provider, `createAgent` lanza.
|
|
51
|
+
- El modelo tiene que existir en `SEED_DATA.models`, o lanza con el nombre del
|
|
52
|
+
provider al que no pertenece.
|
|
53
|
+
- `name` deriva el id del agente (`"Mi Agente"` → `mi_agente`), así que dos
|
|
54
|
+
`createAgent` con el mismo nombre comparten fila e historial.
|
|
55
|
+
- Las tools pasadas acá quedan registradas **y** indexadas, así que el modelo
|
|
56
|
+
puede descubrirlas con `search_knowledge` como a las nativas.
|
|
57
|
+
|
|
58
|
+
> Hasta 0.1.5 `provider`, `model`, `maxIterations`, `skills` y `workspace` se
|
|
59
|
+
> aceptaban y se descartaban: el agente corría con lo que hubiera en la base.
|
|
60
|
+
|
|
61
|
+
### Agent
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
interface Agent {
|
|
65
|
+
readonly name: string;
|
|
66
|
+
readonly config: AgentConfig;
|
|
67
|
+
|
|
68
|
+
// Streaming chat
|
|
69
|
+
chat(message: string, opts?: {
|
|
70
|
+
threadId?: string;
|
|
71
|
+
channel?: string;
|
|
72
|
+
}): AsyncGenerator<AgentEvent>;
|
|
73
|
+
|
|
74
|
+
// Run to completion (devuelve string final)
|
|
75
|
+
run(task: string, opts?: {
|
|
76
|
+
threadId?: string;
|
|
77
|
+
channel?: string;
|
|
78
|
+
}): Promise<string>;
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### AgentEvent
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
type AgentEvent =
|
|
86
|
+
| { type: "token"; content: string } // sólo con `stream: true`
|
|
87
|
+
| { type: "text"; content: string }
|
|
88
|
+
| { type: "tool_call"; name: string; args: Record<string, unknown> }
|
|
89
|
+
| { type: "tool_result"; name: string; result: unknown }
|
|
90
|
+
| { type: "done"; response: string };
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
#### Streaming por token
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
for await (const ev of agent.chat("resumime esto", { stream: true })) {
|
|
97
|
+
if (ev.type === "token") process.stdout.write(ev.content); // se va pintando
|
|
98
|
+
if (ev.type === "done") console.log("\n", ev.response);
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Sin `stream: true` el comportamiento es el de siempre: `text` con la respuesta
|
|
103
|
+
completa del turno. Los proveedores ya emitían estos deltas, pero hasta 0.3.0
|
|
104
|
+
ningún punto de entrada los pasaba, así que la respuesta aparecía de golpe al
|
|
105
|
+
terminar.
|
|
106
|
+
|
|
107
|
+
### Ejemplo
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import { createAgent, defineTool } from "@johpaz/hive-sdk";
|
|
111
|
+
|
|
112
|
+
const agent = await createAgent({
|
|
113
|
+
name: "asistente",
|
|
114
|
+
provider: "openai",
|
|
115
|
+
model: "gpt-5.6-luna",
|
|
116
|
+
systemPrompt: "Eres un asistente útil.",
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Streaming
|
|
120
|
+
for await (const event of agent.chat("Hola!")) {
|
|
121
|
+
if (event.type === "text") process.stdout.write(event.content);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Run to completion
|
|
125
|
+
const respuesta = await agent.run("Analiza las ventas del mes");
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
---
|
|
129
|
+
|
|
130
|
+
## defineTool
|
|
131
|
+
|
|
132
|
+
Define una herramienta que el agente puede invocar.
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
import { defineTool } from "@johpaz/hive-sdk";
|
|
136
|
+
|
|
137
|
+
const tool = defineTool({
|
|
138
|
+
name: "saludar",
|
|
139
|
+
description: "Saluda a alguien por su nombre",
|
|
140
|
+
execute: async (args: { nombre: string }) => {
|
|
141
|
+
return { mensaje: `¡Hola ${args.nombre}!` };
|
|
142
|
+
},
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### ToolDefinition
|
|
147
|
+
|
|
148
|
+
```typescript
|
|
149
|
+
interface ToolDefinition {
|
|
150
|
+
name: string;
|
|
151
|
+
description: string;
|
|
152
|
+
schema?: z.ZodType; // Validación Zod opcional
|
|
153
|
+
execute: (args: any, config?: any) => Promise<any>;
|
|
154
|
+
category?: string;
|
|
155
|
+
}
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## defineSkill
|
|
161
|
+
|
|
162
|
+
Define una composición de herramientas con triggers semánticos.
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
import { defineSkill } from "@johpaz/hive-sdk";
|
|
166
|
+
|
|
167
|
+
const skill = defineSkill({
|
|
168
|
+
name: "analisis-datos",
|
|
169
|
+
description: "Analiza datos y genera reportes",
|
|
170
|
+
steps: [
|
|
171
|
+
{ action: "web_search", instruction: "Buscar datos relevantes" },
|
|
172
|
+
{ action: "create_report", instruction: "Generar reporte" },
|
|
173
|
+
],
|
|
174
|
+
tools: ["web_search", "create_report"],
|
|
175
|
+
triggers: ["analizar", "reporte", "datos"],
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## AgentLoop
|
|
182
|
+
|
|
183
|
+
Clase de bajo nivel para control directo del bucle del agente.
|
|
184
|
+
|
|
185
|
+
```typescript
|
|
186
|
+
import { AgentLoop, buildAgentLoop } from "@johpaz/hive-sdk";
|
|
187
|
+
|
|
188
|
+
const loop = buildAgentLoop({ mcpManager });
|
|
189
|
+
|
|
190
|
+
const stream = loop.stream(
|
|
191
|
+
{ messages: [{ role: "user", content: "Hola" }] },
|
|
192
|
+
{ configurable: { thread_id: "thread-1" } }
|
|
193
|
+
);
|
|
194
|
+
|
|
195
|
+
for await (const chunk of stream) {
|
|
196
|
+
if (chunk.agent?.messages) {
|
|
197
|
+
console.log(chunk.agent.messages[0].content);
|
|
198
|
+
}
|
|
199
|
+
if (chunk.tools?.messages) {
|
|
200
|
+
console.log("Tool result:", chunk.tools.messages);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### StreamChunk
|
|
206
|
+
|
|
207
|
+
```typescript
|
|
208
|
+
interface StreamChunk {
|
|
209
|
+
agent?: { messages: any[]; streamed?: boolean };
|
|
210
|
+
tools?: { messages: any[] };
|
|
211
|
+
usage?: { input_tokens: number; output_tokens: number };
|
|
212
|
+
/** Imágenes que produjeron las tools de este turno, como referencias. */
|
|
213
|
+
artifacts?: { images: Array<{ artifactId: string; mimeType: string }> };
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Cada `yield` es **una respuesta completa del modelo** o un resultado de tool, no
|
|
218
|
+
un delta. Para deltas, `onToken` en `AgentLoopOptions` o `stream: true` en
|
|
219
|
+
`agent.chat()`.
|
|
220
|
+
|
|
221
|
+
### runAgent (bajo nivel)
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
import { runAgent, runAgentIsolated } from "@johpaz/hive-sdk";
|
|
225
|
+
|
|
226
|
+
// Streaming
|
|
227
|
+
for await (const chunk of runAgent({
|
|
228
|
+
agentId: "assistant",
|
|
229
|
+
userMessage: "Analiza las ventas",
|
|
230
|
+
threadId: "thread-123",
|
|
231
|
+
})) {
|
|
232
|
+
// procesar chunk
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// Modo aislado (para workers DAG)
|
|
236
|
+
const result = await runAgentIsolated({
|
|
237
|
+
agentId: "processor",
|
|
238
|
+
taskDescription: "Procesa estos datos",
|
|
239
|
+
threadId: "dag-thread",
|
|
240
|
+
});
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
---
|
|
244
|
+
|
|
245
|
+
## Tool Selector
|
|
246
|
+
|
|
247
|
+
Selección automática de tools por búsqueda BM25 sobre el índice de capacidad.
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import { selectTools, CORE_TOOL_CATALOG } from "@johpaz/hive-sdk";
|
|
251
|
+
|
|
252
|
+
// Seleccionar tools relevantes
|
|
253
|
+
const tools = selectTools("Buscar archivos en el proyecto");
|
|
254
|
+
console.log(tools.map(t => t.name));
|
|
255
|
+
|
|
256
|
+
// Con límite personalizado
|
|
257
|
+
const limited = selectTools("search query", CORE_TOOL_CATALOG, 3);
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Constantes
|
|
261
|
+
|
|
262
|
+
```typescript
|
|
263
|
+
const MIN_RELEVANCE_THRESHOLD = -30;
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### CORE_TOOL_CATALOG
|
|
267
|
+
|
|
268
|
+
60 tools built-in organizadas por categoría:
|
|
269
|
+
|
|
270
|
+
| Categoría | # | Descripción |
|
|
271
|
+
|-----------|---|-------------|
|
|
272
|
+
| agents | 15 | delegación (`task_delegate`, `task_revise`), memoria, catálogo de modelos |
|
|
273
|
+
| web | 10 | `web_search`, `web_fetch`, automatización de browser, `artifact_inspect` |
|
|
274
|
+
| cron | 8 | tareas programadas |
|
|
275
|
+
| office | 8 | PDF, DOCX, XLSX, PPTX |
|
|
276
|
+
| filesystem | 7 | read, write, edit, delete, list, glob, exists |
|
|
277
|
+
| a2ui | 4 | superficies de UI generadas por el agente |
|
|
278
|
+
| core | 4 | `save_note`, `notify`, `report_progress`, `search_knowledge` |
|
|
279
|
+
| cli | 1 | ejecución de comandos |
|
|
280
|
+
| api | 1 | `api_request` |
|
|
281
|
+
|
|
282
|
+
Las categorías `projects`, `canvas`, `codebridge`, `voice` y `meeting`
|
|
283
|
+
desaparecieron en 0.1.5 junto con sus tools.
|
|
284
|
+
|
|
285
|
+
---
|
|
286
|
+
|
|
287
|
+
## Skill Selector
|
|
288
|
+
|
|
289
|
+
```typescript
|
|
290
|
+
import { selectSkills, getMinimalSkills } from "@johpaz/hive-sdk";
|
|
291
|
+
|
|
292
|
+
// Skills según mensaje
|
|
293
|
+
const skills = selectSkills("Analyze the sales data");
|
|
294
|
+
|
|
295
|
+
// Skills mínimos siempre disponibles
|
|
296
|
+
const minimal = getMinimalSkills();
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## LLM Providers
|
|
302
|
+
|
|
303
|
+
### Providers Soportados
|
|
304
|
+
|
|
305
|
+
16 providers, todos sembrados con su catálogo de modelos y su precio por millón
|
|
306
|
+
de tokens. `provider` en `createAgent` acepta cualquiera de estos ids.
|
|
307
|
+
|
|
308
|
+
| Provider | Adapter | Notas |
|
|
309
|
+
|----------|---------|-------|
|
|
310
|
+
| `anthropic` | nativo | extended thinking, round-trip de thinking blocks |
|
|
311
|
+
| `gemini` | nativo | REST v1beta |
|
|
312
|
+
| `ollama` | nativo | modelos locales, flag `think` |
|
|
313
|
+
| `openai` | OpenAI-compat | Sol / Terra / Luna |
|
|
314
|
+
| `deepseek`, `kimi` | OpenAI-compat | round-trip de `reasoning_content` |
|
|
315
|
+
| `mistral`, `groq`, `qwen`, `minimax` | OpenAI-compat | |
|
|
316
|
+
| `z-ai` | OpenAI-compat | sirve en `/api/paas/v4`, no en `/v1` |
|
|
317
|
+
| `hiveagents` | OpenAI-compat | |
|
|
318
|
+
| `nvidia`, `openrouter`, `opencode-go`, `modelscope` | OpenAI-compat | **revendedores** |
|
|
319
|
+
|
|
320
|
+
Los cuatro revendedores prefijan sus ids de modelo con su propio id de provider
|
|
321
|
+
(`modelscope/Qwen/Qwen3.5-397B-A17B`), porque sirven modelos de terceros que se
|
|
322
|
+
solapan entre sí y la colección `models` se indexa por una sola clave. El
|
|
323
|
+
prefijo no llega al cable: el adapter lo quita antes del request.
|
|
324
|
+
|
|
325
|
+
```typescript
|
|
326
|
+
import { catalogModelKey, wireModelId } from "@johpaz/hive-sdk";
|
|
327
|
+
|
|
328
|
+
catalogModelKey("modelscope", "Qwen/Qwen3.5-397B-A17B"); // modelscope/Qwen/Qwen3.5-397B-A17B
|
|
329
|
+
wireModelId("modelscope", "modelscope/Qwen/Qwen3.5-397B-A17B"); // Qwen/Qwen3.5-397B-A17B
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Errores del provider
|
|
333
|
+
|
|
334
|
+
`callLLM` nunca lanza: devuelve `stop_reason: "error"` con un campo `error`
|
|
335
|
+
tipado. Chequealo antes de persistir `content` en cualquier lado — es texto para
|
|
336
|
+
mostrar, no salida del modelo.
|
|
337
|
+
|
|
338
|
+
```typescript
|
|
339
|
+
const response = await callLLM({ ... });
|
|
340
|
+
|
|
341
|
+
if (response.stop_reason === "error") {
|
|
342
|
+
console.error(response.error?.message);
|
|
343
|
+
// HTTP 404/410 → el proveedor retiró el modelo; reintentar no sirve.
|
|
344
|
+
if (response.error?.modelUnavailable) selectAnotherModel();
|
|
345
|
+
}
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### callLLM
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
import { callLLM, resolveProviderConfig } from "@johpaz/hive-sdk";
|
|
352
|
+
|
|
353
|
+
const config = await resolveProviderConfig("openai", "gpt-5.6-luna");
|
|
354
|
+
|
|
355
|
+
const response = await callLLM({
|
|
356
|
+
provider: config.provider,
|
|
357
|
+
model: config.model,
|
|
358
|
+
messages: [{ role: "user", content: "Hola" }],
|
|
359
|
+
});
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
---
|
|
363
|
+
|
|
364
|
+
## Errores Comunes
|
|
365
|
+
|
|
366
|
+
### createAgent: no se encuentra el agente
|
|
367
|
+
|
|
368
|
+
```typescript
|
|
369
|
+
// El agente no necesita existir en DB — createAgent lo gestiona internamente
|
|
370
|
+
// Si falla, verificar API keys en variables de entorno
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
### Tool no encontrada
|
|
374
|
+
|
|
375
|
+
```typescript
|
|
376
|
+
// Verificar que la tool está registrada
|
|
377
|
+
const reg = new ToolRegistry();
|
|
378
|
+
reg.register(myTool);
|
|
379
|
+
reg.has("my_tool"); // true
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
### Context too large
|
|
383
|
+
|
|
384
|
+
```typescript
|
|
385
|
+
// Usar maybeCompact para reducir historial
|
|
386
|
+
const { maybeCompact } = await import("../agent/Compaction.ts");
|
|
387
|
+
await maybeCompact(threadId, { channel, userId });
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
## Resto de la superficie del loop
|
|
391
|
+
|
|
392
|
+
Todo desde `@johpaz/hive-sdk`.
|
|
393
|
+
|
|
394
|
+
### Ejecutar
|
|
395
|
+
|
|
396
|
+
| | |
|
|
397
|
+
|---|---|
|
|
398
|
+
| `runAgent(opts)` | El loop. Devuelve un `AsyncGenerator<StreamChunk>`. |
|
|
399
|
+
| `runAgentIsolated(opts)` | Un worker en contexto aislado; devuelve sólo el texto final. Es lo que usan el enjambre y `task_delegate`. |
|
|
400
|
+
| `runAgentIsolatedDetailed(opts)` | Igual, pero además devuelve la evidencia de las tools que usó — la necesita quien tenga que justificar una entrega. |
|
|
401
|
+
| `createAgentRunner(config, opts?)` | Un `AgentRunner` listo. Construye el loop global, que es lo que `generate()` necesita: `new AgentRunner()` a secas se instancia sin quejarse y falla en la primera llamada. |
|
|
402
|
+
|
|
403
|
+
### El loop global
|
|
404
|
+
|
|
405
|
+
`buildAgentLoop(opts)` lo construye, `getAgentLoop()` lo devuelve (o `null`), y
|
|
406
|
+
`rebuildAgentLoop(opts)` lo rehace — por ejemplo tras conectar un manager MCP.
|
|
407
|
+
|
|
408
|
+
Es estado de proceso: un host multi-inquilino que corra varias colmenas a la vez
|
|
409
|
+
debería usar `runAgent()` directo con `credentials` por llamada, no este
|
|
410
|
+
singleton.
|
|
411
|
+
|
|
412
|
+
### Errores
|
|
413
|
+
|
|
414
|
+
| | |
|
|
415
|
+
|---|---|
|
|
416
|
+
| `LLMCallTimeoutError` | Una llamada al proveedor agotó su ventana. Es por llamada, no del turno entero. |
|
|
417
|
+
| `AgentSynthesisError` | El modelo no pudo redactar la respuesta final tras dos intentos. |
|
|
418
|
+
|
|
419
|
+
`withTimeout(op, ms)` acota una operación a su propia ventana, independiente de
|
|
420
|
+
la del turno. Es lo que evita que una tool lenta se lleve puesto el turno entero.
|
|
421
|
+
|
|
422
|
+
### Interno, expuesto por utilidad
|
|
423
|
+
|
|
424
|
+
`synthesizeFinalResponse` fuerza el cierre de un turno que se quedó sin
|
|
425
|
+
iteraciones. `injectArtifactReadIfNeeded` agrega `artifact_read` al loadout en
|
|
426
|
+
cuanto un resultado devuelve un `artifact_ref` que el modelo va a necesitar
|
|
427
|
+
abrir: descubrirla por búsqueda costaría una iteración y asume que al modelo se
|
|
428
|
+
le ocurra buscarla.
|
|
429
|
+
|
|
430
|
+
*Documentación Hive SDK — ver `version` en package.json*
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# API-ARTIFACTS — archivos fuera de la ventana de contexto
|
|
2
|
+
|
|
3
|
+
## Por qué existe
|
|
4
|
+
|
|
5
|
+
Cuando algo grande entra al turno —una imagen, un PDF, la salida enorme de un
|
|
6
|
+
servidor MCP— serializarlo al prompt es lo peor que se puede hacer: se come el
|
|
7
|
+
contexto y no aporta. En su lugar se guarda como **artefacto** y al modelo le
|
|
8
|
+
llega una referencia (`artifact_ref`) que puede abrir con `artifact_read` si de
|
|
9
|
+
verdad necesita el contenido.
|
|
10
|
+
|
|
11
|
+
Es el mismo mecanismo que sostiene tres cosas distintas: los resultados grandes
|
|
12
|
+
de MCP (`mcp-result-normalizer.ts`), las capturas de navegador, y las imágenes
|
|
13
|
+
que manda el usuario en una conversación.
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createArtifact, listArtifacts } from "@johpaz/hive-sdk/artifacts";
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Guardar y leer
|
|
20
|
+
|
|
21
|
+
| | |
|
|
22
|
+
|---|---|
|
|
23
|
+
| `createArtifact(input)` | Guarda bytes y devuelve la ficha. `expiresAt: null` = no caduca. |
|
|
24
|
+
| `readArtifactBytes(id)` | Los bytes crudos — lo que usa un canal para adjuntar una imagen. |
|
|
25
|
+
| `readArtifactText(id, opts?)` | El contenido como texto, para consumo en proceso. Rechaza lo binario y lo que supere 25 MB: un artefacto más grande que eso ya no es algo que quepa en una ventana de contexto. |
|
|
26
|
+
| `inspectArtifact(id, opts?)` | Metadatos sin abrirlo. |
|
|
27
|
+
| `listArtifacts(userId, opts?)` | Lo que tiene un usuario, de lo más reciente a lo más viejo. Filtra por `kind`. |
|
|
28
|
+
|
|
29
|
+
## Retención
|
|
30
|
+
|
|
31
|
+
Los artefactos **internos** —capturas, resultados de tools— son basura
|
|
32
|
+
transitoria y se limpian solos a los 7 días. Lo que **sube o transforma un
|
|
33
|
+
usuario** no lo es: borrárselo a la semana convierte un servicio en una pérdida
|
|
34
|
+
de datos.
|
|
35
|
+
|
|
36
|
+
| | |
|
|
37
|
+
|---|---|
|
|
38
|
+
| `setArtifactRetention(id, expiresAt)` | `null` = conservarlo indefinidamente. |
|
|
39
|
+
| `deleteArtifact(id)` | Borra la fila y el archivo, ahora. |
|
|
40
|
+
| `expireArtifacts(now?)` | La limpieza. Salta los `expires_at: null`. |
|
|
41
|
+
|
|
42
|
+
`deleteArtifact` elimina la fila; `expireArtifacts` la conserva marcada como
|
|
43
|
+
`expired`. La diferencia es intencional: si alguien pidió borrar, dejar el rastro
|
|
44
|
+
es lo contrario de lo que pidió.
|
|
45
|
+
|
|
46
|
+
> **Cuidado al tocar la limpieza**: en JavaScript `null > now` es `false`, así
|
|
47
|
+
> que una comprobación de caducidad escrita a la ligera trataría "no expira
|
|
48
|
+
> nunca" como "ya venció" y **borraría el archivo**. La comprobación del `null`
|
|
49
|
+
> va antes de comparar fechas.
|
|
50
|
+
|
|
51
|
+
Para trabajar con imágenes concretamente, `@johpaz/hive-sdk/services` expone
|
|
52
|
+
`uploadImage`, `listImages` y `setImageRetention`, que es esta misma capa con la
|
|
53
|
+
forma que espera una UI.
|
|
54
|
+
|
|
55
|
+
*Documentación Hive SDK — ver `version` en package.json*
|