@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.
Files changed (40) hide show
  1. package/CHANGELOG.md +20 -4
  2. package/README.md +48 -7
  3. package/SECURITY.md +17 -0
  4. package/docs/API-AGENTS.md +430 -0
  5. package/docs/API-ARTIFACTS.md +55 -0
  6. package/docs/API-CONTEXT-COMPILER.md +285 -0
  7. package/docs/API-CRON.md +188 -0
  8. package/docs/API-DAG-SCHEDULER.md +291 -0
  9. package/docs/API-HOOKS.md +147 -0
  10. package/docs/API-RESILIENCE.md +45 -0
  11. package/docs/API-SERVICES.md +458 -0
  12. package/docs/API-SESSIONS.md +146 -0
  13. package/docs/API-TOOLS-SKILLS-CHANNELS.md +499 -0
  14. package/docs/API-WORKERS-EVENTS.md +311 -0
  15. package/docs/HIVE-HARNESS.md +232 -0
  16. package/docs/INDEX.md +198 -0
  17. package/docs/SECURITY-GUARDRAILS.md +87 -0
  18. package/docs/TEMPLATE-HIVE-APP.md +360 -0
  19. package/docs/UPGRADING.md +65 -0
  20. package/docs/assets/logoblack.png +0 -0
  21. package/docs/assets/logocolor-dark.png +0 -0
  22. package/docs/assets/logocolorbg.png +0 -0
  23. package/docs/plans/2026-09-05-office-dependency-hardening-design.md +28 -0
  24. package/docs/plans/2026-09-06-dependency-audit-remediation-design.md +25 -0
  25. package/docs/plans/2026-09-06-pptx-image-size-remediation-design.md +54 -0
  26. package/docs/plans/2026-09-06-typescript7-bun142-documentation-design.md +48 -0
  27. package/package.json +5 -4
  28. package/packages/core/src/agent/llm-providers/hiveagents.ts +2 -2
  29. package/packages/core/src/agent/providers/index.ts +17 -1
  30. package/packages/core/src/api/createAgent.ts +4 -2
  31. package/packages/core/src/gateway/server.ts +1 -1
  32. package/packages/core/src/mcp/transports/sse.ts +11 -3
  33. package/packages/core/src/mcp/transports/websocket.ts +11 -9
  34. package/packages/core/src/tool-runtime/tool-worker.ts +3 -1
  35. package/packages/core/src/tools/office/office-escribir-pptx.ts +3 -1
  36. package/packages/core/src/vendor/pptxgenjs/LICENSE +21 -0
  37. package/packages/core/src/vendor/pptxgenjs/README.md +17 -0
  38. package/packages/core/src/vendor/pptxgenjs/pptxgen.es.d.ts +17 -0
  39. package/packages/core/src/vendor/pptxgenjs/pptxgen.es.js +7368 -0
  40. 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 —evaluado contra el runtime 1.4.0—:
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`), ignora la zona horaria en `parse()`, y su handle
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.0**, alineado con `hive`.
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
- # Todos los tests (paralelo)
214
+ # Toda la suite
183
215
  bun test
184
216
 
185
- # Tests con timeout extendido
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.4 — MIT*
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*