diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index ced47d8..855a51f 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -9,10 +9,11 @@ Monorepo Go para bots Matrix autonomos. Modulo: `github.com/enmanuel/agents`. ### 1. Functional PRogramming: Pure core / Impure shell ``` -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) +pkg/ → PURO: tipos, funciones puras, cero side effects +shell/ → IMPURO: todo I/O (Matrix, LLM, SSH, filesystem) +devagents/ → runtime: Agent/Robot ensambla core + shell +agents/ → reglas puras por agente + config.yaml + prompts +tools/ → Def (puro) + Exec (impuro) ``` **Nunca** side effects en `pkg/`. El core produce `[]decision.Action` (datos puros), el shell los interpreta. @@ -56,9 +57,9 @@ shell/mcp/ cliente y servidor MCP (Model Context Protocol) shell/skills/ loader (filesystem) + executor (scripts) shell/effects/ Runner: []Action → side effects shell/bus/ comunicacion inter-agente -agents/types.go Runner interface (comun a Agent y Robot) -agents/runtime.go Agent{}: ensambla core + shell (runtime completo con LLM) -agents/robot.go Robot{}: runtime ligero command-only (sin LLM, reglas, memoria) +devagents/types.go Runner interface (comun a Agent y Robot) +devagents/runtime.go Agent{}: ensambla core + shell (runtime completo con LLM) +devagents/robot.go Robot{}: runtime ligero command-only (sin LLM, reglas, memoria) agents// agent.go (reglas puras) + config.yaml + prompts/system.md tools/ tool registry + tool implementations (subpackages) tools/mcptools/ bridge: convierte MCP tools → tools.Tool diff --git a/.claude/rules/create_agent.md b/.claude/rules/create_agent.md index 6c713e0..592c8b0 100644 --- a/.claude/rules/create_agent.md +++ b/.claude/rules/create_agent.md @@ -7,7 +7,7 @@ Guia ejecutable para Claude. Seguir paso a paso sin desviarse. | | Agent | Robot | |---|---|---| | **Cuando usar** | Necesita LLM, reglas, memoria, tools | Solo responde comandos (!xxx) | -| **Runtime** | `agents.New()` — completo | `agents.NewRobot()` — ligero | +| **Runtime** | `devagents.New()` — completo | `devagents.NewRobot()` — ligero | | **Config type** | `type: agent` (default) | `type: robot` | | **LLM** | Si | No | | **Reglas** | Si (`agent.go` con `Rules()`) | No (sin `agent.go`) | @@ -57,12 +57,12 @@ Template base (generado por el scaffold): package // sin guiones: "monitor-bot" → package monitor (strip hyphens, strip _bot) import ( - "github.com/enmanuel/agents/agents" + "github.com/enmanuel/agents/devagents" "github.com/enmanuel/agents/pkg/decision" ) func init() { - agents.Register("", Rules) + devdevagents.Register("", Rules) } func Rules() []decision.Rule { @@ -84,7 +84,7 @@ func Rules() []decision.Rule { **Reglas estrictas:** - **PURO**: solo imports de `pkg/decision` y `agents` (para Register), cero I/O, cero side effects -- **Auto-registro**: cada agente se registra via `init()` con `agents.Register("", Rules)` +- **Auto-registro**: cada agente se registra via `init()` con `devagents.Register("", Rules)` - Package name = ID sin guiones ni `_bot` (e.g. `monitor-bot` → `package monitor`) - **No usar reglas para comandos** (`!help`, `!ping`, etc.) — los comandos se gestionan via `RegisterCommand` (ver policy `create_command.md`) - Las reglas solo aplican a mensajes normales (sin prefijo `!`) @@ -174,7 +174,7 @@ _ "github.com/enmanuel/agents/agents/" Las reglas se registran automáticamente via `init()` en el paquete del agente. No se necesita editar ningún map ni registry manualmente. -**El ID en `agents.Register()` DEBE coincidir exactamente con `agent.id` en config.yaml.** +**El ID en `devagents.Register()` DEBE coincidir exactamente con `agent.id` en config.yaml.** ## Convención de env vars — REGLA CRÍTICA @@ -228,7 +228,7 @@ tail -f run/launcher.log - **Nunca** side effects en `agent.go` - **Siempre** compilar con `-tags goolm` -- **Siempre** que `agent.id` coincida entre config.yaml, `agents.Register()` y directorio +- **Siempre** que `agent.id` coincida entre config.yaml, `devagents.Register()` y directorio - **No** crear `data/` manualmente — se auto-genera - **No** commitear tokens ni passwords - **No** compartir crypto stores entre agentes diff --git a/.claude/rules/create_command.md b/.claude/rules/create_command.md index 1d79d8c..1f22063 100644 --- a/.claude/rules/create_command.md +++ b/.claude/rules/create_command.md @@ -28,7 +28,7 @@ Todos los agentes los tienen automáticamente: `!help`, `!ping`, `!tools`, `!too ### Agent-specific (por agente) -Se registran con `agent.RegisterCommand(spec, handler)` en el launcher, después de `agents.New()` y antes de `agent.Run()`. +Se registran con `agent.RegisterCommand(spec, handler)` en el launcher, después de `devagents.New()` y antes de `agent.Run()`. ## Pasos para crear un comando de agente @@ -79,10 +79,10 @@ type CommandEntry struct { ### 2. Registrar en el launcher (`cmd/launcher/main.go`) -Después de `agents.New()` y antes de `wg.Add(1)`: +Después de `devagents.New()` y antes de `wg.Add(1)`: ```go -a, err := agents.New(cfg, rules, agentLogger) +a, err := devagents.New(cfg, rules, agentLogger) if err != nil { ... } // Register agent-specific commands diff --git a/.claude/rules/create_tool.md b/.claude/rules/create_tool.md index 0f32b4b..8bfe4af 100644 --- a/.claude/rules/create_tool.md +++ b/.claude/rules/create_tool.md @@ -41,7 +41,7 @@ func NewMiTool(/* deps */) Tool { } ``` -### 2. Registrar en `agents/runtime.go` → `buildToolRegistry()` +### 2. Registrar en `devagents/registry_build.go` → `buildToolRegistry()` ```go if /* condición basada en config */ { diff --git a/.claude/rules/index.md b/.claude/rules/index.md index 5ccb58f..40107bc 100644 --- a/.claude/rules/index.md +++ b/.claude/rules/index.md @@ -66,5 +66,6 @@ Filosofia completa documentada en `CLAUDE.md` seccion "Trunk-based development". Todas las reglas respetan el patron **pure core / impure shell**: - `pkg/` es puro — nunca añadir side effects - `shell/` es impuro — todo I/O va aqui -- `agents/` compone ambos — reglas puras + ensamblado con shell +- `devagents/` runtime: Agent/Robot ensambla core + shell +- `agents/` reglas puras por agente + config + prompts - `tools/` sigue el mismo patron: `Def` (datos puros) + `Exec` (funcion impura) diff --git a/agents/_template/agent.go b/agents/_template/agent.go index 1f6ee40..4de3261 100644 --- a/agents/_template/agent.go +++ b/agents/_template/agent.go @@ -4,12 +4,12 @@ package _template import ( - "github.com/enmanuel/agents/agents" + "github.com/enmanuel/agents/devagents" "github.com/enmanuel/agents/pkg/decision" ) func init() { - agents.Register("AGENT_ID_PLACEHOLDER", Rules) + devagents.Register("AGENT_ID_PLACEHOLDER", Rules) } // Rules devuelve las reglas de este agente (vacio para el template). diff --git a/agents/asistente-2/agent.go b/agents/asistente-2/agent.go index 75547c8..6118fac 100644 --- a/agents/asistente-2/agent.go +++ b/agents/asistente-2/agent.go @@ -3,12 +3,12 @@ package asistente2 import ( - "github.com/enmanuel/agents/agents" + "github.com/enmanuel/agents/devagents" "github.com/enmanuel/agents/pkg/decision" ) func init() { - agents.Register("asistente-2", Rules) + devagents.Register("asistente-2", Rules) } // Rules returns the decision rules for the asistente-2 bot. diff --git a/agents/assistant-bot/agent.go b/agents/assistant-bot/agent.go index aff28d7..4d9374f 100644 --- a/agents/assistant-bot/agent.go +++ b/agents/assistant-bot/agent.go @@ -3,12 +3,12 @@ package assistant import ( - "github.com/enmanuel/agents/agents" + "github.com/enmanuel/agents/devagents" "github.com/enmanuel/agents/pkg/decision" ) func init() { - agents.Register("assistant-bot", Rules) + devagents.Register("assistant-bot", Rules) } // Rules returns the decision rules for the assistant bot. diff --git a/agents/meteorologo/agent.go b/agents/meteorologo/agent.go index d221ed6..8cf8dc9 100644 --- a/agents/meteorologo/agent.go +++ b/agents/meteorologo/agent.go @@ -3,12 +3,12 @@ package meteorologo import ( - "github.com/enmanuel/agents/agents" + "github.com/enmanuel/agents/devagents" "github.com/enmanuel/agents/pkg/decision" ) func init() { - agents.Register("meteorologo", Rules) + devagents.Register("meteorologo", Rules) } // Rules returns the decision rules for the meteorologo bot. diff --git a/agents/test-bot/agent.go b/agents/test-bot/agent.go index eaa2b79..ed12619 100644 --- a/agents/test-bot/agent.go +++ b/agents/test-bot/agent.go @@ -4,12 +4,12 @@ package test import ( - "github.com/enmanuel/agents/agents" + "github.com/enmanuel/agents/devagents" "github.com/enmanuel/agents/pkg/decision" ) func init() { - agents.Register("test-bot", Rules) + devagents.Register("test-bot", Rules) } // Rules devuelve las reglas de este agente (vacio para el template). diff --git a/agents/test-personality/agent.go b/agents/test-personality/agent.go index cf020cc..84b98eb 100644 --- a/agents/test-personality/agent.go +++ b/agents/test-personality/agent.go @@ -2,12 +2,12 @@ package test_personality import ( - "github.com/enmanuel/agents/agents" + "github.com/enmanuel/agents/devagents" "github.com/enmanuel/agents/pkg/decision" ) func init() { - agents.Register("test-personality", Rules) + devagents.Register("test-personality", Rules) } // Rules routes all DMs and mentions to the LLM. diff --git a/cmd/launcher/main.go b/cmd/launcher/main.go index b7f55a3..7053954 100644 --- a/cmd/launcher/main.go +++ b/cmd/launcher/main.go @@ -19,7 +19,7 @@ import ( "github.com/spf13/cobra" - "github.com/enmanuel/agents/agents" + "github.com/enmanuel/agents/devagents" "github.com/enmanuel/agents/internal/config" "github.com/enmanuel/agents/pkg/decision" "github.com/enmanuel/agents/pkg/orchestration" @@ -173,10 +173,10 @@ func main() { } // Branch: robot (command-only, lightweight) vs agent (full runtime). - var runner agents.Runner + var runner devagents.Runner if cfg.Agent.Type == "robot" { - robot, rErr := agents.NewRobot(cfg, agentLogger) + robot, rErr := devagents.NewRobot(cfg, agentLogger) if rErr != nil { logger.Error("failed to create robot", "id", cfg.Agent.ID, "err", rErr) agentCleanup() @@ -201,7 +201,7 @@ func main() { "acl_empty", agentACL.Empty(), ) - a, cErr := agents.New(cfg, rules, agentACL, agentLogger, agents.WithLogDir(logDir)) + a, cErr := devagents.New(cfg, rules, agentACL, agentLogger, devagents.WithLogDir(logDir)) if cErr != nil { logger.Error("failed to create agent", "id", cfg.Agent.ID, "err", cErr) agentCleanup() @@ -312,7 +312,7 @@ func startOrchestrator(agentBus *bus.Bus, logger *slog.Logger) (*orchHandle, err // global registry (populated by init() in each agent package). // Returns nil if no rules are registered (command-only bot). func rulesFor(agentID string, logger *slog.Logger) []decision.Rule { - factory := agents.GetRules(agentID) + factory := devagents.GetRules(agentID) if factory == nil { logger.Warn("no rules registered for agent, using empty ruleset (command-only)", "id", agentID) return nil diff --git a/cmd/launcher/registry.go b/cmd/launcher/registry.go index ce23d14..dfbb3a5 100644 --- a/cmd/launcher/registry.go +++ b/cmd/launcher/registry.go @@ -8,7 +8,7 @@ import ( "sync" "time" - "github.com/enmanuel/agents/agents" + "github.com/enmanuel/agents/devagents" "github.com/enmanuel/agents/internal/config" "github.com/enmanuel/agents/pkg/decision" "github.com/enmanuel/agents/pkg/orchestration" @@ -19,7 +19,7 @@ import ( // runningAgent holds a live runner (Agent or Robot) and the metadata needed to recreate it. type runningAgent struct { - runner agents.Runner + runner devagents.Runner cfg *config.AgentConfig cfgPath string logger *slog.Logger @@ -139,10 +139,10 @@ func (r *agentRegistry) reload(id string, rulesFor func(string, *slog.Logger) [] } // 5. Create new runner (validates config before discarding the old one). - var newRunner agents.Runner + var newRunner devagents.Runner if cfg.Agent.Type == "robot" { - robot, rErr := agents.NewRobot(cfg, newLogger) + robot, rErr := devagents.NewRobot(cfg, newLogger) if rErr != nil { newLogger.Error("reload: failed to create robot", "id", id, "err", rErr) newCleanup() @@ -153,7 +153,7 @@ func (r *agentRegistry) reload(id string, rulesFor func(string, *slog.Logger) [] rules := rulesFor(cfg.Agent.ID, newLogger) agentACL := pksecurity.ResolveACL(cfg.Agent.ID, r.deps.secPolicy) newLogger.Debug("resolved acl for agent (reload)", "agent", cfg.Agent.ID, "acl_empty", agentACL.Empty()) - newAgent, aErr := agents.New(cfg, rules, agentACL, newLogger) + newAgent, aErr := devagents.New(cfg, rules, agentACL, newLogger) if aErr != nil { newLogger.Error("reload: failed to create agent", "id", id, "err", aErr) newCleanup() diff --git a/dev-scripts/agent/convert-to-robot.sh b/dev-scripts/agent/convert-to-robot.sh index 7a21ac2..f28bd10 100755 --- a/dev-scripts/agent/convert-to-robot.sh +++ b/dev-scripts/agent/convert-to-robot.sh @@ -106,12 +106,12 @@ cat > "$DIR/agent.go" << GO package ${PACKAGE} import ( - "github.com/enmanuel/agents/agents" + "github.com/enmanuel/agents/devagents" "github.com/enmanuel/agents/pkg/decision" ) func init() { - agents.Register("${ID}", Rules) + devagents.Register("${ID}", Rules) } // Rules returns nil — robots only respond to commands. diff --git a/devagents/commands.go b/devagents/commands.go index 12e0fb6..80a52f0 100644 --- a/devagents/commands.go +++ b/devagents/commands.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "context" diff --git a/devagents/commands_metrics_test.go b/devagents/commands_metrics_test.go index 16cce03..85aaf04 100644 --- a/devagents/commands_metrics_test.go +++ b/devagents/commands_metrics_test.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "context" diff --git a/devagents/handler.go b/devagents/handler.go index 3ed43be..8e4d638 100644 --- a/devagents/handler.go +++ b/devagents/handler.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "context" diff --git a/devagents/lifecycle_test.go b/devagents/lifecycle_test.go index 93c71b2..5b5fe66 100644 --- a/devagents/lifecycle_test.go +++ b/devagents/lifecycle_test.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "context" diff --git a/devagents/llm.go b/devagents/llm.go index 073261f..f1ebc27 100644 --- a/devagents/llm.go +++ b/devagents/llm.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "context" diff --git a/devagents/memory.go b/devagents/memory.go index b5cd058..a4004ea 100644 --- a/devagents/memory.go +++ b/devagents/memory.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "context" diff --git a/devagents/registry.go b/devagents/registry.go index c941a58..260fb60 100644 --- a/devagents/registry.go +++ b/devagents/registry.go @@ -3,7 +3,7 @@ // Each agent package self-registers via init() using Register. // The launcher retrieves rules via GetRules without importing agent // packages explicitly (only blank imports are needed). -package agents +package devagents import ( "sync" diff --git a/devagents/registry_build.go b/devagents/registry_build.go index 2fcb14c..6dc2c9c 100644 --- a/devagents/registry_build.go +++ b/devagents/registry_build.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "context" diff --git a/devagents/registry_build_test.go b/devagents/registry_build_test.go index 5a3c9a5..f186734 100644 --- a/devagents/registry_build_test.go +++ b/devagents/registry_build_test.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "log/slog" diff --git a/devagents/registry_test.go b/devagents/registry_test.go index 5e71f80..f16e8f2 100644 --- a/devagents/registry_test.go +++ b/devagents/registry_test.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "sort" diff --git a/devagents/robot.go b/devagents/robot.go index bcf8dcf..0e9c7da 100644 --- a/devagents/robot.go +++ b/devagents/robot.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "context" diff --git a/devagents/robot_test.go b/devagents/robot_test.go index 9e8236d..500364d 100644 --- a/devagents/robot_test.go +++ b/devagents/robot_test.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "context" diff --git a/devagents/runtime.go b/devagents/runtime.go index 94f844b..bc2ebbc 100644 --- a/devagents/runtime.go +++ b/devagents/runtime.go @@ -1,5 +1,5 @@ // Package agents defines the Agent runtime that ties core and shell together. -package agents +package devagents import ( "context" diff --git a/devagents/runtime_test.go b/devagents/runtime_test.go index 16d0487..e4d152f 100644 --- a/devagents/runtime_test.go +++ b/devagents/runtime_test.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "context" diff --git a/devagents/types.go b/devagents/types.go index 84dd4fd..c420fa7 100644 --- a/devagents/types.go +++ b/devagents/types.go @@ -1,4 +1,4 @@ -package agents +package devagents import ( "context" diff --git a/docs/e2ee.md b/docs/e2ee.md index 57a96c5..d01cdd6 100644 --- a/docs/e2ee.md +++ b/docs/e2ee.md @@ -10,7 +10,7 @@ La implementación usa Olm puro en Go (`-tags goolm`, sin CGO). ``` config.yaml (encryption section) ↓ -agents/runtime.go → Agent.New() llama a InitCrypto() +devagents/runtime.go → Agent.New() llama a InitCrypto() ↓ shell/matrix/client.go → InitCrypto() configura cryptohelper ↓ @@ -144,7 +144,7 @@ Los nuevos mensajes se descifrarán normalmente tras regenerar las claves. | Archivo | Propósito | |---------|-----------| -| `agents/runtime.go` | Inicializa E2EE por agente | +| `devagents/runtime.go` | Inicializa E2EE por agente | | `shell/matrix/client.go` | `InitCrypto()` — setup de cryptohelper | | `cmd/verify/main.go` | Herramienta de cross-signing | | `cmd/launcher/sqlite.go` | Registro driver SQLite |