Files
agents_and_robots/devagents/registry_build_test.go
T
egutierrez f2718aa17c feat: añadir tools wikipedia_search y exchange_rate
- tools/wikipedia/wikipedia.go: tool wikipedia_search que consulta la
  API pública de Wikipedia (sin auth). Devuelve resumen del artículo.
- tools/exchange/exchange.go: 4 tools de tipo de cambio usando
  exchangerate-api.com: exchange_rate_get, exchange_rate_convert,
  exchange_rate_list, exchange_rate_historical.
- internal/config/schema.go: añadir ExchangeRateToolCfg con Enabled,
  APIKey, APIKeyEnv y Timeout.
- devagents/registry_build.go: registrar ambas tool families.
  wikipedia_search siempre disponible; exchange rate tools requieren
  APIKey configurado (deny-by-default con WARN si falta).
- devagents/registry_build_test.go: actualizar test de registry build.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-11 00:25:10 +00:00

174 lines
5.9 KiB
Go

package devagents
import (
"log/slog"
"os"
"testing"
"github.com/enmanuel/agents/internal/config"
toolmemory "github.com/enmanuel/agents/tools/memorytools"
)
func TestBuildToolRegistry_MinimalConfig(t *testing.T) {
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError}))
cfg := &config.AgentConfig{
Agent: config.AgentMeta{ID: "test-agent"},
}
roomCtx := &toolmemory.RoomContext{}
reg := buildToolRegistry(cfg, nil, nil, nil, nil, nil, nil, nil, nil, roomCtx, logger)
// Always-registered tools: current_time, weather, matrix_send
names := reg.Names()
if len(names) < 3 {
t.Fatalf("expected at least 3 always-on tools, got %d: %v", len(names), names)
}
assertToolRegistered(t, reg, "current_time")
assertToolRegistered(t, reg, "get_weather")
assertToolRegistered(t, reg, "matrix_send")
}
func TestBuildToolRegistry_HTTPEnabled(t *testing.T) {
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError}))
cfg := &config.AgentConfig{
Agent: config.AgentMeta{ID: "test-agent"},
Tools: config.ToolsCfg{
HTTP: config.HTTPToolCfg{Enabled: true, AllowedDomains: []string{"example.com"}},
},
}
roomCtx := &toolmemory.RoomContext{}
reg := buildToolRegistry(cfg, nil, nil, nil, nil, nil, nil, nil, nil, roomCtx, logger)
assertToolRegistered(t, reg, "http_get")
assertToolRegistered(t, reg, "http_post")
}
func TestBuildToolRegistry_HTTPDisabled(t *testing.T) {
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError}))
cfg := &config.AgentConfig{
Agent: config.AgentMeta{ID: "test-agent"},
}
roomCtx := &toolmemory.RoomContext{}
reg := buildToolRegistry(cfg, nil, nil, nil, nil, nil, nil, nil, nil, roomCtx, logger)
assertToolNotRegistered(t, reg, "http_get")
assertToolNotRegistered(t, reg, "http_post")
}
func TestBuildToolRegistry_FileOpsReadOnly(t *testing.T) {
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError}))
cfg := &config.AgentConfig{
Agent: config.AgentMeta{ID: "test-agent"},
Tools: config.ToolsCfg{
FileOps: config.FileOpsCfg{Enabled: true, ReadOnly: true, AllowedPaths: []string{"/tmp"}},
},
}
roomCtx := &toolmemory.RoomContext{}
reg := buildToolRegistry(cfg, nil, nil, nil, nil, nil, nil, nil, nil, roomCtx, logger)
assertToolRegistered(t, reg, "read_file")
assertToolRegistered(t, reg, "list_directory")
assertToolNotRegistered(t, reg, "write_file")
assertToolNotRegistered(t, reg, "append_file")
assertToolNotRegistered(t, reg, "delete_file")
}
func TestBuildToolRegistry_FileOpsReadWrite(t *testing.T) {
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError}))
cfg := &config.AgentConfig{
Agent: config.AgentMeta{ID: "test-agent"},
Tools: config.ToolsCfg{
FileOps: config.FileOpsCfg{Enabled: true, ReadOnly: false, AllowedPaths: []string{"/tmp"}},
},
}
roomCtx := &toolmemory.RoomContext{}
reg := buildToolRegistry(cfg, nil, nil, nil, nil, nil, nil, nil, nil, roomCtx, logger)
assertToolRegistered(t, reg, "read_file")
assertToolRegistered(t, reg, "list_directory")
assertToolRegistered(t, reg, "write_file")
assertToolRegistered(t, reg, "append_file")
assertToolRegistered(t, reg, "delete_file")
}
func TestBuildToolRegistry_IMDbEnabled(t *testing.T) {
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError}))
cfg := &config.AgentConfig{
Agent: config.AgentMeta{ID: "test-agent"},
Tools: config.ToolsCfg{
IMDb: config.IMDbToolCfg{Enabled: true},
},
}
roomCtx := &toolmemory.RoomContext{}
reg := buildToolRegistry(cfg, nil, nil, nil, nil, nil, nil, nil, nil, roomCtx, logger)
assertToolRegistered(t, reg, "imdb_search")
}
func TestBuildToolRegistry_SSHEnabled(t *testing.T) {
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError}))
cfg := &config.AgentConfig{
Agent: config.AgentMeta{ID: "test-agent"},
Tools: config.ToolsCfg{
SSH: config.SSHToolCfg{Enabled: true},
},
}
roomCtx := &toolmemory.RoomContext{}
// SSH tool requires an executor; passing nil is fine for registration (only used at exec time)
reg := buildToolRegistry(cfg, nil, nil, nil, nil, nil, nil, nil, nil, roomCtx, logger)
assertToolRegistered(t, reg, "ssh_command")
}
func TestBuildToolRegistry_ToolCount(t *testing.T) {
logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError}))
// Enable everything that doesn't need external deps
cfg := &config.AgentConfig{
Agent: config.AgentMeta{ID: "test-agent"},
Tools: config.ToolsCfg{
HTTP: config.HTTPToolCfg{Enabled: true},
SSH: config.SSHToolCfg{Enabled: true},
FileOps: config.FileOpsCfg{Enabled: true, AllowedPaths: []string{"/tmp"}},
IMDb: config.IMDbToolCfg{Enabled: true},
},
}
roomCtx := &toolmemory.RoomContext{}
reg := buildToolRegistry(cfg, nil, nil, nil, nil, nil, nil, nil, nil, roomCtx, logger)
// 4 always-on (current_time, get_weather, wikipedia_search, matrix_send) + 2 HTTP + 1 SSH + 5 file + 1 IMDb = 13
expected := 13
if got := reg.Len(); got != expected {
t.Errorf("expected %d tools, got %d: %v", expected, got, reg.Names())
}
}
// ── Test helpers ────────────────────────────────────────────────────────────
func assertToolRegistered(t *testing.T, reg interface{ Names() []string }, name string) {
t.Helper()
for _, n := range reg.Names() {
if n == name {
return
}
}
t.Errorf("expected tool %q to be registered, but it was not. Registered: %v", name, reg.Names())
}
func assertToolNotRegistered(t *testing.T, reg interface{ Names() []string }, name string) {
t.Helper()
for _, n := range reg.Names() {
if n == name {
t.Errorf("expected tool %q NOT to be registered, but it was", name)
return
}
}
}