返回 DeepSeek-Reasonix
skill_disclosure_test.go
根目录 / internal / boot / skill_disclosure_test.go
1 package boot
2
3 import (
4 "context"
5 "fmt"
6 "reflect"
7 "strings"
8 "testing"
9
10 "reasonix/internal/agent/testutil"
11 "reasonix/internal/event"
12 "reasonix/internal/provider"
13 )
14
15 func TestSkillDiscoveryAndEmbeddedReferencesThroughBoot(t *testing.T) {
16 isolateConfigHome(t)
17 dir := robustTempDir(t)
18 t.Chdir(dir)
19 writeFile(t, dir, "reasonix.toml", `
20 default_model = "test-model"
21 [agent]
22 system_prompt = "BASE"
23 [[providers]]
24 name = "test-model"
25 kind = "boot-token-profile-test"
26 model = "x"
27 `)
28 approveWorkspace(t, dir)
29 for i := range 100 {
30 name := fmt.Sprintf("a-%03d-%s", i, strings.Repeat("x", 45))
31 writeFile(t, dir, ".agents/skills/"+name+"/SKILL.md",
32 "---\nname: "+name+"\ndescription: Common fixture operation\n---\nFixture body")
33 }
34 const target = "zzz-rare-diagnostic"
35 writeFile(t, dir, ".agents/skills/"+target+"/SKILL.md",
36 "---\nname: "+target+"\ndescription: Diagnose rare service faults\n---\nRARE_BODY_ON_DEMAND")
37 registerBootTokenProfileTestProvider()
38 prov := testutil.NewMock("skill-disclosure",
39 testutil.Turn{ToolCalls: []provider.ToolCall{{ID: "find", Name: "use_capability",
40 Arguments: `{"action":"search","query":"zzz-rare-diagnostic"}`}}},
41 testutil.Turn{ToolCalls: []provider.ToolCall{{ID: "load", Name: "use_capability",
42 Arguments: `{"action":"call","capability_id":"skill:zzz-rare-diagnostic","arguments":{}}`}}},
43 testutil.Turn{ToolCalls: []provider.ToolCall{{ID: "guide", Name: "use_capability",
44 Arguments: `{"action":"call","capability_id":"tool:read_skill","arguments":{"name":"reasonix-guide"}}`}}},
45 testutil.Turn{ToolCalls: []provider.ToolCall{{ID: "page", Name: "use_capability",
46 Arguments: `{"action":"call","capability_id":"tool:read_skill","arguments":{"name":"reasonix-guide","reference":"references/hooks.md"}}`}}},
47 testutil.Turn{Text: "done"},
48 )
49 setBootTokenProfileTestProvider(t, prov)
50 ctrl, err := Build(context.Background(), Options{Sink: event.Discard})
51 if err != nil {
52 t.Fatal(err)
53 }
54 defer ctrl.Close()
55 if err := ctrl.Run(context.Background(), "Find the rare diagnostic and consult hook matching guidance."); err != nil {
56 t.Fatal(err)
57 }
58 reqs := mainConversationRequests(prov.Requests())
59 if len(reqs) < 5 {
60 t.Fatalf("request count = %d, want full discovery/read sequence", len(reqs))
61 }
62 initial := sessionContextMessage(reqs[0].Messages)
63 if strings.Contains(initial, target) || !strings.Contains(initial, "more skills") {
64 t.Fatalf("fixture did not exercise an omitted catalog entry: %s", initial)
65 }
66 for _, req := range reqs {
67 if systemMessage(req.Messages) != systemMessage(reqs[0].Messages) ||
68 !reflect.DeepEqual(req.Tools, reqs[0].Tools) {
69 t.Fatal("skill discovery/read changed the provider prefix or schemas")
70 }
71 }
72 var outputs []string
73 for _, msg := range ctrl.History() {
74 if msg.Role == provider.RoleTool {
75 outputs = append(outputs, msg.Content)
76 }
77 }
78 if len(outputs) != 4 {
79 t.Fatalf("tool outputs = %d, want 4", len(outputs))
80 }
81 if !strings.Contains(outputs[0], "skill:"+target) ||
82 !strings.Contains(outputs[1], "RARE_BODY_ON_DEMAND") {
83 t.Fatalf("omitted skill not discoverable/invocable: %v", outputs[:2])
84 }
85 if strings.Contains(outputs[2], "hook.invalid_matcher") ||
86 !strings.Contains(outputs[3], "hook.invalid_matcher") {
87 t.Fatalf("reference page not loaded only on demand: %v", outputs[2:])
88 }
89 }
90
90 lines GO