@johpaz/hive 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +44 -0
- package/README.md +310 -0
- package/package.json +96 -0
- package/packages/cli/package.json +28 -0
- package/packages/cli/src/commands/agent-run.ts +168 -0
- package/packages/cli/src/commands/agents.ts +398 -0
- package/packages/cli/src/commands/chat.ts +142 -0
- package/packages/cli/src/commands/config.ts +50 -0
- package/packages/cli/src/commands/cron.ts +161 -0
- package/packages/cli/src/commands/dev.ts +95 -0
- package/packages/cli/src/commands/doctor.ts +133 -0
- package/packages/cli/src/commands/gateway.ts +443 -0
- package/packages/cli/src/commands/logs.ts +57 -0
- package/packages/cli/src/commands/mcp.ts +175 -0
- package/packages/cli/src/commands/message.ts +77 -0
- package/packages/cli/src/commands/onboard.ts +1868 -0
- package/packages/cli/src/commands/security.ts +144 -0
- package/packages/cli/src/commands/service.ts +50 -0
- package/packages/cli/src/commands/sessions.ts +116 -0
- package/packages/cli/src/commands/skills.ts +187 -0
- package/packages/cli/src/commands/update.ts +25 -0
- package/packages/cli/src/index.ts +185 -0
- package/packages/cli/src/utils/token.ts +6 -0
- package/packages/code-bridge/README.md +78 -0
- package/packages/code-bridge/package.json +18 -0
- package/packages/code-bridge/src/index.ts +95 -0
- package/packages/code-bridge/src/process-manager.ts +212 -0
- package/packages/code-bridge/src/schemas.ts +133 -0
- package/packages/core/package.json +46 -0
- package/packages/core/src/agent/agent-loop.ts +369 -0
- package/packages/core/src/agent/compaction.ts +140 -0
- package/packages/core/src/agent/context-compiler.ts +378 -0
- package/packages/core/src/agent/context-guard.ts +91 -0
- package/packages/core/src/agent/context.ts +138 -0
- package/packages/core/src/agent/conversation-store.ts +198 -0
- package/packages/core/src/agent/curator.ts +158 -0
- package/packages/core/src/agent/hooks.ts +166 -0
- package/packages/core/src/agent/index.ts +116 -0
- package/packages/core/src/agent/llm-client.ts +503 -0
- package/packages/core/src/agent/native-tools.ts +505 -0
- package/packages/core/src/agent/prompt-builder.ts +532 -0
- package/packages/core/src/agent/providers/index.ts +167 -0
- package/packages/core/src/agent/providers.ts +1 -0
- package/packages/core/src/agent/reflector.ts +170 -0
- package/packages/core/src/agent/service.ts +64 -0
- package/packages/core/src/agent/stuck-loop.ts +133 -0
- package/packages/core/src/agent/supervisor.ts +39 -0
- package/packages/core/src/agent/tracer.ts +102 -0
- package/packages/core/src/agent/workspace.ts +110 -0
- package/packages/core/src/canvas/canvas-manager.test.ts +161 -0
- package/packages/core/src/canvas/canvas-manager.ts +319 -0
- package/packages/core/src/canvas/canvas-tools.ts +420 -0
- package/packages/core/src/canvas/emitter.ts +115 -0
- package/packages/core/src/canvas/index.ts +2 -0
- package/packages/core/src/channels/base.ts +138 -0
- package/packages/core/src/channels/discord.ts +260 -0
- package/packages/core/src/channels/index.ts +7 -0
- package/packages/core/src/channels/manager.ts +383 -0
- package/packages/core/src/channels/slack.ts +287 -0
- package/packages/core/src/channels/telegram.ts +502 -0
- package/packages/core/src/channels/webchat.ts +128 -0
- package/packages/core/src/channels/whatsapp.ts +375 -0
- package/packages/core/src/config/index.ts +12 -0
- package/packages/core/src/config/loader.ts +529 -0
- package/packages/core/src/events/event-bus.ts +169 -0
- package/packages/core/src/gateway/index.ts +5 -0
- package/packages/core/src/gateway/initializer.ts +290 -0
- package/packages/core/src/gateway/lane-queue.ts +169 -0
- package/packages/core/src/gateway/resolver.ts +108 -0
- package/packages/core/src/gateway/router.ts +124 -0
- package/packages/core/src/gateway/server.ts +3317 -0
- package/packages/core/src/gateway/session.ts +95 -0
- package/packages/core/src/gateway/slash-commands.ts +192 -0
- package/packages/core/src/heartbeat/index.ts +157 -0
- package/packages/core/src/index.ts +19 -0
- package/packages/core/src/integrations/catalog.ts +286 -0
- package/packages/core/src/integrations/env.ts +64 -0
- package/packages/core/src/integrations/index.ts +2 -0
- package/packages/core/src/memory/index.ts +1 -0
- package/packages/core/src/memory/notes.ts +68 -0
- package/packages/core/src/plugins/api.ts +128 -0
- package/packages/core/src/plugins/index.ts +2 -0
- package/packages/core/src/plugins/loader.ts +365 -0
- package/packages/core/src/resilience/circuit-breaker.ts +225 -0
- package/packages/core/src/security/google-chat.ts +269 -0
- package/packages/core/src/security/index.ts +192 -0
- package/packages/core/src/security/pairing.ts +250 -0
- package/packages/core/src/security/rate-limit.ts +270 -0
- package/packages/core/src/security/signal.ts +321 -0
- package/packages/core/src/state/store.ts +312 -0
- package/packages/core/src/storage/bun-sqlite-store.ts +188 -0
- package/packages/core/src/storage/crypto.ts +101 -0
- package/packages/core/src/storage/db-context.ts +333 -0
- package/packages/core/src/storage/onboarding.ts +1087 -0
- package/packages/core/src/storage/schema.ts +541 -0
- package/packages/core/src/storage/seed.ts +571 -0
- package/packages/core/src/storage/sqlite.ts +387 -0
- package/packages/core/src/storage/usage.ts +212 -0
- package/packages/core/src/tools/bridge-events.ts +74 -0
- package/packages/core/src/tools/browser.ts +275 -0
- package/packages/core/src/tools/codebridge.ts +421 -0
- package/packages/core/src/tools/coordinator-tools.ts +179 -0
- package/packages/core/src/tools/cron.ts +611 -0
- package/packages/core/src/tools/exec.ts +140 -0
- package/packages/core/src/tools/fs.ts +364 -0
- package/packages/core/src/tools/index.ts +12 -0
- package/packages/core/src/tools/memory.ts +176 -0
- package/packages/core/src/tools/notify.ts +113 -0
- package/packages/core/src/tools/project-management.ts +376 -0
- package/packages/core/src/tools/project.ts +375 -0
- package/packages/core/src/tools/read.ts +158 -0
- package/packages/core/src/tools/web.ts +436 -0
- package/packages/core/src/tools/workspace.ts +171 -0
- package/packages/core/src/utils/benchmark.ts +80 -0
- package/packages/core/src/utils/crypto.ts +73 -0
- package/packages/core/src/utils/date.ts +42 -0
- package/packages/core/src/utils/index.ts +4 -0
- package/packages/core/src/utils/logger.ts +388 -0
- package/packages/core/src/utils/retry.ts +70 -0
- package/packages/core/src/voice/index.ts +583 -0
- package/packages/core/tsconfig.json +9 -0
- package/packages/mcp/package.json +26 -0
- package/packages/mcp/src/config.ts +13 -0
- package/packages/mcp/src/index.ts +1 -0
- package/packages/mcp/src/logger.ts +42 -0
- package/packages/mcp/src/manager.ts +434 -0
- package/packages/mcp/src/transports/index.ts +67 -0
- package/packages/mcp/src/transports/sse.ts +241 -0
- package/packages/mcp/src/transports/websocket.ts +159 -0
- package/packages/skills/package.json +21 -0
- package/packages/skills/src/bundled/agent_management/SKILL.md +24 -0
- package/packages/skills/src/bundled/browser_automation/SKILL.md +30 -0
- package/packages/skills/src/bundled/context_compact/SKILL.md +35 -0
- package/packages/skills/src/bundled/cron_manager/SKILL.md +52 -0
- package/packages/skills/src/bundled/file_manager/SKILL.md +76 -0
- package/packages/skills/src/bundled/http_client/SKILL.md +24 -0
- package/packages/skills/src/bundled/memory/SKILL.md +42 -0
- package/packages/skills/src/bundled/project_management/SKILL.md +26 -0
- package/packages/skills/src/bundled/shell/SKILL.md +43 -0
- package/packages/skills/src/bundled/system_notify/SKILL.md +52 -0
- package/packages/skills/src/bundled/voice/SKILL.md +25 -0
- package/packages/skills/src/bundled/web_search/SKILL.md +29 -0
- package/packages/skills/src/index.ts +1 -0
- package/packages/skills/src/loader.ts +282 -0
- package/packages/tools/package.json +43 -0
- package/packages/tools/src/browser/browser.test.ts +111 -0
- package/packages/tools/src/browser/index.ts +272 -0
- package/packages/tools/src/canvas/index.ts +220 -0
- package/packages/tools/src/cron/cron.test.ts +164 -0
- package/packages/tools/src/cron/index.ts +304 -0
- package/packages/tools/src/filesystem/filesystem.test.ts +240 -0
- package/packages/tools/src/filesystem/index.ts +379 -0
- package/packages/tools/src/git/index.ts +239 -0
- package/packages/tools/src/index.ts +4 -0
- package/packages/tools/src/shell/detect-env.ts +70 -0
- package/packages/tools/tsconfig.json +9 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: memory
|
|
3
|
+
description: "Store and retrieve persistent information in long-term memory"
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Hive Team
|
|
6
|
+
icon: "🧠"
|
|
7
|
+
category: system
|
|
8
|
+
permissions:
|
|
9
|
+
- memory_read
|
|
10
|
+
- memory_write
|
|
11
|
+
dependencies: []
|
|
12
|
+
tools: [memory, memory_write, memory_read, memory_list, memory_search, memory_delete]
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Memory Skill
|
|
16
|
+
|
|
17
|
+
Esta skill permite al agente mantener una memoria persistente a largo plazo, permitiendo recordar datos entre diferentes sesiones y conversaciones.
|
|
18
|
+
|
|
19
|
+
## Herramientas Disponibles
|
|
20
|
+
|
|
21
|
+
- `memory_write`: Almacena información importante (hechos, preferencias, contexto).
|
|
22
|
+
- `memory_read`: Recupera una entrada de memoria por su título.
|
|
23
|
+
- `memory_list`: Lista todos los títulos de las entradas guardadas.
|
|
24
|
+
- `memory_search`: Busca en el contenido de la memoria usando una consulta de texto.
|
|
25
|
+
- `memory_delete`: Elimina una entrada de memoria específica.
|
|
26
|
+
|
|
27
|
+
## Ejemplos de Uso
|
|
28
|
+
|
|
29
|
+
### Guardar una preferencia del usuario
|
|
30
|
+
```javascript
|
|
31
|
+
memory_write({ title: "Tecnologías", content: "El usuario prefiere TypeScript y Bun" })
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Buscar información relevante
|
|
35
|
+
```javascript
|
|
36
|
+
memory_search({ query: "Preferencias de desarrollo" })
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Mejores Prácticas
|
|
40
|
+
- **Títulos Descriptivos**: Usa títulos únicos y claros para facilitar la recuperación directa.
|
|
41
|
+
- **Actualización**: Si la información cambia, sobrescribe la entrada con el mismo título.
|
|
42
|
+
- **Privacidad**: Evita guardar información sensible o contraseñas en la memoria persistente.
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: project_management
|
|
3
|
+
description: "Track and manage multi-step project tasks and progress"
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Hive Team
|
|
6
|
+
icon: "📊"
|
|
7
|
+
category: projects
|
|
8
|
+
permissions: []
|
|
9
|
+
dependencies: []
|
|
10
|
+
tools: [project_start, project_update, project_done, project_fail]
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Project Management Skill
|
|
14
|
+
|
|
15
|
+
Esta skill permite al agente realizar un seguimiento detallado de tareas complejas que requieren múltiples pasos, informando sobre el progreso y el estado final.
|
|
16
|
+
|
|
17
|
+
## Herramientas Disponibles
|
|
18
|
+
|
|
19
|
+
- `project_start`: Inicia el seguimiento de una tarea multi-paso.
|
|
20
|
+
- `project_update`: Actualiza el progreso de una tarea en curso.
|
|
21
|
+
- `project_done`: Marca una tarea como completada exitosamente.
|
|
22
|
+
- `project_fail`: Marca una tarea como fallida por error irrecuperable.
|
|
23
|
+
|
|
24
|
+
## Mejores Prácticas
|
|
25
|
+
- **Actualizaciones Frecuentes**: Informa sobre hitos importantes durante la ejecución de tareas largas.
|
|
26
|
+
- **Claridad en Errores**: Si una tarea falla, proporciona un motivo claro y detallado en `project_fail`.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: shell
|
|
3
|
+
description: "Execute shell commands safely with allowlist control"
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Hive Team
|
|
6
|
+
icon: "💻"
|
|
7
|
+
category: system
|
|
8
|
+
permissions:
|
|
9
|
+
- shell_exec
|
|
10
|
+
dependencies: []
|
|
11
|
+
tools: [shell, exec, terminal]
|
|
12
|
+
requirements:
|
|
13
|
+
bins: [bash, sh]
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Shell Skill
|
|
17
|
+
|
|
18
|
+
Esta skill permite al agente ejecutar comandos en la terminal de forma segura y controlada.
|
|
19
|
+
|
|
20
|
+
## Herramientas Disponibles
|
|
21
|
+
|
|
22
|
+
- `exec`: Ejecuta un comando básico sujeto a listas de permisos (allowlist/denylist). Recomendado para tareas simples.
|
|
23
|
+
- `terminal`: Ejecuta comandos directamente en la shell (bash/zsh/cmd). Útil para operaciones de Git, scripts de npm o comandos complejos que requieren mayor flexibilidad.
|
|
24
|
+
|
|
25
|
+
## Parámetros de Herramientas
|
|
26
|
+
|
|
27
|
+
### exec
|
|
28
|
+
- `command` (requerido): El comando a ejecutar.
|
|
29
|
+
- `timeout` (opcional): Tiempo de espera en segundos (por defecto: 30).
|
|
30
|
+
|
|
31
|
+
### terminal
|
|
32
|
+
- `command` (requerido): El comando a ejecutar.
|
|
33
|
+
- `cwd` (opcional): Directorio de trabajo.
|
|
34
|
+
- `timeoutSeconds` (opcional): Tiempo de espera en segundos (por defecto: 60).
|
|
35
|
+
|
|
36
|
+
## Seguridad
|
|
37
|
+
- `exec` está limitado por la configuración de seguridad de Hive.
|
|
38
|
+
- `terminal` permite una ejecución más directa pero registra todas las salidas en los puentes de comunicación (`bridge`).
|
|
39
|
+
|
|
40
|
+
## Mejores Prácticas
|
|
41
|
+
- Prefiere comandos de solo lectura siempre que sea posible.
|
|
42
|
+
- Verifica siempre el código de salida (`exitCode`) y las salidas de error (`stderr`).
|
|
43
|
+
- Usa rutas absolutas para mayor fiabilidad entre diferentes sistemas operativos.
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: system_notify
|
|
3
|
+
description: "Send system desktop notifications and interact via Canvas"
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Hive Team
|
|
6
|
+
icon: "🔔"
|
|
7
|
+
category: system
|
|
8
|
+
permissions:
|
|
9
|
+
- desktop_notification
|
|
10
|
+
- canvas_write
|
|
11
|
+
dependencies: []
|
|
12
|
+
tools: [system_notify, notify, report_progress, canvas_render, canvas_ask, canvas_confirm, canvas_show_card, canvas_show_progress, canvas_show_list, canvas_clear]
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# System Notify & Canvas Skill
|
|
16
|
+
|
|
17
|
+
Esta skill permite al agente enviar notificaciones al sistema y renderizar componentes interactivos en el Canvas del usuario (UI).
|
|
18
|
+
|
|
19
|
+
## Herramientas Disponibles
|
|
20
|
+
|
|
21
|
+
### Notificaciones del Sistema
|
|
22
|
+
- `notify`: Envía una notificación de escritorio tradicional.
|
|
23
|
+
- `report_progress`: Informa sobre el progreso de tareas de larga duración.
|
|
24
|
+
|
|
25
|
+
### Herramientas de Canvas (UI)
|
|
26
|
+
- `canvas_render`: Renderiza componentes (botones, tablas, gráficos) en el Canvas.
|
|
27
|
+
- `canvas_ask`: Muestra formularios dinámicos y espera la respuesta del usuario.
|
|
28
|
+
- `canvas_confirm`: Muestra un diálogo de confirmación (Aceptar/Cancelar).
|
|
29
|
+
- `canvas_show_card`: Muestra una tarjeta informativa con ítems etiquetados.
|
|
30
|
+
- `canvas_show_progress`: Muestra barras de progreso múltiples para tareas complejas.
|
|
31
|
+
- `canvas_show_list`: Muestra listas de clave-valor (útil para configuraciones).
|
|
32
|
+
- `canvas_clear`: Limpia el contenido del Canvas para una sesión.
|
|
33
|
+
|
|
34
|
+
## Uso Dinámico del Canvas
|
|
35
|
+
|
|
36
|
+
El Canvas es ideal para presentar información estructurada que es difícil de leer en texto puro, o para requerir entradas complejas del usuario mediante formularios.
|
|
37
|
+
|
|
38
|
+
### Ejemplo: Formulario de Registro
|
|
39
|
+
```javascript
|
|
40
|
+
canvas_ask({
|
|
41
|
+
title: "Datos de Usuario",
|
|
42
|
+
fields: [
|
|
43
|
+
{ name: "email", label: "Correo Electrónico", type: "email", required: true },
|
|
44
|
+
{ name: "role", label: "Rol", type: "select", options: [{label: "Admin", value: "admin"}] }
|
|
45
|
+
]
|
|
46
|
+
})
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Mejores Prácticas
|
|
50
|
+
- **Concisión**: Mantén los mensajes de notificación cortos.
|
|
51
|
+
- **Urgencia**: Usa niveles de urgencia (`low`, `normal`, `critical`) solo para eventos que realmente requieran atención inmediata.
|
|
52
|
+
- **Limpieza**: Usa `canvas_clear` cuando cambies drásticamente de contexto para mantener el espacio de trabajo limpio.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: voice
|
|
3
|
+
description: "Process audio transcriptions and synthesize speech"
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Hive Team
|
|
6
|
+
icon: "🎙️"
|
|
7
|
+
category: voice
|
|
8
|
+
permissions:
|
|
9
|
+
- internet_access
|
|
10
|
+
dependencies: []
|
|
11
|
+
tools: [voice_transcribe, voice_speak]
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Voice Processing Skill
|
|
15
|
+
|
|
16
|
+
Esta skill permite al agente interactuar mediante voz, transcribiendo audio a texto y convirtiendo texto a voz.
|
|
17
|
+
|
|
18
|
+
## Herramientas Disponibles
|
|
19
|
+
|
|
20
|
+
- `voice_transcribe`: Transcribe un archivo de audio a texto.
|
|
21
|
+
- `voice_speak`: Convierte texto a audio y lo envía al canal de comunicación activo.
|
|
22
|
+
|
|
23
|
+
## Mejores Prácticas
|
|
24
|
+
- **Calidad de Audio**: Asegúrate de que los archivos de audio para transcripción sean legibles.
|
|
25
|
+
- **Brevedad**: Para `voice_speak`, prefiere mensajes concisos para una mejor experiencia de usuario.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: web_search
|
|
3
|
+
description: "Search the internet for real-time information"
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: Hive Team
|
|
6
|
+
icon: "🔍"
|
|
7
|
+
category: tools
|
|
8
|
+
permissions:
|
|
9
|
+
- internet_access
|
|
10
|
+
dependencies: []
|
|
11
|
+
tools: [web_search]
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Web Search Skill
|
|
15
|
+
|
|
16
|
+
Esta skill permite al agente buscar información actualizada en internet utilizando motores de búsqueda integrados.
|
|
17
|
+
|
|
18
|
+
## Herramientas Disponibles
|
|
19
|
+
|
|
20
|
+
- `web_search`: Realiza una búsqueda web y devuelve resultados con títulos, URLs y fragmentos de texto.
|
|
21
|
+
|
|
22
|
+
## Parámetros
|
|
23
|
+
|
|
24
|
+
- `query` (requerido): El término de búsqueda.
|
|
25
|
+
- `numResults` (opcional): Número de resultados a devolver (por defecto: 5).
|
|
26
|
+
|
|
27
|
+
## Mejores Prácticas
|
|
28
|
+
- **Especificidad**: Usa términos de búsqueda precisos.
|
|
29
|
+
- **Cruzar Datos**: Combina los resultados de búsqueda con la herramienta `web_fetch` (de la skill `http_client`) para obtener el contenido completo de una página si es necesario.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./loader.ts";
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import * as fs from "node:fs";
|
|
2
|
+
import * as path from "node:path";
|
|
3
|
+
import * as yaml from "js-yaml";
|
|
4
|
+
|
|
5
|
+
export interface SkillsConfig {
|
|
6
|
+
allowBundled?: string[];
|
|
7
|
+
managedDir?: string;
|
|
8
|
+
extraDirs?: string[];
|
|
9
|
+
hotReload?: boolean;
|
|
10
|
+
maxSkillSizeKB?: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface Config {
|
|
14
|
+
skills?: SkillsConfig;
|
|
15
|
+
workspacePath?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
interface Logger {
|
|
19
|
+
debug: (msg: string, ...args: unknown[]) => void;
|
|
20
|
+
info: (msg: string, ...args: unknown[]) => void;
|
|
21
|
+
warn: (msg: string, ...args: unknown[]) => void;
|
|
22
|
+
error: (msg: string, ...args: unknown[]) => void;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function createLogger(): Logger {
|
|
26
|
+
return {
|
|
27
|
+
debug: (msg, ...args) => console.debug(`[skills] ${msg}`, ...args),
|
|
28
|
+
info: (msg, ...args) => console.info(`[skills] ${msg}`, ...args),
|
|
29
|
+
warn: (msg, ...args) => console.warn(`[skills] ${msg}`, ...args),
|
|
30
|
+
error: (msg, ...args) => console.error(`[skills] ${msg}`, ...args),
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface SkillMetadata {
|
|
35
|
+
name: string;
|
|
36
|
+
version?: string;
|
|
37
|
+
author?: string;
|
|
38
|
+
description: string;
|
|
39
|
+
icon?: string;
|
|
40
|
+
category?: string;
|
|
41
|
+
permissions?: string[];
|
|
42
|
+
dependencies?: string[];
|
|
43
|
+
tools?: string[];
|
|
44
|
+
requirements?: {
|
|
45
|
+
os?: string[];
|
|
46
|
+
bins?: string[];
|
|
47
|
+
env?: string[];
|
|
48
|
+
config?: string[];
|
|
49
|
+
};
|
|
50
|
+
// Retrocompatibilidad con el campo metadata.hive previo
|
|
51
|
+
metadata?: {
|
|
52
|
+
hive?: {
|
|
53
|
+
emoji?: string;
|
|
54
|
+
bins?: string[];
|
|
55
|
+
userInvocable?: boolean;
|
|
56
|
+
requires?: {
|
|
57
|
+
config?: string[];
|
|
58
|
+
env?: string[];
|
|
59
|
+
};
|
|
60
|
+
install?: {
|
|
61
|
+
brew?: string;
|
|
62
|
+
apt?: string;
|
|
63
|
+
npm?: string;
|
|
64
|
+
};
|
|
65
|
+
os?: string[];
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface Skill {
|
|
71
|
+
name: string;
|
|
72
|
+
description: string;
|
|
73
|
+
version?: string;
|
|
74
|
+
author?: string;
|
|
75
|
+
icon?: string;
|
|
76
|
+
category?: string;
|
|
77
|
+
content: string;
|
|
78
|
+
raw: string;
|
|
79
|
+
metadata: SkillMetadata;
|
|
80
|
+
source: "bundled" | "managed" | "workspace";
|
|
81
|
+
path: string;
|
|
82
|
+
permissions?: string[];
|
|
83
|
+
dependencies?: string[];
|
|
84
|
+
tools?: string[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function parseFrontmatter(content: string): { frontmatter: Record<string, unknown>; body: string } {
|
|
88
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
89
|
+
|
|
90
|
+
if (!match) {
|
|
91
|
+
return { frontmatter: {}, body: content };
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const frontmatter = yaml.load(match[1]!) as Record<string, unknown>;
|
|
96
|
+
const body = match[2]!;
|
|
97
|
+
return { frontmatter, body };
|
|
98
|
+
} catch {
|
|
99
|
+
return { frontmatter: {}, body: content };
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export class SkillLoader {
|
|
104
|
+
private config: Config;
|
|
105
|
+
private log: Logger;
|
|
106
|
+
private cache: Map<string, Skill> = new Map();
|
|
107
|
+
private bundledDir: string;
|
|
108
|
+
|
|
109
|
+
constructor(config: Config) {
|
|
110
|
+
this.config = config;
|
|
111
|
+
this.log = createLogger();
|
|
112
|
+
this.bundledDir = path.join(__dirname, "bundled");
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
private expandPath(p: string): string {
|
|
116
|
+
if (p.startsWith("~")) {
|
|
117
|
+
return path.join(process.env.HOME ?? "", p.slice(1));
|
|
118
|
+
}
|
|
119
|
+
return p;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
loadSkill(skillPath: string, source: Skill["source"]): Skill | null {
|
|
123
|
+
try {
|
|
124
|
+
const skillMdPath = path.join(skillPath, "SKILL.md");
|
|
125
|
+
|
|
126
|
+
if (!fs.existsSync(skillMdPath)) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
const content = fs.readFileSync(skillMdPath, "utf-8");
|
|
131
|
+
const { frontmatter, body } = parseFrontmatter(content);
|
|
132
|
+
|
|
133
|
+
const rawMetadata = (frontmatter.metadata as any) ?? {};
|
|
134
|
+
const hiveMetadata = rawMetadata.hive ?? {};
|
|
135
|
+
|
|
136
|
+
const name = (frontmatter.name as string) ?? path.basename(skillPath);
|
|
137
|
+
const description = (frontmatter.description as string) ?? "";
|
|
138
|
+
const version = (frontmatter.version as string) ?? "0.0.1";
|
|
139
|
+
const author = (frontmatter.author as string) ?? "Anonymous";
|
|
140
|
+
const icon = (frontmatter.icon as string) ?? hiveMetadata.emoji ?? "🧩";
|
|
141
|
+
const category = (frontmatter.category as string) ?? "general";
|
|
142
|
+
|
|
143
|
+
const permissions = (frontmatter.permissions as string[]) ?? [];
|
|
144
|
+
const dependencies = (frontmatter.dependencies as string[]) ?? [];
|
|
145
|
+
const tools = (frontmatter.tools as string[]) ?? [];
|
|
146
|
+
|
|
147
|
+
const metadata: SkillMetadata = {
|
|
148
|
+
...(frontmatter as any),
|
|
149
|
+
name,
|
|
150
|
+
description,
|
|
151
|
+
version,
|
|
152
|
+
author,
|
|
153
|
+
icon,
|
|
154
|
+
category,
|
|
155
|
+
permissions,
|
|
156
|
+
dependencies,
|
|
157
|
+
tools
|
|
158
|
+
};
|
|
159
|
+
|
|
160
|
+
const skill: Skill = {
|
|
161
|
+
name,
|
|
162
|
+
description,
|
|
163
|
+
version,
|
|
164
|
+
author,
|
|
165
|
+
icon,
|
|
166
|
+
category,
|
|
167
|
+
content: body,
|
|
168
|
+
raw: content,
|
|
169
|
+
metadata,
|
|
170
|
+
source,
|
|
171
|
+
path: skillPath,
|
|
172
|
+
permissions,
|
|
173
|
+
dependencies,
|
|
174
|
+
tools
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
this.cache.set(name, skill);
|
|
178
|
+
return skill;
|
|
179
|
+
} catch (error) {
|
|
180
|
+
this.log.error(`Failed to load skill: ${skillPath}`, { error: (error as Error).message });
|
|
181
|
+
return null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
loadBundledSkills(): Skill[] {
|
|
186
|
+
const skills: Map<string, Skill> = new Map();
|
|
187
|
+
|
|
188
|
+
if (!fs.existsSync(this.bundledDir)) {
|
|
189
|
+
this.log.debug(`Bundled skills directory not found: ${this.bundledDir}`);
|
|
190
|
+
return [];
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
for (const entry of fs.readdirSync(this.bundledDir, { withFileTypes: true })) {
|
|
194
|
+
if (entry.isDirectory()) {
|
|
195
|
+
const skill = this.loadSkill(path.join(this.bundledDir, entry.name), "bundled");
|
|
196
|
+
if (skill) {
|
|
197
|
+
skills.set(skill.name, skill);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
this.log.debug(`Loaded ${skills.size} bundled skills`);
|
|
203
|
+
return Array.from(skills.values());
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
loadAllSkills(): Skill[] {
|
|
207
|
+
const skills: Map<string, Skill> = new Map();
|
|
208
|
+
const allowBundled = this.config.skills?.allowBundled;
|
|
209
|
+
|
|
210
|
+
// 1. Load bundled skills (lowest priority)
|
|
211
|
+
const bundledSkills = this.loadBundledSkills();
|
|
212
|
+
for (const skill of bundledSkills) {
|
|
213
|
+
// If allowBundled is undefined, empty, or contains the skill name, include it
|
|
214
|
+
if (!allowBundled || allowBundled.length === 0 || allowBundled.includes(skill.name)) {
|
|
215
|
+
skills.set(skill.name, skill);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// 2. Load managed skills (medium priority)
|
|
220
|
+
const managedDir = this.expandPath(this.config.skills?.managedDir ?? "~/.hive/skills");
|
|
221
|
+
if (fs.existsSync(managedDir)) {
|
|
222
|
+
for (const entry of fs.readdirSync(managedDir, { withFileTypes: true })) {
|
|
223
|
+
if (entry.isDirectory()) {
|
|
224
|
+
const skill = this.loadSkill(path.join(managedDir, entry.name), "managed");
|
|
225
|
+
if (skill) {
|
|
226
|
+
skills.set(skill.name, skill);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// 3. Load extra directories
|
|
233
|
+
const extraDirs = this.config.skills?.extraDirs ?? [];
|
|
234
|
+
for (const extraDir of extraDirs) {
|
|
235
|
+
const expandedDir = this.expandPath(extraDir);
|
|
236
|
+
if (fs.existsSync(expandedDir)) {
|
|
237
|
+
for (const entry of fs.readdirSync(expandedDir, { withFileTypes: true })) {
|
|
238
|
+
if (entry.isDirectory()) {
|
|
239
|
+
const skill = this.loadSkill(path.join(expandedDir, entry.name), "managed");
|
|
240
|
+
if (skill) {
|
|
241
|
+
skills.set(skill.name, skill);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// 4. Load workspace skills (highest priority)
|
|
249
|
+
const workspacePath = this.config.workspacePath ?? process.cwd();
|
|
250
|
+
const workspaceSkillsDir = path.join(workspacePath, "skills");
|
|
251
|
+
if (fs.existsSync(workspaceSkillsDir)) {
|
|
252
|
+
for (const entry of fs.readdirSync(workspaceSkillsDir, { withFileTypes: true })) {
|
|
253
|
+
if (entry.isDirectory()) {
|
|
254
|
+
const skill = this.loadSkill(path.join(workspaceSkillsDir, entry.name), "workspace");
|
|
255
|
+
if (skill) {
|
|
256
|
+
skills.set(skill.name, skill);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
this.log.info(`Loaded ${skills.size} total skills`);
|
|
263
|
+
return Array.from(skills.values());
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
getSkill(name: string): Skill | undefined {
|
|
267
|
+
return this.cache.get(name);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
listSkills(): string[] {
|
|
271
|
+
return Array.from(this.cache.keys());
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
clearCache(): void {
|
|
275
|
+
this.cache.clear();
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export function createSkillLoader(config: Config): SkillLoader {
|
|
280
|
+
return new SkillLoader(config);
|
|
281
|
+
}
|
|
282
|
+
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@johpaz/hive-tools",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "Native tools for Hive AI Gateway - Browser, Cron, FileSystem, Canvas",
|
|
6
|
+
"main": "./src/index.ts",
|
|
7
|
+
"module": "./src/index.ts",
|
|
8
|
+
"types": "./src/index.ts",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/johpaz/hive.git",
|
|
13
|
+
"directory": "packages/tools"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"hive",
|
|
17
|
+
"ai",
|
|
18
|
+
"tools",
|
|
19
|
+
"browser",
|
|
20
|
+
"cron",
|
|
21
|
+
"filesystem",
|
|
22
|
+
"canvas"
|
|
23
|
+
],
|
|
24
|
+
"files": [
|
|
25
|
+
"src/"
|
|
26
|
+
],
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@johpaz/hive-core": "^1.1.0",
|
|
29
|
+
"cron-parser": "^5.5.0",
|
|
30
|
+
"zod": "latest"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"typescript": "latest",
|
|
34
|
+
"@types/bun": "latest"
|
|
35
|
+
},
|
|
36
|
+
"exports": {
|
|
37
|
+
".": "./src/index.ts",
|
|
38
|
+
"./browser": "./src/browser/index.ts",
|
|
39
|
+
"./cron": "./src/cron/index.ts",
|
|
40
|
+
"./filesystem": "./src/filesystem/index.ts",
|
|
41
|
+
"./canvas": "./src/canvas/index.ts"
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach } from "bun:test";
|
|
2
|
+
import {
|
|
3
|
+
createBrowserNavigateTool,
|
|
4
|
+
createBrowserFetchTool,
|
|
5
|
+
createBrowserScreenshotTool,
|
|
6
|
+
createBrowserClickTool,
|
|
7
|
+
createBrowserTypeTool,
|
|
8
|
+
createBrowserTools,
|
|
9
|
+
} from "./index";
|
|
10
|
+
|
|
11
|
+
describe("Browser Tools", () => {
|
|
12
|
+
describe("createBrowserNavigateTool", () => {
|
|
13
|
+
it("creates tool with correct name and description", () => {
|
|
14
|
+
const tool = createBrowserNavigateTool();
|
|
15
|
+
expect(tool.name).toBe("browser_navigate");
|
|
16
|
+
expect(tool.description).toContain("Navigate");
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
it("has required parameters", () => {
|
|
20
|
+
const tool = createBrowserNavigateTool();
|
|
21
|
+
expect(tool.parameters.type).toBe("object");
|
|
22
|
+
expect(tool.parameters.required).toContain("url");
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
it("fetches content from a URL", async () => {
|
|
26
|
+
const tool = createBrowserNavigateTool();
|
|
27
|
+
try {
|
|
28
|
+
const result = await tool.execute({
|
|
29
|
+
url: "https://example.com",
|
|
30
|
+
}) as { success: boolean; content: string };
|
|
31
|
+
|
|
32
|
+
expect(result.success).toBe(true);
|
|
33
|
+
expect(result.content).toBeDefined();
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.log("Skipping URL fetch test due to network/cert issues");
|
|
36
|
+
}
|
|
37
|
+
}, 30000);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe("createBrowserFetchTool", () => {
|
|
41
|
+
it("creates tool with correct name", () => {
|
|
42
|
+
const tool = createBrowserFetchTool();
|
|
43
|
+
expect(tool.name).toBe("browser_fetch");
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("fetches JSON from API", async () => {
|
|
47
|
+
const tool = createBrowserFetchTool();
|
|
48
|
+
try {
|
|
49
|
+
const result = await tool.execute({
|
|
50
|
+
url: "https://jsonplaceholder.typicode.com/posts/1",
|
|
51
|
+
}) as { success: boolean; data: unknown };
|
|
52
|
+
|
|
53
|
+
expect(result.success).toBe(true);
|
|
54
|
+
expect(result.data).toBeDefined();
|
|
55
|
+
} catch (error) {
|
|
56
|
+
console.log("Skipping URL fetch test due to network/cert issues");
|
|
57
|
+
}
|
|
58
|
+
}, 30000);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("createBrowserScreenshotTool", () => {
|
|
62
|
+
it("creates tool with placeholder response", async () => {
|
|
63
|
+
const tool = createBrowserScreenshotTool();
|
|
64
|
+
const result = await tool.execute({
|
|
65
|
+
url: "https://example.com",
|
|
66
|
+
}) as { success: boolean; error: string };
|
|
67
|
+
|
|
68
|
+
expect(result.success).toBe(false);
|
|
69
|
+
expect(result.error).toContain("puppeteer");
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("createBrowserClickTool", () => {
|
|
74
|
+
it("creates tool with placeholder response", async () => {
|
|
75
|
+
const tool = createBrowserClickTool();
|
|
76
|
+
const result = await tool.execute({
|
|
77
|
+
selector: "#button",
|
|
78
|
+
}) as { success: boolean; error: string };
|
|
79
|
+
|
|
80
|
+
expect(result.success).toBe(false);
|
|
81
|
+
expect(result.error).toContain("puppeteer");
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
describe("createBrowserTypeTool", () => {
|
|
86
|
+
it("creates tool with placeholder response", async () => {
|
|
87
|
+
const tool = createBrowserTypeTool();
|
|
88
|
+
const result = await tool.execute({
|
|
89
|
+
selector: "#input",
|
|
90
|
+
text: "hello",
|
|
91
|
+
}) as { success: boolean; error: string };
|
|
92
|
+
|
|
93
|
+
expect(result.success).toBe(false);
|
|
94
|
+
expect(result.error).toContain("puppeteer");
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe("createBrowserTools", () => {
|
|
99
|
+
it("returns all browser tools", () => {
|
|
100
|
+
const tools = createBrowserTools();
|
|
101
|
+
expect(tools.length).toBe(5);
|
|
102
|
+
expect(tools.map((t) => t.name)).toEqual([
|
|
103
|
+
"browser_navigate",
|
|
104
|
+
"browser_fetch",
|
|
105
|
+
"browser_screenshot",
|
|
106
|
+
"browser_click",
|
|
107
|
+
"browser_type",
|
|
108
|
+
]);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
});
|