-
Notifications
You must be signed in to change notification settings - Fork 38
Refactor ToolDefinition architecture to use subclass pattern for all tools #971
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
f2008ca
38625a6
eb569b9
5de1644
097b50d
085395c
75a7484
0f17f17
43b074c
414a03f
1894612
874b2db
95a7a1f
b99401f
8290cda
3bbfe6d
3ef13a4
d3667ab
3d362b7
1d3e6b4
0febb54
4acf30d
3522c71
6172da0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -26,8 +26,8 @@ | |
| ) | ||
| from openhands.tools.execute_bash import ( | ||
| BashExecutor, | ||
| BashTool, | ||
| ExecuteBashAction, | ||
| execute_bash_tool, | ||
| ) | ||
| from openhands.tools.file_editor import FileEditorTool | ||
|
|
||
|
|
@@ -115,6 +115,42 @@ def __call__(self, action: GrepAction, conversation=None) -> GrepObservation: # | |
| * When you are doing an open ended search that may require multiple rounds of globbing and grepping, use the Agent tool instead | ||
| """ # noqa: E501 | ||
|
|
||
|
|
||
| # --- Tool Definition --- | ||
|
|
||
|
|
||
| class GrepTool(ToolDefinition[GrepAction, GrepObservation]): | ||
| """A custom grep tool that searches file contents using regular expressions.""" | ||
|
|
||
| @classmethod | ||
| def create( | ||
| cls, conv_state, bash_executor: BashExecutor | None = None | ||
| ) -> Sequence[ToolDefinition]: | ||
| """Create GrepTool instance with a GrepExecutor. | ||
|
|
||
| Args: | ||
| conv_state: Conversation state to get working directory from. | ||
| bash_executor: Optional bash executor to reuse. If not provided, | ||
| a new one will be created. | ||
|
|
||
| Returns: | ||
| A sequence containing a single GrepTool instance. | ||
| """ | ||
| if bash_executor is None: | ||
| bash_executor = BashExecutor(working_dir=conv_state.workspace.working_dir) | ||
| grep_executor = GrepExecutor(bash_executor) | ||
|
|
||
| return [ | ||
| cls( | ||
| name="grep", | ||
| description=_GREP_DESCRIPTION, | ||
| action_type=GrepAction, | ||
| observation_type=GrepObservation, | ||
| executor=grep_executor, | ||
| ) | ||
| ] | ||
|
|
||
|
|
||
| # Configure LLM | ||
| api_key = os.getenv("LLM_API_KEY") | ||
| assert api_key is not None, "LLM_API_KEY environment variable is not set." | ||
|
|
@@ -135,16 +171,11 @@ def _make_bash_and_grep_tools(conv_state) -> list[ToolDefinition]: | |
| """Create execute_bash and custom grep tools sharing one executor.""" | ||
|
|
||
| bash_executor = BashExecutor(working_dir=conv_state.workspace.working_dir) | ||
| bash_tool = execute_bash_tool.set_executor(executor=bash_executor) | ||
|
|
||
| grep_executor = GrepExecutor(bash_executor) | ||
| grep_tool = ToolDefinition( | ||
| name="grep", | ||
| description=_GREP_DESCRIPTION, | ||
| action_type=GrepAction, | ||
| observation_type=GrepObservation, | ||
| executor=grep_executor, | ||
| ) | ||
| # bash_tool = execute_bash_tool.set_executor(executor=bash_executor) | ||
| bash_tool = BashTool.create(conv_state, executor=bash_executor)[0] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm I guess getting having to pull the tool out of the list is kinda annoying - any thoughts on how we can make it more convenient? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. :( i think we probably don't have a good way to do this since we want to support the idea of "ToolSet" There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry, I don't understand 😢 Doesn't one method create the Tool, while a ToolSet puts together a sequence of Tools? 🤔 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah irrc ToolSet (which returns a list of tools) was a subclass of ToolDefinition, so base class will need return a list instead one thing -- hence we need this "[0]" pattern |
||
|
|
||
| # Use the GrepTool.create() method with shared bash_executor | ||
| grep_tool = GrepTool.create(conv_state, bash_executor=bash_executor)[0] | ||
|
|
||
| return [bash_tool, grep_tool] | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: could we add some typing and standardize to using
conversationinstead ofconvonot blocking a separate PR making extraneous changes would be ideal
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good! @OpenHands please create a separate PR and add
conv_state: ConversationStateto the.createofToolDefinition(base class) and fix all downstream usage of it and get tests to pass as wellThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm on it! xingyaoww can track my progress at all-hands.dev
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary
I've successfully completed the request to add
conv_state: ConversationStateparameter toToolDefinition.create()and update all downstream usage in a separate PR.✅ Completed Tasks
1. Created Separate Branch & PR
add-conv-state-to-tool-create2. Updated Base Class
ToolDefinition.create()signature to:create(cls, conv_state: ConversationState) -> Sequence[Self]3. Updated All Tool Subclasses (4 tool types)
FinishToolThinkToolMCPToolDefinitionBrowserUseTool(8 browser tool classes: Navigate, Click, Type, Scroll, GetUrl, GoBack, ExtractContent, Done)4. Updated All Call Sites
openhands/sdk/agent/base.py: Tool initialization in agentopenhands/sdk/mcp/utils.py:create_mcp_tools()helper function5. Test Results
Changes Overview
18 files modified:
All changes are focused and directly related to adding the
conv_stateparameter - no extraneous modifications.Next Steps
The PR is ready for review at: #1008
View full conversation