@@ -668,6 +668,130 @@ describe('AutomationChatView', () => {
668668 expect ( wrapper . find ( '.td-hint-card__patterns' ) . exists ( ) ) . toBe ( false )
669669 } )
670670
671+ it ( 'shows truncation notice instead of raw JSON for truncated assistant messages' , async ( ) => {
672+ const now = new Date ( ) . toISOString ( )
673+ const truncatedSession = {
674+ id : 'session-trunc' ,
675+ userId : 'user-1' ,
676+ boardId : null ,
677+ title : 'Truncation test' ,
678+ status : 'Active' ,
679+ createdAt : now ,
680+ updatedAt : now ,
681+ recentMessages : [
682+ {
683+ id : 'msg-user' ,
684+ sessionId : 'session-trunc' ,
685+ role : 'User' ,
686+ content : 'Tell me about the board' ,
687+ messageType : 'text' as const ,
688+ proposalId : null ,
689+ tokenUsage : null ,
690+ createdAt : now ,
691+ } ,
692+ {
693+ id : 'msg-trunc' ,
694+ sessionId : 'session-trunc' ,
695+ role : 'Assistant' ,
696+ content : '{"reply":"I understand your question about' ,
697+ messageType : 'text' as const ,
698+ proposalId : null ,
699+ tokenUsage : 50 ,
700+ createdAt : now ,
701+ } ,
702+ ] ,
703+ }
704+ mocks . getMySessions . mockResolvedValue ( [ truncatedSession ] )
705+ mocks . getSession . mockResolvedValue ( truncatedSession )
706+
707+ const wrapper = mountView ( )
708+ await waitForAsyncUi ( )
709+
710+ const truncatedMsg = wrapper . find ( '.td-message-content--truncated' )
711+ expect ( truncatedMsg . exists ( ) ) . toBe ( true )
712+ expect ( truncatedMsg . text ( ) ) . toContain ( 'This response was cut short' )
713+ expect ( wrapper . text ( ) ) . not . toContain ( '{"reply"' )
714+ } )
715+
716+ it ( 'shows truncation notice for degraded messages with truncated JSON content' , async ( ) => {
717+ const now = new Date ( ) . toISOString ( )
718+ const degradedTruncSession = {
719+ id : 'session-deg-trunc' ,
720+ userId : 'user-1' ,
721+ boardId : null ,
722+ title : 'Degraded truncation test' ,
723+ status : 'Active' ,
724+ createdAt : now ,
725+ updatedAt : now ,
726+ recentMessages : [
727+ {
728+ id : 'msg-user' ,
729+ sessionId : 'session-deg-trunc' ,
730+ role : 'User' ,
731+ content : 'Hello' ,
732+ messageType : 'text' as const ,
733+ proposalId : null ,
734+ tokenUsage : null ,
735+ createdAt : now ,
736+ } ,
737+ {
738+ id : 'msg-deg-trunc' ,
739+ sessionId : 'session-deg-trunc' ,
740+ role : 'Assistant' ,
741+ content : '{"reply":"I understand' ,
742+ messageType : 'degraded' as const ,
743+ proposalId : null ,
744+ tokenUsage : 10 ,
745+ createdAt : now ,
746+ degradedReason : 'Response was truncated' ,
747+ } ,
748+ ] ,
749+ }
750+ mocks . getMySessions . mockResolvedValue ( [ degradedTruncSession ] )
751+ mocks . getSession . mockResolvedValue ( degradedTruncSession )
752+
753+ const wrapper = mountView ( )
754+ await waitForAsyncUi ( )
755+
756+ expect ( wrapper . text ( ) ) . toContain ( 'Degraded response: Response was truncated' )
757+ expect ( wrapper . find ( '.td-message-content--truncated' ) . exists ( ) ) . toBe ( true )
758+ expect ( wrapper . text ( ) ) . toContain ( 'This response was cut short' )
759+ expect ( wrapper . text ( ) ) . not . toContain ( '{"reply"' )
760+ } )
761+
762+ it ( 'detects truncated JSON arrays starting with [' , async ( ) => {
763+ const now = new Date ( ) . toISOString ( )
764+ const arrayTruncSession = {
765+ id : 'session-arr-trunc' ,
766+ userId : 'user-1' ,
767+ boardId : null ,
768+ title : 'Array truncation test' ,
769+ status : 'Active' ,
770+ createdAt : now ,
771+ updatedAt : now ,
772+ recentMessages : [
773+ {
774+ id : 'msg-arr-trunc' ,
775+ sessionId : 'session-arr-trunc' ,
776+ role : 'Assistant' ,
777+ content : '[{"id":1,"name":"incomplete' ,
778+ messageType : 'text' as const ,
779+ proposalId : null ,
780+ tokenUsage : 30 ,
781+ createdAt : now ,
782+ } ,
783+ ] ,
784+ }
785+ mocks . getMySessions . mockResolvedValue ( [ arrayTruncSession ] )
786+ mocks . getSession . mockResolvedValue ( arrayTruncSession )
787+
788+ const wrapper = mountView ( )
789+ await waitForAsyncUi ( )
790+
791+ expect ( wrapper . find ( '.td-message-content--truncated' ) . exists ( ) ) . toBe ( true )
792+ expect ( wrapper . text ( ) ) . toContain ( 'This response was cut short' )
793+ } )
794+
671795 it ( 'surfaces provider-health loading failures explicitly' , async ( ) => {
672796 mocks . getHealth . mockRejectedValueOnce ( new Error ( 'health down' ) )
673797
0 commit comments