From 8a8fe42f60c167545685029550ef170f316c7a7f Mon Sep 17 00:00:00 2001 From: Anton Bogdanovich <27antonb@gmail.com> Date: Wed, 6 May 2026 21:05:22 -0700 Subject: [PATCH] fix(tools): rebind discovery tools when cloning registries --- pkg/tools/registry.go | 9 ++++++++- pkg/tools/registry_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/pkg/tools/registry.go b/pkg/tools/registry.go index 0ff9293a3..a81e79d63 100644 --- a/pkg/tools/registry.go +++ b/pkg/tools/registry.go @@ -412,8 +412,15 @@ func (r *ToolRegistry) Clone() *ToolRegistry { mediaStore: r.mediaStore, } for name, entry := range r.tools { + tool := entry.Tool + switch t := entry.Tool.(type) { + case *RegexSearchTool: + tool = NewRegexSearchTool(clone, t.ttl, t.maxSearchResults) + case *BM25SearchTool: + tool = NewBM25SearchTool(clone, t.ttl, t.maxSearchResults) + } clone.tools[name] = &ToolEntry{ - Tool: entry.Tool, + Tool: tool, IsCore: entry.IsCore, TTL: entry.TTL, } diff --git a/pkg/tools/registry_test.go b/pkg/tools/registry_test.go index eac96382f..f98ad6574 100644 --- a/pkg/tools/registry_test.go +++ b/pkg/tools/registry_test.go @@ -515,6 +515,32 @@ func TestToolRegistry_Clone_PreservesTTLValue(t *testing.T) { } } +func TestToolRegistry_Clone_RebindsDiscoveryToolsToClone(t *testing.T) { + parent := NewToolRegistry() + parent.RegisterHidden(newMockTool("mcp_research", "deep research report tool")) + parent.Register(NewBM25SearchTool(parent, 3, 5)) + + clone := parent.Clone() + + searchTool, ok := clone.Get("tool_search_tool_bm25") + if !ok { + t.Fatal("expected cloned registry to expose BM25 search tool") + } + result := searchTool.Execute(context.Background(), map[string]any{ + "query": "deep research", + }) + if result == nil || result.IsError { + t.Fatalf("search result error: %+v", result) + } + + if _, ok := clone.Get("mcp_research"); !ok { + t.Fatal("expected search in clone to promote hidden tool in clone") + } + if _, ok := parent.Get("mcp_research"); ok { + t.Fatal("expected search in clone not to promote hidden tool in parent") + } +} + func TestToolRegistry_ConcurrentAccess(t *testing.T) { r := NewToolRegistry() var wg sync.WaitGroup