Files
Agent-System/internal/app/pi_narrative_test.go
T
weichenandCursor db1706cd24 feat(docrevision): send clipped diff text to the change-report narrator
The narrator only received counts, so it could not describe the actual change. Caps keep the full document out and leave the input digest unchanged; the flag stays off.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-20 05:03:31 +00:00

120 lines
3.5 KiB
Go

package app
import (
"context"
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
"time"
"chat-agent-system/internal/agent"
"chat-agent-system/internal/config"
"chat-agent-system/internal/docrevision"
)
type recordingNarrativeBackend struct {
last agent.Request
payload []byte
body string
fail bool
}
func (r *recordingNarrativeBackend) Name() string { return "recording-narrative" }
func (r *recordingNarrativeBackend) Execute(_ context.Context, req agent.Request) (*agent.Result, error) {
r.last = req
if b, err := os.ReadFile(filepath.Join(req.WorkDir, "facts.json")); err == nil {
r.payload = b
}
if r.fail {
return &agent.Result{Success: false, ErrorReason: "TIMEOUT"}, nil
}
body := r.body
if body == "" {
body = `{"schema_version":1,"schema_kind":"change_report_narrative_v1","input_digest":"abc","from_sha":"f","to_sha":"t","summary":["叙事"]}`
}
return &agent.Result{Success: true, Patches: map[string][]byte{"narrative.md": []byte(body)}}, nil
}
func TestPiChangeReportNarrator_NoTools(t *testing.T) {
rec := &recordingNarrativeBackend{}
n := &PiChangeReportNarrator{Backend: rec, Model: "test"}
raw, err := n.Fetch(context.Background(), docrevision.NarrativeFetchSpec{
InputDigest: "abc", FromSHA: "f", ToSHA: "t",
Hunks: []docrevision.DiffHunk{{ID: "h1", Kind: "modify", BeforeText: "1.0", AfterText: "新阈值 2.5"}},
})
if err != nil {
t.Fatal(err)
}
if !strings.Contains(raw, "change_report_narrative_v1") {
t.Fatalf("raw=%s", raw)
}
if !strings.Contains(strings.ToLower(rec.last.Instructions), "zero tool") {
t.Fatalf("instructions=%s", rec.last.Instructions)
}
var facts map[string]any
if err := json.Unmarshal(rec.payload, &facts); err != nil {
t.Fatal(err)
}
if facts["input_digest"] != "abc" || facts["hunk_count"] != float64(1) {
t.Fatalf("facts=%v", facts)
}
hunks, _ := facts["hunks"].([]any)
if len(hunks) != 1 {
t.Fatalf("hunks=%v", facts["hunks"])
}
hunk, _ := hunks[0].(map[string]any)
if hunk["after_text"] != "新阈值 2.5" || rec.last.ToolProfile != agent.ToolProfileReasoning {
t.Fatalf("hunk=%v profile=%s", hunk, rec.last.ToolProfile)
}
}
func TestPiChangeReportNarrator_LiveMiniMax(t *testing.T) {
if os.Getenv("RUN_PI_E2E") != "1" {
t.Skip("set RUN_PI_E2E=1 for live PI narrative")
}
if testing.Short() {
t.Skip("live PI narrative is not a -short test")
}
if err := os.Chdir(filepath.Clean(filepath.Join("..", ".."))); err != nil {
t.Fatal(err)
}
cfg, err := config.Load("")
if err != nil || cfg == nil {
t.Fatalf("config: %v", err)
}
if strings.TrimSpace(cfg.PiAgentRunnerAuthToken) == "" {
if tok := runnerTokenFromDotenv(); tok != "" {
cfg.PiAgentRunnerAuthToken = tok
}
}
if strings.TrimSpace(cfg.PiAgentRunnerAuthToken) == "" {
t.Fatal("runner auth token missing")
}
cfg.PiAgentRunnerURL = "http://127.0.0.1:18865"
dataDir, err := filepath.Abs("data/dev")
if err != nil {
t.Fatal(err)
}
n := &PiChangeReportNarrator{
Backend: agent.NewBackend("pi-agent", cfg),
Model: cfg.PiAgentModel,
Timeout: 4 * time.Minute,
DataDir: dataDir,
}
digest := strings.Repeat("ab", 32)
start := time.Now()
raw, err := n.Fetch(context.Background(), docrevision.NarrativeFetchSpec{
FromSHA: "fromsha", ToSHA: "tosha", RuleRisk: "medium", InputDigest: digest,
})
if err != nil {
t.Fatalf("live fetch: %v", err)
}
t.Logf("elapsed=%s raw=%s", time.Since(start).Round(time.Millisecond), raw)
if !strings.Contains(raw, "change_report_narrative_v1") && !strings.Contains(raw, digest) {
t.Fatalf("expected schema or digest in payload: %s", raw)
}
}