feat: 持久化 AI 审查结果,文件级内联展示与页面集成
This commit is contained in:
+20
-8
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user