summaryrefslogtreecommitdiffhomepage
path: root/spec/dispatch/tools/registry_spec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'spec/dispatch/tools/registry_spec.rb')
-rw-r--r--spec/dispatch/tools/registry_spec.rb227
1 files changed, 227 insertions, 0 deletions
diff --git a/spec/dispatch/tools/registry_spec.rb b/spec/dispatch/tools/registry_spec.rb
new file mode 100644
index 0000000..fc7332c
--- /dev/null
+++ b/spec/dispatch/tools/registry_spec.rb
@@ -0,0 +1,227 @@
+# frozen_string_literal: true
+
+RSpec.describe Dispatch::Tools::Registry do
+ let(:read_file_tool) do
+ Dispatch::Tools::Definition.new(
+ name: "read_file",
+ description: "Read the contents of a file",
+ parameters: {
+ type: "object",
+ properties: {
+ path: { type: "string" }
+ },
+ required: ["path"]
+ }
+ ) { |params, _context| Dispatch::Tools::Result.success(output: "contents of #{params[:path]}") }
+ end
+
+ let(:write_file_tool) do
+ Dispatch::Tools::Definition.new(
+ name: "write_file",
+ description: "Write contents to a file",
+ parameters: {
+ type: "object",
+ properties: {
+ path: { type: "string" },
+ content: { type: "string" }
+ },
+ required: %w[path content]
+ }
+ ) { |_params, _context| Dispatch::Tools::Result.success(output: "written") }
+ end
+
+ let(:delete_file_tool) do
+ Dispatch::Tools::Definition.new(
+ name: "delete_file",
+ description: "Delete a file",
+ parameters: {
+ type: "object",
+ properties: {
+ path: { type: "string" }
+ },
+ required: ["path"]
+ }
+ ) { |_params, _context| Dispatch::Tools::Result.success(output: "deleted") }
+ end
+
+ let(:registry) { described_class.new }
+
+ describe "#register" do
+ it "adds a tool definition to the registry" do
+ registry.register(read_file_tool)
+
+ expect(registry.has?("read_file")).to be true
+ end
+
+ it "returns self for chaining" do
+ result = registry.register(read_file_tool)
+
+ expect(result).to be(registry)
+ end
+
+ it "supports chaining multiple registrations" do
+ registry.register(read_file_tool).register(write_file_tool)
+
+ expect(registry.has?("read_file")).to be true
+ expect(registry.has?("write_file")).to be true
+ end
+
+ it "raises DuplicateToolError when registering a tool with the same name" do
+ registry.register(read_file_tool)
+
+ duplicate_tool = Dispatch::Tools::Definition.new(
+ name: "read_file",
+ description: "Another read file",
+ parameters: { type: "object", properties: {}, required: [] }
+ ) { |_params, _context| Dispatch::Tools::Result.success(output: "dupe") }
+
+ expect { registry.register(duplicate_tool) }.to raise_error(Dispatch::Tools::DuplicateToolError)
+ end
+ end
+
+ describe "#get" do
+ before { registry.register(read_file_tool) }
+
+ it "returns the tool definition by name" do
+ tool = registry.get("read_file")
+
+ expect(tool).to be(read_file_tool)
+ end
+
+ it "raises ToolNotFoundError for unknown tool name" do
+ expect { registry.get("nonexistent") }.to raise_error(Dispatch::Tools::ToolNotFoundError)
+ end
+ end
+
+ describe "#has?" do
+ it "returns true when the tool is registered" do
+ registry.register(read_file_tool)
+
+ expect(registry.has?("read_file")).to be true
+ end
+
+ it "returns false when the tool is not registered" do
+ expect(registry.has?("read_file")).to be false
+ end
+ end
+
+ describe "#tools" do
+ it "returns an empty array when no tools are registered" do
+ expect(registry.tools).to eq([])
+ end
+
+ it "returns all registered tool definitions" do
+ registry.register(read_file_tool).register(write_file_tool)
+
+ expect(registry.tools).to contain_exactly(read_file_tool, write_file_tool)
+ end
+ end
+
+ describe "#tool_names" do
+ it "returns an empty array when no tools are registered" do
+ expect(registry.tool_names).to eq([])
+ end
+
+ it "returns all registered tool names as strings" do
+ registry.register(read_file_tool).register(write_file_tool)
+
+ expect(registry.tool_names).to contain_exactly("read_file", "write_file")
+ end
+ end
+
+ describe "#to_a" do
+ it "returns an empty array when no tools are registered" do
+ expect(registry.to_a).to eq([])
+ end
+
+ it "returns an array of hashes with name, description, and parameters" do
+ registry.register(read_file_tool)
+
+ result = registry.to_a
+
+ expect(result).to be_an(Array)
+ expect(result.size).to eq(1)
+ expect(result.first).to eq({
+ name: "read_file",
+ description: "Read the contents of a file",
+ parameters: {
+ type: "object",
+ properties: {
+ path: { type: "string" }
+ },
+ required: ["path"]
+ }
+ })
+ end
+
+ it "returns plain hashes, not structs" do
+ registry.register(read_file_tool)
+
+ registry.to_a.each do |entry|
+ expect(entry).to be_a(Hash)
+ end
+ end
+
+ it "includes all registered tools" do
+ registry.register(read_file_tool).register(write_file_tool)
+
+ names = registry.to_a.map { |h| h[:name] }
+
+ expect(names).to contain_exactly("read_file", "write_file")
+ end
+ end
+
+ describe "#subset" do
+ before do
+ registry.register(read_file_tool).register(write_file_tool).register(delete_file_tool)
+ end
+
+ it "returns a new Registry containing only the specified tools" do
+ sub = registry.subset("read_file", "write_file")
+
+ expect(sub).to be_a(described_class)
+ expect(sub.tool_names).to contain_exactly("read_file", "write_file")
+ end
+
+ it "does not include tools not specified" do
+ sub = registry.subset("read_file")
+
+ expect(sub.has?("write_file")).to be false
+ expect(sub.has?("delete_file")).to be false
+ end
+
+ it "returns a different registry instance" do
+ sub = registry.subset("read_file")
+
+ expect(sub).not_to be(registry)
+ end
+
+ it "raises ToolNotFoundError when a requested name is not found" do
+ expect { registry.subset("read_file", "nonexistent") }.to raise_error(Dispatch::Tools::ToolNotFoundError)
+ end
+ end
+
+ describe "#size" do
+ it "returns 0 for an empty registry" do
+ expect(registry.size).to eq(0)
+ end
+
+ it "returns the number of registered tools" do
+ registry.register(read_file_tool).register(write_file_tool)
+
+ expect(registry.size).to eq(2)
+ end
+ end
+
+ describe "#empty?" do
+ it "returns true when no tools are registered" do
+ expect(registry.empty?).to be true
+ end
+
+ it "returns false when tools are registered" do
+ registry.register(read_file_tool)
+
+ expect(registry.empty?).to be false
+ end
+ end
+end