返回 DeepSeek-Reasonix
interrupted_recovery_precedence_test.go
根目录 / internal / agent / interrupted_recovery_precedence_test.go
1 package agent
2
3 import (
4 "context"
5 "errors"
6 "strings"
7 "testing"
8
9 "reasonix/internal/agent/testutil"
10 "reasonix/internal/event"
11 "reasonix/internal/provider"
12 )
13
14 const wantPrecedence = "The user's new message takes precedence. If it is unrelated to the interrupted task, do not resume that task."
15
16 func TestInterruptedRecoveryBlockStatesUserMessagePrecedence(t *testing.T) {
17 apiErr := errors.New("upstream reset")
18 mp := testutil.NewMock("m",
19 testutil.Turn{Text: "partial", ChunkError: apiErr},
20 testutil.Turn{Text: "ok"},
21 )
22 session := NewSession("system")
23 a := New(mp, echoRegistry(), session, Options{}, event.Discard)
24 if err := a.Run(withNoClosedLoop(context.Background()), "refactor the parser"); !errors.Is(err, apiErr) {
25 t.Fatalf("first Run error = %v, want %v", err, apiErr)
26 }
27 const next = "list the files in the docs folder"
28 if err := a.Run(withNoClosedLoop(context.Background()), next); err != nil {
29 t.Fatalf("second Run: %v", err)
30 }
31
32 msgs := mp.Requests()[1].Messages
33 last := msgs[len(msgs)-1]
34 if last.Role != provider.RoleUser {
35 t.Fatalf("last message role = %v, want user", last.Role)
36 }
37 if !strings.HasPrefix(last.Content, "<"+interruptedRecoveryTag+">") || !strings.HasSuffix(last.Content, next) {
38 t.Fatalf("recovery block must precede the user text at the tail: %q", last.Content)
39 }
40 if !strings.Contains(last.Content, wantPrecedence) {
41 t.Fatalf("recovery block missing precedence clause: %q", last.Content)
42 }
43 if strings.Index(last.Content, wantPrecedence) > strings.Index(last.Content, "</"+interruptedRecoveryTag+">") {
44 t.Fatalf("precedence clause must sit inside the recovery block: %q", last.Content)
45 }
46 for _, m := range msgs[:len(msgs)-1] {
47 if strings.Contains(m.Content, interruptedRecoveryTag) {
48 t.Fatalf("recovery block leaked into the stable prefix: %+v", m)
49 }
50 }
51 }
52
52 lines GO