Files
sproutclaw/packages/coding-agent/examples/extensions/dynamic-tools.ts
Aliou Diallo 01ec6e2e7f docs(coding-agent): fix promptGuidelines examples to name tools explicitly (#3489)
promptGuidelines bullets are appended flat to the Guidelines section
with no tool name prefix. Using 'Use this tool when...' is ambiguous
because the LLM cannot tell which tool 'this' refers to. Updated docs
and examples to use explicit tool names instead.
2026-04-21 13:07:42 +02:00

75 lines
2.2 KiB
TypeScript

/**
* Dynamic Tools Extension
*
* Demonstrates registering tools after session initialization.
*
* - Registers one tool during session_start
* - Registers additional tools at runtime via /add-echo-tool <name>
*/
import type { ExtensionAPI } from "@mariozechner/pi-coding-agent";
import { Type } from "@sinclair/typebox";
const ECHO_PARAMS = Type.Object({
message: Type.String({ description: "Message to echo" }),
});
function normalizeToolName(input: string): string | undefined {
const trimmed = input.trim().toLowerCase();
if (!trimmed) return undefined;
if (!/^[a-z0-9_]+$/.test(trimmed)) return undefined;
return trimmed;
}
export default function dynamicToolsExtension(pi: ExtensionAPI) {
const registeredToolNames = new Set<string>();
const registerEchoTool = (name: string, label: string, prefix: string): boolean => {
if (registeredToolNames.has(name)) {
return false;
}
registeredToolNames.add(name);
pi.registerTool({
name,
label,
description: `Echo a message with prefix: ${prefix}`,
promptSnippet: `Echo back user-provided text with ${prefix.trim()} prefix`,
promptGuidelines: ["Use echo_session when the user asks for exact echo output."],
parameters: ECHO_PARAMS,
async execute(_toolCallId, params) {
return {
content: [{ type: "text", text: `${prefix}${params.message}` }],
details: { tool: name, prefix },
};
},
});
return true;
};
pi.on("session_start", (_event, ctx) => {
registerEchoTool("echo_session", "Echo Session", "[session] ");
ctx.ui.notify("Registered dynamic tool: echo_session", "info");
});
pi.registerCommand("add-echo-tool", {
description: "Register a new echo tool dynamically: /add-echo-tool <tool_name>",
handler: async (args, ctx) => {
const toolName = normalizeToolName(args);
if (!toolName) {
ctx.ui.notify("Usage: /add-echo-tool <tool_name> (lowercase, numbers, underscores)", "warning");
return;
}
const created = registerEchoTool(toolName, `Echo ${toolName}`, `[${toolName}] `);
if (!created) {
ctx.ui.notify(`Tool already registered: ${toolName}`, "warning");
return;
}
ctx.ui.notify(`Registered dynamic tool: ${toolName}`, "info");
},
});
}