Pinned pi SDK 0.85.1 bridge, Python supervisor, artifact exporter, scripted backend peer, image checks and boundary checks under agent/**. Review findings F1-F3 are recorded in docs/implementation/PI_AGENT_REVIEW.md.
105 lines
3.4 KiB
TypeScript
105 lines
3.4 KiB
TypeScript
import { Type } from "typebox";
|
||
import type { AgentTool, AgentToolResult } from "@earendil-works/pi-agent-core";
|
||
|
||
export type SendToolRequestFn = (
|
||
toolName: string,
|
||
parameters: Record<string, any>
|
||
) => Promise<any>;
|
||
|
||
/**
|
||
* 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<any>[] {
|
||
const searchTool: AgentTool<any> = {
|
||
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<AgentToolResult<any>> => {
|
||
const result = await sendToolRequest("confluence_search", params as Record<string, any>);
|
||
return {
|
||
content: [{ type: "text", text: JSON.stringify(result) }],
|
||
details: result
|
||
};
|
||
}
|
||
};
|
||
|
||
const viewTool: AgentTool<any> = {
|
||
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<AgentToolResult<any>> => {
|
||
const result = await sendToolRequest("confluence_view", params as Record<string, any>);
|
||
return {
|
||
content: [{ type: "text", text: JSON.stringify(result) }],
|
||
details: result
|
||
};
|
||
}
|
||
};
|
||
|
||
const listSpacesTool: AgentTool<any> = {
|
||
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<AgentToolResult<any>> => {
|
||
const result = await sendToolRequest("confluence_list_spaces", params as Record<string, any>);
|
||
return {
|
||
content: [{ type: "text", text: JSON.stringify(result) }],
|
||
details: result
|
||
};
|
||
}
|
||
};
|
||
|
||
return [searchTool, viewTool, listSpacesTool];
|
||
}
|