openhands-tools 1.56.0__tar.gz → 1.57.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.
Files changed (110) hide show
  1. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/PKG-INFO +1 -1
  2. openhands_tools-1.57.0/openhands/tools/terminal/terminal/process_priority.py +39 -0
  3. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/terminal/subprocess_terminal.py +4 -1
  4. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/terminal/tmux_pane_pool.py +8 -3
  5. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/terminal/tmux_terminal.py +7 -3
  6. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/terminal/windows_terminal.py +10 -4
  7. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands_tools.egg-info/PKG-INFO +1 -1
  8. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands_tools.egg-info/SOURCES.txt +2 -0
  9. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/pyproject.toml +1 -1
  10. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/__init__.py +0 -0
  11. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/apply_patch/__init__.py +0 -0
  12. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/apply_patch/core.py +0 -0
  13. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/apply_patch/definition.py +0 -0
  14. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/ask_oracle/__init__.py +0 -0
  15. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/ask_oracle/definition.py +0 -0
  16. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/ask_oracle/impl.py +0 -0
  17. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/browser_use/__init__.py +0 -0
  18. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/browser_use/definition.py +0 -0
  19. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/browser_use/event_storage.py +0 -0
  20. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/browser_use/impl.py +0 -0
  21. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/browser_use/logging_fix.py +0 -0
  22. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/browser_use/recording.py +0 -0
  23. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/browser_use/server.py +0 -0
  24. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/child_conversation/__init__.py +0 -0
  25. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/child_conversation/definition.py +0 -0
  26. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/child_conversation/impl.py +0 -0
  27. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/delegate/__init__.py +0 -0
  28. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/delegate/definition.py +0 -0
  29. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/delegate/impl.py +0 -0
  30. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/delegate/visualizer.py +0 -0
  31. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/__init__.py +0 -0
  32. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/definition.py +0 -0
  33. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/editor.py +0 -0
  34. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/exceptions.py +0 -0
  35. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/impl.py +0 -0
  36. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/utils/__init__.py +0 -0
  37. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/utils/config.py +0 -0
  38. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/utils/constants.py +0 -0
  39. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/utils/diff.py +0 -0
  40. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/utils/encoding.py +0 -0
  41. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/utils/file_cache.py +0 -0
  42. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/utils/history.py +0 -0
  43. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/file_editor/utils/shell.py +0 -0
  44. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/__init__.py +0 -0
  45. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/edit/__init__.py +0 -0
  46. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/edit/definition.py +0 -0
  47. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/edit/impl.py +0 -0
  48. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/file_change.py +0 -0
  49. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/list_directory/__init__.py +0 -0
  50. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/list_directory/definition.py +0 -0
  51. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/list_directory/impl.py +0 -0
  52. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/read_file/__init__.py +0 -0
  53. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/read_file/definition.py +0 -0
  54. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/read_file/impl.py +0 -0
  55. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/write_file/__init__.py +0 -0
  56. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/write_file/definition.py +0 -0
  57. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/gemini/write_file/impl.py +0 -0
  58. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/glob/__init__.py +0 -0
  59. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/glob/definition.py +0 -0
  60. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/glob/impl.py +0 -0
  61. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/grep/__init__.py +0 -0
  62. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/grep/definition.py +0 -0
  63. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/grep/impl.py +0 -0
  64. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/planning_file_editor/__init__.py +0 -0
  65. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/planning_file_editor/definition.py +0 -0
  66. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/planning_file_editor/impl.py +0 -0
  67. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/preset/__init__.py +0 -0
  68. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/preset/default.py +0 -0
  69. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/preset/gemini.py +0 -0
  70. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/preset/gpt5.py +0 -0
  71. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/preset/planning.py +0 -0
  72. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/preset/subagents/bash_runner.md +0 -0
  73. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/preset/subagents/code_explorer.md +0 -0
  74. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/preset/subagents/default.md +0 -0
  75. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/preset/subagents/web_researcher.md +0 -0
  76. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/preset/task_outcome.py +0 -0
  77. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/py.typed +0 -0
  78. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/task/__init__.py +0 -0
  79. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/task/definition.py +0 -0
  80. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/task/impl.py +0 -0
  81. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/task/manager.py +0 -0
  82. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/task_tracker/__init__.py +0 -0
  83. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/task_tracker/definition.py +0 -0
  84. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/__init__.py +0 -0
  85. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/constants.py +0 -0
  86. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/definition.py +0 -0
  87. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/descriptions.py +0 -0
  88. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/env.py +0 -0
  89. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/impl.py +0 -0
  90. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/metadata.py +0 -0
  91. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/terminal/__init__.py +0 -0
  92. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/terminal/factory.py +0 -0
  93. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/terminal/interface.py +0 -0
  94. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/terminal/terminal_session.py +0 -0
  95. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/timeout_policy.py +0 -0
  96. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/utils/__init__.py +0 -0
  97. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/utils/command.py +0 -0
  98. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/terminal/utils/escape_filter.py +0 -0
  99. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/tom_consult/__init__.py +0 -0
  100. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/tom_consult/definition.py +0 -0
  101. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/tom_consult/executor.py +0 -0
  102. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/utils/__init__.py +0 -0
  103. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/utils/timeout.py +0 -0
  104. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/workflow/__init__.py +0 -0
  105. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/workflow/definition.py +0 -0
  106. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands/tools/workflow/impl.py +0 -0
  107. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands_tools.egg-info/dependency_links.txt +0 -0
  108. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands_tools.egg-info/requires.txt +0 -0
  109. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/openhands_tools.egg-info/top_level.txt +0 -0
  110. {openhands_tools-1.56.0 → openhands_tools-1.57.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openhands-tools
3
- Version: 1.56.0
3
+ Version: 1.57.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
@@ -0,0 +1,39 @@
1
+ """Lower the CPU priority of agent terminals so they cannot starve the server."""
2
+
3
+ import os
4
+ import platform
5
+ import shutil
6
+ from collections.abc import Mapping
7
+ from typing import Final
8
+
9
+
10
+ TERMINAL_PROCESS_PRIORITY_ENV: Final[str] = "OH_TERMINAL_PROCESS_PRIORITY"
11
+
12
+ # macOS largely ignores nice; the utility QoS clamp is what keeps the server
13
+ # responsive. Avoid the background clamp: it also throttles I/O heavily.
14
+ _TASKPOLICY_PATH: Final[str] = "/usr/sbin/taskpolicy"
15
+ _LINUX_NICE_INCREMENT: Final[str] = "10"
16
+
17
+
18
+ def should_lower_process_priority(env: Mapping[str, str]) -> bool:
19
+ """Return False when the terminal env opts out with ``none``."""
20
+ value = env.get(TERMINAL_PROCESS_PRIORITY_ENV, "")
21
+ return value.strip().lower() != "none"
22
+
23
+
24
+ def process_priority_prefix(env: Mapping[str, str]) -> list[str]:
25
+ """Return an argv prefix that runs the shell at lower CPU priority.
26
+
27
+ This must be an argv prefix rather than a ``preexec_fn``: a macOS QoS class
28
+ set on the calling thread does not survive ``exec``. Both ``taskpolicy``
29
+ and ``nice`` are inherited by every process the shell starts.
30
+ """
31
+ if not should_lower_process_priority(env):
32
+ return []
33
+
34
+ system = platform.system()
35
+ if system == "Darwin" and os.path.exists(_TASKPOLICY_PATH):
36
+ return [_TASKPOLICY_PATH, "-c", "utility"]
37
+ if system == "Linux" and (nice_path := shutil.which("nice")) is not None:
38
+ return [nice_path, "-n", _LINUX_NICE_INCREMENT]
39
+ return []
@@ -35,6 +35,9 @@ from openhands.tools.terminal.env import (
35
35
  from openhands.tools.terminal.metadata import CmdOutputMetadata
36
36
  from openhands.tools.terminal.terminal import TerminalInterface
37
37
  from openhands.tools.terminal.terminal.interface import parse_ctrl_key
38
+ from openhands.tools.terminal.terminal.process_priority import (
39
+ process_priority_prefix,
40
+ )
38
41
 
39
42
 
40
43
  logger = get_logger(__name__)
@@ -151,7 +154,7 @@ class SubprocessTerminal(TerminalInterface):
151
154
  env["PS2"] = ""
152
155
  env["TERM"] = "xterm-256color"
153
156
 
154
- bash_cmd = [resolved_shell_path, "-i"]
157
+ bash_cmd = [*process_priority_prefix(env), resolved_shell_path, "-i"]
155
158
 
156
159
  # Create a PTY; give the slave to the child, keep the master
157
160
  master_fd, slave_fd = pty.openpty()
@@ -6,6 +6,7 @@ tmux session, enabling concurrent command execution across panes.
6
6
 
7
7
  from __future__ import annotations
8
8
 
9
+ import shlex
9
10
  import threading
10
11
  import time
11
12
  import uuid
@@ -27,6 +28,9 @@ from openhands.tools.terminal.env import (
27
28
  build_terminal_env,
28
29
  normalize_terminal_env,
29
30
  )
31
+ from openhands.tools.terminal.terminal.process_priority import (
32
+ process_priority_prefix,
33
+ )
30
34
  from openhands.tools.terminal.terminal.tmux_terminal import (
31
35
  TmuxTerminal,
32
36
  _new_owned_session,
@@ -169,13 +173,14 @@ class TmuxPanePool:
169
173
  """Create a new PooledTmuxTerminal within the shared session."""
170
174
  assert self._session is not None
171
175
 
172
- shell_command = "/bin/bash"
176
+ shell_command = ["/bin/bash"]
173
177
  if self.username in ["root", "openhands"]:
174
- shell_command = f"su {self.username} -"
178
+ shell_command = ["su", self.username, "-"]
179
+ priority_prefix = process_priority_prefix(build_terminal_env(self.env))
175
180
 
176
181
  window = self._session.new_window(
177
182
  window_name=f"pane-{len(self._all_panes)}",
178
- window_shell=shell_command,
183
+ window_shell=shlex.join([*priority_prefix, *shell_command]),
179
184
  start_directory=self.work_dir,
180
185
  )
181
186
  active_pane = window.active_pane
@@ -2,6 +2,7 @@
2
2
 
3
3
  import logging
4
4
  import os
5
+ import shlex
5
6
  import sys
6
7
  import time
7
8
  import uuid
@@ -29,6 +30,9 @@ from openhands.tools.terminal.env import (
29
30
  from openhands.tools.terminal.metadata import CmdOutputMetadata
30
31
  from openhands.tools.terminal.terminal import TerminalInterface
31
32
  from openhands.tools.terminal.terminal.interface import parse_ctrl_key
33
+ from openhands.tools.terminal.terminal.process_priority import (
34
+ process_priority_prefix,
35
+ )
32
36
 
33
37
 
34
38
  logger = get_logger(__name__)
@@ -212,12 +216,12 @@ class TmuxTerminal(TerminalInterface):
212
216
  # auto-launch `less` on a TTY don't capture the pane and wedge the session.
213
217
  env.setdefault("GIT_PAGER", "cat")
214
218
  env.setdefault("PAGER", "cat")
215
- _shell_command = "/bin/bash"
219
+ shell_command = ["/bin/bash"]
216
220
  if self.username in ["root", "openhands"]:
217
221
  # This starts a non-login (new) shell for the given user
218
- _shell_command = f"su {self.username} -"
222
+ shell_command = ["su", self.username, "-"]
219
223
 
220
- window_command = _shell_command
224
+ window_command = shlex.join([*process_priority_prefix(env), *shell_command])
221
225
 
222
226
  logger.debug(f"Initializing tmux terminal with command: {window_command}")
223
227
  # Never reuse a socket: tmux numeric IDs restart at zero after server exit.
@@ -26,6 +26,9 @@ from openhands.tools.terminal.terminal.interface import (
26
26
  TerminalInterface,
27
27
  parse_ctrl_key,
28
28
  )
29
+ from openhands.tools.terminal.terminal.process_priority import (
30
+ should_lower_process_priority,
31
+ )
29
32
 
30
33
 
31
34
  logger = get_logger(__name__)
@@ -92,6 +95,10 @@ class WindowsTerminal(TerminalInterface):
92
95
  if self._initialized:
93
96
  return
94
97
 
98
+ env = build_terminal_env(self._env)
99
+ env.setdefault("PYTHONIOENCODING", "utf-8")
100
+ env.setdefault("PYTHONUTF8", "1")
101
+
95
102
  startupinfo = None
96
103
  creationflags = 0
97
104
  if platform.system() == "Windows":
@@ -101,10 +108,9 @@ class WindowsTerminal(TerminalInterface):
101
108
  startupinfo.dwFlags |= getattr(subprocess, "STARTF_USESHOWWINDOW", 0)
102
109
  creationflags = getattr(subprocess, "CREATE_NEW_PROCESS_GROUP", 0)
103
110
  creationflags |= getattr(subprocess, "CREATE_NO_WINDOW", 0)
104
-
105
- env = build_terminal_env(self._env)
106
- env.setdefault("PYTHONIOENCODING", "utf-8")
107
- env.setdefault("PYTHONUTF8", "1")
111
+ # Not PROCESS_MODE_BACKGROUND_BEGIN: it also throttles disk I/O.
112
+ if should_lower_process_priority(env):
113
+ creationflags |= getattr(subprocess, "BELOW_NORMAL_PRIORITY_CLASS", 0)
108
114
 
109
115
  self.process = subprocess.Popen(
110
116
  [self.shell_path, "-NoLogo", "-NoProfile"],
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: openhands-tools
3
- Version: 1.56.0
3
+ Version: 1.57.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
@@ -84,6 +84,7 @@ pyproject.toml
84
84
  ./openhands/tools/terminal/terminal/__init__.py
85
85
  ./openhands/tools/terminal/terminal/factory.py
86
86
  ./openhands/tools/terminal/terminal/interface.py
87
+ ./openhands/tools/terminal/terminal/process_priority.py
87
88
  ./openhands/tools/terminal/terminal/subprocess_terminal.py
88
89
  ./openhands/tools/terminal/terminal/terminal_session.py
89
90
  ./openhands/tools/terminal/terminal/tmux_pane_pool.py
@@ -185,6 +186,7 @@ openhands/tools/terminal/timeout_policy.py
185
186
  openhands/tools/terminal/terminal/__init__.py
186
187
  openhands/tools/terminal/terminal/factory.py
187
188
  openhands/tools/terminal/terminal/interface.py
189
+ openhands/tools/terminal/terminal/process_priority.py
188
190
  openhands/tools/terminal/terminal/subprocess_terminal.py
189
191
  openhands/tools/terminal/terminal/terminal_session.py
190
192
  openhands/tools/terminal/terminal/tmux_pane_pool.py
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "openhands-tools"
3
- version = "1.56.0"
3
+ version = "1.57.0"
4
4
  description = "OpenHands Tools - Runtime tools for AI agents"
5
5
 
6
6
  requires-python = ">=3.12"