diff --git a/external/eyrie b/external/eyrie index 25a5d200..3e832f42 160000 --- a/external/eyrie +++ b/external/eyrie @@ -1 +1 @@ -Subproject commit 25a5d200db9300ddb4f619066531a2f68de5e952 +Subproject commit 3e832f42fc0f5fcbe225d19ac2524ced2245ebe0 diff --git a/external/tok b/external/tok index 138f7e42..5df7ee7a 160000 --- a/external/tok +++ b/external/tok @@ -1 +1 @@ -Subproject commit 138f7e42f958e4f29beb6fdc73a749d6c0b9a007 +Subproject commit 5df7ee7ad745309015d13a613a7226b635876bfd diff --git a/external/yaad b/external/yaad index df99a3a6..c846f014 160000 --- a/external/yaad +++ b/external/yaad @@ -1 +1 @@ -Subproject commit df99a3a675e427de5e709c48b344e29434614770 +Subproject commit c846f014965d8f94f9c1fa1a26cc7d29497994be diff --git a/internal/tool/tool.go b/internal/tool/tool.go index 7bde0def..2b48eace 100644 --- a/internal/tool/tool.go +++ b/internal/tool/tool.go @@ -6,6 +6,7 @@ import ( "fmt" "os" "strings" + "sync" "github.com/GrayCodeAI/eyrie/client" "github.com/GrayCodeAI/hawk/internal/intelligence/memory" @@ -145,6 +146,7 @@ func canonicalForReadOnly(name string) string { // Registry holds all registered tools. type Registry struct { + mu sync.RWMutex tools map[string]Tool primary []Tool } @@ -171,12 +173,16 @@ func NewRegistry(tools ...Tool) *Registry { // Get returns a tool by name. func (r *Registry) Get(name string) (Tool, bool) { + r.mu.RLock() + defer r.mu.RUnlock() t, ok := r.tools[name] return t, ok } // PrimaryTools returns the model-visible tools registered in this registry. func (r *Registry) PrimaryTools() []Tool { + r.mu.RLock() + defer r.mu.RUnlock() out := make([]Tool, len(r.primary)) copy(out, r.primary) return out @@ -184,6 +190,8 @@ func (r *Registry) PrimaryTools() []Tool { // Filter returns a new Registry containing only tools whose names are in the allowlist. func (r *Registry) Filter(allow []string) *Registry { + r.mu.RLock() + defer r.mu.RUnlock() set := make(map[string]bool, len(allow)) for _, name := range allow { set[name] = true @@ -199,6 +207,8 @@ func (r *Registry) Filter(allow []string) *Registry { // EyrieTools converts all tools to eyrie tool definitions for the API. func (r *Registry) EyrieTools() []client.EyrieTool { + r.mu.RLock() + defer r.mu.RUnlock() out := make([]client.EyrieTool, 0, len(r.primary)) for _, t := range r.primary { out = append(out, client.EyrieTool{ @@ -212,6 +222,8 @@ func (r *Registry) EyrieTools() []client.EyrieTool { // Execute runs a tool by name with the given JSON input. func (r *Registry) Execute(ctx context.Context, name string, input json.RawMessage) (string, error) { + r.mu.RLock() + defer r.mu.RUnlock() t, ok := r.tools[name] if !ok { return "", fmt.Errorf("unknown tool: %s", name) @@ -222,6 +234,8 @@ func (r *Registry) Execute(ctx context.Context, name string, input json.RawMessa // Register adds a tool to the registry after creation. // Returns error if a tool with the same name already exists (unless it's an alias). func (r *Registry) Register(t Tool) error { + r.mu.Lock() + defer r.mu.Unlock() if _, exists := r.tools[t.Name()]; exists { return fmt.Errorf("tool %q already registered", t.Name()) }