@@ -468,6 +468,7 @@ pi.on("session_before_compact", async (event, ctx) => {
|
||||
summary: "...",
|
||||
firstKeptEntryId: preparation.firstKeptEntryId,
|
||||
tokensBefore: preparation.tokensBefore,
|
||||
// usage: summaryResponse.usage, // Optional; included in session totals
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -489,7 +490,13 @@ pi.on("session_before_tree", async (event, ctx) => {
|
||||
const { preparation, signal } = event;
|
||||
return { cancel: true };
|
||||
// OR provide custom summary:
|
||||
return { summary: { summary: "...", details: {} } };
|
||||
return {
|
||||
summary: {
|
||||
summary: "...",
|
||||
// usage: summaryResponse.usage, // Optional; included in session totals
|
||||
details: {},
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
pi.on("session_tree", async (event, ctx) => {
|
||||
@@ -813,7 +820,7 @@ In parallel tool mode, `tool_result` and `tool_execution_end` may interleave in
|
||||
`tool_result` handlers chain like middleware:
|
||||
- Handlers run in extension load order
|
||||
- Each handler sees the latest result after previous handler changes
|
||||
- Handlers can return partial patches (`content`, `details`, or `isError`); omitted fields keep their current values
|
||||
- Handlers can return partial patches (`content`, `details`, `isError`, or `usage`); omitted fields keep their current values
|
||||
|
||||
Use `ctx.signal` for nested async work inside the handler. This lets Esc cancel model calls, `fetch()`, and other abort-aware operations started by the extension.
|
||||
|
||||
@@ -822,7 +829,7 @@ import { isBashToolResult } from "@earendil-works/pi-coding-agent";
|
||||
|
||||
pi.on("tool_result", async (event, ctx) => {
|
||||
// event.toolName, event.toolCallId, event.input
|
||||
// event.content, event.details, event.isError
|
||||
// event.content, event.details, event.isError, event.usage
|
||||
|
||||
if (isBashToolResult(event)) {
|
||||
// event.details is typed as BashToolDetails
|
||||
@@ -835,7 +842,7 @@ pi.on("tool_result", async (event, ctx) => {
|
||||
});
|
||||
|
||||
// Modify result:
|
||||
return { content: [...], details: {...}, isError: false };
|
||||
return { content: [...], details: {...}, isError: false, usage: nestedModelUsage };
|
||||
});
|
||||
```
|
||||
|
||||
@@ -1932,6 +1939,7 @@ pi.registerTool({
|
||||
return {
|
||||
content: [{ type: "text", text: "Done" }], // Sent to LLM
|
||||
details: { data: result }, // For rendering & state
|
||||
// usage: nestedModelResponse.usage, // Optional nested LLM usage
|
||||
// Optional: stop after this tool batch when every finalized tool result
|
||||
// in the batch also returns terminate: true.
|
||||
terminate: true,
|
||||
@@ -1944,6 +1952,8 @@ pi.registerTool({
|
||||
});
|
||||
```
|
||||
|
||||
**Usage accounting:** If a tool makes nested LLM calls, return their combined `Usage` as `usage`. Pi persists it on the tool result and includes it in footer, `/session`, and RPC session totals. `tool_result` handlers can inspect or replace this value.
|
||||
|
||||
**Signaling errors:** To mark a tool execution as failed (sets `isError: true` on the result and reports it to the LLM), throw an error from `execute`. Returning a value never sets the error flag regardless of what properties you include in the return object.
|
||||
|
||||
**Early termination:** Return `terminate: true` from `execute()` to hint that the automatic follow-up LLM call should be skipped after the current tool batch. This only takes effect when every finalized tool result in that batch is terminating. See [examples/extensions/structured-output.ts](../examples/extensions/structured-output.ts) for a minimal example where the agent ends on a final structured-output tool call.
|
||||
|
||||
Reference in New Issue
Block a user