Describe the bug
Toolset documents that it "implements the collection interface (__iter__, __contains__, __len__, __getitem__), making it behave like a list of Tools." Toolset.__getitem__ delegates to a real list (self.tools[index]), so negative indices work as expected (e.g. toolset[-1] returns the last tool).
However, when you combine two Toolsets with +, the result is a _ToolsetWrapper (haystack/tools/toolset.py), whose __getitem__ only does a forward enumerate scan over self and never matches a negative index:
def __getitem__(self, index: int) -> Tool:
"""Get a tool by index across all toolsets."""
# Leverage iteration instead of manual index tracking
for i, tool in enumerate(self):
if i == index:
return tool
raise IndexError("ToolsetWrapper index out of range")
So combined[-1] raises IndexError instead of returning the last tool, breaking the documented "behaves like a list" contract as soon as two toolsets are combined.
Error message
IndexError: ToolsetWrapper index out of range
Expected behavior
_ToolsetWrapper.__getitem__ should support negative indices the same way a plain Toolset/list does, so indexing behaves consistently whether or not the Toolset came from combining others with +.
To Reproduce
from haystack.tools import Toolset, create_tool_from_function
def addition_tool(a: int, b: int) -> int:
return a + b
def multiplication_tool(a: int, b: int) -> int:
return a * b
add_tool = create_tool_from_function(function=addition_tool, name="addition_tool", description="adds two ints")
mult_tool = create_tool_from_function(function=multiplication_tool, name="multiplication_tool", description="multiplies two ints")
combined = Toolset([add_tool]) + Toolset([mult_tool]) # -> _ToolsetWrapper
print(combined[0].name) # "addition_tool" - fine
print(combined[1].name) # "multiplication_tool" - fine
print(combined[-1].name) # IndexError: ToolsetWrapper index out of range
# For comparison, a plain Toolset supports this fine:
print(Toolset([add_tool, mult_tool])[-1].name) # "multiplication_tool"
Additional context
I'd like to fix _ToolsetWrapper.__getitem__ to support negative indices and add a regression test, then submit a PR.
System:
- OS: Windows
- Haystack version: main
Describe the bug
Toolsetdocuments that it "implements the collection interface (__iter__,__contains__,__len__,__getitem__), making it behave like a list of Tools."Toolset.__getitem__delegates to a real list (self.tools[index]), so negative indices work as expected (e.g.toolset[-1]returns the last tool).However, when you combine two
Toolsets with+, the result is a_ToolsetWrapper(haystack/tools/toolset.py), whose__getitem__only does a forwardenumeratescan overselfand never matches a negative index:So
combined[-1]raisesIndexErrorinstead of returning the last tool, breaking the documented "behaves like a list" contract as soon as two toolsets are combined.Error message
Expected behavior
_ToolsetWrapper.__getitem__should support negative indices the same way a plainToolset/list does, so indexing behaves consistently whether or not theToolsetcame from combining others with+.To Reproduce
Additional context
I'd like to fix
_ToolsetWrapper.__getitem__to support negative indices and add a regression test, then submit a PR.System: