77 lines
2.3 KiB
Go
77 lines
2.3 KiB
Go
package control
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
"testing"
|
|
|
|
"reasonix/internal/provider"
|
|
)
|
|
|
|
type classifierProvider struct {
|
|
text string
|
|
err error
|
|
req provider.Request
|
|
}
|
|
|
|
func (p *classifierProvider) Name() string { return "classifier" }
|
|
|
|
func (p *classifierProvider) Stream(ctx context.Context, req provider.Request) (<-chan provider.Chunk, error) {
|
|
p.req = req
|
|
if p.err != nil {
|
|
return nil, p.err
|
|
}
|
|
ch := make(chan provider.Chunk, 1)
|
|
ch <- provider.Chunk{Type: provider.ChunkText, Text: p.text}
|
|
close(ch)
|
|
return ch, nil
|
|
}
|
|
|
|
func TestProviderAutoPlanClassifierParsesJSON(t *testing.T) {
|
|
p := &classifierProvider{text: "```json\n{\"needs_plan\":true,\"reason\":\"multi-file\"}\n```"}
|
|
c := NewProviderAutoPlanClassifier(p)
|
|
|
|
needsPlan, reason, err := c.NeedsPlan(context.Background(), "implement feature", 1)
|
|
if err != nil {
|
|
t.Fatalf("NeedsPlan error: %v", err)
|
|
}
|
|
if !needsPlan || reason != "multi-file" {
|
|
t.Fatalf("NeedsPlan = (%v,%q), want (true,multi-file)", needsPlan, reason)
|
|
}
|
|
if len(p.req.Messages) != 2 || p.req.Messages[0].Role != provider.RoleSystem {
|
|
t.Fatalf("request messages = %+v", p.req.Messages)
|
|
}
|
|
if p.req.MaxTokens != 80 || p.req.Temperature == nil || *p.req.Temperature != 0 {
|
|
t.Fatalf("request limits = max %d temp %v, want 80/ptr(0)", p.req.MaxTokens, p.req.Temperature)
|
|
}
|
|
if !strings.Contains(p.req.Messages[1].Content, "heuristic_score=1") {
|
|
t.Fatalf("user message missing score: %q", p.req.Messages[1].Content)
|
|
}
|
|
}
|
|
|
|
func TestProviderAutoPlanClassifierRejectsBadJSON(t *testing.T) {
|
|
p := &classifierProvider{text: "needs plan"}
|
|
c := NewProviderAutoPlanClassifier(p)
|
|
|
|
if _, _, err := c.NeedsPlan(context.Background(), "x", 1); err == nil {
|
|
t.Fatal("NeedsPlan should reject non-JSON response")
|
|
}
|
|
}
|
|
|
|
func TestProviderAutoPlanClassifierRequiresNeedsPlan(t *testing.T) {
|
|
p := &classifierProvider{text: `{"reason":"missing decision"}`}
|
|
c := NewProviderAutoPlanClassifier(p)
|
|
|
|
if _, _, err := c.NeedsPlan(context.Background(), "x", 1); err == nil {
|
|
t.Fatal("NeedsPlan should reject JSON without needs_plan")
|
|
}
|
|
}
|
|
|
|
func TestProviderAutoPlanClassifierNilReceiverReturnsError(t *testing.T) {
|
|
var c *ProviderAutoPlanClassifier
|
|
|
|
if _, _, err := c.NeedsPlan(context.Background(), "x", 1); err == nil {
|
|
t.Fatal("NeedsPlan should reject nil classifier")
|
|
}
|
|
}
|