Compare commits
1 Commits
ac5ff7aeeb
...
61d538d4a5
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
61d538d4a5 |
@@ -37,18 +37,13 @@ type LLMConfig struct {
|
||||
Model string `help:"Model to use" env:"LLM_MODEL"`
|
||||
}
|
||||
|
||||
// ReviewConfig holds the review‑specific CLI options.
|
||||
// The `default:"60000"` tag sets an integer default of 60 KB – Kong parses the string value into the int field, which can be confusing for readers.
|
||||
type ReviewConfig struct {
|
||||
MaxChunkSize int `help:"Maximum diff chunk size in bytes" default:"60000"`
|
||||
Guidelines []string `help:"Project guidelines to prepend" sep:","`
|
||||
DisableComments bool `help:"Disable posting comments (dry run)"`
|
||||
MaxChunkChars int `help:"Maximum diff chunk size in characters (default 60000)" default:"60000"`
|
||||
Guidelines []string `help:"Project-specific review guidelines"`
|
||||
DisableComments bool `help:"Do not post comments to the Git provider (dry‑run mode)"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
// Embedding ReviewConfig with a prefix changes flag names to `--review-…`.
|
||||
// Existing configuration files using the old flag names will need to be updated.
|
||||
// Consider keeping backwards compatibility if required.
|
||||
Review ReviewConfig `embed:"" prefix:"review-"`
|
||||
GitProvider string `help:"Git provider (bitbucket or gitea)" env:"GIT_PROVIDER"`
|
||||
Bitbucket BitbucketConfig `embed:"" prefix:"bitbucket-"`
|
||||
@@ -129,7 +124,7 @@ func main() {
|
||||
log.Fatalf("Error initializing AI: %v", err)
|
||||
}
|
||||
|
||||
pierreService := pierre.New(ai, git, cfg.Review.MaxChunkSize, cfg.Review.Guidelines, cfg.Review.DisableComments)
|
||||
pierreService := pierre.New(ai, git, cfg.Review.MaxChunkChars, cfg.Review.Guidelines, cfg.Review.DisableComments)
|
||||
if err := pierreService.MakeReview(context.Background(), cfg.Repo.Owner, cfg.Repo.Repo, cfg.Repo.PRID); err != nil {
|
||||
log.Fatalf("Error during review: %v", err)
|
||||
}
|
||||
|
||||
@@ -9,8 +9,6 @@ import (
|
||||
"git.schreifuchs.ch/schreifuchs/pierre-bot/internal/chatter"
|
||||
)
|
||||
|
||||
const defaultChunkSize = 60000
|
||||
|
||||
type Comment struct {
|
||||
File string `json:"file"`
|
||||
Line int `json:"line"`
|
||||
@@ -26,7 +24,7 @@ func (s *Service) judgePR(ctx context.Context, diff io.Reader) (comments []Comme
|
||||
// Determine chunk size (use default if not set)
|
||||
maxSize := s.maxChunkSize
|
||||
if maxSize <= 0 {
|
||||
maxSize = defaultChunkSize // default 60KB ~ 15k tokens
|
||||
maxSize = 60000 // default 60KB ~ 15k tokens
|
||||
}
|
||||
|
||||
chunks := splitDiffIntoChunks(diffBytes, maxSize)
|
||||
@@ -35,7 +33,7 @@ func (s *Service) judgePR(ctx context.Context, diff io.Reader) (comments []Comme
|
||||
// Build optional guidelines text
|
||||
guidelinesText := ""
|
||||
if len(s.guidelines) > 0 {
|
||||
guidelinesText = "Project guidelines:\n"
|
||||
guidelinesText = "\nProject guidelines:\n"
|
||||
for _, g := range s.guidelines {
|
||||
guidelinesText += "- " + g + "\n"
|
||||
}
|
||||
@@ -104,13 +102,9 @@ func splitDiffIntoChunks(diff []byte, maxSize int) []string {
|
||||
// Split further by hunks
|
||||
hunks := strings.Split(seg, "\n@@ ")
|
||||
for j, h := range hunks {
|
||||
var hseg string
|
||||
if j == 0 {
|
||||
// First hunk segment already contains the preceding content (including any needed newline)
|
||||
hseg = h
|
||||
} else {
|
||||
// Subsequent hunks need the leading newline and "@@ " marker restored
|
||||
hseg = "\n@@ " + h
|
||||
hseg := h
|
||||
if j != 0 {
|
||||
hseg = "@@ " + h
|
||||
}
|
||||
if current.Len()+len(hseg) > maxSize && current.Len() > 0 {
|
||||
chunks = append(chunks, current.String())
|
||||
@@ -135,3 +129,4 @@ func splitDiffIntoChunks(diff []byte, maxSize int) []string {
|
||||
}
|
||||
return chunks
|
||||
}
|
||||
|
||||
|
||||
@@ -12,10 +12,9 @@ import (
|
||||
)
|
||||
|
||||
// mockChat implements the ChatAdapter interface for testing.
|
||||
type mockChat struct{ callCount int }
|
||||
type mockChat struct{}
|
||||
|
||||
func (m *mockChat) GenerateStructured(ctx context.Context, msgs []chatter.Message, target interface{}) error {
|
||||
m.callCount++
|
||||
if cSlice, ok := target.(*[]Comment); ok {
|
||||
*cSlice = []Comment{{File: "file.go", Line: 1, Message: "test comment"}}
|
||||
return nil
|
||||
@@ -107,12 +106,11 @@ func TestSplitDiffIntoChunks(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestJudgePR_ChunkAggregationAndDeduplication(t *testing.T) {
|
||||
chatMock := &mockChat{}
|
||||
svc := &Service{
|
||||
maxChunkSize: 50,
|
||||
guidelines: nil,
|
||||
git: &mockGit{},
|
||||
chat: chatMock,
|
||||
chat: &mockChat{},
|
||||
}
|
||||
diffReader, err := svc.git.GetDiff(context.Background(), "", "", 0)
|
||||
if err != nil {
|
||||
@@ -126,7 +124,4 @@ func TestJudgePR_ChunkAggregationAndDeduplication(t *testing.T) {
|
||||
if got, want := len(comments), 1; got != want {
|
||||
t.Fatalf("expected %d comment after deduplication, got %d", want, got)
|
||||
}
|
||||
if chatMock.callCount != 2 {
|
||||
t.Fatalf("expected mockChat to be called for each chunk (2), got %d", chatMock.callCount)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,11 +7,6 @@ import (
|
||||
"git.schreifuchs.ch/schreifuchs/pierre-bot/internal/chatter"
|
||||
)
|
||||
|
||||
// Service holds the core collaborators and configuration for Pierre.
|
||||
// The order of the fields is intentional: configuration fields first (used
|
||||
// during initialization) followed by the adapters. This prevents accidental
|
||||
// changes to the serialized layout if encoding/gob or encoding/json is used
|
||||
// elsewhere in the future.
|
||||
type Service struct {
|
||||
maxChunkSize int
|
||||
guidelines []string
|
||||
|
||||
Reference in New Issue
Block a user