@@ -143,7 +143,10 @@ const FloatingAssistant: React.FC<FloatingAssistantProps> = () => {
143143
144144 abortRef . current = new AbortController ( ) ;
145145
146- console . log ( "sendMessage" , pageId )
146+ let accumulated = '' ;
147+ let finalContent = 'Sorry, something went wrong. Please try again.' ;
148+ let aborted = false ;
149+
147150 try {
148151 const response = await fetch (
149152 `${ CLOUDFLARE_URL } /agent/embed-assistant` ,
@@ -152,9 +155,9 @@ const FloatingAssistant: React.FC<FloatingAssistantProps> = () => {
152155 headers : { 'Content-Type' : 'application/json' } ,
153156 signal : abortRef . current . signal ,
154157 body : JSON . stringify ( {
155- playgroundType :'ask-docs' ,
158+ playgroundType : 'ask-docs' ,
156159 messages : updatedMessages ,
157- pageId :pageId
160+ pageId : pageId ,
158161 } ) ,
159162 } ,
160163 ) ;
@@ -163,53 +166,37 @@ const FloatingAssistant: React.FC<FloatingAssistantProps> = () => {
163166 throw new Error ( `API error: ${ response . status } ` ) ;
164167 }
165168
166- let accumulated = '' ;
167- let aborted = false ;
168-
169- try {
170- for await ( const event of parseSseStream ( response ) ) {
171- if ( event . type === 'text' ) {
172- accumulated += event . content ;
173- setStreamingText ( accumulated ) ;
174- } else if ( event . type === 'tool-start' ) {
175- setToolStatus ( `Using ${ event . toolName } …` ) ;
176- } else if ( event . type === 'tool-result' ) {
177- setToolStatus ( '' ) ;
178- } else if ( event . type === 'done' ) {
179- break ;
180- } else if ( event . type === 'error' ) {
181- throw new Error ( event . content ) ;
182- }
183- }
184- } catch ( err : unknown ) {
185- if ( err instanceof Error && err . name === 'AbortError' ) {
186- aborted = true ;
187- } else {
188- accumulated = '' ;
169+ for await ( const event of parseSseStream ( response ) ) {
170+ if ( event . type === 'text' ) {
171+ accumulated += event . content ;
172+ setStreamingText ( accumulated ) ;
173+ } else if ( event . type === 'tool-start' ) {
174+ setToolStatus ( `Using ${ event . toolName } …` ) ;
175+ } else if ( event . type === 'tool-result' ) {
176+ setToolStatus ( '' ) ;
177+ } else if ( event . type === 'done' ) {
178+ break ;
179+ } else if ( event . type === 'error' ) {
180+ throw new Error ( event . content ) ;
189181 }
190182 }
191183
192- // Batch all final state updates together in one synchronous block
193- // so React never renders a frame with both messages + isLoading true
184+ finalContent = accumulated || 'No response received.' ;
185+ } catch ( err : unknown ) {
186+ if ( err instanceof Error && err . name === 'AbortError' ) {
187+ aborted = true ;
188+ }
189+ } finally {
190+ // All state updates batched here so React never renders
191+ // a frame where messages is updated but isLoading is still true
194192 if ( ! aborted ) {
195- setMessages ( [
196- ...updatedMessages ,
197- {
198- role : 'assistant' ,
199- content : accumulated || 'Sorry, something went wrong. Please try again.' ,
200- } ,
201- ] ) ;
193+ setMessages ( [ ...updatedMessages , { role : 'assistant' , content : finalContent } ] ) ;
202194 }
203195 setStreamingText ( '' ) ;
204196 setToolStatus ( '' ) ;
205197 setIsLoading ( false ) ;
206198 abortRef . current = null ;
207- } catch ( err : unknown ) {
208- setStreamingText ( '' ) ;
209- setToolStatus ( '' ) ;
210- setIsLoading ( false ) ;
211- abortRef . current = null ;
212- } finally {
199+ }
213200 } ;
214201
215202 const handleKeyDown = ( e : React . KeyboardEvent < HTMLTextAreaElement > ) => {
0 commit comments