feat(agent): rendered conversation logs with preferred tool syntax
- Updated compaction, branch summarization, and session dump formatting to pass preferred model tool syntax into conversation serialization. - Enhanced shared serializers to render assistant tool calls and tool results through grammar envelopes when syntax is available, with the prior compact format as fallback. - Aligned prompt, preview, and test fixtures to the new transcript tags: `[Think]`, `[Tool Call]`, and `[Tool Result]`.
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
[User]: Fix the settings overlay crash. Wheeling past the last row throws.
|
||||
|
||||
[Assistant tool calls]: read(path="src/select-list.ts:140-180")
|
||||
[Tool Call]: read(path="src/select-list.ts:140-180")
|
||||
|
||||
[Tool result]: 162: const index = Math.floor(line / rowHeight); index is never checked against bounds.
|
||||
[Tool Result]: 162: const index = Math.floor(line / rowHeight); index is never checked against bounds.
|
||||
|
||||
[Assistant]: Found it. The hit test indexes past the filtered list; clamping to the last row fixes the crash.
|
||||
|
||||
|
||||
@@ -38,10 +38,10 @@ const ZOOM_SCALE = 4;
|
||||
const MAX_IMAGE_COLS = 28;
|
||||
const MAX_IMAGE_ROWS = 14;
|
||||
|
||||
/** Sample transcript with `[Tool result]:` bodies wrapped in dim-ink toggles. */
|
||||
/** Sample transcript with `[Tool Result]:` bodies wrapped in dim-ink toggles. */
|
||||
const PREVIEW_TEXT = sampleDoc
|
||||
.trim()
|
||||
.replace(/\[Tool result\]: ([^[]*)/g, (_match, body: string) => `[Tool result]: ${DIM_ON}${body}${DIM_OFF}`);
|
||||
.replace(/\[Tool Result\]: ([^[]*)/g, (_match, body: string) => `[Tool Result]: ${DIM_ON}${body}${DIM_OFF}`);
|
||||
|
||||
type PreviewEntry =
|
||||
| { state: "rendering" }
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
import type { AgentMessage, ThinkingLevel } from "@oh-my-pi/pi-agent-core";
|
||||
import { INTENT_FIELD } from "@oh-my-pi/pi-agent-core";
|
||||
import type { AssistantMessage, Model, ToolExample, TSchema } from "@oh-my-pi/pi-ai";
|
||||
import { renderToolInventory } from "@oh-my-pi/pi-ai/grammar";
|
||||
import { getInbandGrammar, renderToolInventory } from "@oh-my-pi/pi-ai/grammar";
|
||||
import { preferredToolSyntax } from "@oh-my-pi/pi-catalog/identity";
|
||||
import { getVisibleThinkingText } from "../utils/thinking-display";
|
||||
import {
|
||||
type BashExecutionMessage,
|
||||
@@ -34,22 +35,12 @@ export interface FormatSessionDumpTextOptions {
|
||||
tools?: readonly SessionDumpToolInfo[];
|
||||
}
|
||||
|
||||
/** Serialize an object as XML parameter elements, one per key. */
|
||||
function formatArgsAsXml(args: Record<string, unknown>, indent = "\t"): string {
|
||||
const parts: string[] = [];
|
||||
for (const [key, value] of Object.entries(args)) {
|
||||
if (key === INTENT_FIELD) continue;
|
||||
const text = typeof value === "string" ? value : JSON.stringify(value);
|
||||
parts.push(`${indent}<parameter name="${key}">${text}</parameter>`);
|
||||
}
|
||||
return parts.join("\n");
|
||||
}
|
||||
|
||||
/**
|
||||
* Format messages and session metadata as markdown/plain text (same as AgentSession.formatSessionAsText / /dump).
|
||||
*/
|
||||
export function formatSessionDumpText(options: FormatSessionDumpTextOptions): string {
|
||||
const lines: string[] = [];
|
||||
const grammar = getInbandGrammar(preferredToolSyntax(options.model?.id ?? ""));
|
||||
|
||||
const systemPrompt = options.systemPrompt?.filter(prompt => prompt.length > 0) ?? [];
|
||||
if (systemPrompt.length > 0) {
|
||||
@@ -112,11 +103,9 @@ export function formatSessionDumpText(options: FormatSessionDumpTextOptions): st
|
||||
lines.push(thinking);
|
||||
lines.push("</thinking>\n");
|
||||
} else if (c.type === "toolCall") {
|
||||
lines.push(`<invoke name="${c.name}">`);
|
||||
if (c.arguments && typeof c.arguments === "object") {
|
||||
lines.push(formatArgsAsXml(c.arguments as Record<string, unknown>));
|
||||
}
|
||||
lines.push("<" + "/invoke>\n");
|
||||
const args = { ...(c.arguments as Record<string, unknown>) };
|
||||
delete args[INTENT_FIELD];
|
||||
lines.push(grammar.renderToolCall({ ...c, arguments: args }));
|
||||
}
|
||||
}
|
||||
lines.push("");
|
||||
|
||||
@@ -18,7 +18,7 @@ describe("serializeConversation", () => {
|
||||
|
||||
const result = serializeConversation(messages);
|
||||
|
||||
expect(result).toContain("[Tool result]:");
|
||||
expect(result).toContain("[Tool Result]:");
|
||||
expect(result).toContain("[... 3000 more characters truncated]");
|
||||
expect(result).toContain("x".repeat(2000));
|
||||
expect(result).not.toContain("x".repeat(3000));
|
||||
@@ -39,7 +39,7 @@ describe("serializeConversation", () => {
|
||||
|
||||
const result = serializeConversation(messages);
|
||||
|
||||
expect(result).toBe(`[Tool result]: ${shortContent}`);
|
||||
expect(result).toBe(`[Tool Result]: ${shortContent}`);
|
||||
expect(result).not.toContain("truncated");
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user