Skip to content

Commit 99f6f6c

Browse files
authored
chore: sync submodules to latest main + fix tool registry race (#40)
* chore(deps): bump eyrie/yaad/tok submodules to latest main * fix(tool): eliminate race between Registry.Register and EyrieTools
1 parent 5392775 commit 99f6f6c

4 files changed

Lines changed: 17 additions & 3 deletions

File tree

external/eyrie

Submodule eyrie updated from 25a5d20 to 3e832f4

internal/tool/tool.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"fmt"
77
"os"
88
"strings"
9+
"sync"
910

1011
"github.com/GrayCodeAI/eyrie/client"
1112
"github.com/GrayCodeAI/hawk/internal/intelligence/memory"
@@ -145,6 +146,7 @@ func canonicalForReadOnly(name string) string {
145146

146147
// Registry holds all registered tools.
147148
type Registry struct {
149+
mu sync.RWMutex
148150
tools map[string]Tool
149151
primary []Tool
150152
}
@@ -171,19 +173,25 @@ func NewRegistry(tools ...Tool) *Registry {
171173

172174
// Get returns a tool by name.
173175
func (r *Registry) Get(name string) (Tool, bool) {
176+
r.mu.RLock()
177+
defer r.mu.RUnlock()
174178
t, ok := r.tools[name]
175179
return t, ok
176180
}
177181

178182
// PrimaryTools returns the model-visible tools registered in this registry.
179183
func (r *Registry) PrimaryTools() []Tool {
184+
r.mu.RLock()
185+
defer r.mu.RUnlock()
180186
out := make([]Tool, len(r.primary))
181187
copy(out, r.primary)
182188
return out
183189
}
184190

185191
// Filter returns a new Registry containing only tools whose names are in the allowlist.
186192
func (r *Registry) Filter(allow []string) *Registry {
193+
r.mu.RLock()
194+
defer r.mu.RUnlock()
187195
set := make(map[string]bool, len(allow))
188196
for _, name := range allow {
189197
set[name] = true
@@ -199,6 +207,8 @@ func (r *Registry) Filter(allow []string) *Registry {
199207

200208
// EyrieTools converts all tools to eyrie tool definitions for the API.
201209
func (r *Registry) EyrieTools() []client.EyrieTool {
210+
r.mu.RLock()
211+
defer r.mu.RUnlock()
202212
out := make([]client.EyrieTool, 0, len(r.primary))
203213
for _, t := range r.primary {
204214
out = append(out, client.EyrieTool{
@@ -212,6 +222,8 @@ func (r *Registry) EyrieTools() []client.EyrieTool {
212222

213223
// Execute runs a tool by name with the given JSON input.
214224
func (r *Registry) Execute(ctx context.Context, name string, input json.RawMessage) (string, error) {
225+
r.mu.RLock()
226+
defer r.mu.RUnlock()
215227
t, ok := r.tools[name]
216228
if !ok {
217229
return "", fmt.Errorf("unknown tool: %s", name)
@@ -222,6 +234,8 @@ func (r *Registry) Execute(ctx context.Context, name string, input json.RawMessa
222234
// Register adds a tool to the registry after creation.
223235
// Returns error if a tool with the same name already exists (unless it's an alias).
224236
func (r *Registry) Register(t Tool) error {
237+
r.mu.Lock()
238+
defer r.mu.Unlock()
225239
if _, exists := r.tools[t.Name()]; exists {
226240
return fmt.Errorf("tool %q already registered", t.Name())
227241
}

0 commit comments

Comments
 (0)