feat: 持久化 AI 审查结果,文件级内联展示与页面集成

This commit is contained in:
2026-06-19 23:24:06 +08:00
parent a89d057716
commit 0528eee4de
7 changed files with 518 additions and 23 deletions
+20 -8
View File
@@ -34,6 +34,13 @@ type ReviewSummary struct {
Recommendations string `json:"recommendations"`
}
// ReviewResult holds the complete review output for persistence.
type ReviewResult struct {
FileReviews []FileReview `json:"file_reviews"`
Summary ReviewSummary `json:"summary"`
TopN int `json:"top_n"`
}
// countDiffLines counts the number of added/removed lines in a diff patch.
func countDiffLines(patch string) int {
count := 0
@@ -48,24 +55,25 @@ func countDiffLines(patch string) int {
}
// GenerateReview performs AI code review on diff files with Top-N strategy.
// It streams events (file_start, suggestion, file_end, summary, done) via callback.
func GenerateReview(db *sql.DB, repoPath, base, head string, topN int, callback StreamCallback) error {
// It streams events (file_start, suggestion, file_end, summary, done) via callback
// and returns the complete ReviewResult for persistence.
func GenerateReview(db *sql.DB, repoPath, base, head string, topN int, callback StreamCallback) (*ReviewResult, error) {
// Read LLM config
config, err := GetLLMConfig(db)
if err != nil {
return err
return nil, err
}
// Open repo
repo, err := OpenRepo(repoPath)
if err != nil {
return fmt.Errorf("open repo: %w", err)
return nil, fmt.Errorf("open repo: %w", err)
}
// Get diff files
files, err := GetDiffFiles(repo, base, head)
if err != nil {
return fmt.Errorf("get diff files: %w", err)
return nil, fmt.Errorf("get diff files: %w", err)
}
if len(files) == 0 {
@@ -73,7 +81,7 @@ func GenerateReview(db *sql.DB, repoPath, base, head string, topN int, callback
callback("summary", map[string]interface{}{"content": "没有检测到代码变更。"})
callback("done", map[string]interface{}{"content": ""})
}
return nil
return &ReviewResult{TopN: topN}, nil
}
// Sort by change size (descending)
@@ -226,6 +234,7 @@ func GenerateReview(db *sql.DB, repoPath, base, head string, topN int, callback
}
// Generate summary
var summary ReviewSummary
if len(fileReviews) > 0 {
if callback != nil {
callback("progress", map[string]interface{}{"step": "generating_summary"})
@@ -265,7 +274,6 @@ func GenerateReview(db *sql.DB, repoPath, base, head string, topN int, callback
summaryResponse, err := ChatStream(config, messages, callback)
if err == nil {
jsonStr := extractJSON(summaryResponse)
var summary ReviewSummary
if json.Unmarshal([]byte(jsonStr), &summary) == nil {
summaryText := fmt.Sprintf("整体评分: %d/10\n\n%s", summary.Score, summary.Overall)
if summary.Findings != "" {
@@ -294,5 +302,9 @@ func GenerateReview(db *sql.DB, repoPath, base, head string, topN int, callback
callback("done", map[string]interface{}{"content": ""})
}
return nil
return &ReviewResult{
FileReviews: fileReviews,
Summary: summary,
TopN: topN,
}, nil
}