Debug tool rendering.

This commit is contained in:
Mario Zechner 2025-10-18 01:11:31 +02:00
parent 2d5054e6c0
commit 4ecbc2fe81
5 changed files with 350 additions and 139 deletions

View file

@ -11,6 +11,17 @@ registerToolRenderer("bash", new BashRenderer());
const defaultRenderer = new DefaultRenderer();
// Global flag to force default JSON rendering for all tools
let showJsonMode = false;
/**
* Enable or disable show JSON mode
* When enabled, all tool renderers will use the default JSON renderer
*/
export function setShowJsonMode(enabled: boolean): void {
showJsonMode = enabled;
}
/**
* Render tool - unified function that handles params, result, and streaming state
*/
@ -20,6 +31,11 @@ export function renderTool(
result: ToolResultMessage | undefined,
isStreaming?: boolean,
): ToolRenderResult {
// If showJsonMode is enabled, always use the default renderer
if (showJsonMode) {
return defaultRenderer.render(params, result, isStreaming);
}
const renderer = getToolRenderer(toolName);
if (renderer) {
return renderer.render(params, result, isStreaming);

View file

@ -1,45 +1,98 @@
import { html } from "@mariozechner/mini-lit";
import type { ToolResultMessage } from "@mariozechner/pi-ai";
import { Code } from "lucide";
import { i18n } from "../../utils/i18n.js";
import { renderHeader } from "../renderer-registry.js";
import type { ToolRenderer, ToolRenderResult } from "../types.js";
export class DefaultRenderer implements ToolRenderer {
render(params: any | undefined, result: ToolResultMessage | undefined, isStreaming?: boolean): ToolRenderResult {
// Show result if available
const state = result ? (result.isError ? "error" : "complete") : isStreaming ? "inprogress" : "complete";
// Format params as JSON
let paramsJson = "";
if (params) {
try {
paramsJson = JSON.stringify(JSON.parse(params), null, 2);
} catch {
try {
paramsJson = JSON.stringify(params, null, 2);
} catch {
paramsJson = String(params);
}
}
}
// With result: show header + params + result
if (result) {
const text = result.output || i18n("(no output)");
let outputJson = result.output || i18n("(no output)");
let outputLanguage = "text";
// Try to parse and pretty-print if it's valid JSON
try {
const parsed = JSON.parse(outputJson);
outputJson = JSON.stringify(parsed, null, 2);
outputLanguage = "json";
} catch {
// Not valid JSON, leave as-is and use text highlighting
}
return {
content: html`<div class="text-sm text-muted-foreground whitespace-pre-wrap font-mono">${text}</div>`,
content: html`
<div class="space-y-3">
${renderHeader(state, Code, "Tool Call")}
${
paramsJson
? html`<div>
<div class="text-xs font-medium mb-1 text-muted-foreground">${i18n("Input")}</div>
<code-block .code=${paramsJson} language="json"></code-block>
</div>`
: ""
}
<div>
<div class="text-xs font-medium mb-1 text-muted-foreground">${i18n("Output")}</div>
<code-block .code=${outputJson} language="${outputLanguage}"></code-block>
</div>
</div>
`,
isCustom: false,
};
}
// Show params
// Just params (streaming or waiting for result)
if (params) {
let text: string;
try {
text = JSON.stringify(JSON.parse(params), null, 2);
} catch {
try {
text = JSON.stringify(params, null, 2);
} catch {
text = String(params);
}
}
if (isStreaming && (!text || text === "{}" || text === "null")) {
if (isStreaming && (!paramsJson || paramsJson === "{}" || paramsJson === "null")) {
return {
content: html`<div class="text-sm text-muted-foreground">${i18n("Preparing tool parameters...")}</div>`,
content: html`
<div>
${renderHeader(state, Code, "Preparing tool parameters...")}
</div>
`,
isCustom: false,
};
}
return { content: html`<console-block .content=${text}></console-block>`, isCustom: false };
return {
content: html`
<div class="space-y-3">
${renderHeader(state, Code, "Tool Call")}
<div>
<div class="text-xs font-medium mb-1 text-muted-foreground">${i18n("Input")}</div>
<code-block .code=${paramsJson} language="json"></code-block>
</div>
</div>
`,
isCustom: false,
};
}
// No params or result yet
return {
content: html`<div class="text-sm text-muted-foreground">${i18n("Preparing tool...")}</div>`,
content: html`
<div>
${renderHeader(state, Code, "Preparing tool...")}
</div>
`,
isCustom: false,
};
}