fix(cli): embed summary into JSON output to avoid breaking JSON parsing

When using --audience agent --format json, the text summary line was
printed before the JSON body, causing parse failures for integrations.
Move summary data into the JSON "summary" field and skip PrintTraceSummary
in JSON mode.
This commit is contained in:
kite 2026-06-03 15:38:22 +08:00
parent fe647bc489
commit 49e1c700ed
2 changed files with 27 additions and 5 deletions

View file

@ -5,6 +5,7 @@ import (
"fmt"
"os"
"strings"
"time"
"github.com/open-code-review/open-code-review/internal/agent"
"github.com/open-code-review/open-code-review/internal/model"
@ -161,9 +162,19 @@ func buildDiffLines(comment model.LlmComment) []suggestdiff.DiffLine {
return suggestdiff.ComputeLineDiff(oldLines, newLines)
}
type jsonSummary struct {
FilesReviewed int64 `json:"files_reviewed"`
Comments int64 `json:"comments"`
TotalTokens int64 `json:"total_tokens"`
InputTokens int64 `json:"input_tokens"`
OutputTokens int64 `json:"output_tokens"`
Elapsed string `json:"elapsed"`
}
type jsonOutput struct {
Status string `json:"status"`
Message string `json:"message,omitempty"`
Summary *jsonSummary `json:"summary,omitempty"`
Comments []model.LlmComment `json:"comments"`
Warnings []agent.AgentWarning `json:"warnings,omitempty"`
}
@ -181,10 +192,19 @@ func outputJSON(comments []model.LlmComment) error {
return enc.Encode(out)
}
func outputJSONWithWarnings(comments []model.LlmComment, warnings []agent.AgentWarning) error {
func outputJSONWithWarnings(comments []model.LlmComment, warnings []agent.AgentWarning,
filesReviewed, inputTokens, outputTokens, totalTokens int64, duration time.Duration) error {
out := jsonOutput{
Status: "success",
Comments: comments,
Summary: &jsonSummary{
FilesReviewed: filesReviewed,
Comments: int64(len(comments)),
TotalTokens: totalTokens,
InputTokens: inputTokens,
OutputTokens: outputTokens,
Elapsed: duration.Round(time.Second).String(),
},
}
if len(comments) == 0 {
if hasSubtaskErrors(warnings) {

View file

@ -153,16 +153,18 @@ func runReview(args []string) error {
return outputJSONNoFiles()
}
// In agent mode, restore stdout so Summary reaches the terminal.
if opts.audience == "agent" && unsilence != nil {
// In agent mode (text output), restore stdout so Summary reaches the terminal.
if opts.audience == "agent" && opts.outputFormat != "json" && unsilence != nil {
unsilence()
unsilence = nil
}
telemetry.PrintTraceSummary(ag.FilesReviewed(), int64(len(comments)), ag.TotalInputTokens(), ag.TotalOutputTokens(), ag.TotalTokensUsed(), duration)
if opts.outputFormat != "json" {
telemetry.PrintTraceSummary(ag.FilesReviewed(), int64(len(comments)), ag.TotalInputTokens(), ag.TotalOutputTokens(), ag.TotalTokensUsed(), duration)
}
if opts.outputFormat == "json" {
return outputJSONWithWarnings(comments, ag.Warnings())
return outputJSONWithWarnings(comments, ag.Warnings(), ag.FilesReviewed(), ag.TotalInputTokens(), ag.TotalOutputTokens(), ag.TotalTokensUsed(), duration)
}
if opts.audience == "agent" {
outputTextWithWarnings(comments, ag.Warnings())