@@ -96,6 +96,87 @@ func TestStreamAccumulatorSuppressesCitationTextWhenSearchEnabled(t *testing.T)
9696 }
9797}
9898
99+ func TestStreamAccumulatorStripsToolResultSectionAcrossTextChunks (t * testing.T ) {
100+ acc := StreamAccumulator {StripReferenceMarkers : true }
101+ first := acc .Apply (sse.LineResult {
102+ Parsed : true ,
103+ Parts : []sse.ContentPart {{Type : "text" , Text : "visible:<|Tool|>" }},
104+ })
105+ second := acc .Apply (sse.LineResult {
106+ Parsed : true ,
107+ Parts : []sse.ContentPart {{Type : "text" , Text : `[{"content":"secret","tool_call_id":"call_123"}]` }},
108+ })
109+ third := acc .Apply (sse.LineResult {
110+ Parsed : true ,
111+ Parts : []sse.ContentPart {{Type : "text" , Text : "<|end_of_toolresults|> after" }},
112+ })
113+
114+ if got := acc .RawText .String (); got != `visible:<|Tool|>[{"content":"secret","tool_call_id":"call_123"}]<|end_of_toolresults|> after` {
115+ t .Fatalf ("raw text = %q" , got )
116+ }
117+ if got := acc .Text .String (); got != "visible: after" {
118+ t .Fatalf ("visible text = %q" , got )
119+ }
120+ if ! first .ContentSeen || ! second .ContentSeen || ! third .ContentSeen {
121+ t .Fatalf ("expected all chunks to mark upstream content" )
122+ }
123+ if got := first .Parts [0 ].VisibleText ; got != "visible:" {
124+ t .Fatalf ("first visible delta = %q" , got )
125+ }
126+ if got := second .Parts [0 ].VisibleText ; got != "" {
127+ t .Fatalf ("payload visible delta = %q" , got )
128+ }
129+ if got := third .Parts [0 ].VisibleText ; got != " after" {
130+ t .Fatalf ("closing visible delta = %q" , got )
131+ }
132+ }
133+
134+ func TestStreamAccumulatorStripsFullwidthToolResultSectionAcrossTextChunks (t * testing.T ) {
135+ acc := StreamAccumulator {StripReferenceMarkers : true }
136+ acc .Apply (sse.LineResult {
137+ Parsed : true ,
138+ Parts : []sse.ContentPart {{Type : "text" , Text : "x<|Tool|>" }},
139+ })
140+ acc .Apply (sse.LineResult {
141+ Parsed : true ,
142+ Parts : []sse.ContentPart {{Type : "text" , Text : `{"content":"secret"}` }},
143+ })
144+ acc .Apply (sse.LineResult {
145+ Parsed : true ,
146+ Parts : []sse.ContentPart {{Type : "text" , Text : "<|end▁of▁toolresults|>y" }},
147+ })
148+
149+ if got := acc .Text .String (); got != "xy" {
150+ t .Fatalf ("visible text = %q" , got )
151+ }
152+ }
153+
154+ func TestStreamAccumulatorStripsToolResultSectionAcrossThinkingChunks (t * testing.T ) {
155+ acc := StreamAccumulator {ThinkingEnabled : true , StripReferenceMarkers : true }
156+ acc .Apply (sse.LineResult {
157+ Parsed : true ,
158+ Parts : []sse.ContentPart {{Type : "thinking" , Text : "thought <|Tool|>" }},
159+ })
160+ payload := acc .Apply (sse.LineResult {
161+ Parsed : true ,
162+ Parts : []sse.ContentPart {{Type : "thinking" , Text : `[{"content":"secret"}]` }},
163+ })
164+ acc .Apply (sse.LineResult {
165+ Parsed : true ,
166+ Parts : []sse.ContentPart {{Type : "thinking" , Text : "<|end_of_toolresults|>resumes" }},
167+ })
168+
169+ if got := acc .RawThinking .String (); got != `thought <|Tool|>[{"content":"secret"}]<|end_of_toolresults|>resumes` {
170+ t .Fatalf ("raw thinking = %q" , got )
171+ }
172+ if got := acc .Thinking .String (); got != "thought resumes" {
173+ t .Fatalf ("visible thinking = %q" , got )
174+ }
175+ if got := payload .Parts [0 ].VisibleText ; got != "" {
176+ t .Fatalf ("payload visible delta = %q" , got )
177+ }
178+ }
179+
99180func TestStreamAccumulatorStripsInlineCitationAndReferenceMarkers (t * testing.T ) {
100181 acc := StreamAccumulator {SearchEnabled : true , StripReferenceMarkers : true }
101182 result := acc .Apply (sse.LineResult {
0 commit comments