@@ -22,7 +22,15 @@ import {
2222import { agentStream } from "@/trigger/agent-stream" ;
2323import type { analyzeRepo } from "@/trigger/analyze-repo" ;
2424import { useState } from "react" ;
25- import ReactMarkdown from "react-markdown" ;
25+ import { Streamdown } from "streamdown" ;
26+
27+ interface RunMetadata {
28+ progress ?: number ;
29+ status ?: string ;
30+ repository ?: string ;
31+ repoSize ?: string ;
32+ error ?: string ;
33+ }
2634
2735export default function ResponsePage ( ) {
2836 const params = useParams ( ) ;
@@ -69,25 +77,7 @@ export default function ResponsePage() {
6977 } ;
7078
7179 // Process streamed text chunks
72- const getFormattedContent = ( ) => {
73- if ( ! parts || parts . length === 0 ) return null ;
74-
75- // parts is now an array of text strings
76- const combinedText = parts . join ( "" ) ;
77-
78- // Return the combined text as markdown
79- if ( combinedText . trim ( ) ) {
80- return (
81- < div className = "prose prose-sm dark:prose-invert max-w-none prose-p:my-4 prose-headings:mt-6 prose-headings:mb-3" >
82- < ReactMarkdown > { combinedText } </ ReactMarkdown >
83- </ div >
84- ) ;
85- }
86-
87- return null ;
88- } ;
89-
90- const formattedContent = getFormattedContent ( ) ;
80+ const combinedText = parts ?. join ( "" ) || "" ;
9181
9282 // Determine status
9383 const getStatus = ( ) => {
@@ -111,7 +101,8 @@ export default function ResponsePage() {
111101 } ;
112102
113103 const status = getStatus ( ) ;
114- const metadata = run ?. metadata as any ;
104+ const isStreaming = status === "running" || status === "loading" ;
105+ const metadata = run ?. metadata as RunMetadata | undefined ;
115106 const progress = metadata ?. progress || 0 ;
116107 const statusText = metadata ?. status || "Initializing..." ;
117108
@@ -120,41 +111,40 @@ export default function ResponsePage() {
120111 < div className = "container mx-auto px-4 py-8 max-w-4xl" >
121112 { /* Header */ }
122113 < div className = "mb-8" >
123- < Button variant = "ghost" onClick = { handleNewQuestion } className = "mb-4 " >
114+ < Button variant = "ghost" onClick = { handleNewQuestion } className = "mb-3 " >
124115 < ArrowLeft className = "w-4 h-4 mr-2" />
125116 Ask Another Question
126117 </ Button >
127118
128119 < h1 className = "text-3xl font-bold mb-2" > Repository Analysis</ h1 >
129- { question && (
130- < p className = "text-muted-foreground" >
131- < span className = "font-medium" > Question:</ span > { question }
132- </ p >
133- ) }
134120 </ div >
135121
136122 { /* Status Card */ }
137- < Card className = "mb-6 " >
123+ < Card className = "mb-4 " >
138124 < CardHeader >
139- < CardTitle className = "flex items-center gap-2" >
140- { status === "loading" && (
141- < Loader2 className = "w-5 h-5 animate-spin" />
142- ) }
143- { status === "running" && (
144- < Loader2 className = "w-5 h-5 animate-spin text-blue-500" />
145- ) }
146- { status === "completed" && (
147- < CheckCircle className = "w-5 h-5 text-green-500" />
148- ) }
149- { status === "error" && (
150- < XCircle className = "w-5 h-5 text-red-500" />
151- ) }
152- Analysis Status
125+ < CardTitle className = "flex justify-between gap-2" >
126+ < div className = "flex items-center gap-2" >
127+ { status === "loading" && (
128+ < Loader2 className = "w-5 h-5 animate-spin" />
129+ ) }
130+ { status === "running" && (
131+ < Loader2 className = "w-5 h-5 animate-spin text-blue-500" />
132+ ) }
133+ { status === "completed" && (
134+ < CheckCircle className = "w-5 h-5 text-green-500" />
135+ ) }
136+ { status === "error" && (
137+ < XCircle className = "w-5 h-5 text-red-500" />
138+ ) }
139+ < span className = "text-xl" > Analysis Status:</ span >
140+ </ div >
141+ < CardDescription className = "text-lg font-medium" >
142+ { statusText }
143+ </ CardDescription >
153144 </ CardTitle >
154- < CardDescription > { statusText } </ CardDescription >
155145 </ CardHeader >
156146 < CardContent >
157- < Progress value = { progress } className = "mb-2 " />
147+ < Progress value = { progress } className = "mb-3 " />
158148 < div className = "flex justify-between text-sm text-muted-foreground" >
159149 < span > { metadata ?. repository || "Repository" } </ span >
160150 < span > { metadata ?. repoSize || "" } </ span >
@@ -180,7 +170,14 @@ export default function ResponsePage() {
180170 ) }
181171 </ CardContent >
182172 </ Card >
183-
173+ { question && (
174+ < div className = "flex items-center gap-2 bg-black/90 p-3 rounded-md border mt-3 w-fit" >
175+ < p className = "text-white" >
176+ < span className = "font-medium text-white/70" > Question:</ span > { " " }
177+ { question }
178+ </ p >
179+ </ div >
180+ ) }
184181 { /* Error Alert */ }
185182 { ( runError || streamError || metadata ?. error ) && (
186183 < Alert variant = "destructive" className = "mb-6" >
@@ -195,24 +192,19 @@ export default function ResponsePage() {
195192 ) }
196193
197194 { /* Response Content */ }
198- { ( formattedContent || ( parts && parts . length > 0 ) ) && (
199- < Card >
200- < CardHeader >
201- < CardTitle > Analysis Result</ CardTitle >
202- </ CardHeader >
203- < CardContent >
204- { formattedContent || (
205- < div className = "text-muted-foreground" >
206- Waiting for response...
207- </ div >
208- ) }
195+ { combinedText . trim ( ) && (
196+ < Card className = "border-none" >
197+ < CardContent className = "p-0 py-4" >
198+ < Streamdown isAnimating = { isStreaming } mode = "streaming" >
199+ { combinedText }
200+ </ Streamdown >
209201 </ CardContent >
210202 </ Card >
211203 ) }
212204
213205 { /* Completion Actions */ }
214206 { status === "completed" && (
215- < div className = "mt-6 text-center" >
207+ < div className = "mt-6 text-center place-self-start " >
216208 < Button onClick = { handleNewQuestion } size = "lg" >
217209 Ask Another Question
218210 </ Button >
0 commit comments