diff --git a/web/ui/app.js b/web/ui/app.js index bcff449d..398cfd6c 100644 --- a/web/ui/app.js +++ b/web/ui/app.js @@ -196,10 +196,18 @@ function renderMarkdown(value) { } async function api(path, options = {}) { - const response = await fetch(path, { - ...options, - headers: { ...headers(Boolean(options.body)), ...options.headers }, - }); + const controller = new AbortController(); + const timeout = window.setTimeout(() => controller.abort(), 30_000); + let response; + try { + response = await fetch(path, { + ...options, + headers: { ...headers(Boolean(options.body)), ...options.headers }, + signal: options.signal || controller.signal, + }); + } finally { + window.clearTimeout(timeout); + } const body = await response.json().catch(() => ({})); if (!response.ok) throw new Error(body.error || `Request failed (${response.status})`); return body; @@ -382,8 +390,17 @@ function messageMarkup(entry) { } if (message.role === "toolResult") { const toolName = message.toolName || "tool"; + const kind = /(?:read|cat|file)/iu.test(toolName) + ? "file" + : /diff/iu.test(toolName) + ? "diff" + : /test/iu.test(toolName) + ? "test" + : /(?:bash|terminal|exec)/iu.test(toolName) + ? "terminal" + : "generic"; const summary = compactSummary(message.content || "completed"); - return `
+ return `
${escapeHtml(toolName)} ยท ${escapeHtml(summary)}
${escapeHtml(message.content || "completed")}