@@ -4,7 +4,17 @@ import { cn } from "@/lib/utils";
44import type { ChatMessage , ContextItem } from "@/types/chat" ;
55import { AGENTS } from "@/types/chat" ;
66import { useState } from "react" ;
7- import { ChevronDown , ChevronUp , Code , User , Bot } from "lucide-react" ;
7+ import {
8+ ChevronDown ,
9+ ChevronUp ,
10+ Code ,
11+ User ,
12+ FileCode ,
13+ Box ,
14+ GitCommit ,
15+ File ,
16+ } from "lucide-react" ;
17+ import { MarkdownRenderer } from "./MarkdownRenderer" ;
818
919interface ChatMessageProps {
1020 message : ChatMessage ;
@@ -17,6 +27,12 @@ export function ChatMessageItem({ message }: ChatMessageProps) {
1727 ? AGENTS . find ( ( a ) => a . type === message . agentType )
1828 : null ;
1929
30+ // Filter out empty context items
31+ const validContext = message . context ?. filter (
32+ ( item ) =>
33+ item . name && item . name !== "N/A" && item . content && item . content . trim ( )
34+ ) ;
35+
2036 return (
2137 < div
2238 className = { cn (
@@ -37,7 +53,7 @@ export function ChatMessageItem({ message }: ChatMessageProps) {
3753 ) : agent ? (
3854 < agent . Icon className = "w-4 h-4" />
3955 ) : (
40- < Bot className = "w-4 h-4" />
56+ < Code className = "w-4 h-4" />
4157 ) }
4258 </ div >
4359
@@ -56,34 +72,42 @@ export function ChatMessageItem({ message }: ChatMessageProps) {
5672 </ span >
5773 </ div >
5874
59- < div className = "prose prose-sm dark:prose-invert max-w-none" >
60- < p className = "whitespace-pre-wrap wrap-break-word " >
75+ { isUser ? (
76+ < p className = "whitespace-pre-wrap overflow- wrap-anywhere " >
6177 { message . content }
78+ </ p >
79+ ) : (
80+ < div className = "relative" >
81+ < MarkdownRenderer content = { message . content } />
6282 { message . isStreaming && (
6383 < span className = "inline-block w-2 h-4 ml-1 bg-primary animate-pulse" />
6484 ) }
65- </ p >
66- </ div >
85+ </ div >
86+ ) }
6787
68- { message . context && message . context . length > 0 && (
69- < div className = "mt-3 " >
88+ { validContext && validContext . length > 0 && (
89+ < div className = "mt-4 pt-3 border-t border-border/50 " >
7090 < button
7191 onClick = { ( ) => setShowContext ( ! showContext ) }
72- className = "flex items-center gap-1 text-xs text-muted-foreground hover:text-foreground transition-colors"
92+ className = "flex items-center gap-2 text-xs text-muted-foreground hover:text-foreground transition-colors"
7393 >
74- < Code className = "w-3 h-3" />
75- { message . context . length } context item
76- { message . context . length > 1 ? "s" : "" }
77- { showContext ? (
78- < ChevronUp className = "w-3 h-3" />
79- ) : (
80- < ChevronDown className = "w-3 h-3" />
81- ) }
94+ < div className = "flex items-center gap-1.5 px-2 py-1 rounded-md bg-muted/50 hover:bg-muted transition-colors" >
95+ < FileCode className = "w-3.5 h-3.5" />
96+ < span className = "font-medium" >
97+ { validContext . length } source
98+ { validContext . length > 1 ? "s" : "" }
99+ </ span >
100+ { showContext ? (
101+ < ChevronUp className = "w-3.5 h-3.5" />
102+ ) : (
103+ < ChevronDown className = "w-3.5 h-3.5" />
104+ ) }
105+ </ div >
82106 </ button >
83107
84108 { showContext && (
85- < div className = "mt-2 space-y-2" >
86- { message . context . map ( ( item , index ) => (
109+ < div className = "mt-3 space-y-2" >
110+ { validContext . map ( ( item , index ) => (
87111 < ContextItemCard key = { index } item = { item } />
88112 ) ) }
89113 </ div >
@@ -99,36 +123,59 @@ interface ContextItemCardProps {
99123 item : ContextItem ;
100124}
101125
126+ function getContextIcon ( type : string ) {
127+ switch ( type ?. toLowerCase ( ) ) {
128+ case "function" :
129+ return < Code className = "w-3 h-3" /> ;
130+ case "class" :
131+ return < Box className = "w-3 h-3" /> ;
132+ case "commit" :
133+ return < GitCommit className = "w-3 h-3" /> ;
134+ case "file" :
135+ return < File className = "w-3 h-3" /> ;
136+ default :
137+ return < FileCode className = "w-3 h-3" /> ;
138+ }
139+ }
140+
102141function ContextItemCard ( { item } : ContextItemCardProps ) {
103142 const [ expanded , setExpanded ] = useState ( false ) ;
104- const maxPreviewLength = 200 ;
105- const needsExpansion = item . content . length > maxPreviewLength ;
143+ const maxPreviewLength = 300 ;
144+ const content = item . content || "" ;
145+ const needsExpansion = content . length > maxPreviewLength ;
106146
107147 return (
108- < div className = "border rounded-md overflow-hidden bg-muted/30" >
109- < div className = "flex items-center justify-between px-3 py-2 bg-muted/50 border-b" >
110- < div className = "flex items-center gap-2" >
111- < span className = "text-xs font-medium px-2 py-0.5 rounded bg-primary/10 text-primary" >
112- { item . type }
148+ < div className = "group rounded-lg border border-border/60 bg-muted/30 overflow-hidden hover:border-border transition-colors" >
149+ < div className = "flex items-center justify-between px-3 py-2 bg-muted/50" >
150+ < div className = "flex items-center gap-2 min-w-0" >
151+ < div className = "flex items-center gap-1.5 shrink-0 text-muted-foreground" >
152+ { getContextIcon ( item . type ) }
153+ < span className = "text-xs font-medium uppercase tracking-wide" >
154+ { item . type || "Code" }
155+ </ span >
156+ </ div >
157+ < span className = "text-xs text-muted-foreground/60" > •</ span >
158+ < span className = "text-xs font-mono text-foreground/80 truncate" >
159+ { item . name }
113160 </ span >
114- < span className = "text-sm font-mono" > { item . name } </ span >
115161 </ div >
116- { item . score !== undefined && (
117- < span className = "text-xs text-muted-foreground" >
118- Score: { ( item . score * 100 ) . toFixed ( 1 ) } %
162+ { item . score !== undefined && item . score > 0 && (
163+ < span className = "text-[10px] font-medium text-muted-foreground bg-background/50 px-1.5 py-0.5 rounded shrink-0 ml-2 " >
164+ { ( item . score * 100 ) . toFixed ( 0 ) } %
119165 </ span >
120166 ) }
121167 </ div >
122- < div className = "p-3" >
123- < pre className = "text-xs overflow-x-auto whitespace-pre-wrap font-mono" >
168+
169+ < div className = "px-3 py-2 bg-background/50" >
170+ < pre className = "text-xs overflow-x-auto whitespace-pre-wrap font-mono text-foreground/70 leading-relaxed" >
124171 { expanded || ! needsExpansion
125- ? item . content
126- : `${ item . content . slice ( 0 , maxPreviewLength ) } ...` }
172+ ? content
173+ : `${ content . slice ( 0 , maxPreviewLength ) } ...` }
127174 </ pre >
128175 { needsExpansion && (
129176 < button
130177 onClick = { ( ) => setExpanded ( ! expanded ) }
131- className = "text-xs text-primary hover:underline mt-2"
178+ className = "text-xs text-primary/80 hover:text-primary hover: underline mt-2 font-medium "
132179 >
133180 { expanded ? "Show less" : "Show more" }
134181 </ button >
0 commit comments