import { describe, expect, it } from "vitest"; import { ALLOWED_TOOLS, CLAWBOOK_TOOL_NAMES, CLAWBOOK_TOOLS, MOLTBOOK_TOOL_NAMES, MOLTBOOK_TOOLS, TOOL_DEFINITIONS, TOOL_NAMES, } from "../../src/agent/tool-definitions"; const EXPECTED_CLAWBOOK_TOOLS = [ "read_feed", "read_replies", "read_post", "read_channel", "list_channels", "read_profile", "create_post", "reply_to_post", "like_post", "unlike_post", "follow_user", "unfollow_user", "register_agent", "create_channel", "following_feed", ]; const EXPECTED_MOLTBOOK_TOOLS = [ "moltbook_read_feed", "moltbook_read_post", "moltbook_read_comments", "moltbook_list_submolts", "moltbook_read_submolt", "moltbook_create_submolt", "moltbook_subscribe", "moltbook_unsubscribe", "moltbook_submolt_feed", "moltbook_update_submolt", "moltbook_list_moderators", "moltbook_create_post", "moltbook_comment", "moltbook_upvote", "moltbook_downvote", "moltbook_delete_post", "moltbook_upvote_comment", "moltbook_register", "moltbook_follow_user", "moltbook_unfollow_user", "moltbook_personalized_feed", "moltbook_check_status", "moltbook_my_profile", "moltbook_read_profile", "moltbook_update_profile", "moltbook_upload_avatar", "moltbook_delete_avatar", "moltbook_pin_post", "moltbook_unpin_post", "moltbook_add_moderator", "moltbook_remove_moderator", "moltbook_search", "moltbook_dm_check", "moltbook_dm_requests", "moltbook_dm_approve", "moltbook_dm_conversations", "moltbook_dm_read", "moltbook_dm_send", "moltbook_dm_request", ]; describe("TOOL_DEFINITIONS", () => { it("defines exactly 54 tools", () => { expect(TOOL_DEFINITIONS).toHaveLength(54); }); it("contains all expected Clawbook tool names", () => { expect(TOOL_NAMES).toEqual(expect.arrayContaining(EXPECTED_CLAWBOOK_TOOLS)); }); it("contains all expected Moltbook tool names", () => { expect(TOOL_NAMES).toEqual(expect.arrayContaining(EXPECTED_MOLTBOOK_TOOLS)); }); it("has no duplicate tool names", () => { const unique = new Set(TOOL_NAMES); expect(unique.size).toBe(TOOL_NAMES.length); }); it("generates correct MCP-prefixed allowed tools", () => { for (const name of EXPECTED_CLAWBOOK_TOOLS) { expect(ALLOWED_TOOLS).toContain(`mcp__clawbook__${name}`); } for (const name of EXPECTED_MOLTBOOK_TOOLS) { expect(ALLOWED_TOOLS).toContain(`mcp__moltbook__${name}`); } expect(ALLOWED_TOOLS).toHaveLength(54); }); it("every tool has a non-empty description", () => { for (const tool of TOOL_DEFINITIONS) { expect(tool.description.length).toBeGreaterThan(0); } }); it("authed Clawbook POST/DELETE tools have bodyFields defined", () => { for (const tool of CLAWBOOK_TOOLS) { if (tool.auth && tool.method !== "GET") { expect(tool.bodyFields).toBeDefined(); expect(tool.bodyFields?.length).toBeGreaterThan(0); } } }); it("path param tools have pathParams defined", () => { const pathParamTools = TOOL_DEFINITIONS.filter((t) => t.path.includes(":")); for (const tool of pathParamTools) { expect(tool.pathParams).toBeDefined(); expect(tool.pathParams?.length).toBeGreaterThan(0); } }); it("create_post and reply_to_post use POST /api/posts", () => { const createPost = TOOL_DEFINITIONS.find((t) => t.name === "create_post"); const replyPost = TOOL_DEFINITIONS.find((t) => t.name === "reply_to_post"); expect(createPost?.method).toBe("POST"); expect(createPost?.path).toBe("/api/posts"); expect(replyPost?.method).toBe("POST"); expect(replyPost?.path).toBe("/api/posts"); }); it("all Clawbook tools have network: clawbook", () => { for (const tool of CLAWBOOK_TOOLS) { expect(tool.network).toBe("clawbook"); } }); it("all Moltbook tools have network: moltbook", () => { for (const tool of MOLTBOOK_TOOLS) { expect(tool.network).toBe("moltbook"); } }); it("authed Clawbook tools have authScheme: bitcoin-auth", () => { for (const tool of CLAWBOOK_TOOLS) { if (tool.auth) { expect(tool.authScheme).toBe("bitcoin-auth"); } } }); it("authed Moltbook tools have authScheme: bearer", () => { for (const tool of MOLTBOOK_TOOLS) { if (tool.auth) { expect(tool.authScheme).toBe("bearer"); } } }); it("Moltbook tool names are prefixed with mcp__moltbook__", () => { for (const name of MOLTBOOK_TOOL_NAMES) { expect(name).toMatch(/^mcp__moltbook__/); } }); it("Clawbook tool names are prefixed with mcp__clawbook__", () => { for (const name of CLAWBOOK_TOOL_NAMES) { expect(name).toMatch(/^mcp__clawbook__/); } }); });