@@ -9,6 +9,28 @@ type MessagesProps = {
99 messages : Message [ ] ;
1010} ;
1111
12+ type QuestionData = {
13+ question : string ;
14+ suggestions : string [ ] ;
15+ } ;
16+
17+ const parseQuestionData = ( text : string ) : QuestionData | null => {
18+ try {
19+ const parsed = JSON . parse ( text ) ;
20+
21+ if ( parsed ?. question && Array . isArray ( parsed . suggest ) ) {
22+ return {
23+ question : parsed . question ,
24+ suggestions : parsed . suggest ,
25+ } ;
26+ }
27+ } catch {
28+ // Not valid JSON
29+ }
30+
31+ return null ;
32+ } ;
33+
1234export const Messages = ( { messages } : MessagesProps ) => {
1335 const conversation = useMemo (
1436 ( ) =>
@@ -20,31 +42,68 @@ export const Messages = ({ messages }: MessagesProps) => {
2042
2143 return (
2244 < div className = "space-y-6" >
23- { conversation . map ( ( message ) => (
24- < div
25- key = { message . id }
26- className = { cn (
27- 'flex flex-col gap-3 rounded-lg p-4' ,
28- message . role === 'user' ? 'bg-primary/10' : 'bg-secondary/10' ,
29- ) }
30- >
31- < div className = "flex flex-row items-center justify-between gap-2 text-xs font-medium text-muted-foreground" >
32- < div className = "flex items-center gap-2" >
33- < div > { message . name } </ div >
34- < div > ·</ div >
35- < div > { message . timestamp } </ div >
45+ { conversation . map ( ( message ) => {
46+ const isQuestion = message . type === 'ask' && message . ask === 'followup' ;
47+ const isCommand = message . type === 'ask' && message . ask === 'command' ;
48+ const questionData =
49+ isQuestion && message . text ? parseQuestionData ( message . text ) : null ;
50+
51+ return (
52+ < div
53+ key = { message . id }
54+ className = { cn (
55+ 'flex flex-col gap-3 rounded-lg p-4' ,
56+ message . role === 'user' ? 'bg-primary/10' : 'bg-secondary/10' ,
57+ ) }
58+ >
59+ < div className = "flex flex-row items-center justify-between gap-2 text-xs font-medium text-muted-foreground" >
60+ < div className = "flex items-center gap-2" >
61+ < div > { message . name } </ div >
62+ < div > ·</ div >
63+ < div > { message . timestamp } </ div >
64+ </ div >
65+ { message . mode && (
66+ < div className = "px-2 py-1 bg-muted rounded text-xs font-medium" >
67+ { message . mode }
68+ </ div >
69+ ) }
3670 </ div >
37- { message . mode && (
38- < div className = "px-2 py-1 bg-muted rounded text-xs font-medium" >
39- { message . mode }
71+
72+ { isQuestion && questionData ? (
73+ < div className = "space-y-4" >
74+ { questionData . question && (
75+ < div className = "text-sm leading-relaxed" >
76+ { questionData . question }
77+ </ div >
78+ ) }
79+ { questionData . suggestions &&
80+ questionData . suggestions . length > 0 && (
81+ < div className = "space-y-2" >
82+ { questionData . suggestions . map ( ( suggestion , index ) => (
83+ < div
84+ key = { index }
85+ className = "px-4 py-3 bg-background border border-border rounded-md text-sm hover:bg-muted/50 cursor-pointer transition-colors"
86+ >
87+ { suggestion }
88+ </ div >
89+ ) ) }
90+ </ div >
91+ ) }
92+ </ div >
93+ ) : isCommand ? (
94+ < div className = "space-y-3" >
95+ < div className = "bg-black/90 text-green-400 p-3 rounded-md font-mono text-sm" >
96+ { message . text }
97+ </ div >
98+ </ div >
99+ ) : (
100+ < div className = "text-sm leading-relaxed markdown-prose" >
101+ < ReactMarkdown > { message . text } </ ReactMarkdown >
40102 </ div >
41103 ) }
42104 </ div >
43- < div className = "text-sm leading-relaxed markdown-prose" >
44- < ReactMarkdown > { message . text } </ ReactMarkdown >
45- </ div >
46- </ div >
47- ) ) }
105+ ) ;
106+ } ) }
48107 </ div >
49108 ) ;
50109} ;
@@ -59,10 +118,22 @@ const decorate = ({ message, index }: { message: Message; index: number }) => {
59118 return { ...message , role, name, timestamp } ;
60119} ;
61120
62- const isVisible = ( message : Message ) =>
63- ( message . ask === 'text' ||
64- message . say === 'text' ||
65- message . say === 'completion_result' ||
66- message . say === 'user_feedback' ) &&
67- typeof message . text === 'string' &&
68- message . text . length > 0 ;
121+ const isVisible = ( message : Message ) => {
122+ // Always show followup and command messages regardless of text content
123+ if (
124+ message . type === 'ask' &&
125+ ( message . ask === 'followup' || message . ask === 'command' )
126+ ) {
127+ return true ;
128+ }
129+
130+ // For other message types, require non-empty text
131+ return (
132+ ( message . ask === 'text' ||
133+ message . say === 'text' ||
134+ message . say === 'completion_result' ||
135+ message . say === 'user_feedback' ) &&
136+ typeof message . text === 'string' &&
137+ message . text . length > 0
138+ ) ;
139+ } ;
0 commit comments