Files
pierre-bot/internal/pierre/resource.go
2026-02-13 18:32:13 +01:00

87 lines
2.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package pierre
import (
"context"
"fmt"
"io"
"strings"
"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 // stored as slice of lines; legacy, see WithGuidelines
skipSanityCheck bool // if true, skip LLM sanitycheck prompts per comment
disableComments bool
git GitAdapter
chat ChatAdapter
}
func New(chat ChatAdapter, git GitAdapter, maxChunkSize int, guidelines []string, disableComments bool) *Service {
// Existing constructor retains slice based guidelines for backward compatibility.
return &Service{
git: git,
chat: chat,
maxChunkSize: maxChunkSize,
guidelines: guidelines,
skipSanityCheck: false,
disableComments: disableComments,
}
}
// WithGuidelines parses a raw Markdown string (or any multiline string) into
// individual guideline lines, validates the linecount (max 1000 nonempty lines),
// and stores the result in the Service. It returns an error if validation fails.
// This is a convenience mutator for callers that have the guidelines as a
// single string.
func (s *Service) WithGuidelines(md string) error {
lines, err := parseGuidelinesFromString(md)
if err != nil {
return err
}
s.guidelines = lines
return nil
}
// parseGuidelinesFromString splits a markdown string into trimmed, nonempty
// lines and ensures the total number of lines does not exceed 1000.
func (s *Service) SetSanityCheck(enabled bool) {
s.skipSanityCheck = !enabled
}
// parseGuidelinesFromString splits a markdown string into trimmed, nonempty
func parseGuidelinesFromString(md string) ([]string, error) {
var result []string
// Split on newline. Handles both \n and \r\n because TrimSpace removes \r.
rawLines := strings.Split(md, "\n")
for _, l := range rawLines {
trimmed := strings.TrimSpace(l)
if trimmed == "" {
continue
}
result = append(result, trimmed)
}
if len(result) > 1000 {
return nil, fmt.Errorf("guidelines exceed 1000 lines (found %d)", len(result))
}
return result, nil
}
type GitAdapter interface {
GetDiff(ctx context.Context, owner, repo string, prID int) (io.ReadCloser, error)
AddComment(ctx context.Context, owner, repo string, prID int, comment Comment) error
GetFileContent(ctx context.Context, owner, repo, path, ref string) (string, error)
GetPRHeadSHA(ctx context.Context, owner, repo string, prID int) (string, error)
}
type ChatAdapter interface {
GenerateStructured(ctx context.Context, messages []chatter.Message, target interface{}) error
GetProviderName() string
}