diff --git a/.changeset/show-tool-images-outside-events.md b/.changeset/show-tool-images-outside-events.md new file mode 100644 index 00000000..35d8cb9b --- /dev/null +++ b/.changeset/show-tool-images-outside-events.md @@ -0,0 +1,5 @@ +--- +"@jmfederico/pi-web": patch +--- + +Keep image content from tool results visible outside collapsed event groups while retaining technical tool metadata inside the group. diff --git a/src/client/src/chatGroups.test.ts b/src/client/src/chatGroups.test.ts index eef8bb60..d29230ab 100644 --- a/src/client/src/chatGroups.test.ts +++ b/src/client/src/chatGroups.test.ts @@ -41,6 +41,34 @@ describe("groupChatMessages", () => { ]); }); + it("keeps image content visible outside collapsed event groups", () => { + const image = { type: "image" as const, mimeType: "image/png", data: "QUJD" }; + const messages: ChatLine[] = [ + { role: "tool", parts: [{ type: "toolResult", toolName: "read", text: "Read image file [image/png]", isError: false }, image] }, + ]; + + expect(groupChatMessages(messages)).toEqual([ + { + kind: "group", + startIndex: 0, + endIndex: 0, + messages: [{ role: "tool", parts: [{ type: "toolResult", toolName: "read", text: "Read image file [image/png]", isError: false }] }], + }, + { kind: "message", index: 0, message: { role: "tool", parts: [image] } }, + ]); + }); + + it("preserves image metadata when splitting technical and readable parts", () => { + const meta = { timestamp: "2026-07-13T22:00:00.000Z" }; + const image = { type: "image" as const, mimeType: "image/webp", data: "QUJD" }; + const message: ChatLine = { role: "tool", parts: [{ type: "toolResult", toolName: "read", text: "ok", isError: false }, image], meta }; + + expect(groupChatMessages([message])).toEqual([ + { kind: "group", startIndex: 0, endIndex: 0, messages: [{ role: "tool", parts: [message.parts[0]], meta }] }, + { kind: "message", index: 0, message: { role: "tool", parts: [image], meta } }, + ]); + }); + it("preserves message metadata when grouping", () => { const message: ChatLine = { role: "assistant", parts: [{ type: "thinking", text: "hidden" }, { type: "text", text: "shown" }], meta: { timestamp: "2026-05-09T12:00:00.000Z", model: { provider: "test", id: "model" } } }; diff --git a/src/client/src/chatGroups.ts b/src/client/src/chatGroups.ts index 917a2f71..af06f1a1 100644 --- a/src/client/src/chatGroups.ts +++ b/src/client/src/chatGroups.ts @@ -49,6 +49,6 @@ export function summarizeChatGroup(messages: ChatLine[]): string { function isReadablePart(message: ChatLine, part: ChatPart): boolean { if (message.source === "compaction" || message.source === "branch_summary") return false; - if (part.type === "skillInvocation" || part.type === "skillRead") return true; + if (part.type === "skillInvocation" || part.type === "skillRead" || part.type === "image") return true; return part.type === "text" && (message.role === "user" || message.role === "assistant" || message.role === "system" || message.role === "bash"); }