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 } } }