@@ -228,10 +228,13 @@ func (s *Server) handleChatbotChat(w http.ResponseWriter, r *http.Request) {
228228 chunkChan := make (chan string , 64 )
229229 errCh := make (chan error , 1 )
230230
231+ ctx , cancel := context .WithCancel (r .Context ())
232+ defer cancel () // ensure cancel is called on all exit paths
233+
231234 go func () {
232235 // Prepend system prompt as first message when needed.
233236 fullHistory := prependSystemMessage (history , systemPrompt )
234- errCh <- llm .ChatCompletionStream (r . Context () , req .Prompt , fullHistory , chunkChan )
237+ errCh <- llm .ChatCompletionStream (ctx , req .Prompt , fullHistory , chunkChan )
235238 close (chunkChan )
236239 }()
237240
@@ -240,13 +243,16 @@ func (s *Server) handleChatbotChat(w http.ResponseWriter, r *http.Request) {
240243
241244 for chunk := range chunkChan {
242245 fullResponse .WriteString (chunk )
243- fmt .Fprintf (w , "data: %s\n \n " , chunk )
246+ if _ , err := fmt .Fprintf (w , "data: %s\n \n " , chunk ); err != nil {
247+ cancel () // cancel the LLM request context to stop token generation
248+ return
249+ }
244250 flusher .Flush ()
245251 }
246252
247253 if err := <- errCh ; err != nil {
248254 s .logger .Error ("chatbot streaming error" , "error" , err )
249- fmt .Fprintf (w , "event: error\n data: %s\n \n " , err .Error ())
255+ fmt .Fprintf (w , "event: error\n data: %s\n \n " , escapeSSEData ( err .Error () ))
250256 flusher .Flush ()
251257 return
252258 }
@@ -272,7 +278,7 @@ func (s *Server) handleChatbotChat(w http.ResponseWriter, r *http.Request) {
272278 } else {
273279 // Validation failed – stream auto-correction progress.
274280 fmt .Fprintf (w , "event: dry_run_status\n data: {\" success\" :false,\" error\" :\" %s\" }\n \n " ,
275- strings . ReplaceAll (err .Error (), " \" " , " \\ \" " ))
281+ escapeSSEData (err .Error ()))
276282 fmt .Fprintf (w , "event: manifests\n data: %s\n \n " , escapeSSEData (yamlBlock ))
277283 flusher .Flush ()
278284
@@ -331,7 +337,7 @@ func runAutoCorrectSSE(
331337
332338 if streamErr := <- errCh ; streamErr != nil {
333339 fmt .Fprintf (w , "event: correction_error\n data: {\" error\" :\" %s\" }\n \n " ,
334- strings . ReplaceAll (streamErr .Error (), " \" " , " \\ \" " ))
340+ escapeSSEData (streamErr .Error ()))
335341 flusher .Flush ()
336342 return
337343 }
0 commit comments