import { describe, it, expect, vi, beforeEach } from "vitest"; import { getAllTools, getToolById, executeTool, TOOL_REGISTRY } from "./tools"; // Mock agents module vi.mock("./agents", () => ({ getAgentById: vi.fn(), getAgentAccessControl: vi.fn(), })); import { getAgentById, getAgentAccessControl } from "./agents"; const mockAgent = { id: 1, name: "Test Agent", model: "gpt-4", provider: "OpenAI", allowedTools: ["http_get", "http_post", "file_read"], temperature: "0.7", maxTokens: 2048, }; describe("Tool Registry", () => { it("should return all tools", () => { const tools = getAllTools(); expect(tools.length).toBeGreaterThan(0); expect(tools.every((t) => t.id && t.name && t.category)).toBe(true); }); it("should have required fields for each tool", () => { const tools = getAllTools(); for (const tool of tools) { expect(tool.id).toBeTruthy(); expect(tool.name).toBeTruthy(); expect(tool.description).toBeTruthy(); expect(tool.category).toBeTruthy(); expect(typeof tool.dangerous).toBe("boolean"); expect(typeof tool.parameters).toBe("object"); } }); it("should find tool by ID", () => { const tool = getToolById("http_get"); expect(tool).toBeDefined(); expect(tool?.name).toBe("HTTP GET"); expect(tool?.category).toBe("http"); }); it("should return undefined for unknown tool ID", () => { const tool = getToolById("nonexistent_tool"); expect(tool).toBeUndefined(); }); it("should have http tools", () => { const httpTools = TOOL_REGISTRY.filter((t) => t.category === "http"); expect(httpTools.length).toBeGreaterThanOrEqual(2); }); it("should have shell tools", () => { const shellTools = TOOL_REGISTRY.filter((t) => t.category === "shell"); expect(shellTools.length).toBeGreaterThanOrEqual(1); }); it("should have docker tools", () => { const dockerTools = TOOL_REGISTRY.filter((t) => t.category === "docker"); expect(dockerTools.length).toBeGreaterThanOrEqual(2); }); it("should mark dangerous tools correctly", () => { const shellExec = getToolById("shell_exec"); expect(shellExec?.dangerous).toBe(true); const httpGet = getToolById("http_get"); expect(httpGet?.dangerous).toBe(false); }); }); describe("Tool Execution", () => { beforeEach(() => { vi.clearAllMocks(); (getAgentById as any).mockResolvedValue(mockAgent); (getAgentAccessControl as any).mockResolvedValue([]); }); it("should return error for non-existent agent", async () => { (getAgentById as any).mockResolvedValue(null); const result = await executeTool(999, "http_get", { url: "https://example.com" }); expect(result.success).toBe(false); expect(result.error).toContain("Agent not found"); }); it("should return error for unknown tool", async () => { const result = await executeTool(1, "nonexistent_tool", {}); expect(result.success).toBe(false); expect(result.error).toContain("Unknown tool"); }); it("should block tool not in agent's allowed list", async () => { const agentWithLimitedTools = { ...mockAgent, allowedTools: ["http_get"] }; (getAgentById as any).mockResolvedValue(agentWithLimitedTools); const result = await executeTool(1, "shell_exec", { command: "echo hello" }); expect(result.success).toBe(false); expect(result.error).toContain("not in agent's allowed tools list"); }); it("should block tool explicitly denied in access control", async () => { (getAgentAccessControl as any).mockResolvedValue([ { tool: "http_get", isAllowed: false }, ]); const agentWithAllTools = { ...mockAgent, allowedTools: [] }; (getAgentById as any).mockResolvedValue(agentWithAllTools); const result = await executeTool(1, "http_get", { url: "https://example.com" }); expect(result.success).toBe(false); expect(result.error).toContain("blocked"); }); it("should include executionTimeMs in result", async () => { // Agent with no allowed tools (empty = all allowed) const agentAllTools = { ...mockAgent, allowedTools: [] }; (getAgentById as any).mockResolvedValue(agentAllTools); // This will fail (no actual HTTP), but should still return executionTimeMs const result = await executeTool(1, "http_get", { url: "https://httpbin.org/get" }); expect(typeof result.executionTimeMs).toBe("number"); expect(result.executionTimeMs).toBeGreaterThanOrEqual(0); }); });