返回 DeepSeek-Reasonix
skill.go
根目录 / internal / control / skill.go
1 package control
2
3 import "reasonix/internal/skill"
4
5 // skillSet owns the session's discovered skills: the enabled subset surfaced to
6 // the model, the full set (including config-disabled ones) for management
7 // surfaces, and the optional reloadable stores that supersede the
8 // construction-time snapshots. It is the skills slice of the Capabilities concern
9 // (alongside mcpManager).
10 //
11 // No lock: every field is set once at construction and only read thereafter.
12 // Skills are discovered at boot and never mutated in place — SetSkillEnabled
13 // persists a config preference and relies on a controller rebuild to take effect.
14 type skillSet struct {
15 enabled []skill.Skill // discovered + enabled skills (the live store supersedes when set)
16 all []skill.Skill // every discoverable skill, including config-disabled ones
17 store *skill.Store // reloadable enabled-skill store; nil falls back to enabled
18 allStore *skill.Store // reloadable all-skill store; nil falls back to all/enabled
19 }
20
21 func newSkillSet(enabled, all []skill.Skill, store, allStore *skill.Store) skillSet {
22 return skillSet{enabled: enabled, all: all, store: store, allStore: allStore}
23 }
24
25 // list returns the enabled skills, preferring the live store.
26 func (s *skillSet) list() []skill.Skill {
27 if s.store != nil {
28 return s.store.List()
29 }
30 return s.enabled
31 }
32
33 func (s *skillSet) slashList() []skill.Skill {
34 if s.store != nil {
35 return s.store.SlashList()
36 }
37 return skill.VisibleSlashSkills(s.enabled)
38 }
39
40 // listAll returns every discoverable skill (including disabled), preferring the
41 // live store, for management surfaces that re-enable a hidden skill.
42 func (s *skillSet) listAll() []skill.Skill {
43 if s.allStore != nil {
44 return s.allStore.List()
45 }
46 if len(s.all) > 0 {
47 return s.all
48 }
49 return s.enabled
50 }
51
52 func (s *skillSet) bySlashName(name string) (skill.Skill, bool) {
53 if s.store != nil {
54 return s.store.ReadSlash(name)
55 }
56 return skill.ResolveSlashSkill(s.enabled, name)
57 }
58
59 func (s *skillSet) prepare(sk skill.Skill) skill.Skill {
60 if s.store != nil {
61 return s.store.Prepare(sk)
62 }
63 return sk
64 }
65
66 func (s *skillSet) render(sk skill.Skill, args string) string {
67 if s.store != nil {
68 return s.store.Render(sk, args)
69 }
70 return skill.Render(sk, args)
71 }
72
73 // discovered returns the construction-time enabled snapshot (not the live store),
74 // for the /skills listing which reflects what was discovered at boot.
75 func (s *skillSet) discovered() []skill.Skill {
76 return s.enabled
77 }
78
79 // writer returns the live store to use for authoring (create/delete), preferring
80 // allStore since management surfaces must resolve disabled and builtin skills
81 // too (e.g. a create-time name-collision check). nil when this session has no
82 // reloadable store (e.g. a construction-time-only test snapshot).
83 func (s *skillSet) writer() *skill.Store {
84 if s.allStore != nil {
85 return s.allStore
86 }
87 return s.store
88 }
89
89 lines GO