docs(coding-agent): add terminating structured output example closes #3525
This commit is contained in:
@@ -34,6 +34,7 @@ cp permission-gate.ts ~/.pi/agent/extensions/
|
||||
| `questionnaire.ts` | Multi-question input with tab bar navigation between questions |
|
||||
| `tool-override.ts` | Override built-in tools (e.g., add logging/access control to `read`) |
|
||||
| `dynamic-tools.ts` | Register tools after startup (`session_start`) and at runtime via command, with prompt snippets and tool-specific prompt guidelines |
|
||||
| `structured-output.ts` | Final structured-output tool that returns `terminate: true` so the agent can end on the tool call |
|
||||
| `built-in-tool-renderer.ts` | Custom compact rendering for built-in tools (read, bash, edit, write) while keeping original behavior |
|
||||
| `minimal-mode.ts` | Override built-in tool rendering for minimal display (only tool calls, no output in collapsed mode) |
|
||||
| `truncated-tool.ts` | Wraps ripgrep with proper output truncation (50KB/2000 lines) |
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Structured Output Tool
|
||||
*
|
||||
* Demonstrates `terminate: true` so the agent can end on a tool call
|
||||
* without paying for an extra follow-up LLM turn.
|
||||
*/
|
||||
|
||||
import { defineTool, type ExtensionAPI } from "@mariozechner/pi-coding-agent";
|
||||
import { Text } from "@mariozechner/pi-tui";
|
||||
import { Type } from "@sinclair/typebox";
|
||||
|
||||
interface StructuredOutputDetails {
|
||||
headline: string;
|
||||
summary: string;
|
||||
actionItems: string[];
|
||||
}
|
||||
|
||||
const structuredOutputTool = defineTool({
|
||||
name: "structured_output",
|
||||
label: "Structured Output",
|
||||
description:
|
||||
"Return a final structured answer. Use this as your last action when the user asks for structured output or a machine-readable summary.",
|
||||
promptSnippet: "Emit a final structured answer as a terminating tool result",
|
||||
promptGuidelines: [
|
||||
"Use structured_output as your final action when the user asks for structured output, JSON-like output, or a machine-readable summary.",
|
||||
"After calling structured_output, do not emit another assistant response in the same turn.",
|
||||
],
|
||||
parameters: Type.Object({
|
||||
headline: Type.String({ description: "Short title for the result" }),
|
||||
summary: Type.String({ description: "One-paragraph summary" }),
|
||||
actionItems: Type.Array(Type.String(), { description: "Concrete next steps or key bullets" }),
|
||||
}),
|
||||
|
||||
async execute(_toolCallId, params) {
|
||||
return {
|
||||
content: [{ type: "text", text: `Saved structured output: ${params.headline}` }],
|
||||
details: {
|
||||
headline: params.headline,
|
||||
summary: params.summary,
|
||||
actionItems: params.actionItems,
|
||||
} satisfies StructuredOutputDetails,
|
||||
terminate: true,
|
||||
};
|
||||
},
|
||||
|
||||
renderResult(result, _options, theme) {
|
||||
const details = result.details as StructuredOutputDetails | undefined;
|
||||
if (!details) {
|
||||
const text = result.content[0];
|
||||
return new Text(text?.type === "text" ? text.text : "", 0, 0);
|
||||
}
|
||||
|
||||
const lines = [
|
||||
theme.fg("toolTitle", theme.bold(details.headline)),
|
||||
theme.fg("text", details.summary),
|
||||
"",
|
||||
...details.actionItems.map((item, index) => theme.fg("muted", `${index + 1}. ${item}`)),
|
||||
];
|
||||
return new Text(lines.join("\n"), 0, 0);
|
||||
},
|
||||
});
|
||||
|
||||
export default function (pi: ExtensionAPI) {
|
||||
pi.registerTool(structuredOutputTool);
|
||||
}
|
||||
Reference in New Issue
Block a user