返回 DeepSeek-Reasonix
effect_message_ids_test.go
根目录 / internal / boot / effect_message_ids_test.go
1 package boot
2
3 import (
4 "context"
5 "testing"
6
7 "reasonix/internal/ablation"
8 "reasonix/internal/event"
9 "reasonix/internal/provider"
10 )
11
12 // withoutMessageIDs strips the per-session local ids so two independent runs
13 // can be compared on provider-visible content.
14 func withoutMessageIDs(msgs []provider.Message) []provider.Message {
15 out := append([]provider.Message(nil), msgs...)
16 for i := range out {
17 out[i].ID = ""
18 }
19 return out
20 }
21
22 // TestEffectMessageIDsPersistThroughRealBuild pins the identity contract at
23 // both boundaries the real stack crosses: every message handed to the provider
24 // carries an id, and the transcript reloaded from disk carries the same ids.
25 func TestEffectMessageIDsPersistThroughRealBuild(t *testing.T) {
26 isolateConfigHome(t)
27 dir := robustTempDir(t)
28 t.Chdir(dir)
29
30 rec := &effectRecordingProvider{}
31 provider.Register("boot-effect-message-ids", func(provider.Config) (provider.Provider, error) {
32 return rec, nil
33 })
34 writeFile(t, dir, "reasonix.toml", `
35 default_model = "test-model"
36
37 [agent]
38 system_prompt = "BASE"
39
40 [environment]
41 enabled = false
42
43 [[providers]]
44 name = "test-model"
45 kind = "boot-effect-message-ids"
46 model = "x"
47 `)
48 ctrl, err := Build(context.Background(), withTestSession(t, Options{Sink: event.Discard, Ablation: ablation.Set{}}))
49 if err != nil {
50 t.Fatalf("Build: %v", err)
51 }
52 ctrl.EnsureSessionPath()
53 if err := ctrl.Run(context.Background(), "reply ok"); err != nil {
54 t.Fatalf("Run: %v", err)
55 }
56 service, runtime, ok := ctrl.SessionBinding()
57 if !ok {
58 t.Fatal("controller did not bind a v3 session")
59 }
60 ref := runtime.Ref()
61 ctrl.Close()
62 reqs := rec.requests()
63 if len(reqs) == 0 {
64 t.Fatal("no request reached the provider boundary")
65 }
66 sent := make(map[string]string)
67 for _, m := range reqs[len(reqs)-1].Messages {
68 if m.ID == "" {
69 t.Fatalf("message %q reached the provider boundary without an id", m.Content)
70 }
71 sent[m.ID] = m.Content
72 }
73 loaded, err := service.Query().History(context.Background(), ref)
74 if err != nil {
75 t.Fatalf("cold v3 History(%s): %v", ref.SessionID, err)
76 }
77 matched := 0
78 for _, m := range loaded {
79 if m.ID == "" {
80 t.Fatalf("persisted message %q lost its id", m.Content)
81 }
82 if content, ok := sent[m.ID]; ok {
83 if content != m.Content {
84 t.Fatalf("id %s maps to %q in the request but %q on disk", m.ID, content, m.Content)
85 }
86 matched++
87 }
88 }
89 if matched == 0 {
90 t.Fatalf("no request message id survived the save/load round trip (sent %d, loaded %d)", len(sent), len(loaded))
91 }
92 }
93
93 lines GO