Commit Graph

64 Commits

Author SHA1 Message Date
egutierrez dd2fa05f87 test: tests para buildToolRegistry con configs parciales
Agrega 8 tests para buildToolRegistry() que verifican:
- Config minima: solo tools always-on (current_time, get_weather, matrix_send)
- HTTP habilitado/deshabilitado: http_get y http_post
- FileOps read-only: registra read_file y list_directory pero NO write/append/delete
- FileOps read-write: registra todas las 5 file tools
- IMDb habilitado: imdb_search
- SSH habilitado: ssh_command
- Conteo total: 12 tools con todo habilitado (sin deps externas)

Estos tests validan la logica condicional de registro que ahora vive
en registry_build.go, separada del runtime principal.
2026-04-08 23:19:07 +00:00
egutierrez ee8e74be1b refactor: separar runtime.go en archivos por responsabilidad
Divide agents/runtime.go (1188 lineas) en 5 archivos especializados:

- runtime.go (350 lineas): struct Agent, New(), Run(), Stop(), lifecycle
- handler.go: handleEvent(), executeActions(), command routing, bus, sanitizacion
- llm.go: runLLM(), tool-use loop, system prompt, initLLM(), prompt-commands
- memory.go: ensureWindowLoaded(), appendToWindow(), persistMessage(), ClearWindow()
- registry_build.go: buildToolRegistry(), initToolDeps(), initRateLimiter()

Zero cambios en API publica. Todos los metodos siguen siendo del struct Agent,
solo viven en archivos separados por responsabilidad.

Funciones helper extraidas de New() para reducir su tamaño:
- initCrypto(): inicializacion E2EE
- initLLM(): cliente LLM con fallback
- initMemoryStore(): store SQLite + window size
- initToolDeps(): knowledge, MCP, skills
- initRateLimiter(): rate limiting de tools

Reduccion: 1188 → 350 lineas en runtime.go (70% menos).
2026-04-08 23:17:12 +00:00
egutierrez ac5cde3f3e merge: issue/0031-expand-file-tools — write, list, append, delete para tools/file/
# Conflicts:
#	dev/issues/README.md
2026-04-08 23:06:52 +00:00
egutierrez b519bb4ef8 merge: issue/0028-decouple-launcher — auto-discovery de agentes via init()
# Conflicts:
#	dev/issues/README.md
2026-04-08 23:06:31 +00:00
egutierrez 57affc2e44 test: tests para agents/registry.go
Cobertura completa del registro global de reglas:
- Register + GetRules: registro exitoso y recuperacion
- GetRules con ID inexistente: retorna nil
- Register duplicado: panic con mensaje descriptivo
- RegisteredIDs: retorna todos los IDs registrados
- resetRegistry: limpia el registro (helper para tests)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 23:02:48 +00:00
egutierrez 2bf3d289ac refactor: eliminar structs muertos del config schema
Elimina 14 structs nunca referenciados en el codebase:
- ObservabilityCfg y sub-structs (LoggingCfg, MetricsCfg, HealthCfg, TracingCfg)
- ResilienceCfg y sub-structs (CircuitBreakerCfg, RetryCfg, ShutdownCfg, QueueCfg)
- AgentsCfg y sub-structs (PeerCfg, DelegationCfg, ProtocolCfg)

Se eliminan los campos Agents, Observability y Resilience del AgentConfig root.
CommunicationCfg se mantiene porque esta activamente usada por pkg/personality/
y agents/commands.go.

schema.go pasa de 561 lineas / 61 structs a 460 lineas / 47 structs.
El template _template/config.yaml se reduce de 414 a ~220 lineas.
Los configs de assistant-bot y asistente-2 se limpian de secciones muertas.

yaml.v3 ignora campos extra, asi que YAMLs antiguos siguen parseando sin error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 23:01:53 +00:00
egutierrez 931e6928f5 feat: agregar write_file, list_directory, append_file, delete_file a tools/file/
Expande el paquete tools/file/ con 4 operaciones nuevas para que los agentes
puedan interactuar con carpetas de trabajo (workspaces, outputs).

Cambios:
- Extraer validatePath() y resolveReal() a validate.go para reutilizarlos
- Agregar validateWritePath() que verifica ReadOnly == false
- write_file: crea/sobreescribe archivos, crea dirs padre, limite 1MB
- list_directory: lista archivos con metadata, modo recursivo, limite 500 entries
- append_file: agrega contenido al final, crea si no existe, limite 10MB total
- delete_file: borra solo archivos (nunca directorios), previene rm -rf accidental
- Registrar las 4 tools nuevas en runtime.go condicionalmente:
  - list_directory: siempre (no requiere escritura)
  - write/append/delete: solo si ReadOnly == false

Seguridad: todas las tools reutilizan validatePath() con deny-by-default,
resolucion de symlinks y proteccion contra path traversal.
2026-04-08 23:01:31 +00:00
egutierrez 0cd7e36a14 feat: desacoplar launcher del registro estatico de agentes
Introduce un registro global de reglas en agents/registry.go con
Register() y GetRules(). Cada paquete de agente se auto-registra
via init(), eliminando la necesidad de editar manualmente el map
rulesRegistry en cmd/launcher/main.go.

Cambios:
- agents/registry.go: nuevo registro global con sync.RWMutex
- agents/*/agent.go: cada agente llama agents.Register() en init()
- agents/_template/agent.go: placeholder AGENT_ID_PLACEHOLDER para scaffold
- cmd/launcher/main.go: elimina rulesRegistry, usa blank imports +
  agents.GetRules() para obtener reglas por agent ID

Patron: init() + blank import (estandar Go: database/sql, image codecs)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 23:00:08 +00:00
egutierrez f8fa7e7c7b feat: agregar tool imdb_search para buscar películas en IMDb
Implementa una nueva tool que permite buscar películas y series en IMDb
usando la API de OMDb. Retorna hasta 5 resultados con título, año, tipo,
poster URL e IMDb ID.

Cambios:
- tools/imdb/imdb.go: tool imdb_search con integración a OMDb API
- internal/config/schema.go: IMDbToolCfg con api_key, api_key_env y timeout
- agents/runtime.go: registro de tool en buildToolRegistry
- agents/asistente-2/config.yaml: habilitación de tool imdb
- .env.example: OMDB_API_KEY para configuración

La tool soporta parámetros:
- query (requerido): título de película/serie a buscar
- year (opcional): año para filtrar resultados

Configuración via api_key directa o variable de entorno OMDB_API_KEY.
API key gratuita disponible en http://www.omdbapi.com/

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-08 23:04:05 +00:00
egutierrez 2557ade40d docs: añadir template minimalista para generar agentes
Se crea template_para_llm.md en agents/_template/ con los campos mínimos necesarios para que Claude genere un agente completo:

- Campos obligatorios: id, name, description, system prompt
- Campos opcionales con defaults: provider LLM, model, tool_use, personalidad
- Checkboxes para capacidades específicas (HTTP, SSH, files, etc.)
- Ejemplo completado para referencia

El template permite crear agentes solo proporcionando lo esencial, sin necesidad de entender toda la estructura interna del sistema.
2026-03-08 22:46:04 +00:00
egutierrez ffa0911235 feat: enriquecer comando !info con metadata completa
Fase 4: Comando !info enriquecido
- Mostrar identidad completa (nombre, ID, version, descripcion, tags)
- Mostrar personalidad (rol, tono, formalidad, tipo, humor)
- Mostrar LLM (provider, modelo, tool_use config)
- Mostrar tools disponibles (total + lista de nombres si <= 20)
- Mostrar skills (si estan habilitadas + categorias + cantidad)
- Mostrar knowledge (privado/compartido)
- Mostrar memoria (window size)
- Mostrar schedules (cantidad de cron jobs)
- Mostrar uptime

El comando !info ahora proporciona una vista completa y estructurada
de las capacidades y configuracion del agente.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-08 22:30:26 +00:00
egutierrez e743a3e982 feat: sistema de personalidades enriquecido + agente template
Fase 1: Sistema de personalidades enriquecido
- Ampliar PersonalityCfg con role, backstory, expertise, limitations
- Añadir CommunicationCfg (formality, humor, personality, response_style, quirks, catchphrases)
- Crear tipos puros en pkg/personality/traits.go
- Implementar BuildPersonalityPrompt() para generar bloque de system prompt
- Integrar personalidad en agents/runtime.go (FromConfig + concatenacion al system prompt)

Fase 2: Agente plantilla
- Añadir campo Template bool a AgentMeta
- Filtrar agentes template en launcher (skip si template: true)
- Crear agents/_template/ con config.yaml completo y documentado
- Incluir TODAS las secciones (skills, shared_knowledge, schedules, security)
- agent.go minimo + prompts/system.md plantilla
- Actualizar dev-scripts/agent/new-agent.sh para copiar desde _template/

Fase 3: Ejemplos de personalidades
- Crear agents/_template/PERSONALITIES.md con 4 perfiles:
  * DevOps pragmatico
  * Analista meticuloso
  * Asistente amigable
  * Guardian de seguridad

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-08 22:28:40 +00:00
egutierrez b68ced5c23 feat: integrar skills en runtime de agentes
Integrar sistema de skills en agents/runtime.go:

- Agregar skillLoader al struct Agent
- Inicializar loader y executor cuando skills.enabled = true
- Registrar skill tools en buildToolRegistry
- Respetar filtro de categorias configurado
- Aplicar timeout configurado para scripts

Las skills quedan disponibles automaticamente para agentes que
las habiliten en su config YAML.

Arquitectura: skills como extension opcional, no dependencia core.
2026-03-08 22:13:32 +00:00
egutierrez 0ac2afb573 docs: documentar coexistencia knowledge privado/compartido en prompts
- Separar herramientas en dos secciones
- Explicar diferencia entre knowledge privado y shared
- Guía de cuándo usar cada una
- Issue 0018: Shared Knowledge (fase 5)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-08 21:57:05 +00:00
egutierrez 8fcbcba39c feat: integrar shared knowledge store en runtime
- Agregar campo sharedKnowledgeStore al Agent struct
- Inicializar shared store si cfg.Tools.SharedKnowledge.Enabled
- Registrar shared tools en buildToolRegistry
- Cerrar shared store en Run defer
- Defaults: dir=knowledges, db=knowledges/data/knowledge.db
- Issue 0018: Shared Knowledge (fase 3)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-08 21:56:51 +00:00
egutierrez 1fccae1568 feat: añadir cliente MCP para consumir servidores externos
Implementa el cliente MCP que permite a los agentes conectarse a servidores
MCP externos y usar sus tools como si fueran tools nativas del agente.

Arquitectura implementada:
- shell/mcp/client.go: Cliente MCP con soporte stdio y SSE
- shell/mcp/manager.go: Gestor de múltiples clientes MCP
- tools/mcptools/mcp.go: Bridge que convierte MCP tools → tools.Tool
- shell/mcp/server.go: Movido desde shell/protocols/ para colocación junto al client

Cambios en config:
- MCPServerCfg extendido con campos Transport, Command, Args, Env, Headers,
  Prefix, Timeout para soportar stdio y SSE transport

Integración en runtime:
- agents/runtime.go: Inicializa MCP manager si config.Tools.MCP.Enabled
- buildToolRegistry: Registra tools MCP automáticamente con prefijos configurables
- Agent: Campo mcpManager que se cierra en shutdown

Transportes soportados:
- stdio: Lanza subproceso (ej: npx -y @anthropic/mcp-server-brave-search)
- SSE: Se conecta a servidor HTTP MCP

Las tools MCP son indistinguibles de tools nativas desde el punto de vista
del LLM. Auto-discovery via ListTools(), conversión de JSON Schema a tools.Param.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-03-08 21:22:33 +00:00
egutierrez 8811d45fd1 feat: conectar sistema centralizado de seguridad al launcher y runtime
- Migrar admin a security/user-groups.yaml (admins group)
- agents.New() ahora acepta acl.ACL pre-resuelta como parámetro;
  elimina construcción interna desde cfg.Security.Roles
- cmd/launcher: carga shellsecurity.Load("security/") al arranque;
  si falla, WARN + política vacía (open access). Para cada agente
  llama pksecurity.ResolveACL y pasa la ACL a agents.New()
- cmd/launcher/registry.go: stores secPolicy en launchDeps para
  que reload() también resuelva ACL centralmente
- shell/matrix/listener.go: elimina invite gating y allowlist check
  basados en AllowedUsers; el control de acceso lo hace el runtime
- internal/config/schema.go: depreca campos Roles y AllowedUsers
  (backward compat, no eliminados)
- agents/*/config.yaml: elimina bloques security.roles y allowed_users
- dev/feature_flags.json: activa centralized-security-groups (enabled: true)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 20:56:21 +00:00
egutierrez 9d1ab2d28e feat: integrar Scheduler en agents/runtime.go
Se instancia shellcron.Scheduler en agents.New() cuando cfg.Schedules tiene
entradas (scheduler queda nil en agentes sin schedules, sin overhead).

En agents.Run() se arranca el scheduler en una goroutine independiente que
termina cuando el ctx del agente es cancelado — el shutdown es limpio gracias
a cron.Stop() que devuelve un contexto que se espera.

La integración no rompe agentes existentes: el campo scheduler es nil por
defecto y todo el código nuevo está tras if a.scheduler != nil.
2026-03-08 19:00:38 +00:00
egutierrez f95370de80 test: tests para hot-reload (bus, registry, ciclo de vida del agente)
- shell/bus/bus_test.go: tests de Subscribe/Send/Unsubscribe incluyendo
  idempotencia, canal cerrado tras unsubscribe y resubscribe posterior.

- cmd/launcher/registry_test.go: tests para readReloadTarget (archivo
  ausente, vacío, '*', agentID, whitespace).

- agents/lifecycle_test.go: tests para Agent.Stop()/Done() verificando
  que Stop() desbloquea Run y que es seguro llamarlo múltiples veces o
  con cancel nil.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 18:43:46 +00:00
egutierrez 069f8758b1 feat: hot-reload de agentes individuales via SIGHUP
Implementa el mecanismo de hot-reload descrito en el issue 0013:

- agents/runtime.go: añade Agent.Stop() y Agent.Done() para ciclo de vida
  individual. Run() crea un contexto hijo cancelable y cierra el canal
  done al retornar.

- cmd/launcher/registry.go (nuevo): agentRegistry rastrea agentes vivos
  por ID. Métodos: register, stopAndWait, reload, reloadAll, waitAll,
  cleanupLogs. reload() sigue el flujo completo: stop→wait→unsubscribe
  →reload config→recreate→rewire bus/orch→start nueva goroutine.

- cmd/launcher/main.go: usa agentRegistry en lugar de sync.WaitGroup.
  Añade handler de SIGHUP en goroutine separada que lee run/reload.txt
  para determinar el agente objetivo (* o vacío = todos). Tras leer,
  borra run/reload.txt para no afectar el siguiente SIGHUP.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-08 18:41:32 +00:00
egutierrez 5d3ab834a7 fix: responder en thread cuando el mensaje viene de un thread
Dos problemas corregidos:

1. Detección de threads con E2EE: después de desencriptar un evento,
   evt.Content.Raw puede no contener m.relates_to. Se añade fallback
   usando el contenido tipado (evt.Content.Parsed) que es más robusto
   tras la desencriptación de mautrix.

2. Notificaciones de tools fuera del thread: la notificación "🔨 tool"
   se enviaba con SendMarkdown directo a la sala, ignorando el contexto
   de thread. Ahora usa sendReply que respeta ThreadID.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 13:14:21 +00:00
egutierrez 1852169665 chore: habilitar threads por defecto en todos los agentes
Añade la seccion matrix.threads con enabled: true a los 3 agentes
existentes (assistant-bot, asistente-2, meteorologo). Esto activa
el soporte de threads implementado en issue 0012, permitiendo que
los bots respondan dentro de threads cuando reciben mensajes en uno.
auto_thread queda en false para no cambiar el comportamiento actual.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 12:55:46 +00:00
egutierrez 38d11a0b32 feat: soporte de threads de Matrix (m.thread)
Implementa el soporte completo de threads de Matrix:
- Listener extrae ThreadID de m.relates_to con rel_type=m.thread
- Client.SendThreadMarkdown envia mensajes como parte de un thread
  usando SetThread de mautrix con fallback m.in_reply_to
- Runner detecta ThreadID en ReplyAction y rutea a SendThreadMarkdown
- MatrixSender interfaz actualizada con SendThreadMarkdown
- runtime.go propaga ThreadID en todas las respuestas (comandos, LLM, RBAC)
- sendReply helper centraliza la logica de envio con/sin thread
- Auto-thread: si matrix.threads.auto_thread=true, crea thread nuevo
  para cada conversacion que no esta ya en un thread
- Memoria por thread: usa ThreadID como clave de window cuando el mensaje
  esta en un thread, permitiendo conversaciones paralelas independientes
- Config: matrix.threads.enabled y matrix.threads.auto_thread en ThreadsCfg

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 12:50:34 +00:00
egutierrez 893ac74a16 feat: update user actions to allow all in security configuration for assistant agents 2026-03-08 12:43:35 +00:00
egutierrez d05ec0bd57 feat: configurar working_dir aislado para ambos agentes
Setear working_dir a /tmp/claude-agents/<agent-id> en assistant-bot
y asistente-2, evitando que claude -p herede el CWD del launcher
(raiz del repo). El directorio se crea automaticamente al arrancar
gracias al MkdirAll añadido en el commit anterior.

Se mantiene bypassPermissions ya que el aislamiento real viene del
working_dir — sin acceso al repo, el bypass no expone codigo fuente.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-08 11:46:01 +00:00
egutierrez aeba5d1e86 feat: hardening de system prompts contra prompt injection
Crea template reutilizable en .claude/templates/security-prompt.md y
aplica seccion de seguridad obligatoria a todos los system prompts:

- assistant-bot/prompts/assistant-system.md
- asistente-2/prompts/system.md
- meteorologo/prompts/system.md

Las instrucciones cubren:
- Rechazo de acciones fuera del rol
- Proteccion del system prompt (no revelar)
- Rechazo de comandos destructivos
- Validacion de coherencia contextual de tool calls
- Resistencia a redefinicion de identidad
- Prohibicion de generar contenido para ataques

Tareas 3.1, 3.2, 3.3 del issue 0019.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:49:57 +00:00
egutierrez 536fa0bc54 feat: storage.base_path configurable para aislar datos de runtime
Añade BasePath a StorageCfg y resolveDataBase() en runtime.go para
centralizar la resolucion del directorio base de datos del agente.

Prioridad: config storage.base_path > $AGENTS_DATA_DIR/<id> > agents/<id>/data

Esto permite mover los datos de runtime fuera del arbol del proyecto,
evitando que herramientas de desarrollo lean bases de datos, logs o
crypto stores por accidente.

Los paths de memory.db y knowledge.db ahora usan el base resuelto.
Los configs existentes no se rompen (fallback al path original).

Tareas 1.1 y 1.2 del issue 0019.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:49:02 +00:00
egutierrez 69efb6ab95 feat: rate limiting de tools por room en registry
Añade rate limiting de tool calls por room usando sliding window:

- tools/ratelimit.go: RateLimiter con sliding window per key (room),
  Allow() para verificar/registrar llamadas, Cleanup() para limpiar
  entries expiradas
- tools/registry.go: SetRateLimiter() y ExecuteForRoom() que verifica
  el rate limit antes de ejecutar, logueando tool_rate_limited si excede
- internal/config/schema.go: ToolRateLimitCfg en SecurityCfg con
  enabled, max_calls_per_min y cleanup_interval_s
- agents/runtime.go: inicializa rate limiter desde config y arranca
  goroutine de cleanup periodico
- agents/commands.go: usa ExecuteForRoom en !tool command

Config YAML:
  security:
    tool_rate_limit:
      enabled: true
      max_calls_per_min: 10

Parte de issue 0019c (prompt injection hardening — rate limiting).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:45:41 +00:00
egutierrez 64d29e5968 feat: integrar sanitizacion de input en runtime y config
- agents/runtime.go: campo sanitizeOpts en Agent, sanitizeInput() que
  llama a sanitize.Sanitize() y loguea warnings. Integrado en
  executeActions() y handleTaskEvent() antes de enviar al LLM.
  En modo reject, responde al usuario y corta el flujo.
- internal/config/schema.go: nuevo tipo SanitizeCfg dentro de SecurityCfg
  con campos enabled, mode, min_severity, disabled_patterns.

Protegido por feature flag prompt-injection-hardening (OFF).
Se activa por agente via security.sanitize.enabled en config.yaml.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:34:33 +00:00
egutierrez 4e7aa95adb feat: hardening de tools — deny-by-default, SSRF, path traversal, allowlists
Cambios de seguridad en las 4 herramientas de agentes:

- tools/file: deny-by-default (AllowedPaths vacío = todo denegado),
  resolución de symlinks con EvalSymlinks, protección contra path
  traversal (../) y confusión de prefijos (/opt vs /opt1234)
- tools/ssh: nuevo AllowedCommands allowlist (complementa ForbiddenCommands),
  validación de sintaxis shell (bloquea pipes, subshells, redirects, chains)
- tools/http: protección SSRF bloqueando IPs privadas, loopback, link-local,
  metadata (169.254.169.254). Validación de dominio case-insensitive.
- tools/matrix: nuevo parámetro AllowedRooms para restringir rooms destino
- internal/config/schema: AllowedCommands en SSHToolCfg, MatrixToolCfg nueva
- agents/runtime: pasa MatrixToolCfg al constructor de matrix_send

Parte de issue 0019 (prompt injection hardening). Feature flag OFF.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:17:00 +00:00
egutierrez 7d4fa78569 feat: implementar unauthorized_response explicit en listener
Conectar el campo unauthorized_response de FiltersCfg al shouldHandle()
del listener. Cuando está configurado como "explicit", el bot responde
con un mensaje de permisos denegados en lugar de ignorar silenciosamente.

También se añaden los campos allowed_users y unauthorized_response
(comentados como ejemplo) a los configs de assistant-bot y asistente-2.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 19:02:06 +00:00
egutierrez b60782959d feat: integrar RBAC y allowlist de usuarios en runtime y listener
Cambios en 3 archivos:
- agents/runtime.go: construye ACL desde config de roles, verifica permisos
  antes de ejecutar comandos (command:<name>), interacción LLM (ask) y
  ejecución de tools (tool:<name>). Mensajes denegados se loguean y
  responden al usuario.
- shell/matrix/listener.go: filtra invites y mensajes de usuarios no
  autorizados cuando se configura allowed_users (allowlist vacía = todos).
- internal/config/schema.go: añade campos AllowedUsers y
  UnauthorizedResponse a FiltersCfg para soportar la allowlist en config.

Esto conecta el paquete pkg/acl con el runtime para dar soporte completo
a control de acceso por rol, sin romper la compatibilidad (ACL vacío
permite todo como antes).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:59:09 +00:00
egutierrez bb1e11f456 feat: sistema de prompts externos y mejoras en runtime de agentes
Añade pkg/command/prompts.go para cargar prompts desde archivos .md externos
en el directorio prompts/. Mejoras en agents/runtime.go para el manejo de
herramientas y flujo de ejecución. Nuevos comandos en agents/commands.go.
Ajustes menores en pkg/command/builtins.go para integrar las nuevas capacidades.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 17:17:00 +00:00
egutierrez 8e089ec07e chore: renumerar tasks a 3 dígitos + añadir nuevas + config tweaks
Renumera todos los archivos de tasks de 2 dígitos (01-, 02-...) a
3 dígitos (001-, 002-...) para mejor ordenación. Añade tres nuevas
tasks pendientes: 012-threads, 013-hot-reload, 014-template-agent.

Deshabilita memory temporalmente en assistant-bot config mientras
se estabiliza el sistema de memoria.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 15:46:29 +00:00
egutierrez d95ae173de feat: formato markdown en salida de comandos built-in
Mejora la salida de !help, !tools, !status e !info para usar markdown
nativo: encabezados en negrita, listas con bullet points, código inline
con backticks. Aprovecha el rendering HTML que ya hace el bot para que
los clientes Matrix muestren la información formateada correctamente.

No se cambia lógica de comandos, solo formato de texto de salida.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 15:46:13 +00:00
egutierrez 76ff9394d0 feat: respuestas como reply de Matrix + presencia online/offline
Añade soporte para que las respuestas de los bots sean replies nativos
de Matrix (m.in_reply_to) en lugar de mensajes sueltos. Los clientes
Matrix mostrarán el mensaje original citado.

Cambios:
- EventID en MessageContext para capturar el ID del evento entrante
- InReplyTo en ReplyAction para indicar a qué evento responder
- SendReplyMarkdown en el cliente Matrix (shell/matrix/client.go)
- Runner usa SendReplyMarkdown cuando InReplyTo está presente
- runtime.go pasa InReplyTo en todas las respuestas LLM y comandos
- SetPresence online al arrancar, offline al apagar (graceful)

No se tocan: herramientas, TUI, configuración de agentes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 15:46:07 +00:00
egutierrez 0eb9e8741d feat: añadir agente meteorologo con tool get_weather
Nuevo agente Matrix especializado en consultas meteorológicas.
Usa la API pública Open-Meteo (sin API key) para obtener
condiciones actuales y previsión de 3 días para cualquier ciudad.

Incluye:
- agents/meteorologo/ — reglas puras, config.yaml, system prompt
- tools/weather.go — tool get_weather (geocoding + forecast)
- Registro en runtime.go (tool registry) y launcher (rulesRegistry)

El agente responde a DMs y menciones delegando al LLM con tool_use
habilitado. No tiene comandos directos (!xxx).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 13:54:38 +00:00
egutierrez 828eb175fe feat: renderizar Markdown a HTML en mensajes Matrix con goldmark
Se reemplaza SendText por SendMarkdown en todos los puntos donde el agente
envía respuestas: runtime.go (comandos built-in y tareas orquestadas),
effects/runner.go (acciones Reply) y tools/matrix.go (matrix_send tool).

shell/matrix/client.go ahora usa goldmark para convertir Markdown a HTML real
en el campo FormattedBody del evento Matrix, cumpliendo con la spec de Matrix
para mensajes formateados. El Body conserva el markdown raw como fallback.

Se añade dependencia github.com/yuin/goldmark v1.7.16.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 02:21:06 +00:00
egutierrez 4b72b5ab28 feat: sistema RegisterCommand para comandos por agente
Añade RegisterCommand(spec, handler) al Agent para que cada agente pueda
registrar comandos propios (!xxx) sin modificar built-ins ni usar reglas.

Cambios principales:
- agents/runtime.go: nuevo método RegisterCommand + campo customSpecs
- agents/commands.go: !help muestra comandos del agente en sección separada,
  extrae writeSpec helper, elimina customCommandRules (ya no se usan reglas
  para comandos)
- handleEvent simplificado: los comandos se resuelven por lookup directo
  (built-in + registered), nunca pasan por reglas ni LLM

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-07 01:39:50 +00:00
egutierrez 3f6921d3fd refactor: eliminar regla !help hardcodeada de agentes existentes
Elimina la regla MatchCommand("help") de assistant-bot y asistente-2
ya que ahora !help es un comando built-in del sistema de comandos.
Los agentes solo conservan la regla llm-all para DM/mention → LLM.
2026-03-07 01:11:33 +00:00
egutierrez 33b11a63c8 feat: añadir sistema de comandos directos (!command)
Implementa pkg/command/ como core puro: tipos Spec/ParsedArgs, parser de
args key=value con soporte de comillas, specs de 8 comandos built-in
(help, tools, tool, ping, status, info, clear, version) y BuiltinNames()
para aliases.

En agents/runtime.go: nuevo flujo handleEvent que prioriza comandos sobre
LLM — custom rules del agente → built-in handlers → comando desconocido →
LLM fallback. Handlers en agents/commands.go. El comando !tool ejecuta
tools directamente via Registry con args key=value parseados.

LLM ahora es opcional: si no hay provider configurado, el agente corre
como simple_bot respondiendo solo a comandos.

Se extrae executeActions() como helper reutilizable para ambos flujos
(comando y no-comando).
2026-03-07 01:11:26 +00:00
egutierrez 6eb8ea829f docs: habilitar knowledge en agentes y actualizar prompts
Activa knowledge.enabled en config.yaml de assistant-bot y asistente-2.
Actualiza los system prompts para documentar las 4 tools de knowledge
(search, read, write, list) e incluir hábitos de uso: buscar antes de
responder y guardar información valiosa.

En assistant-bot se reemplaza la sección de "Limitaciones" por una de
"Base de conocimiento" con instrucciones claras de cuándo guardar y
buscar documentos.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:02:45 +00:00
egutierrez 69607b3a65 feat: añadir sistema de knowledge por agente
Implementa una base de conocimiento persistente por agente siguiendo
el patrón pure core / impure shell:

- pkg/knowledge/: tipos puros (Document, Store interface)
- shell/knowledge/: FileStore con SQLite para indexación y archivos .md
- tools/knowledge.go: 4 tools LLM (search, read, write, list)
- tools/knowledge_test.go: tests unitarios de las tools
- internal/config/schema.go: nuevo KnowledgeToolCfg en ToolsCfg
- agents/runtime.go: inicialización del store y registro de tools
- agents/*/knowledge/about-me.md: documentos semilla para cada agente

Cada agente puede buscar, leer, crear y actualizar documentos de
conocimiento. Los archivos .md viven en agents/<id>/knowledge/ y se
indexan en SQLite (agents/<id>/data/knowledge.db).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 23:02:39 +00:00
egutierrez 9862ae9e6f chore: migrar agentes a claude-code como provider primario
Cambia el provider primario de ambos agentes (assistant-bot y asistente-2)
de openai/gpt-4o a claude-code/sonnet.

Configuración aplicada:
- disable_tools: true — claude no ejecuta herramientas internas
- permission_mode: bypassPermissions — sin diálogos interactivos
- model: sonnet — modelo interno de claude -p
- fallback desactivado temporalmente para validar que claude-code funciona

El launcher ya ejecutó exitosamente con este config, confirmado en logs:
claude_code_response con content_len=279, cost_usd=0.023514.
2026-03-06 22:14:36 +00:00
egutierrez 4634ad104b feat: añadir claude-code como proveedor LLM via claude -p
Implementa un nuevo proveedor LLM que ejecuta 'claude -p' como subproceso,
permitiendo usar Claude Code como backend de cualquier agente Matrix.

Cambios:
- pkg/llm/types.go: nueva constante ProviderClaudeCode
- pkg/llm/router.go: routing de 'claude-code' antes de 'claude*' (Anthropic API)
- internal/config/schema.go: nuevo tipo ClaudeCodeCfg con campos para binary,
  timeout, disable_tools, allowed/disallowed tools, permission_mode, model,
  fallback_model, session_id y add_dirs
- shell/llm/claudecode.go: provider completo — buildClaudeArgs(), flattenMessages(),
  parseClaudeOutput() y filterEnv() para limpiar ANTHROPIC_API_KEY del entorno
  y que claude use su propia auth OAuth
- shell/llm/factory.go: case 'claude-code' en FromConfig(), WithFallback() ahora
  recibe fallbackCfg para sobreescribir model/max_tokens al hacer fallback
- agents/runtime.go: actualizado para pasar fallbackCfg a WithFallback()

No se tocó: los proveedores existentes (anthropic.go, openai.go), el core puro
de decision ni el listener de Matrix.
2026-03-06 22:14:28 +00:00
egutierrez 5697b92ab8 feat: integrar structured logging en todos los componentes del shell
Se propaga *slog.Logger a todos los componentes impuros del shell:
- shell/bus/ — logs de subscribe, send, reply, timeout, unsubscribe
- shell/effects/ — duración y resultado de cada action ejecutada
- shell/llm/ (anthropic, openai, factory) — request/response con tokens, duración, fallback
- shell/memory/sqlite — open, save, recall, close con detalles
- shell/ssh/ — inicio, fin, errores y duración de comandos SSH
- tools/registry — registro, ejecución y errores de herramientas

Se usa el paquete shell/logger para field names consistentes (FieldDurationMS, FieldTokensUsed, etc.).
Cada componente recibe el logger por inyección de dependencias, sin globals.
Las firmas de New/FromConfig se actualizan para aceptar *slog.Logger.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 21:53:31 +00:00
egutierrez b596a967cc feat: detect plural/group-addressed questions to trigger all-agent responses
Se añade detección de preguntas dirigidas al grupo en los prompts de routing
y quality. Cuando el usuario usa plural o se dirige colectivamente a los
agentes ("¿qué opinan?", "chicos", "hey everyone", etc.), el routing baja
la confianza a 0.2 y el evaluador de calidad mantiene continue=true hasta
que todos los agentes hayan participado.

Esto garantiza que preguntas con intención grupal reciban respuestas de
todos los agentes disponibles, no solo del más relevante.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 17:16:12 +00:00
egutierrez 485d6e86be feat: enhance orchestrator prompts for multi-agent collaboration
Se reescriben los tres prompts del orquestador (routing, quality, refinement)
para fomentar la interacción entre agentes en lugar de respuestas individuales.

- Routing: instruye al LLM a mantener confianza baja (0.3-0.6) en preguntas
  generales para disparar contribuciones de múltiples agentes.
- Quality: nuevo sistema de scoring que favorece la colaboración. Un solo agente
  respondiendo nunca supera 0.5, forzando que otros participen.
- Refinement: cambia el enfoque de "mejorar" a "enriquecer con perspectiva única",
  priorizando agentes con expertise diferente al anterior.
- Config: max_iterations 3→6, quality_threshold 0.8→0.85, nuevo campo
  repetition_threshold: 0.6 para detección de bucles.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 17:10:52 +00:00
egutierrez 7176afde0a feat: update orchestrator for enhanced multi-bot management and room discovery 2026-03-06 17:03:08 +00:00
egutierrez 2667af52cc feat: implement multi-bot orchestration system with LLM routing
Implementa el sistema de orquestación para salas Matrix con múltiples bots.
El orquestador es un "special agent" sin identidad Matrix que coordina qué bot
responde y cuándo, usando LLM (Claude) para routing y evaluación de calidad.

Cambios principales:
- pkg/orchestration/task.go: tipos puros (TaskEvent, BotResponse, QualityScore, RoutingDecision)
- shell/orchestration/: runtime del orquestador (orchestrator.go, router.go, evaluator.go)
- agents/specials/orchestrator/: config + prompts (routing, quality, refinement)
- internal/config/: SpecialConfig, OrchestrationCfg, LoadSpecial()
- shell/bus/bus.go: protocolo request-reply (SendAndWait, Reply) para delegación
- shell/matrix/listener.go: InterceptFunc para interceptar eventos en salas orquestadas
- agents/runtime.go: SetBus, listenBus, handleTaskEvent para recibir tareas del orquestador
- cmd/launcher/main.go: creación de bus compartido, arranque del orquestador antes de bots

Incluye deduplicación para evitar que múltiples listeners en la misma sala
disparen el orquestador más de una vez por mensaje.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 09:05:42 +00:00