import { describe, expect, it } from "vitest"; import type { ClawdbotConfig } from "../config/config.js"; import { resolveAgentConfig, resolveAgentModelFallbacksOverride, resolveAgentModelPrimary, } from "./agent-scope.js"; describe("resolveAgentConfig", () => { it("should return undefined when no agents config exists", () => { const cfg: ClawdbotConfig = {}; const result = resolveAgentConfig(cfg, "main"); expect(result).toBeUndefined(); }); it("should return undefined when agent id does not exist", () => { const cfg: ClawdbotConfig = { agents: { list: [{ id: "main", workspace: "~/clawd" }], }, }; const result = resolveAgentConfig(cfg, "nonexistent"); expect(result).toBeUndefined(); }); it("should return basic agent config", () => { const cfg: ClawdbotConfig = { agents: { list: [ { id: "main", name: "Main Agent", workspace: "~/clawd", agentDir: "~/.clawdbot/agents/main", model: "anthropic/claude-opus-4", }, ], }, }; const result = resolveAgentConfig(cfg, "main"); expect(result).toEqual({ name: "Main Agent", workspace: "~/clawd", agentDir: "~/.clawdbot/agents/main", model: "anthropic/claude-opus-4", identity: undefined, groupChat: undefined, subagents: undefined, sandbox: undefined, tools: undefined, }); }); it("supports per-agent model primary+fallbacks", () => { const cfg: ClawdbotConfig = { agents: { defaults: { model: { primary: "anthropic/claude-sonnet-4", fallbacks: ["openai/gpt-4.1"], }, }, list: [ { id: "linus", model: { primary: "anthropic/claude-opus-4", fallbacks: ["openai/gpt-5.2"], }, }, ], }, }; expect(resolveAgentModelPrimary(cfg, "linus")).toBe("anthropic/claude-opus-4"); expect(resolveAgentModelFallbacksOverride(cfg, "linus")).toEqual(["openai/gpt-5.2"]); // If fallbacks isn't present, we don't override the global fallbacks. const cfgNoOverride: ClawdbotConfig = { agents: { list: [ { id: "linus", model: { primary: "anthropic/claude-opus-4", }, }, ], }, }; expect(resolveAgentModelFallbacksOverride(cfgNoOverride, "linus")).toBe(undefined); // Explicit empty list disables global fallbacks for that agent. const cfgDisable: ClawdbotConfig = { agents: { list: [ { id: "linus", model: { primary: "anthropic/claude-opus-4", fallbacks: [], }, }, ], }, }; expect(resolveAgentModelFallbacksOverride(cfgDisable, "linus")).toEqual([]); }); it("should return agent-specific sandbox config", () => { const cfg: ClawdbotConfig = { agents: { list: [ { id: "work", workspace: "~/clawd-work", sandbox: { mode: "all", scope: "agent", perSession: false, workspaceAccess: "ro", workspaceRoot: "~/sandboxes", }, }, ], }, }; const result = resolveAgentConfig(cfg, "work"); expect(result?.sandbox).toEqual({ mode: "all", scope: "agent", perSession: false, workspaceAccess: "ro", workspaceRoot: "~/sandboxes", }); }); it("should return agent-specific tools config", () => { const cfg: ClawdbotConfig = { agents: { list: [ { id: "restricted", workspace: "~/clawd-restricted", tools: { allow: ["read"], deny: ["exec", "write", "edit"], elevated: { enabled: false, allowFrom: { whatsapp: ["+15555550123"] }, }, }, }, ], }, }; const result = resolveAgentConfig(cfg, "restricted"); expect(result?.tools).toEqual({ allow: ["read"], deny: ["exec", "write", "edit"], elevated: { enabled: false, allowFrom: { whatsapp: ["+15555550123"] }, }, }); }); it("should return both sandbox and tools config", () => { const cfg: ClawdbotConfig = { agents: { list: [ { id: "family", workspace: "~/clawd-family", sandbox: { mode: "all", scope: "agent", }, tools: { allow: ["read"], deny: ["exec"], }, }, ], }, }; const result = resolveAgentConfig(cfg, "family"); expect(result?.sandbox?.mode).toBe("all"); expect(result?.tools?.allow).toEqual(["read"]); }); it("should normalize agent id", () => { const cfg: ClawdbotConfig = { agents: { list: [{ id: "main", workspace: "~/clawd" }], }, }; // Should normalize to "main" (default) const result = resolveAgentConfig(cfg, ""); expect(result).toBeDefined(); expect(result?.workspace).toBe("~/clawd"); }); });