@@ -211,9 +211,9 @@ type claudeStreamMessage struct {
211211 } `json:"error,omitempty"`
212212}
213213
214- // extractContentText extracts text from a Claude message content field.
215- // Content can be a plain string or an array of content blocks
216- // (e.g. [{"type":"text","text":"..."}]).
214+ // extractContentText extracts only the text that appears after the last tool-use
215+ // block in a Claude message content field. Content can be a plain string or an
216+ // array of content blocks (e.g. [{"type":"text","text":"..."}]).
217217func extractContentText (raw json.RawMessage ) string {
218218 if len (raw ) == 0 {
219219 return ""
@@ -229,13 +229,16 @@ func extractContentText(raw json.RawMessage) string {
229229 Text string `json:"text"`
230230 }
231231 if json .Unmarshal (raw , & blocks ) == nil {
232- var texts [] string
232+ texts := newTrailingReviewText ()
233233 for _ , b := range blocks {
234- if b .Type == "text" && b .Text != "" {
235- texts = append (texts , b .Text )
234+ switch b .Type {
235+ case "text" :
236+ texts .Add (b .Text )
237+ case "tool_use" , "tool_result" :
238+ texts .ResetAfterTool ()
236239 }
237240 }
238- return strings .Join (texts , "\n " )
241+ return texts .Join ("\n " )
239242 }
240243 return ""
241244}
@@ -248,7 +251,7 @@ func parseStreamJSON(r io.Reader, output io.Writer) (string, error) {
248251 br := bufio .NewReader (r )
249252
250253 var lastResult string
251- var assistantMessages [] string
254+ assistantMessages := newTrailingReviewText ()
252255 var errorMessages []string
253256 var validEventsParsed bool
254257
@@ -274,9 +277,14 @@ func parseStreamJSON(r io.Reader, output io.Writer) (string, error) {
274277 // Content can be a string or an array of content blocks.
275278 if msg .Type == "assistant" {
276279 if text := extractContentText (msg .Message .Content ); text != "" {
277- assistantMessages = append ( assistantMessages , text )
280+ assistantMessages . Add ( text )
278281 }
279282 }
283+ if msg .Type == "tool_use" || msg .Type == "tool_result" {
284+ // Only the trailing post-tool assistant segment is treated
285+ // as the review body.
286+ assistantMessages .ResetAfterTool ()
287+ }
280288
281289 // The final result message contains the summary.
282290 // When is_error is set, the result event signals a
@@ -315,7 +323,7 @@ func parseStreamJSON(r io.Reader, output io.Writer) (string, error) {
315323 }
316324
317325 // Build partial output for error context
318- partial := strings .Join (assistantMessages , "\n " )
326+ partial := assistantMessages .Join ("\n " )
319327
320328 // If error events were received but we got no result, report them with any partial output
321329 if len (errorMessages ) > 0 && lastResult == "" {
@@ -326,8 +334,8 @@ func parseStreamJSON(r io.Reader, output io.Writer) (string, error) {
326334 if lastResult != "" {
327335 return lastResult , nil
328336 }
329- if len ( assistantMessages ) > 0 {
330- return strings . Join ( assistantMessages , " \n " ) , nil
337+ if result := assistantMessages . Join ( " \n " ); result != "" {
338+ return result , nil
331339 }
332340
333341 return "" , nil
0 commit comments