diff --git a/src/server/services/html-exporter.ts b/src/server/services/html-exporter.ts
index 77c1177..c591e6a 100644
--- a/src/server/services/html-exporter.ts
+++ b/src/server/services/html-exporter.ts
@@ -1,7 +1,7 @@
import { marked } from "marked";
import hljs from "highlight.js";
import { markedHighlight } from "marked-highlight";
-import type { ExportRequest, ParsedMessage } from "../../shared/types.js";
+import type { ExportRequest, ParsedMessage, ProgressSubtype } from "../../shared/types.js";
import { CATEGORY_LABELS } from "../../shared/types.js";
import { redactMessage } from "../../shared/sensitive-redactor.js";
import { escapeHtml } from "../../shared/escape-html.js";
@@ -22,7 +22,11 @@ marked.use(
// Categories whose content is structured data (JSON, logs, snapshots) — not markdown.
// Rendered as preformatted text to avoid the cost of markdown parsing on large blobs.
-const PREFORMATTED_CATEGORIES = new Set(["hook_progress", "tool_result", "file_snapshot"]);
+// Note: tool_result is handled explicitly in renderMessage() for diff detection.
+const PREFORMATTED_CATEGORIES = new Set(["hook_progress", "file_snapshot"]);
+
+// Categories that render collapsed by default
+const COLLAPSIBLE_CATEGORIES = new Set(["thinking", "tool_call", "tool_result"]);
// Category dot/border colors matching the client-side design
const CATEGORY_STYLES: Record = {
@@ -37,10 +41,19 @@ const CATEGORY_STYLES: Record = {
+ hook: { text: "#484f58", bg: "rgba(72,79,88,0.1)" },
+ bash: { text: "#d29922", bg: "rgba(210,153,34,0.1)" },
+ mcp: { text: "#8b8cf8", bg: "rgba(139,140,248,0.1)" },
+ agent: { text: "#bc8cff", bg: "rgba(188,140,255,0.1)" },
+};
+
export async function generateExportHtml(
req: ExportRequest
): Promise {
const { session, visibleMessageUuids, redactedMessageUuids, autoRedactEnabled } = req;
+ const toolProgress = session.toolProgress || {};
const visibleSet = new Set(visibleMessageUuids);
const redactedSet = new Set(redactedMessageUuids);
@@ -65,7 +78,8 @@ export async function generateExportHtml(
lastWasRedacted = false;
}
const msgToRender = autoRedactEnabled ? redactMessage(msg) : msg;
- messageHtmlParts.push(renderMessage(msgToRender));
+ const progressEvents = msg.toolUseId ? toolProgress[msg.toolUseId] : undefined;
+ messageHtmlParts.push(renderMessage(msgToRender, progressEvents));
}
const hljsCss = getHighlightCss();
@@ -100,7 +114,7 @@ ${hljsCss}
- ${messageCount} message${messageCount !== 1 ? "s" : ""}
+ ${messageCount} message${messageCount !== 1 ? "s" : ""}
@@ -108,6 +122,9 @@ ${hljsCss}
${messageHtmlParts.join("\n ")}
+