import { beforeEach, describe, expect, it, vi } from "vitest"; // Mock @vercel/sandbox const mockRunCommand = vi.fn(); const mockWriteFiles = vi.fn(); const mockStop = vi.fn(); const mockCreate = vi.fn().mockResolvedValue({ runCommand: mockRunCommand, writeFiles: mockWriteFiles, stop: mockStop, }); vi.mock("@vercel/sandbox", () => ({ Sandbox: { create: mockCreate }, })); function cmdResult(exitCode: number, stdoutStr: string, stderrStr = "") { return { exitCode, stdout: async () => stdoutStr, stderr: async () => stderrStr, }; } async function loadRunner() { return import("../../src/agent/runner"); } describe("buildAgentScript", () => { it("generates a script that uses the Claude Agent SDK", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "You are a bot", userMessage: "Read the feed", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", }); expect(script).toContain('from "@anthropic-ai/claude-agent-sdk"'); expect(script).toContain("query("); expect(script).toContain("You are a bot"); expect(script).toContain("Read the feed"); expect(script).toContain("https://clawbook.network"); }); it("does not import @anthropic-ai/sdk directly", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "test", userMessage: "test", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", }); expect(script).not.toContain('from "@anthropic-ai/sdk"'); }); it("includes all 15 Clawbook tool definitions", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "test", userMessage: "test", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", }); expect(script).toContain("read_feed"); expect(script).toContain("read_replies"); expect(script).toContain("read_post"); expect(script).toContain("read_channel"); expect(script).toContain("list_channels"); expect(script).toContain("read_profile"); expect(script).toContain("create_post"); expect(script).toContain("reply_to_post"); expect(script).toContain("like_post"); expect(script).toContain("unlike_post"); expect(script).toContain("follow_user"); expect(script).toContain("unfollow_user"); expect(script).toContain("register_agent"); expect(script).toContain("create_channel"); expect(script).toContain("following_feed"); }); it("script with moltbookApiKey includes Moltbook server and tools", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "test", userMessage: "test", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", moltbookApiUrl: "https://www.moltbook.com/api/v1", moltbookApiKey: "test-key", }); expect(script).toContain("moltbookRequest"); expect(script).toContain('name: "moltbook"'); expect(script).toContain("Authorization"); expect(script).toContain("Bearer"); expect(script).toContain("moltbook_read_feed"); expect(script).toContain("moltbook_create_post"); }); it("script without moltbookApiKey does not include Moltbook code", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "test", userMessage: "test", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", }); expect(script).not.toContain("moltbookRequest"); expect(script).not.toContain('name: "moltbook"'); }); it("defines tools via createSdkMcpServer", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "test", userMessage: "test", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", }); expect(script).toContain("createSdkMcpServer"); expect(script).toContain('name: "clawbook"'); }); it("outputs JSON result to stdout", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "test", userMessage: "test", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", }); expect(script).toContain("console.log"); expect(script).toContain("JSON.stringify"); }); it("captures tool_use blocks into actions", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "test", userMessage: "test", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", }); expect(script).toContain('"tool_use"'); expect(script).toContain("actions.push"); }); it("imports getAuthToken from bitcoin-auth", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "test", userMessage: "test", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", }); expect(script).toContain('import { getAuthToken } from "bitcoin-auth"'); }); it("includes signRequest helper function", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "test", userMessage: "test", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", }); expect(script).toContain("function signRequest(path, bodyObj)"); expect(script).toContain("getAuthToken("); expect(script).toContain("privateKeyWif: WIF"); }); it("uses X-Auth-Token header instead of Authorization Bearer", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "test", userMessage: "test", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", }); expect(script).toContain("X-Auth-Token"); expect(script).not.toContain("Authorization"); expect(script).not.toContain("Bearer"); }); it("uses query() with maxTurns and bypassPermissions", async () => { const { buildAgentScript } = await loadRunner(); const script = buildAgentScript({ systemPrompt: "test", userMessage: "test", clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", }); expect(script).toContain("maxTurns: 10"); expect(script).toContain('permissionMode: "bypassPermissions"'); expect(script).toContain("allowDangerouslySkipPermissions: true"); }); }); describe("runAgentTurn", () => { beforeEach(() => { vi.clearAllMocks(); mockRunCommand.mockResolvedValue(cmdResult(0, "")); }); it("creates a sandbox, writes files, installs CLI and deps, and runs script", async () => { mockRunCommand.mockImplementation(({ cmd, args }) => { if (cmd === "node" && args?.[0] === "agent.mjs") { return cmdResult( 0, JSON.stringify({ success: true, summary: "Posted something", actions: [{ tool: "create_post", input: { content: "Hello" } }], }), ); } return cmdResult(0, ""); }); const { runAgentTurn } = await loadRunner(); const result = await runAgentTurn("scheduled_post", { clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", anthropicAuthToken: "sk-ant-oat01-test", }); expect(mockCreate).toHaveBeenCalled(); expect(mockWriteFiles).toHaveBeenCalled(); expect(mockRunCommand).toHaveBeenCalled(); expect(mockStop).toHaveBeenCalled(); expect(result.success).toBe(true); expect(result.summary).toBe("Posted something"); expect(result.actions).toHaveLength(1); }); it("returns error result when script fails", async () => { mockRunCommand.mockImplementation(({ cmd, args }) => { if (cmd === "node" && args?.[0] === "agent.mjs") { return cmdResult(1, "", "Error: auth failed"); } return cmdResult(0, ""); }); const { runAgentTurn } = await loadRunner(); const result = await runAgentTurn("scheduled_post", { clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", anthropicAuthToken: "sk-ant-oat01-test", }); expect(result.success).toBe(false); expect(result.error).toContain("auth failed"); expect(mockStop).toHaveBeenCalled(); }); it("stops sandbox even on error", async () => { mockWriteFiles.mockRejectedValueOnce(new Error("Write failed")); const { runAgentTurn } = await loadRunner(); const result = await runAgentTurn("scheduled_post", { clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", anthropicAuthToken: "sk-ant-oat01-test", }); expect(result.success).toBe(false); expect(mockStop).toHaveBeenCalled(); }); it("passes CLAUDE_CODE_OAUTH_TOKEN to sandbox runCommand env", async () => { mockRunCommand.mockImplementation(({ cmd, args }) => { if (cmd === "node" && args?.[0] === "agent.mjs") { return cmdResult( 0, JSON.stringify({ success: true, summary: "Done", actions: [] }), ); } return cmdResult(0, ""); }); const { runAgentTurn } = await loadRunner(); await runAgentTurn("scheduled_post", { clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", anthropicAuthToken: "sk-ant-oat01-test", }); expect(mockRunCommand).toHaveBeenCalledWith( expect.objectContaining({ cmd: "node", args: ["agent.mjs"], env: expect.objectContaining({ CLAUDE_CODE_OAUTH_TOKEN: "sk-ant-oat01-test", }), }), ); }); it("installs Claude Code CLI globally in sandbox", async () => { mockRunCommand.mockImplementation(({ cmd, args }) => { if (cmd === "node" && args?.[0] === "agent.mjs") { return cmdResult( 0, JSON.stringify({ success: true, summary: "Done", actions: [] }), ); } return cmdResult(0, ""); }); const { runAgentTurn } = await loadRunner(); await runAgentTurn("scheduled_post", { clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", anthropicAuthToken: "sk-ant-oat01-test", }); expect(mockRunCommand).toHaveBeenCalledWith( expect.objectContaining({ cmd: "npm", args: ["install", "-g", "@anthropic-ai/claude-code"], }), ); }); it("installs agent SDK and bitcoin-auth in sandbox", async () => { mockRunCommand.mockImplementation(({ cmd, args }) => { if (cmd === "node" && args?.[0] === "agent.mjs") { return cmdResult( 0, JSON.stringify({ success: true, summary: "Done", actions: [] }), ); } return cmdResult(0, ""); }); const { runAgentTurn } = await loadRunner(); await runAgentTurn("scheduled_post", { clawbookApiUrl: "https://clawbook.network", sigmaMemberWif: "L1test", anthropicAuthToken: "sk-ant-oat01-test", }); expect(mockRunCommand).toHaveBeenCalledWith( expect.objectContaining({ cmd: "npm", args: expect.arrayContaining([ "@anthropic-ai/claude-agent-sdk", "bitcoin-auth", "zod", ]), }), ); }); });