From 5537b0b04297ae1201a813c57f20d69d78084b04 Mon Sep 17 00:00:00 2001 From: Shaun Arman Date: Tue, 31 Mar 2026 08:40:36 -0500 Subject: [PATCH] feat: inline file/screenshot attachment in triage chat MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - NewIssue navigates directly to /triage — log upload is never a blocker - ChatWindow: paperclip button opens Tauri file dialog; pending files shown as removable chips above the input; send enabled with files and no text - Triage: uploads selected files via uploadLogFileCmd, reads text content (capped at 8KB), appends file contents to AI message for context while showing only filenames in the chat bubble - Images/binary files are referenced by name with a prompt for the user to describe them --- src/components/ChatWindow.tsx | 41 ++++++++++++++++++++++--- src/pages/NewIssue/index.tsx | 2 +- src/pages/Triage/index.tsx | 58 +++++++++++++++++++++++++++++++++-- 3 files changed, 92 insertions(+), 9 deletions(-) diff --git a/src/components/ChatWindow.tsx b/src/components/ChatWindow.tsx index d4ce2bb6..166b60ad 100644 --- a/src/components/ChatWindow.tsx +++ b/src/components/ChatWindow.tsx @@ -1,5 +1,5 @@ import React, { useState, useRef, useEffect } from "react"; -import { Send, Bot, User } from "lucide-react"; +import { Send, Bot, User, Paperclip, X } from "lucide-react"; import type { TriageMessage } from "@/lib/tauriCommands"; interface ChatWindowProps { @@ -7,9 +7,12 @@ interface ChatWindowProps { onSend: (message: string) => Promise; isLoading?: boolean; placeholder?: string; + pendingFiles?: { name: string }[]; + onAttach?: () => void; + onRemoveFile?: (index: number) => void; } -export function ChatWindow({ messages, onSend, isLoading, placeholder }: ChatWindowProps) { +export function ChatWindow({ messages, onSend, isLoading, placeholder, pendingFiles, onAttach, onRemoveFile }: ChatWindowProps) { const [input, setInput] = useState(""); const bottomRef = useRef(null); @@ -76,20 +79,48 @@ export function ChatWindow({ messages, onSend, isLoading, placeholder }: ChatWin )}
-
+
+ {pendingFiles && pendingFiles.length > 0 && ( +
+ {pendingFiles.map((f, i) => ( + + + {f.name} + {onRemoveFile && ( + + )} + + ))} +
+ )}
+ {onAttach && ( + + )}