openhands-tools 1.50.1__tar.gz → 1.52.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/PKG-INFO +2 -2
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/ask_oracle/definition.py +3 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/browser_use/definition.py +20 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/definition.py +3 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/edit/definition.py +3 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/list_directory/definition.py +3 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/read_file/definition.py +3 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/write_file/definition.py +3 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/glob/definition.py +3 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/grep/definition.py +5 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/planning_file_editor/definition.py +3 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/task/definition.py +53 -6
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/task/manager.py +19 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/task_tracker/definition.py +5 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/definition.py +5 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/tmux_pane_pool.py +4 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/tmux_terminal.py +4 -2
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/workflow/definition.py +14 -5
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/workflow/impl.py +7 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands_tools.egg-info/PKG-INFO +2 -2
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands_tools.egg-info/requires.txt +1 -1
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/pyproject.toml +2 -2
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/apply_patch/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/apply_patch/core.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/apply_patch/definition.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/ask_oracle/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/ask_oracle/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/browser_use/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/browser_use/event_storage.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/browser_use/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/browser_use/logging_fix.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/browser_use/recording.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/browser_use/server.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/delegate/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/delegate/definition.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/delegate/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/delegate/visualizer.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/editor.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/exceptions.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/config.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/constants.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/diff.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/encoding.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/file_cache.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/history.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/shell.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/edit/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/edit/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/file_change.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/list_directory/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/list_directory/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/read_file/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/read_file/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/write_file/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/write_file/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/glob/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/glob/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/grep/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/grep/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/planning_file_editor/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/planning_file_editor/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/default.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/gemini.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/gpt5.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/planning.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/subagents/bash_runner.md +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/subagents/code_explorer.md +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/subagents/default.md +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/subagents/web_researcher.md +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/task_outcome.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/py.typed +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/task/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/task/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/task_tracker/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/constants.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/descriptions.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/env.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/impl.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/metadata.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/factory.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/interface.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/subprocess_terminal.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/terminal_session.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/windows_terminal.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/timeout_policy.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/utils/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/utils/command.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/utils/escape_filter.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/tom_consult/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/tom_consult/definition.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/tom_consult/executor.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/utils/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/utils/timeout.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/workflow/__init__.py +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands_tools.egg-info/SOURCES.txt +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands_tools.egg-info/dependency_links.txt +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands_tools.egg-info/top_level.txt +0 -0
- {openhands_tools-1.50.1 → openhands_tools-1.52.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openhands-tools
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.52.0
|
|
4
4
|
Summary: OpenHands Tools - Runtime tools for AI agents
|
|
5
5
|
Project-URL: Source, https://github.com/OpenHands/software-agent-sdk
|
|
6
6
|
Project-URL: Homepage, https://github.com/OpenHands/software-agent-sdk
|
|
@@ -13,7 +13,7 @@ Requires-Dist: tree-sitter-bash>=0.23
|
|
|
13
13
|
Requires-Dist: binaryornot>=0.6.0
|
|
14
14
|
Requires-Dist: cachetools
|
|
15
15
|
Requires-Dist: libtmux>=0.53.0
|
|
16
|
-
Requires-Dist: pydantic>=2.
|
|
16
|
+
Requires-Dist: pydantic>=2.13.5
|
|
17
17
|
Requires-Dist: browser-use>=0.8.0
|
|
18
18
|
Requires-Dist: func-timeout>=4.3.5
|
|
19
19
|
Requires-Dist: tom-swe>=1.0.3
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"""Action, observation, and tool definitions for the ask_oracle tool."""
|
|
2
2
|
|
|
3
3
|
from collections.abc import Sequence
|
|
4
|
-
from typing import TYPE_CHECKING, Final, Self
|
|
4
|
+
from typing import TYPE_CHECKING, ClassVar, Final, Self
|
|
5
5
|
|
|
6
6
|
from pydantic import Field
|
|
7
7
|
from rich.text import Text
|
|
@@ -82,6 +82,8 @@ _DESCRIPTION = (
|
|
|
82
82
|
class AskOracleTool(ToolDefinition[AskOracleAction, AskOracleObservation]):
|
|
83
83
|
"""Tool for consulting the Oracle (a saved LLM profile named "oracle")."""
|
|
84
84
|
|
|
85
|
+
user_selectable: ClassVar[bool] = False
|
|
86
|
+
|
|
85
87
|
@classmethod
|
|
86
88
|
def create(
|
|
87
89
|
cls,
|
|
@@ -775,6 +775,18 @@ class BrowserStopRecordingTool(
|
|
|
775
775
|
]
|
|
776
776
|
|
|
777
777
|
|
|
778
|
+
BROWSER_PROMPT_GUIDANCE = """\
|
|
779
|
+
<BROWSER_TOOLS>
|
|
780
|
+
You have a browser for navigating pages and interacting with web UIs.
|
|
781
|
+
* Try curl/wget/fetch first. Use the browser only when simpler tools fail or the page requires JS/interaction.
|
|
782
|
+
* ALWAYS call `browser_get_state` before EVERY `browser_click` or `browser_type` — indices change after each action. Flow: navigate → get_state → interact → get_state → get_content.
|
|
783
|
+
* Max 10 browser actions per sub-task. If stuck, switch approach entirely.
|
|
784
|
+
* If 20+ total steps without converging, stop exploring and commit to your best answer.
|
|
785
|
+
* On 403/CAPTCHA/login wall: try one alternative, then abandon the browser.
|
|
786
|
+
* Do NOT submit forms or create accounts unless explicitly asked.
|
|
787
|
+
</BROWSER_TOOLS>""" # noqa: E501
|
|
788
|
+
|
|
789
|
+
|
|
778
790
|
class BrowserToolSet(ToolDefinition[BrowserAction, BrowserObservation]):
|
|
779
791
|
"""A set of all browser tools.
|
|
780
792
|
|
|
@@ -785,6 +797,10 @@ class BrowserToolSet(ToolDefinition[BrowserAction, BrowserObservation]):
|
|
|
785
797
|
when created and automatically installs it if missing.
|
|
786
798
|
"""
|
|
787
799
|
|
|
800
|
+
catalog_description: ClassVar[str] = (
|
|
801
|
+
"Browse the web: navigate pages, click, type and read content."
|
|
802
|
+
)
|
|
803
|
+
|
|
788
804
|
# Shared executor: reuse a single Chromium/CDP instance across parent
|
|
789
805
|
# and subagents to avoid CDP port conflicts in sandbox containers.
|
|
790
806
|
_shared_executor: ClassVar["BrowserToolExecutor | None"] = None
|
|
@@ -870,7 +886,10 @@ class BrowserToolSet(ToolDefinition[BrowserAction, BrowserObservation]):
|
|
|
870
886
|
BrowserStopRecordingTool,
|
|
871
887
|
]:
|
|
872
888
|
tools.extend(tool_class.create(executor))
|
|
873
|
-
return
|
|
889
|
+
return [
|
|
890
|
+
tool.model_copy(update={"prompt_guidance": BROWSER_PROMPT_GUIDANCE})
|
|
891
|
+
for tool in tools
|
|
892
|
+
]
|
|
874
893
|
|
|
875
894
|
|
|
876
895
|
register_tool(BrowserToolSet.name, BrowserToolSet)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from collections.abc import Sequence
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import TYPE_CHECKING, Literal
|
|
5
|
+
from typing import TYPE_CHECKING, ClassVar, Literal
|
|
6
6
|
|
|
7
7
|
from pydantic import Field, PrivateAttr
|
|
8
8
|
|
|
@@ -193,6 +193,8 @@ Remember: when making multiple file edits in a row to the same file, you should
|
|
|
193
193
|
class FileEditorTool(ToolDefinition[FileEditorAction, FileEditorObservation]):
|
|
194
194
|
"""A ToolDefinition subclass that automatically initializes a FileEditorExecutor."""
|
|
195
195
|
|
|
196
|
+
catalog_description: ClassVar[str] = "View, create and edit files."
|
|
197
|
+
|
|
196
198
|
def declared_resources(self, action: Action) -> DeclaredResources:
|
|
197
199
|
"""Declare file resources accessed by this action.
|
|
198
200
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from collections.abc import Sequence
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
6
6
|
|
|
7
7
|
from pydantic import Field
|
|
8
8
|
|
|
@@ -96,6 +96,8 @@ Examples:
|
|
|
96
96
|
class EditTool(ToolDefinition[EditAction, EditObservation]):
|
|
97
97
|
"""Tool for editing files via find/replace."""
|
|
98
98
|
|
|
99
|
+
user_selectable: ClassVar[bool] = False
|
|
100
|
+
|
|
99
101
|
def declared_resources(self, action: Action) -> DeclaredResources:
|
|
100
102
|
"""Lock on the target file path so concurrent edits to the same
|
|
101
103
|
file are serialized, while edits to different files run in parallel.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from collections.abc import Sequence
|
|
4
4
|
from datetime import datetime
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
6
6
|
|
|
7
7
|
from pydantic import BaseModel, Field
|
|
8
8
|
from rich.text import Text
|
|
@@ -141,6 +141,8 @@ MAX_ENTRIES = 500
|
|
|
141
141
|
class ListDirectoryTool(ToolDefinition[ListDirectoryAction, ListDirectoryObservation]):
|
|
142
142
|
"""Tool for listing directory contents with metadata."""
|
|
143
143
|
|
|
144
|
+
user_selectable: ClassVar[bool] = False
|
|
145
|
+
|
|
144
146
|
def declared_resources(self, action: Action) -> DeclaredResources: # noqa: ARG002
|
|
145
147
|
"""Declare resource usage for parallel execution.
|
|
146
148
|
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/read_file/definition.py
RENAMED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from collections.abc import Sequence
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
6
6
|
|
|
7
7
|
from pydantic import Field
|
|
8
8
|
from rich.text import Text
|
|
@@ -109,6 +109,8 @@ MAX_LINES_PER_READ = 1000
|
|
|
109
109
|
class ReadFileTool(ToolDefinition[ReadFileAction, ReadFileObservation]):
|
|
110
110
|
"""Tool for reading file contents with pagination support."""
|
|
111
111
|
|
|
112
|
+
user_selectable: ClassVar[bool] = False
|
|
113
|
+
|
|
112
114
|
def declared_resources(self, action: Action) -> DeclaredResources:
|
|
113
115
|
"""Lock on the target file path so a read never sees
|
|
114
116
|
partially-written content from a concurrent write.
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/write_file/definition.py
RENAMED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from collections.abc import Sequence
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
6
6
|
|
|
7
7
|
from pydantic import Field
|
|
8
8
|
|
|
@@ -69,6 +69,8 @@ Examples:
|
|
|
69
69
|
class WriteFileTool(ToolDefinition[WriteFileAction, WriteFileObservation]):
|
|
70
70
|
"""Tool for writing complete file contents."""
|
|
71
71
|
|
|
72
|
+
user_selectable: ClassVar[bool] = False
|
|
73
|
+
|
|
72
74
|
def declared_resources(self, action: Action) -> DeclaredResources:
|
|
73
75
|
"""Lock on the target file path so concurrent writes to the same
|
|
74
76
|
file are serialized, while writes to different files run in parallel.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
from collections.abc import Sequence
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
6
6
|
|
|
7
7
|
from pydantic import Field
|
|
8
8
|
|
|
@@ -65,6 +65,8 @@ Examples:
|
|
|
65
65
|
class GlobTool(ToolDefinition[GlobAction, GlobObservation]):
|
|
66
66
|
"""A ToolDefinition subclass that automatically initializes a GlobExecutor."""
|
|
67
67
|
|
|
68
|
+
catalog_description: ClassVar[str] = "Find files by name pattern, such as **/*.ts."
|
|
69
|
+
|
|
68
70
|
def declared_resources(self, action: Action) -> DeclaredResources:
|
|
69
71
|
"""Declare resource usage based on the active backend.
|
|
70
72
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import os
|
|
4
4
|
from collections.abc import Sequence
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
6
6
|
|
|
7
7
|
from pydantic import Field
|
|
8
8
|
|
|
@@ -67,6 +67,10 @@ TOOL_DESCRIPTION = """Fast content search tool.
|
|
|
67
67
|
class GrepTool(ToolDefinition[GrepAction, GrepObservation]):
|
|
68
68
|
"""A ToolDefinition subclass that automatically initializes a GrepExecutor."""
|
|
69
69
|
|
|
70
|
+
catalog_description: ClassVar[str] = (
|
|
71
|
+
"Search file contents with regular expressions."
|
|
72
|
+
)
|
|
73
|
+
|
|
70
74
|
def declared_resources(self, action: Action) -> DeclaredResources:
|
|
71
75
|
"""Declare resource usage for parallel execution.
|
|
72
76
|
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/planning_file_editor/definition.py
RENAMED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from collections.abc import Sequence
|
|
4
4
|
from pathlib import Path
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
5
|
+
from typing import TYPE_CHECKING, ClassVar
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
if TYPE_CHECKING:
|
|
@@ -65,6 +65,8 @@ class PlanningFileEditorTool(
|
|
|
65
65
|
):
|
|
66
66
|
"""A planning file editor tool with read-all, edit-PLAN.md-only access."""
|
|
67
67
|
|
|
68
|
+
user_selectable: ClassVar[bool] = False
|
|
69
|
+
|
|
68
70
|
@classmethod
|
|
69
71
|
def create(
|
|
70
72
|
cls,
|
|
@@ -10,14 +10,20 @@ and TaskToolSet (the entry-point that wires up a TaskManager-backed executor).
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
from collections.abc import Sequence
|
|
13
|
-
from typing import TYPE_CHECKING, Final
|
|
13
|
+
from typing import TYPE_CHECKING, ClassVar, Final
|
|
14
14
|
|
|
15
15
|
from pydantic import Field
|
|
16
16
|
from pydantic.json_schema import SkipJsonSchema
|
|
17
17
|
from rich.text import Text
|
|
18
18
|
|
|
19
19
|
from openhands.sdk import ImageContent, TextContent
|
|
20
|
-
from openhands.sdk.
|
|
20
|
+
from openhands.sdk.logger import get_logger
|
|
21
|
+
from openhands.sdk.subagent import (
|
|
22
|
+
AgentDefinition,
|
|
23
|
+
SubAgentScope,
|
|
24
|
+
get_factory_info,
|
|
25
|
+
get_registered_agent_definitions,
|
|
26
|
+
)
|
|
21
27
|
from openhands.sdk.tool import (
|
|
22
28
|
Action,
|
|
23
29
|
DeclaredResources,
|
|
@@ -29,11 +35,15 @@ from openhands.sdk.tool import (
|
|
|
29
35
|
|
|
30
36
|
|
|
31
37
|
if TYPE_CHECKING:
|
|
38
|
+
from openhands.sdk.agent.base import AgentBase
|
|
32
39
|
from openhands.sdk.conversation.state import ConversationState
|
|
33
40
|
from openhands.tools.task.impl import TaskExecutor
|
|
34
41
|
from openhands.tools.task.manager import ConfirmationHandler
|
|
35
42
|
|
|
36
43
|
|
|
44
|
+
logger = get_logger(__name__)
|
|
45
|
+
|
|
46
|
+
|
|
37
47
|
class TaskAction(Action):
|
|
38
48
|
"""Schema for launching a sub-agent task."""
|
|
39
49
|
|
|
@@ -169,6 +179,8 @@ Example — Perform a multi-step task involving code editing and shell commands:
|
|
|
169
179
|
class TaskTool(ToolDefinition[TaskAction, TaskObservation]):
|
|
170
180
|
"""Tool for launching (blocking) sub-agent tasks."""
|
|
171
181
|
|
|
182
|
+
user_selectable: ClassVar[bool] = False
|
|
183
|
+
|
|
172
184
|
def declared_resources(self, action: Action) -> DeclaredResources: # noqa: ARG002
|
|
173
185
|
return DeclaredResources(keys=(), declared=True)
|
|
174
186
|
|
|
@@ -213,11 +225,16 @@ class TaskToolSet(ToolDefinition[TaskAction, TaskObservation]):
|
|
|
213
225
|
)
|
|
214
226
|
"""
|
|
215
227
|
|
|
228
|
+
catalog_description: ClassVar[str] = (
|
|
229
|
+
"Delegate a self-contained sub-task to a separate agent."
|
|
230
|
+
)
|
|
231
|
+
|
|
216
232
|
@classmethod
|
|
217
233
|
def create(
|
|
218
234
|
cls,
|
|
219
|
-
conv_state: "ConversationState",
|
|
235
|
+
conv_state: "ConversationState",
|
|
220
236
|
confirmation_handler: "ConfirmationHandler | None" = None,
|
|
237
|
+
sub_agent_scope: SubAgentScope | dict[str, bool] | None = None,
|
|
221
238
|
) -> list[ToolDefinition]:
|
|
222
239
|
"""Create the task tool.
|
|
223
240
|
|
|
@@ -227,15 +244,30 @@ class TaskToolSet(ToolDefinition[TaskAction, TaskObservation]):
|
|
|
227
244
|
confirmation policy requires user approval. Receives
|
|
228
245
|
`(task_id, pending_actions)` and must return `True` to
|
|
229
246
|
approve or `False` to reject.
|
|
247
|
+
sub_agent_scope: Which of this agent's capabilities the sub-agents
|
|
248
|
+
it offers and starts must stay within.
|
|
230
249
|
|
|
231
250
|
Returns:
|
|
232
251
|
List containing a single TaskTool.
|
|
233
252
|
"""
|
|
234
253
|
from openhands.tools.task.impl import TaskExecutor, TaskManager
|
|
235
254
|
|
|
236
|
-
|
|
255
|
+
scope = SubAgentScope.model_validate(sub_agent_scope or {})
|
|
256
|
+
registered = {
|
|
257
|
+
d.name
|
|
258
|
+
for d in get_registered_agent_definitions()
|
|
259
|
+
if not scope.restricts or _offered(scope, conv_state.agent, d)
|
|
260
|
+
}
|
|
261
|
+
if not scope.restricts:
|
|
262
|
+
agent_types_info = get_factory_info()
|
|
263
|
+
elif registered:
|
|
264
|
+
agent_types_info = get_factory_info(lambda d: d.name in registered)
|
|
265
|
+
else:
|
|
266
|
+
agent_types_info = (
|
|
267
|
+
"- None: every registered agent uses tools or MCP servers "
|
|
268
|
+
"this agent does not have."
|
|
269
|
+
)
|
|
237
270
|
|
|
238
|
-
registered = {d.name for d in get_registered_agent_definitions()}
|
|
239
271
|
task_tool_examples = "\n".join(
|
|
240
272
|
ex for name, ex in TASK_TOOL_EXAMPLES.items() if name in registered
|
|
241
273
|
)
|
|
@@ -245,7 +277,9 @@ class TaskToolSet(ToolDefinition[TaskAction, TaskObservation]):
|
|
|
245
277
|
task_tool_examples=task_tool_examples,
|
|
246
278
|
)
|
|
247
279
|
|
|
248
|
-
manager = TaskManager(
|
|
280
|
+
manager = TaskManager(
|
|
281
|
+
confirmation_handler=confirmation_handler, sub_agent_scope=scope
|
|
282
|
+
)
|
|
249
283
|
task_executor = TaskExecutor(manager=manager)
|
|
250
284
|
|
|
251
285
|
tools: list[ToolDefinition] = []
|
|
@@ -258,6 +292,19 @@ class TaskToolSet(ToolDefinition[TaskAction, TaskObservation]):
|
|
|
258
292
|
return tools
|
|
259
293
|
|
|
260
294
|
|
|
295
|
+
def _offered(
|
|
296
|
+
scope: SubAgentScope, parent: "AgentBase", definition: AgentDefinition
|
|
297
|
+
) -> bool:
|
|
298
|
+
missing = scope.missing_from(parent, definition)
|
|
299
|
+
if missing:
|
|
300
|
+
logger.info(
|
|
301
|
+
"Not offering sub-agent %r: it uses %s, which this agent lacks",
|
|
302
|
+
definition.name,
|
|
303
|
+
", ".join(missing),
|
|
304
|
+
)
|
|
305
|
+
return not missing
|
|
306
|
+
|
|
307
|
+
|
|
261
308
|
# Automatically register when this module is imported
|
|
262
309
|
register_tool(TaskToolSet.name, TaskToolSet)
|
|
263
310
|
register_tool(TaskTool.name, TaskTool)
|
|
@@ -35,6 +35,7 @@ from openhands.sdk.logger import get_logger
|
|
|
35
35
|
from openhands.sdk.observability.laminar import detached_delegate_context
|
|
36
36
|
from openhands.sdk.security import ConfirmationPolicyBase
|
|
37
37
|
from openhands.sdk.subagent.registry import AgentFactory, get_agent_factory
|
|
38
|
+
from openhands.sdk.subagent.scope import SubAgentScope, scope_delegation_tools
|
|
38
39
|
|
|
39
40
|
|
|
40
41
|
if TYPE_CHECKING:
|
|
@@ -98,9 +99,11 @@ class TaskManager:
|
|
|
98
99
|
def __init__(
|
|
99
100
|
self,
|
|
100
101
|
confirmation_handler: ConfirmationHandler | None = None,
|
|
102
|
+
sub_agent_scope: SubAgentScope | None = None,
|
|
101
103
|
):
|
|
102
104
|
self._parent_conversation: LocalConversation | None = None
|
|
103
105
|
self._confirmation_handler = confirmation_handler
|
|
106
|
+
self._sub_agent_scope = sub_agent_scope or SubAgentScope()
|
|
104
107
|
|
|
105
108
|
self._tasks: dict[str, Task] = {}
|
|
106
109
|
self._tasks_lock = threading.Lock()
|
|
@@ -375,9 +378,24 @@ class TaskManager:
|
|
|
375
378
|
|
|
376
379
|
sub_agent = factory.factory_func(sub_agent_llm)
|
|
377
380
|
|
|
381
|
+
if self._sub_agent_scope.restricts and not isinstance(sub_agent, Agent):
|
|
382
|
+
raise ValueError(
|
|
383
|
+
f"Agent '{factory.definition.name}' runs as "
|
|
384
|
+
f"{type(sub_agent).__name__}, whose tools cannot be checked."
|
|
385
|
+
)
|
|
386
|
+
missing = self._sub_agent_scope.missing_from(parent.agent, sub_agent)
|
|
387
|
+
if missing:
|
|
388
|
+
raise ValueError(
|
|
389
|
+
f"Agent '{factory.definition.name}' uses {', '.join(missing)}, "
|
|
390
|
+
"which this agent does not have."
|
|
391
|
+
)
|
|
392
|
+
|
|
378
393
|
# ensuring that the sub-agent LLM has stream deactivated
|
|
379
394
|
sub_agent = sub_agent.model_copy(
|
|
380
|
-
update={
|
|
395
|
+
update={
|
|
396
|
+
"llm": sub_agent.llm.model_copy(update={"stream": False}),
|
|
397
|
+
"tools": scope_delegation_tools(sub_agent.tools, self._sub_agent_scope),
|
|
398
|
+
}
|
|
381
399
|
)
|
|
382
400
|
return sub_agent
|
|
383
401
|
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/task_tracker/definition.py
RENAMED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from collections.abc import Sequence
|
|
3
3
|
from pathlib import Path
|
|
4
|
-
from typing import TYPE_CHECKING, Literal
|
|
4
|
+
from typing import TYPE_CHECKING, ClassVar, Literal
|
|
5
5
|
|
|
6
6
|
from pydantic import BaseModel, Field, ValidationError
|
|
7
7
|
|
|
@@ -403,6 +403,10 @@ systematic approach and ensures comprehensive requirement fulfillment.""" # noq
|
|
|
403
403
|
class TaskTrackerTool(ToolDefinition[TaskTrackerAction, TaskTrackerObservation]):
|
|
404
404
|
"""A ToolDefinition subclass that automatically initializes a TaskTrackerExecutor.""" # noqa: E501
|
|
405
405
|
|
|
406
|
+
catalog_description: ClassVar[str] = (
|
|
407
|
+
"Keep a running task list to organise multi-step work."
|
|
408
|
+
)
|
|
409
|
+
|
|
406
410
|
@classmethod
|
|
407
411
|
def create(cls, conv_state: "ConversationState") -> Sequence["TaskTrackerTool"]:
|
|
408
412
|
"""Initialize TaskTrackerTool with a TaskTrackerExecutor.
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
import os
|
|
4
4
|
import platform
|
|
5
5
|
from collections.abc import Mapping, Sequence
|
|
6
|
-
from typing import TYPE_CHECKING, Literal
|
|
6
|
+
from typing import TYPE_CHECKING, ClassVar, Literal
|
|
7
7
|
|
|
8
8
|
from pydantic import Field
|
|
9
9
|
|
|
@@ -268,6 +268,10 @@ class TerminalObservation(Observation):
|
|
|
268
268
|
class TerminalTool(ToolDefinition[TerminalAction, TerminalObservation]):
|
|
269
269
|
"""A ToolDefinition subclass that automatically initializes a TerminalExecutor with auto-detection.""" # noqa: E501
|
|
270
270
|
|
|
271
|
+
catalog_description: ClassVar[str] = (
|
|
272
|
+
"Run shell commands in a persistent terminal session."
|
|
273
|
+
)
|
|
274
|
+
|
|
271
275
|
def declared_resources(self, action: Action) -> DeclaredResources: # noqa: ARG002
|
|
272
276
|
# When using the tmux backend, TmuxPanePool handles concurrency
|
|
273
277
|
# internally via pane-level isolation — opt out of framework
|
|
@@ -118,7 +118,10 @@ class TmuxPanePool:
|
|
|
118
118
|
return
|
|
119
119
|
|
|
120
120
|
env = build_terminal_env(self.env)
|
|
121
|
-
|
|
121
|
+
# Stale handles must not reach another pool after tmux restarts.
|
|
122
|
+
self._server = libtmux.Server(
|
|
123
|
+
socket_name=f"{TMUX_SOCKET_NAME}-{uuid.uuid4().hex}", environment=env
|
|
124
|
+
)
|
|
122
125
|
session_name = f"openhands-pool-{self.username}-{uuid.uuid4()}"
|
|
123
126
|
self._session = self._server.new_session(
|
|
124
127
|
session_name=session_name,
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/tmux_terminal.py
RENAMED
|
@@ -122,8 +122,10 @@ class TmuxTerminal(TerminalInterface):
|
|
|
122
122
|
# auto-launch `less` on a TTY don't capture the pane and wedge the session.
|
|
123
123
|
env.setdefault("GIT_PAGER", "cat")
|
|
124
124
|
env.setdefault("PAGER", "cat")
|
|
125
|
-
#
|
|
126
|
-
self.server = libtmux.Server(
|
|
125
|
+
# Never reuse a socket: tmux numeric IDs restart at zero after server exit.
|
|
126
|
+
self.server = libtmux.Server(
|
|
127
|
+
socket_name=f"{TMUX_SOCKET_NAME}-{uuid.uuid4().hex}", environment=env
|
|
128
|
+
)
|
|
127
129
|
_shell_command = "/bin/bash"
|
|
128
130
|
if self.username in ["root", "openhands"]:
|
|
129
131
|
# This starts a non-login (new) shell for the given user
|
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from collections.abc import Sequence
|
|
6
|
-
from typing import TYPE_CHECKING, Final, Literal
|
|
6
|
+
from typing import TYPE_CHECKING, ClassVar, Final, Literal
|
|
7
7
|
|
|
8
8
|
from pydantic import Field
|
|
9
9
|
|
|
10
|
+
from openhands.sdk.subagent import SubAgentScope
|
|
10
11
|
from openhands.sdk.tool import (
|
|
11
12
|
Action,
|
|
12
13
|
Observation,
|
|
@@ -142,15 +143,22 @@ class WorkflowTool(ToolDefinition[WorkflowAction, WorkflowObservation]):
|
|
|
142
143
|
(e.g., in tests or extensions).
|
|
143
144
|
"""
|
|
144
145
|
|
|
146
|
+
user_selectable: ClassVar[bool] = False
|
|
147
|
+
|
|
145
148
|
@classmethod
|
|
146
149
|
def create(
|
|
147
150
|
cls,
|
|
148
151
|
conv_state: ConversationState | None = None, # noqa: ARG003
|
|
149
152
|
executor: WorkflowExecutor | None = None,
|
|
150
153
|
description: str = _WORKFLOW_DESCRIPTION,
|
|
154
|
+
sub_agent_scope: SubAgentScope | dict[str, bool] | None = None,
|
|
151
155
|
) -> Sequence[WorkflowTool]:
|
|
152
156
|
from openhands.tools.workflow.impl import WorkflowExecutor
|
|
153
157
|
|
|
158
|
+
if executor is None:
|
|
159
|
+
executor = WorkflowExecutor(
|
|
160
|
+
sub_agent_scope=SubAgentScope.model_validate(sub_agent_scope or {})
|
|
161
|
+
)
|
|
154
162
|
return [
|
|
155
163
|
cls(
|
|
156
164
|
action_type=WorkflowAction,
|
|
@@ -163,7 +171,7 @@ class WorkflowTool(ToolDefinition[WorkflowAction, WorkflowObservation]):
|
|
|
163
171
|
idempotentHint=False,
|
|
164
172
|
openWorldHint=True,
|
|
165
173
|
),
|
|
166
|
-
executor=executor
|
|
174
|
+
executor=executor,
|
|
167
175
|
)
|
|
168
176
|
]
|
|
169
177
|
|
|
@@ -171,14 +179,15 @@ class WorkflowTool(ToolDefinition[WorkflowAction, WorkflowObservation]):
|
|
|
171
179
|
class WorkflowToolSet(ToolDefinition[WorkflowAction, WorkflowObservation]):
|
|
172
180
|
"""Tool set that creates the dynamic workflow tool."""
|
|
173
181
|
|
|
182
|
+
user_selectable: ClassVar[bool] = False
|
|
183
|
+
|
|
174
184
|
@classmethod
|
|
175
185
|
def create(
|
|
176
186
|
cls,
|
|
177
187
|
conv_state: ConversationState, # noqa: ARG003
|
|
188
|
+
sub_agent_scope: SubAgentScope | dict[str, bool] | None = None,
|
|
178
189
|
) -> Sequence[WorkflowTool]:
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
return WorkflowTool.create(executor=WorkflowExecutor())
|
|
190
|
+
return WorkflowTool.create(sub_agent_scope=sub_agent_scope)
|
|
182
191
|
|
|
183
192
|
|
|
184
193
|
register_tool(WorkflowToolSet.name, WorkflowToolSet)
|
|
@@ -10,6 +10,7 @@ from collections.abc import Callable, Sequence
|
|
|
10
10
|
from typing import TYPE_CHECKING, Any, Protocol
|
|
11
11
|
|
|
12
12
|
from openhands.sdk.logger import get_logger
|
|
13
|
+
from openhands.sdk.subagent import SubAgentScope
|
|
13
14
|
from openhands.sdk.tool import ToolExecutor
|
|
14
15
|
from openhands.tools.task.manager import TaskManager
|
|
15
16
|
from openhands.tools.workflow.definition import WorkflowObservation
|
|
@@ -80,13 +81,14 @@ class WorkflowContext:
|
|
|
80
81
|
parent_conversation: LocalConversation,
|
|
81
82
|
max_concurrency: int,
|
|
82
83
|
manager: _TaskStarter | None = None,
|
|
84
|
+
sub_agent_scope: SubAgentScope | None = None,
|
|
83
85
|
) -> None:
|
|
84
86
|
if max_concurrency < 1:
|
|
85
87
|
raise ValueError("max_concurrency must be at least 1")
|
|
86
88
|
self._parent_conversation = parent_conversation
|
|
87
89
|
self._max_concurrency = max_concurrency
|
|
88
90
|
if manager is None:
|
|
89
|
-
task_manager = TaskManager()
|
|
91
|
+
task_manager = TaskManager(sub_agent_scope=sub_agent_scope)
|
|
90
92
|
task_manager.attach_parent(parent_conversation)
|
|
91
93
|
self._manager = task_manager
|
|
92
94
|
else:
|
|
@@ -501,6 +503,9 @@ def _safe_globals() -> dict[str, Any]:
|
|
|
501
503
|
class WorkflowExecutor(ToolExecutor["WorkflowAction", WorkflowObservation]):
|
|
502
504
|
"""Executor for the dynamic workflow tool."""
|
|
503
505
|
|
|
506
|
+
def __init__(self, sub_agent_scope: SubAgentScope | None = None) -> None:
|
|
507
|
+
self._sub_agent_scope = sub_agent_scope
|
|
508
|
+
|
|
504
509
|
def __call__(
|
|
505
510
|
self,
|
|
506
511
|
action: WorkflowAction,
|
|
@@ -517,6 +522,7 @@ class WorkflowExecutor(ToolExecutor["WorkflowAction", WorkflowObservation]):
|
|
|
517
522
|
context = WorkflowContext(
|
|
518
523
|
parent_conversation=conversation,
|
|
519
524
|
max_concurrency=action.max_concurrency,
|
|
525
|
+
sub_agent_scope=self._sub_agent_scope,
|
|
520
526
|
)
|
|
521
527
|
try:
|
|
522
528
|
result = execute_workflow_script(action.script, context)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: openhands-tools
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.52.0
|
|
4
4
|
Summary: OpenHands Tools - Runtime tools for AI agents
|
|
5
5
|
Project-URL: Source, https://github.com/OpenHands/software-agent-sdk
|
|
6
6
|
Project-URL: Homepage, https://github.com/OpenHands/software-agent-sdk
|
|
@@ -13,7 +13,7 @@ Requires-Dist: tree-sitter-bash>=0.23
|
|
|
13
13
|
Requires-Dist: binaryornot>=0.6.0
|
|
14
14
|
Requires-Dist: cachetools
|
|
15
15
|
Requires-Dist: libtmux>=0.53.0
|
|
16
|
-
Requires-Dist: pydantic>=2.
|
|
16
|
+
Requires-Dist: pydantic>=2.13.5
|
|
17
17
|
Requires-Dist: browser-use>=0.8.0
|
|
18
18
|
Requires-Dist: func-timeout>=4.3.5
|
|
19
19
|
Requires-Dist: tom-swe>=1.0.3
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "openhands-tools"
|
|
3
|
-
version = "1.
|
|
3
|
+
version = "1.52.0"
|
|
4
4
|
description = "OpenHands Tools - Runtime tools for AI agents"
|
|
5
5
|
|
|
6
6
|
requires-python = ">=3.12"
|
|
@@ -11,7 +11,7 @@ dependencies = [
|
|
|
11
11
|
"binaryornot>=0.6.0",
|
|
12
12
|
"cachetools",
|
|
13
13
|
"libtmux>=0.53.0",
|
|
14
|
-
"pydantic>=2.
|
|
14
|
+
"pydantic>=2.13.5",
|
|
15
15
|
"browser-use>=0.8.0",
|
|
16
16
|
"func-timeout>=4.3.5",
|
|
17
17
|
"tom-swe>=1.0.3",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/browser_use/event_storage.py
RENAMED
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/browser_use/logging_fix.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/__init__.py
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/config.py
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/constants.py
RENAMED
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/encoding.py
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/file_cache.py
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/history.py
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/file_editor/utils/shell.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/list_directory/__init__.py
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/list_directory/impl.py
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/read_file/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/gemini/write_file/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/planning_file_editor/__init__.py
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/planning_file_editor/impl.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/subagents/bash_runner.md
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/subagents/code_explorer.md
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/subagents/default.md
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/preset/subagents/web_researcher.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/__init__.py
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/factory.py
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/terminal/interface.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/timeout_policy.py
RENAMED
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/utils/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands/tools/terminal/utils/escape_filter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{openhands_tools-1.50.1 → openhands_tools-1.52.0}/openhands_tools.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|