Compare commits

..

1 Commits

Author SHA1 Message Date
u80864958
cc321be658 feat(pierre): add diff chunking and configurable review settings 2026-02-13 17:09:18 +01:00
2 changed files with 27 additions and 18 deletions

View File

@@ -9,7 +9,8 @@ import (
"git.schreifuchs.ch/schreifuchs/pierre-bot/internal/chatter" "git.schreifuchs.ch/schreifuchs/pierre-bot/internal/chatter"
) )
const defaultChunkSize = 60000 // DefaultChunkSize is the fallback maximum size (in bytes) for a diff chunk when no explicit value is configured.
const DefaultChunkSize = 60000
type Comment struct { type Comment struct {
File string `json:"file"` File string `json:"file"`
@@ -26,36 +27,41 @@ func (s *Service) judgePR(ctx context.Context, diff io.Reader) (comments []Comme
// Determine chunk size (use default if not set) // Determine chunk size (use default if not set)
maxSize := s.maxChunkSize maxSize := s.maxChunkSize
if maxSize <= 0 { if maxSize <= 0 {
maxSize = defaultChunkSize // default 60KB ~ 15k tokens maxSize = DefaultChunkSize // default 60KB ~ 15k tokens
} }
chunks := splitDiffIntoChunks(diffBytes, maxSize) chunks := splitDiffIntoChunks(diffBytes, maxSize)
allComments := []Comment{} allComments := []Comment{}
// Build optional guidelines text // Build optional guidelines text (added as a separate section with a clear delimiter)
guidelinesText := "" guidelinesText := ""
if len(s.guidelines) > 0 { if len(s.guidelines) > 0 {
guidelinesText = "Project guidelines:\n" // Two newlines ensure the guidelines start on a fresh paragraph.
guidelinesText = "\n\nProject guidelines:\n"
for _, g := range s.guidelines { for _, g := range s.guidelines {
guidelinesText += "- " + g + "\n" guidelinesText += "- " + g + "\n"
} }
} }
// System prompt that instructs the LLM precisely.
baseSystem := strings.TrimSpace(` baseSystem := strings.TrimSpace(`
You are a very strict senior software architect. You are a strict senior software architect.
You review **only** newly added or modified lines in a unified diff, together with the immediate hunk context. Only comment on newly added or modified lines in the diff; ignore deletions, pure formatting, or reordering that does not change behavior.
You do **not** report issues that appear **solely** in deleted lines (“-") or that have already been fixed by the change. For each issue output a JSON object with fields "file", "line", and "message" (message should be concise, ≤2 sentences, and actionable).
No comments are made on pure formatting/whitespace changes or reordering that does not alter the programs behavior.`) + guidelinesText If project guidelines are provided, treat them as hard rules that must be respected.`) + guidelinesText
for i, chunk := range chunks { for i, chunk := range chunks {
// Add a small header so the model knows this is a fragment // Include the chunk identifier in the system message only if there are multiple chunks.
header := fmt.Sprintf("\n--- Chunk %d of %d ---\n", i+1, len(chunks)) systemContent := baseSystem
userContent := fmt.Sprintf("Hello please review my PR. Write comments where improvements are necessary in new lines.%s\nHere is the git diff of it: %s", header, chunk) if len(chunks) > 1 {
systemContent = fmt.Sprintf("%s\nChunk %d of %d.", baseSystem, i+1, len(chunks))
}
userContent := chunk
var chunkComments []Comment var chunkComments []Comment
err = s.chat.GenerateStructured(ctx, []chatter.Message{{ err = s.chat.GenerateStructured(ctx, []chatter.Message{{
Role: chatter.RoleSystem, Role: chatter.RoleSystem,
Content: baseSystem, Content: systemContent,
}, { }, {
Role: chatter.RoleUser, Role: chatter.RoleUser,
Content: userContent, Content: userContent,

View File

@@ -26,15 +26,18 @@ func (s *Service) MakeReview(ctx context.Context, organisation string, repo stri
for _, c := range comments { for _, c := range comments {
c.Message = fmt.Sprintf("%s (Generated by: %s)", c.Message, model) c.Message = fmt.Sprintf("%s (Generated by: %s)", c.Message, model)
fmt.Printf("File: %s\nLine: %d\nMessage: %s\n%s\n",
c.File, c.Line, c.Message, "---")
if s.disableComments { if s.disableComments {
log.Printf("dry-run: not posting comment for %s:%d", c.File, c.Line) // Dryrun: just log what would have been posted.
} else if err := s.git.AddComment(ctx, organisation, repo, prID, c); err != nil { log.Printf("dryrun: %s:%d => %s", c.File, c.Line, c.Message)
log.Printf("Failed to add comment: %v", err) } else {
// Normal mode: print to stdout and post the comment to the VCS.
fmt.Printf("File: %s\nLine: %d\nMessage: %s\n%s\n",
c.File, c.Line, c.Message, "---")
if err := s.git.AddComment(ctx, organisation, repo, prID, c); err != nil {
log.Printf("Failed to add comment: %v", err)
}
} }
} }
return nil return nil