-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathcatalog.go
More file actions
148 lines (127 loc) · 3.65 KB
/
catalog.go
File metadata and controls
148 lines (127 loc) · 3.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package agent
import (
"fmt"
"strings"
"sync"
)
// StaticToolCatalog is the default in-memory implementation of ToolCatalog used by the runtime.
type StaticToolCatalog struct {
mu sync.RWMutex
tools map[string]Tool
specs map[string]ToolSpec
order []string
}
// NewStaticToolCatalog constructs a catalog seeded with the provided tools.
func NewStaticToolCatalog(tools []Tool) *StaticToolCatalog {
catalog := &StaticToolCatalog{
tools: make(map[string]Tool),
specs: make(map[string]ToolSpec),
}
for _, tool := range tools {
_ = catalog.Register(tool) // skip invalid entries silently to match legacy behaviour
}
return catalog
}
// Register adds a tool to the catalog using a lower-cased key. Duplicate names return an error.
func (c *StaticToolCatalog) Register(tool Tool) error {
if tool == nil {
return fmt.Errorf("tool is nil")
}
spec := tool.Spec()
key := strings.ToLower(strings.TrimSpace(spec.Name))
if key == "" {
return fmt.Errorf("tool name is empty")
}
c.mu.Lock()
defer c.mu.Unlock()
if _, exists := c.tools[key]; exists {
return fmt.Errorf("tool %s already registered", spec.Name)
}
c.tools[key] = tool
c.specs[key] = spec
c.order = append(c.order, key)
return nil
}
// Lookup returns the tool and its specification if present.
func (c *StaticToolCatalog) Lookup(name string) (Tool, ToolSpec, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
key := strings.ToLower(strings.TrimSpace(name))
tool, ok := c.tools[key]
if !ok {
return nil, ToolSpec{}, false
}
return tool, c.specs[key], true
}
// Specs returns a snapshot of the tool specifications in registration order.
func (c *StaticToolCatalog) Specs() []ToolSpec {
c.mu.RLock()
defer c.mu.RUnlock()
specs := make([]ToolSpec, 0, len(c.order))
for _, key := range c.order {
specs = append(specs, c.specs[key])
}
return specs
}
// Tools returns the registered tools in order.
func (c *StaticToolCatalog) Tools() []Tool {
c.mu.RLock()
defer c.mu.RUnlock()
tools := make([]Tool, 0, len(c.order))
for _, key := range c.order {
tools = append(tools, c.tools[key])
}
return tools
}
// StaticSubAgentDirectory is the default SubAgentDirectory implementation.
type StaticSubAgentDirectory struct {
mu sync.RWMutex
subagents map[string]SubAgent
order []string
}
// NewStaticSubAgentDirectory constructs a directory from the provided sub-agents.
func NewStaticSubAgentDirectory(subagents []SubAgent) *StaticSubAgentDirectory {
dir := &StaticSubAgentDirectory{
subagents: make(map[string]SubAgent),
}
for _, sa := range subagents {
_ = dir.Register(sa)
}
return dir
}
// Register adds a sub-agent to the directory. Duplicate names return an error.
func (d *StaticSubAgentDirectory) Register(subAgent SubAgent) error {
if subAgent == nil {
return fmt.Errorf("sub-agent is nil")
}
key := strings.ToLower(strings.TrimSpace(subAgent.Name()))
if key == "" {
return fmt.Errorf("sub-agent name is empty")
}
d.mu.Lock()
defer d.mu.Unlock()
if _, exists := d.subagents[key]; exists {
return fmt.Errorf("sub-agent %s already registered", subAgent.Name())
}
d.subagents[key] = subAgent
d.order = append(d.order, key)
return nil
}
// Lookup retrieves a sub-agent by name.
func (d *StaticSubAgentDirectory) Lookup(name string) (SubAgent, bool) {
d.mu.RLock()
defer d.mu.RUnlock()
key := strings.ToLower(strings.TrimSpace(name))
sa, ok := d.subagents[key]
return sa, ok
}
// All returns the registered sub-agents in registration order.
func (d *StaticSubAgentDirectory) All() []SubAgent {
d.mu.RLock()
defer d.mu.RUnlock()
subagents := make([]SubAgent, 0, len(d.order))
for _, key := range d.order {
subagents = append(subagents, d.subagents[key])
}
return subagents
}