@@ -563,4 +563,132 @@ describe("ClaudeCodeHandler", () => {
563563
564564 consoleSpy . mockRestore ( )
565565 } )
566+
567+ test ( "should convert escaped newlines to actual newlines in string chunks" , async ( ) => {
568+ const systemPrompt = "You are a helpful assistant"
569+ const messages = [ { role : "user" as const , content : "Hello" } ]
570+
571+ // Mock async generator that yields string chunks with escaped newlines
572+ const mockGenerator = async function * ( ) : AsyncGenerator < ClaudeCodeMessage | string > {
573+ yield "Line 1\\nLine 2\\nLine 3"
574+ yield "Another chunk\\nwith newlines"
575+ }
576+
577+ mockRunClaudeCode . mockReturnValue ( mockGenerator ( ) )
578+
579+ const stream = handler . createMessage ( systemPrompt , messages )
580+ const results = [ ]
581+
582+ for await ( const chunk of stream ) {
583+ results . push ( chunk )
584+ }
585+
586+ expect ( results ) . toHaveLength ( 2 )
587+ expect ( results [ 0 ] ) . toEqual ( {
588+ type : "text" ,
589+ text : "Line 1\nLine 2\nLine 3" ,
590+ } )
591+ expect ( results [ 1 ] ) . toEqual ( {
592+ type : "text" ,
593+ text : "Another chunk\nwith newlines" ,
594+ } )
595+ } )
596+
597+ test ( "should convert escaped newlines in text content from assistant messages" , async ( ) => {
598+ const systemPrompt = "You are a helpful assistant"
599+ const messages = [ { role : "user" as const , content : "Hello" } ]
600+
601+ // Mock async generator that yields assistant message with escaped newlines
602+ const mockGenerator = async function * ( ) : AsyncGenerator < ClaudeCodeMessage | string > {
603+ yield {
604+ type : "assistant" as const ,
605+ message : {
606+ id : "msg_123" ,
607+ type : "message" ,
608+ role : "assistant" ,
609+ model : "claude-3-5-sonnet-20241022" ,
610+ content : [
611+ {
612+ type : "text" ,
613+ text : "# Claude Chat History\\n\\n## 2025-08-05\\n\\nHello there!" ,
614+ } ,
615+ ] ,
616+ stop_reason : null ,
617+ stop_sequence : null ,
618+ usage : {
619+ input_tokens : 10 ,
620+ output_tokens : 20 ,
621+ } ,
622+ } as any ,
623+ session_id : "session_123" ,
624+ }
625+ }
626+
627+ mockRunClaudeCode . mockReturnValue ( mockGenerator ( ) )
628+
629+ const stream = handler . createMessage ( systemPrompt , messages )
630+ const results = [ ]
631+
632+ for await ( const chunk of stream ) {
633+ results . push ( chunk )
634+ }
635+
636+ expect ( results ) . toHaveLength ( 1 )
637+ expect ( results [ 0 ] ) . toEqual ( {
638+ type : "text" ,
639+ text : "# Claude Chat History\n\n## 2025-08-05\n\nHello there!" ,
640+ } )
641+ } )
642+
643+ test ( "should handle mixed escaped sequences correctly" , async ( ) => {
644+ const systemPrompt = "You are a helpful assistant"
645+ const messages = [ { role : "user" as const , content : "Hello" } ]
646+
647+ // Mock async generator that yields text with various escape sequences
648+ const mockGenerator = async function * ( ) : AsyncGenerator < ClaudeCodeMessage | string > {
649+ yield "Text with\\nnewlines and\\ttabs"
650+ yield {
651+ type : "assistant" as const ,
652+ message : {
653+ id : "msg_123" ,
654+ type : "message" ,
655+ role : "assistant" ,
656+ model : "claude-3-5-sonnet-20241022" ,
657+ content : [
658+ {
659+ type : "text" ,
660+ text : "More text\\nwith\\\\backslashes\\nand newlines" ,
661+ } ,
662+ ] ,
663+ stop_reason : null ,
664+ stop_sequence : null ,
665+ usage : {
666+ input_tokens : 10 ,
667+ output_tokens : 20 ,
668+ } ,
669+ } as any ,
670+ session_id : "session_123" ,
671+ }
672+ }
673+
674+ mockRunClaudeCode . mockReturnValue ( mockGenerator ( ) )
675+
676+ const stream = handler . createMessage ( systemPrompt , messages )
677+ const results = [ ]
678+
679+ for await ( const chunk of stream ) {
680+ results . push ( chunk )
681+ }
682+
683+ expect ( results ) . toHaveLength ( 2 )
684+ // Only \n should be converted, not \t or \\
685+ expect ( results [ 0 ] ) . toEqual ( {
686+ type : "text" ,
687+ text : "Text with\nnewlines and\\ttabs" ,
688+ } )
689+ expect ( results [ 1 ] ) . toEqual ( {
690+ type : "text" ,
691+ text : "More text\nwith\\\\backslashes\nand newlines" ,
692+ } )
693+ } )
566694} )
0 commit comments