80 lines
2.6 KiB
Go
80 lines
2.6 KiB
Go
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
|
||
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,
|
||
disableComments: disableComments,
|
||
}
|
||
}
|
||
|
||
// WithGuidelines parses a raw Markdown string (or any multiline string) into
|
||
// individual guideline lines, validates the line‑count (max 1000 non‑empty 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, non‑empty
|
||
// lines and ensures the total number of lines does not exceed 1000.
|
||
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
|
||
}
|