diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index ce5ccc6..b282059 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -1,284 +1,97 @@ -# CLAUDE.md — Contexto del proyecto agents_and_robots +# CLAUDE.md — agents_and_robots -## Qué es este proyecto +Monorepo Go para bots Matrix autonomos. Modulo: `github.com/enmanuel/agents`. -Monorepo en Go para gestionar bots Matrix. Cada bot es un agente autónomo con personalidad, reglas de decisión y acceso a herramientas (LLM, SSH, HTTP, MCP). Los bots se comunican entre sí y con humanos a través de Matrix (mautrix-go). +**Homeserver:** `https://matrix-af2f3d.organic-machine.com` | **Server name:** `matrix-af2f3d.organic-machine.com` -**Homeserver activo:** `https://matrix-af2f3d.organic-machine.com` -**Server name:** `matrix-af2f3d.organic-machine.com` +## Los dos pilares — SIEMPRE APLICAR -## Filosofía de diseño — LA REGLA MÁS IMPORTANTE - -El proyecto usa el patrón **pure core / impure shell** estrictamente: +### 1. Functional PRogramming: Pure core / Impure shell ``` -pkg/ → PURE: solo tipos, funciones puras, cero side effects -shell/ → IMPURE: todo I/O, red, filesystem, procesos -agents/ → composición: reglas puras + ensamblado con shell en runtime.go +pkg/ → PURO: tipos, funciones puras, cero side effects +shell/ → IMPURO: todo I/O (Matrix, LLM, SSH, filesystem) +agents/ → composicion: reglas puras + ensamblado con shell +tools/ → Def (puro) + Exec (impuro) ``` -**Nunca** añadir side effects (I/O, red, llamadas a APIs) dentro de `pkg/`. -**Siempre** que el core necesite "hacer algo", produce un `[]decision.Action` (datos puros) que el shell interpreta. +**Nunca** side effects en `pkg/`. El core produce `[]decision.Action` (datos puros), el shell los interpreta. -El flujo es siempre: ``` Matrix event → Parse (pure) → Evaluate rules (pure) → []Action (pure data) → Runner.Execute (impure) → efectos reales ``` -## Módulo Go +### 2. TBD: Trunk-based development -`github.com/enmanuel/agents` - -## Estructura de directorios +**master** es el unico branch estable. Nunca trabajar directamente en master. ``` -pkg/decision/ → motor de reglas puro (Evaluate, Rule, MatchFunc, Action) -pkg/llm/ → tipos de LLM puros (CompleteFunc, CompletionRequest, Route) -pkg/tools/ → specs declarativas de herramientas (SSHCommandSpec, etc.) -pkg/message/ → parse y format de mensajes Matrix (puros) -pkg/personality/ → tipos de personalidad (Personality, Tone, etc.) - -shell/llm/ → clientes LLM reales (anthropic.go, openai.go, factory.go) -shell/matrix/ → cliente Matrix mautrix-go (client.go, listener.go) -shell/ssh/ → ejecutor SSH real (executor.go) -shell/effects/ → Runner que interpreta []Action → side effects -shell/bus/ → comunicación inter-agente via Go channels -shell/protocols/ → adaptadores MCP (mcp.go) - -agents/runtime.go → Agent{}: ensambla core + shell, maneja eventos -agents/assistant-bot/ → reglas puras + config del assistant-bot - -internal/config/schema.go → tipos completos del YAML de configuración -internal/config/loader.go → Load() con expand env vars, LoadMeta() sin validación -cmd/launcher/main.go → inicia agentes, tiene rulesRegistry -cmd/agentctl/main.go → CLI de gestión (list, start, stop, remove) -cmd/register/main.go → registra bots en Synapse via admin API -dev-scripts/ → scripts bash para operaciones del día a día -dev-scripts/server/ → gestión del launcher (start, stop, restart, ps, logs, dashboard) -dev-scripts/agent/ → gestión de agentes (new, register, verify, avatar, remove, list) -``` - -## Reglas para LLMs - -Las reglas guían cómo ejecutar tareas específicas respetando la arquitectura del proyecto. -Ver índice completo en `.claude/rules/index.md`. - -| Regla | Cuándo aplicarla | -|-------|------------------| -| `.claude/rules/create_agent.md` | Al crear un nuevo bot/agente Matrix | -| `.claude/rules/create_tool.md` | Al añadir una nueva tool para function calling | -| `.claude/rules/create_command.md` | Al añadir un comando directo (!xxx) a un agente | -| `.claude/rules/create_issue.md` | Al crear un nuevo issue en `dev/issues/` | -| `.claude/rules/fix_issue.md` | Al implementar/arreglar un issue existente | - -Documentación detallada para humanos en `docs/creating-agents.md`. - -## Agentes existentes - -| ID | Estado | LLM | Descripción | -|----------------|-----------|---------|------------------------------------------| -| assistant-bot | activo | GPT-4o | Asistente general, responde DMs | -| asistente-2 | activo | GPT-4o | Asistente con tools (current_time) | - -## Dependencias clave - -``` -maunium.net/go/mautrix v0.21.1 → Matrix client -github.com/sashabaranov/go-openai → OpenAI + Ollama-compatible -github.com/mark3labs/mcp-go → MCP protocol server/client -golang.org/x/crypto/ssh → SSH execution -github.com/spf13/cobra → CLI -gopkg.in/yaml.v3 → Config parsing -``` - -## Configuración de agentes - -Cada agente vive en `agents//`: -- `config.yaml` — configuración completa (ver schema en `internal/config/schema.go`) -- `agent.go` — reglas puras que implementan `Rules() []decision.Rule` -- `prompts/system.md` — system prompt del LLM -- `data/` — datos de runtime (SQLite, crypto, logs) — en .gitignore - -El `config.yaml` soporta variables de entorno con `${VAR}` y `$VAR`. El loader usa `os.ExpandEnv`. - -Secciones principales del config: `agent`, `personality`, `llm`, `tools`, `matrix`, `agents` (peers), `ssh`, `security`, `schedules`, `observability`, `resilience`, `storage`. - -## Cómo añadir un nuevo bot - -Guía rápida (detalle completo en `docs/creating-agents.md`, regla en `.claude/rules/create_agent.md`): - -1. Crear scaffold: `./dev-scripts/agent/new-agent.sh "Display Name"` o manual en `agents//` -2. Crear `agent.go` (reglas puras), `config.yaml`, `prompts/system.md` -3. Registrar en `cmd/launcher/main.go` → import + `rulesRegistry` -4. Registrar en Matrix: `./dev-scripts/agent/register.sh "Display Name"` -5. Avatar y nombre: `./dev-scripts/agent/avatar.sh static/.jpg` -6. Verificación E2EE: `go run -tags goolm ./cmd/verify --homeserver ... --username --password ... --token ...` -7. Arrancar: `./dev-scripts/server/start.sh ` - -## Dev-scripts disponibles - -```bash -# === server/ — gestión del launcher === -./dev-scripts/server/start.sh # iniciar el launcher -./dev-scripts/server/stop.sh # detener el launcher -./dev-scripts/server/restart.sh # reiniciar el launcher -./dev-scripts/server/ps.sh # procesos con detalle (PID, mem, CPU, uptime) -./dev-scripts/server/logs.sh [lines] # tail -f de logs -./dev-scripts/server/dashboard.sh # TUI interactiva - -# Gestión unificada (wrapper) -./dev-scripts/server/server.sh start # iniciar -./dev-scripts/server/server.sh stop # detener -./dev-scripts/server/server.sh restart # reiniciar -./dev-scripts/server/server.sh status # resumen general del servidor -./dev-scripts/server/server.sh ps # procesos con detalle -./dev-scripts/server/server.sh logs # tail -f de logs -./dev-scripts/server/server.sh kill # SIGKILL forzado (emergencia) - -# === agent/ — gestión de agentes === -./dev-scripts/agent/list.sh # ver todos los bots y estado -./dev-scripts/agent/new-agent.sh [name] # scaffold completo -./dev-scripts/agent/register.sh [name] # registrar bot en Matrix -./dev-scripts/agent/verify.sh [agent-id] # verificación E2EE -./dev-scripts/agent/avatar.sh # subir avatar -./dev-scripts/agent/reset-password.sh # resetear password -./dev-scripts/agent/remove.sh # deshabilitar (sin borrar datos) -``` - -PID files: `run/.pid` | Log files: `run/.log` - -## Gestión de procesos - -Los bots corren como procesos independientes lanzados por `agentctl` o `dev-scripts/server/start.sh`. -Cada proceso escribe su PID en `run/.pid` y su log en `run/.log`. -`is_running()` usa `kill -0 ` para verificar sin matar el proceso. - -## Variables de entorno críticas - -```bash -MATRIX_HOMESERVER # URL del servidor Matrix -MATRIX_SERVER_NAME # nombre del servidor (parte después de :) -MATRIX_ADMIN_TOKEN # token admin para registrar bots (cmd/register) -MATRIX_TOKEN_ # access token de cada bot -OPENAI_API_KEY # OpenAI -ANTHROPIC_API_KEY # Anthropic/Claude -``` - -Nunca commitear `.env`. Plantilla en `.env.example`. - -## Trunk-based development (TBD) - -El proyecto usa trunk-based development estricto. **master** es el único branch estable y siempre deployable. - -### Flujo de trabajo - -``` -master (trunk) ← siempre deployable, único branch permanente +master ← siempre deployable ↑ - └── issue/- ← rama efímera (horas, no días) - ├── commit: feat: ... - ├── commit: test: ... - └── commit: docs: ... + └── issue/- ← rama efimera (horas) + commits atomicos (feat:, fix:, test:, docs:, refactor:, chore:) merge --no-ff → master → push → delete branch ``` -1. **`/git-branch`** — crea rama `issue/-` desde master actualizado -2. Implementar en la rama con commits granulares por bloque lógico -3. **`/git-push`** — tests → merge `--no-ff` a master → push → eliminar rama +- `/git-branch` — crea rama desde master +- `/git-push` — tests → merge --no-ff → push → elimina rama +- Commits atomicos por bloque logico, titulo corto + cuerpo en espanol +- No WIP, no squash, no rebase -i -### Convención de commits +**Feature flags** (solo para features multi-issue): codigo completo y testeado, mergeado pero desactivado. Flag != WIP. Archivo: `dev/feature_flags.json`. -Dentro de la rama, cada commit es **atómico por bloque lógico** (no mezclar feat + test en uno): - -| Prefijo | Uso | -|---------|-----| -| `feat:` | nueva funcionalidad | -| `fix:` | corrección de error | -| `refactor:` | cambio estructural sin cambio funcional | -| `docs:` | documentación | -| `chore:` | mantenimiento | -| `test:` | tests nuevos o modificados | -| `merge:` | commit de merge (generado por `--no-ff`) | - -- **Título** (`-m` corto): resumen del bloque -- **Cuerpo** (`-m` largo): en español, explica qué, por qué, impacto y alcance -- **No hacer commits WIP**: nada de "wip", "tmp", "fix fix" — cada commit debe tener mensaje real -- **No squash**: `--no-ff` preserva los commits individuales; `git log --first-parent master` da la vista limpia (un merge = un issue) - -### Reglas de ramas - -- **Nunca trabajar directamente en master** — siempre crear rama con `/git-branch` -- **Una rama por issue** — no mezclar issues en la misma rama -- **Ramas cortas** — idealmente horas, no días -- **Nunca pushear la rama** — solo se pushea master después del merge -- **No rebase interactivo** — si los commits ya son limpios, no hay nada que reescribir - -### Feature flags — features grandes en TBD - -En TBD no existen ramas largas. Para features que no caben en una sola rama, se usan **feature flags**: código completo y testeado que se mergea a master pero desactivado hasta que todas las piezas estén listas. - -**Feature flag ≠ WIP.** Un flag protege código terminado; un WIP es código a medias. Nunca commitear código incompleto. - -**Cuándo usar feature flags:** -- Feature multi-issue que requiere varias ramas para completarse -- Cambio con riesgo que necesita poder desactivarse en producción -- Despliegue gradual (activar para un agente primero, después para todos) - -**Cuándo NO usarlos:** -- Issue autocontenido que se completa en una rama → mergear directo -- Bug fix, refactor, docs → no necesitan flag - -**Flujo para features multi-issue:** +## Estructura ``` -Feature grande (ej: 0015 Telegram) - ├── issue/0015a-telegram-types → pkg/ types, flag OFF → merge - ├── issue/0015b-telegram-client → shell/ client, flag OFF → merge - ├── issue/0015c-telegram-listener → integration, flag OFF → merge - └── issue/0015d-telegram-enable → flag ON, cleanup → merge +pkg/decision/ motor de reglas puro +pkg/llm/ tipos LLM puros +pkg/message/ parse/format mensajes +pkg/personality/ tipos de personalidad +shell/llm/ clientes LLM (anthropic, openai) +shell/matrix/ cliente Matrix (mautrix-go) +shell/ssh/ ejecutor SSH +shell/effects/ Runner: []Action → side effects +shell/bus/ comunicacion inter-agente +agents/runtime.go Agent{}: ensambla core + shell +agents// agent.go (reglas puras) + config.yaml + prompts/system.md +tools/ tool registry + tool implementations (subpackages) +internal/config/ schema.go + loader.go +cmd/launcher/ entrypoint principal (rulesRegistry) +cmd/agentctl/ CLI de gestion +dev-scripts/server/ start, stop, restart, ps, logs, dashboard +dev-scripts/agent/ new, register, verify, avatar, remove, list ``` -Cada rama es corta, cada merge es seguro, master nunca se rompe. +## Reglas operativas -**Archivo:** `dev/feature_flags.json` +Guias detalladas en `.claude/rules/index.md`: -```json -{ - "flags": { - "telegram-support": { - "enabled": false, - "issue": "0015", - "description": "Soporte multi-plataforma Telegram", - "added": "2026-03-07" - } - } -} -``` +| Regla | Cuando | +|-------|--------| +| `create_agent.md` | Crear nuevo bot/agente | +| `create_tool.md` | Añadir tool para function calling | +| `create_command.md` | Añadir comando !xxx | +| `create_issue.md` | Crear issue en dev/issues/ | +| `fix_issue.md` | Implementar un issue existente | -### Comandos disponibles +## Agentes -- `/git-branch` — crear rama de trabajo (`.claude/commands/git-branch.md`) -- `/git-push` — integrar rama a master y publicar (`.claude/commands/git-push.md`) +| ID | LLM | Descripcion | +|----|-----|-------------| +| assistant-bot | GPT-4o | Asistente general, DMs | +| asistente-2 | GPT-4o | Asistente con tools | -## Preferencias del usuario +## Build -- **Idioma**: español en configs/comentarios de dominio, inglés en código Go -- **Estilo**: FP estricto (pure core / impure shell), sin abstracción prematura -- **Desarrollo**: trunk-based, Gitea como remote -- **Go version**: 1.23.5 en `/usr/local/go/bin` -- **No usar** frameworks de agentes externos — arquitectura propia +- Go 1.23.5 (`/usr/local/go/bin`), siempre compilar con `-tags goolm` +- CGO_ENABLED=0 (pure-Go SQLite via modernc, shim en `cmd/launcher/sqlite.go`) +- Secrets via env vars (`.env.example`), nunca commitear `.env` -## Documentacion de desarrollo +## Preferencias -Ver `dev/README.md` para el indice de documentacion interna (issues pendientes, diseños tecnicos, etc.). -Issues detallados en `dev/issues/`. - -## Próximas extensiones naturales - -- Scheduling: cron runner en `shell/` para `ScheduleCfg` -- Conversation history: mantener `[]Message` por room en memoria/SQLite -- RBAC real: conectar `SecurityCfg.Roles` al listener -- E2EE: habilitar `encryption.enabled: true` con crypto store de mautrix -- MCP: exponer tools de los agentes como MCP server en el puerto configurado -- A2A: agent card HTTP endpoint para comunicación con agentes externos +- Espanol en configs/comentarios de dominio, ingles en codigo Go +- FP estricto, sin abstraccion prematura +- Trunk-based, Gitea como remote +- Arquitectura propia, sin frameworks de agentes externos +- Issues en `dev/issues/`, docs internas en `dev/README.md`