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

@ -1804,6 +1804,23 @@ export const MODELS = {
} satisfies Model<"anthropic-messages">,
},
openrouter: {
"deepcogito/cogito-v2-preview-llama-405b": {
id: "deepcogito/cogito-v2-preview-llama-405b",
name: "Deep Cogito: Cogito V2 Preview Llama 405B",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: true,
input: ["text"],
cost: {
input: 3.5,
output: 3.5,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 32768,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"qwen/qwen3-vl-8b-thinking": {
id: "qwen/qwen3-vl-8b-thinking",
name: "Qwen: Qwen3 VL 8B Thinking",
@ -1838,6 +1855,23 @@ export const MODELS = {
contextWindow: 262144,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"inclusionai/ring-1t": {
id: "inclusionai/ring-1t",
name: "inclusionAI: Ring 1T",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: true,
input: ["text"],
cost: {
input: 0.5700000000000001,
output: 2.2800000000000002,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 131072,
maxTokens: 131072,
} satisfies Model<"openai-completions">,
"inclusionai/ling-1t": {
id: "inclusionai/ling-1t",
name: "inclusionAI: Ling-1T",
@ -1847,8 +1881,8 @@ export const MODELS = {
reasoning: false,
input: ["text"],
cost: {
input: 0.5700000000000001,
output: 2.2800000000000002,
input: 0.39999999999999997,
output: 2,
cacheRead: 0,
cacheWrite: 0,
},
@ -1949,8 +1983,8 @@ export const MODELS = {
reasoning: true,
input: ["text", "image"],
cost: {
input: 0.44999999999999996,
output: 3.5,
input: 0.3,
output: 1.2,
cacheRead: 0,
cacheWrite: 0,
},
@ -2031,7 +2065,7 @@ export const MODELS = {
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
reasoning: true,
input: ["text"],
cost: {
input: 0,
@ -2246,23 +2280,6 @@ export const MODELS = {
contextWindow: 32767,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"deepcogito/cogito-v2-preview-llama-405B": {
id: "deepcogito/cogito-v2-preview-llama-405B",
name: "Deep Cogito: Cogito V2 Preview Llama 405B",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: true,
input: ["text"],
cost: {
input: 3.5,
output: 3.5,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 32768,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"stepfun-ai/step3": {
id: "stepfun-ai/step3",
name: "StepFun: Step3",
@ -2365,6 +2382,40 @@ export const MODELS = {
contextWindow: 131072,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"baidu/ernie-4.5-21b-a3b": {
id: "baidu/ernie-4.5-21b-a3b",
name: "Baidu: ERNIE 4.5 21B A3B",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.07,
output: 0.28,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 120000,
maxTokens: 8000,
} satisfies Model<"openai-completions">,
"baidu/ernie-4.5-vl-28b-a3b": {
id: "baidu/ernie-4.5-vl-28b-a3b",
name: "Baidu: ERNIE 4.5 VL 28B A3B",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: true,
input: ["text", "image"],
cost: {
input: 0.14,
output: 0.56,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 30000,
maxTokens: 8000,
} satisfies Model<"openai-completions">,
"z-ai/glm-4.5v": {
id: "z-ai/glm-4.5v",
name: "Z.AI: GLM 4.5V",
@ -2575,7 +2626,7 @@ export const MODELS = {
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
reasoning: true,
input: ["text"],
cost: {
input: 0.22,
@ -2592,7 +2643,7 @@ export const MODELS = {
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
reasoning: true,
input: ["text"],
cost: {
input: 0.08,
@ -2654,6 +2705,23 @@ export const MODELS = {
contextWindow: 128000,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"tngtech/deepseek-r1t2-chimera": {
id: "tngtech/deepseek-r1t2-chimera",
name: "TNG: DeepSeek R1T2 Chimera",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: true,
input: ["text"],
cost: {
input: 0.3,
output: 1.2,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 163840,
maxTokens: 163840,
} satisfies Model<"openai-completions">,
"inception/mercury": {
id: "inception/mercury",
name: "Inception: Mercury",
@ -2736,7 +2804,7 @@ export const MODELS = {
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 40000,
contextWindow: 32768,
maxTokens: 40000,
} satisfies Model<"openai-completions">,
"mistralai/magistral-medium-2506:thinking": {
@ -2841,6 +2909,23 @@ export const MODELS = {
contextWindow: 128000,
maxTokens: 4028,
} satisfies Model<"openai-completions">,
"nousresearch/deephermes-3-mistral-24b-preview": {
id: "nousresearch/deephermes-3-mistral-24b-preview",
name: "Nous: DeepHermes 3 Mistral 24B Preview",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: true,
input: ["text"],
cost: {
input: 0.15,
output: 0.59,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 32768,
maxTokens: 32768,
} satisfies Model<"openai-completions">,
"mistralai/mistral-medium-3": {
id: "mistralai/mistral-medium-3",
name: "Mistral: Mistral Medium 3",
@ -3085,7 +3170,7 @@ export const MODELS = {
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
reasoning: true,
input: ["text"],
cost: {
input: 0.24,
@ -3130,23 +3215,6 @@ export const MODELS = {
contextWindow: 128000,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"microsoft/phi-4-multimodal-instruct": {
id: "microsoft/phi-4-multimodal-instruct",
name: "Microsoft: Phi 4 Multimodal Instruct",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text", "image"],
cost: {
input: 0.049999999999999996,
output: 0.09999999999999999,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 131072,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"qwen/qwq-32b": {
id: "qwen/qwq-32b",
name: "Qwen: QwQ 32B",
@ -3164,6 +3232,23 @@ export const MODELS = {
contextWindow: 32768,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"nousresearch/deephermes-3-llama-3-8b-preview": {
id: "nousresearch/deephermes-3-llama-3-8b-preview",
name: "Nous: DeepHermes 3 Llama 3 8B Preview",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.03,
output: 0.11,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 131072,
maxTokens: 131072,
} satisfies Model<"openai-completions">,
"mistralai/mistral-saba": {
id: "mistralai/mistral-saba",
name: "Mistral: Saba",
@ -3266,6 +3351,23 @@ export const MODELS = {
contextWindow: 32768,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"deepseek/deepseek-r1-distill-llama-70b": {
id: "deepseek/deepseek-r1-distill-llama-70b",
name: "DeepSeek: R1 Distill Llama 70B",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: true,
input: ["text"],
cost: {
input: 0.03,
output: 0.13,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 131072,
maxTokens: 131072,
} satisfies Model<"openai-completions">,
"deepseek/deepseek-r1": {
id: "deepseek/deepseek-r1",
name: "DeepSeek: R1",
@ -3416,7 +3518,7 @@ export const MODELS = {
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 131072,
contextWindow: 32768,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"mistralai/mistral-large-2407": {
@ -3572,6 +3674,23 @@ export const MODELS = {
contextWindow: 32768,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"cohere/command-r-08-2024": {
id: "cohere/command-r-08-2024",
name: "Cohere: Command R (08-2024)",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.15,
output: 0.6,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 128000,
maxTokens: 4000,
} satisfies Model<"openai-completions">,
"cohere/command-r-plus-08-2024": {
id: "cohere/command-r-plus-08-2024",
name: "Cohere: Command R+ (08-2024)",
@ -3589,22 +3708,22 @@ export const MODELS = {
contextWindow: 128000,
maxTokens: 4000,
} satisfies Model<"openai-completions">,
"cohere/command-r-08-2024": {
id: "cohere/command-r-08-2024",
name: "Cohere: Command R (08-2024)",
"sao10k/l3.1-euryale-70b": {
id: "sao10k/l3.1-euryale-70b",
name: "Sao10K: Llama 3.1 Euryale 70B v2.2",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.15,
output: 0.6,
input: 0.65,
output: 0.75,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 128000,
maxTokens: 4000,
contextWindow: 32768,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"microsoft/phi-3.5-mini-128k-instruct": {
id: "microsoft/phi-3.5-mini-128k-instruct",
@ -3640,23 +3759,6 @@ export const MODELS = {
contextWindow: 65536,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"meta-llama/llama-3.1-8b-instruct": {
id: "meta-llama/llama-3.1-8b-instruct",
name: "Meta: Llama 3.1 8B Instruct",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.02,
output: 0.03,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 131072,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"meta-llama/llama-3.1-405b-instruct": {
id: "meta-llama/llama-3.1-405b-instruct",
name: "Meta: Llama 3.1 405B Instruct",
@ -3691,6 +3793,23 @@ export const MODELS = {
contextWindow: 131072,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"meta-llama/llama-3.1-8b-instruct": {
id: "meta-llama/llama-3.1-8b-instruct",
name: "Meta: Llama 3.1 8B Instruct",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.02,
output: 0.03,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 131072,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"mistralai/mistral-nemo": {
id: "mistralai/mistral-nemo",
name: "Mistral: Mistral Nemo",
@ -3708,6 +3827,40 @@ export const MODELS = {
contextWindow: 131072,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"sao10k/l3-euryale-70b": {
id: "sao10k/l3-euryale-70b",
name: "Sao10k: Llama 3 Euryale 70B v2.1",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 1.48,
output: 1.48,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 8192,
maxTokens: 8192,
} satisfies Model<"openai-completions">,
"mistralai/mistral-7b-instruct-v0.3": {
id: "mistralai/mistral-7b-instruct-v0.3",
name: "Mistral: Mistral 7B Instruct v0.3",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.028,
output: 0.054,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 32768,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"mistralai/mistral-7b-instruct:free": {
id: "mistralai/mistral-7b-instruct:free",
name: "Mistral: Mistral 7B Instruct (free)",
@ -3742,23 +3895,6 @@ export const MODELS = {
contextWindow: 32768,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"mistralai/mistral-7b-instruct-v0.3": {
id: "mistralai/mistral-7b-instruct-v0.3",
name: "Mistral: Mistral 7B Instruct v0.3",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.028,
output: 0.054,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 32768,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"microsoft/phi-3-mini-128k-instruct": {
id: "microsoft/phi-3-mini-128k-instruct",
name: "Microsoft: Phi-3 Mini 128K Instruct",
@ -3793,23 +3929,6 @@ export const MODELS = {
contextWindow: 128000,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"meta-llama/llama-3-8b-instruct": {
id: "meta-llama/llama-3-8b-instruct",
name: "Meta: Llama 3 8B Instruct",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.03,
output: 0.06,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 8192,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"meta-llama/llama-3-70b-instruct": {
id: "meta-llama/llama-3-70b-instruct",
name: "Meta: Llama 3 70B Instruct",
@ -3827,6 +3946,23 @@ export const MODELS = {
contextWindow: 8192,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"meta-llama/llama-3-8b-instruct": {
id: "meta-llama/llama-3-8b-instruct",
name: "Meta: Llama 3 8B Instruct",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.03,
output: 0.06,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 8192,
maxTokens: 16384,
} satisfies Model<"openai-completions">,
"mistralai/mixtral-8x22b-instruct": {
id: "mistralai/mixtral-8x22b-instruct",
name: "Mistral: Mixtral 8x22B Instruct",
@ -3861,23 +3997,6 @@ export const MODELS = {
contextWindow: 128000,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"mistralai/mistral-small": {
id: "mistralai/mistral-small",
name: "Mistral Small",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.19999999999999998,
output: 0.6,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 32768,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"mistralai/mistral-tiny": {
id: "mistralai/mistral-tiny",
name: "Mistral Tiny",
@ -3895,6 +4014,23 @@ export const MODELS = {
contextWindow: 32768,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"mistralai/mistral-small": {
id: "mistralai/mistral-small",
name: "Mistral Small",
api: "openai-completions",
provider: "openrouter",
baseUrl: "https://openrouter.ai/api/v1",
reasoning: false,
input: ["text"],
cost: {
input: 0.19999999999999998,
output: 0.6,
cacheRead: 0,
cacheWrite: 0,
},
contextWindow: 32768,
maxTokens: 4096,
} satisfies Model<"openai-completions">,
"mistralai/mixtral-8x7b-instruct": {
id: "mistralai/mixtral-8x7b-instruct",
name: "Mistral: Mixtral 8x7B Instruct",

View file

@ -87,7 +87,7 @@ export { SvgArtifact } from "./tools/artifacts/SvgArtifact.js";
export { TextArtifact } from "./tools/artifacts/TextArtifact.js";
export { createExtractDocumentTool, extractDocumentTool } from "./tools/extract-document.js";
// Tools
export { getToolRenderer, registerToolRenderer, renderTool } from "./tools/index.js";
export { getToolRenderer, registerToolRenderer, renderTool, setShowJsonMode } from "./tools/index.js";
export { createJavaScriptReplTool, javascriptReplTool } from "./tools/javascript-repl.js";
export { renderCollapsibleHeader, renderHeader } from "./tools/renderer-registry.js";
export { BashRenderer } from "./tools/renderers/BashRenderer.js";

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,
};
}

View file

@ -63,6 +63,8 @@ declare module "@mariozechner/mini-lit" {
"No session set": string;
"Preparing tool parameters...": string;
"(no output)": string;
Input: string;
Output: string;
"Writing expression...": string;
"Waiting for expression...": string;
Calculating: string;
@ -237,6 +239,8 @@ export const translations = {
"No session set": "No session set",
"Preparing tool parameters...": "Preparing tool parameters...",
"(no output)": "(no output)",
Input: "Input",
Output: "Output",
"Waiting for expression...": "Waiting for expression...",
"Writing expression...": "Writing expression...",
Calculating: "Calculating",
@ -414,6 +418,8 @@ export const translations = {
"No session set": "Keine Sitzung gesetzt",
"Preparing tool parameters...": "Bereite Tool-Parameter vor...",
"(no output)": "(keine Ausgabe)",
Input: "Eingabe",
Output: "Ausgabe",
"Waiting for expression...": "Warte auf Ausdruck",
"Writing expression...": "Schreibe Ausdruck...",
Calculating: "Berechne",