import { Type } from "typebox"; import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core"; export type SendToolRequestFn = ( toolName: string, parameters: Record ) => Promise; /** * Creates the three native Confluence tools for the pi runtime. * They execute purely via bridge requests; no remote HTTP clients or credentials exist here. */ export function createConfluenceTools(sendToolRequest: SendToolRequestFn): AgentTool[] { const searchTool: AgentTool = { name: "confluence_search", label: "confluence_search", description: "Search Confluence documentation using plain keywords. Returns matching pages, space keys, canonical URLs, and snippets.", parameters: Type.Object({ query: Type.String({ description: "Search keywords (plain text, escaped into CQL by backend)" }), space: Type.Optional( Type.String({ maxLength: 256, description: "Optional space key filter (up to 256 UTF-8 bytes)" }) ), limit: Type.Optional( Type.Integer({ minimum: 1, maximum: 50, description: "Maximum number of pages to return (1–50, default 10)" }) ), offset: Type.Optional( Type.Integer({ minimum: 0, maximum: 10000, description: "Pagination offset (default 0, maximum 10,000)" }) ) }, { additionalProperties: false }), execute: async (_toolCallId, params): Promise> => { const result = await sendToolRequest("confluence_search", params as Record); return { content: [{ type: "text", text: JSON.stringify(result) }], details: result }; } }; const viewTool: AgentTool = { name: "confluence_view", label: "confluence_view", description: "Read a Confluence page by numeric page ID. Returns page title, space, canonical URL, and Markdown content.", parameters: Type.Object({ page_id: Type.String({ pattern: "^[0-9]+$", description: "Numeric page ID string (e.g. '847291')" }) }, { additionalProperties: false }), execute: async (_toolCallId, params): Promise> => { const result = await sendToolRequest("confluence_view", params as Record); return { content: [{ type: "text", text: JSON.stringify(result) }], details: result }; } }; const listSpacesTool: AgentTool = { name: "confluence_list_spaces", label: "confluence_list_spaces", description: "List available Confluence spaces. Returns space keys and display names.", parameters: Type.Object({ limit: Type.Optional( Type.Integer({ minimum: 1, maximum: 50, description: "Maximum number of spaces to return (1–50, default 25)" }) ), offset: Type.Optional( Type.Integer({ minimum: 0, maximum: 10000, description: "Pagination offset (default 0, maximum 10,000)" }) ) }, { additionalProperties: false }), execute: async (_toolCallId, params): Promise> => { const result = await sendToolRequest("confluence_list_spaces", params as Record); return { content: [{ type: "text", text: JSON.stringify(result) }], details: result }; } }; return [searchTool, viewTool, listSpacesTool]; }