返回 DeepSeek-Reasonix
subagent_effort_inherit_test.go
根目录 / internal / boot / subagent_effort_inherit_test.go
1 package boot
2
3 import (
4 "context"
5 "errors"
6 "strings"
7 "sync"
8 "testing"
9
10 "reasonix/internal/config"
11 "reasonix/internal/event"
12 )
13
14 func undeclaredEffortConfig() *config.Config {
15 cfg := config.Default()
16 cfg.DefaultModel = "custom/some-model"
17 cfg.Agent.PlannerModel = ""
18 cfg.Providers = []config.ProviderEntry{{Name: "custom", Kind: "openai", BaseURL: "https://example.com/v1", Model: "some-model"}}
19 cfg.Agent.SubagentEffort = "max"
20 return cfg
21 }
22
23 func TestInheritedGlobalSubagentEffortYieldsToExecutionModel(t *testing.T) {
24 cfg := undeclaredEffortConfig()
25 if err := preflightRoleReasoning(cfg, Options{}, nil, false); err != nil {
26 t.Fatalf("inherited agent.subagent_effort blocked assembly: %v", err)
27 }
28 entry, ok := cfg.ResolveModel(cfg.DefaultModel)
29 if !ok {
30 t.Fatal("execution model does not resolve")
31 }
32 if effort, dropped := inheritedSubagentEffort(cfg, entry); effort != "" || dropped != "max" {
33 t.Fatalf("inheritedSubagentEffort = (%q, %q), want (\"\", \"max\")", effort, dropped)
34 }
35 if cfg.Agent.SubagentEffort != "max" {
36 t.Fatal("preflight rewrote the configured agent.subagent_effort")
37 }
38 }
39
40 func TestExplicitSubagentEffortsStayStrict(t *testing.T) {
41 cfg := undeclaredEffortConfig()
42 cfg.Agent.SubagentEfforts = map[string]string{"task": "max"}
43 var role *RoleReasoningError
44 if err := preflightRoleReasoning(cfg, Options{}, nil, false); !errors.As(err, &role) || role.Source != "agent.subagent_efforts.task" {
45 t.Fatalf("per-profile effort must stay strict, got %v", err)
46 }
47
48 cfg = undeclaredEffortConfig()
49 cfg.Agent.SubagentModel = "custom/some-model"
50 if err := preflightRoleReasoning(cfg, Options{}, nil, false); !errors.As(err, &role) || role.Source != "agent.subagent_effort" {
51 t.Fatalf("effort paired with agent.subagent_model must stay strict, got %v", err)
52 }
53 }
54
55 func TestInheritedGlobalSubagentEffortKeptWhenModelDeclaresIt(t *testing.T) {
56 cfg := undeclaredEffortConfig()
57 cfg.Providers[0].SupportedEfforts = []string{"high", "max"}
58 entry, _ := cfg.ResolveModel(cfg.DefaultModel)
59 if effort, dropped := inheritedSubagentEffort(cfg, entry); effort != "max" || dropped != "" {
60 t.Fatalf("inheritedSubagentEffort = (%q, %q), want (\"max\", \"\")", effort, dropped)
61 }
62 }
63
64 type noticeCollector struct {
65 mu sync.Mutex
66 texts []string
67 }
68
69 func (c *noticeCollector) Emit(e event.Event) {
70 if e.Kind != event.Notice {
71 return
72 }
73 c.mu.Lock()
74 defer c.mu.Unlock()
75 c.texts = append(c.texts, e.Text+" "+e.Detail)
76 }
77
78 func TestBuildNamesTheInheritedSubagentEffortItDropped(t *testing.T) {
79 isolateConfigHome(t)
80 root := robustTempDir(t)
81 sink := &noticeCollector{}
82 ctrl, err := Build(context.Background(), Options{WorkspaceRoot: root, ConfigSnapshot: undeclaredEffortConfig(), Sink: sink})
83 if err != nil {
84 t.Fatalf("Build: %v", err)
85 }
86 defer ctrl.Close()
87 sink.mu.Lock()
88 defer sink.mu.Unlock()
89 for _, text := range sink.texts {
90 if strings.Contains(text, "agent.subagent_effort") && strings.Contains(text, `"max"`) {
91 return
92 }
93 }
94 t.Fatalf("no notice names the dropped agent.subagent_effort: %q", sink.texts)
95 }
96
96 lines GO