hud-python 0.4.21__py3-none-any.whl → 0.4.22__py3-none-any.whl
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.
Potentially problematic release.
This version of hud-python might be problematic. Click here for more details.
- hud/agents/base.py +2 -0
- hud/agents/claude.py +11 -6
- hud/agents/grounded_openai.py +280 -0
- hud/agents/tests/test_client.py +6 -1
- hud/agents/tests/test_grounded_openai_agent.py +155 -0
- hud/cli/eval.py +2 -2
- hud/cli/utils/interactive.py +1 -1
- hud/settings.py +6 -0
- hud/tools/executors/tests/test_base_executor.py +1 -1
- hud/tools/executors/xdo.py +1 -1
- hud/tools/grounding/__init__.py +13 -0
- hud/tools/grounding/config.py +54 -0
- hud/tools/grounding/grounded_tool.py +314 -0
- hud/tools/grounding/grounder.py +301 -0
- hud/tools/grounding/tests/__init__.py +1 -0
- hud/tools/grounding/tests/test_grounded_tool.py +196 -0
- hud/tools/tests/test_playwright_tool.py +1 -1
- hud/tools/tests/test_tools_init.py +1 -1
- hud/tools/tests/test_utils.py +2 -2
- hud/utils/agent_factories.py +86 -0
- hud/utils/tests/test_version.py +1 -1
- hud/version.py +1 -1
- {hud_python-0.4.21.dist-info → hud_python-0.4.22.dist-info}/METADATA +1 -1
- {hud_python-0.4.21.dist-info → hud_python-0.4.22.dist-info}/RECORD +27 -18
- {hud_python-0.4.21.dist-info → hud_python-0.4.22.dist-info}/WHEEL +0 -0
- {hud_python-0.4.21.dist-info → hud_python-0.4.22.dist-info}/entry_points.txt +0 -0
- {hud_python-0.4.21.dist-info → hud_python-0.4.22.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
import mcp.types as types
|
|
7
|
+
import pytest
|
|
8
|
+
|
|
9
|
+
from hud.tools.grounding.grounded_tool import GroundedComputerTool
|
|
10
|
+
from hud.types import MCPToolCall, MCPToolResult
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass
|
|
14
|
+
class FakeResult:
|
|
15
|
+
content: list[types.ContentBlock]
|
|
16
|
+
isError: bool = False
|
|
17
|
+
structuredContent: dict | None = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class FakeMCPClient:
|
|
21
|
+
"""Fake MCP client that implements AgentMCPClient protocol."""
|
|
22
|
+
|
|
23
|
+
_initialized: bool
|
|
24
|
+
|
|
25
|
+
def __init__(self) -> None:
|
|
26
|
+
self.calls: list[tuple[str, dict[str, Any]]] = []
|
|
27
|
+
self._initialized = False
|
|
28
|
+
|
|
29
|
+
@property
|
|
30
|
+
def mcp_config(self) -> dict[str, dict[str, Any]]:
|
|
31
|
+
return {"test": {"command": "echo", "args": ["test"]}}
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def is_connected(self) -> bool:
|
|
35
|
+
return self._initialized
|
|
36
|
+
|
|
37
|
+
async def initialize(self, mcp_config: dict[str, dict[str, Any]] | None = None) -> None:
|
|
38
|
+
self._initialized = True
|
|
39
|
+
|
|
40
|
+
async def list_tools(self) -> list[types.Tool]:
|
|
41
|
+
return [types.Tool(name="computer", description="Test tool", inputSchema={})]
|
|
42
|
+
|
|
43
|
+
async def call_tool(self, tool_call: MCPToolCall) -> MCPToolResult:
|
|
44
|
+
self.calls.append((tool_call.name, tool_call.arguments or {}))
|
|
45
|
+
return MCPToolResult(content=[types.TextContent(text="ok", type="text")], isError=False)
|
|
46
|
+
|
|
47
|
+
async def shutdown(self) -> None:
|
|
48
|
+
self._initialized = False
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class FakeGrounder:
|
|
52
|
+
"""Fake grounder that implements Grounder interface."""
|
|
53
|
+
|
|
54
|
+
def __init__(self, coords: tuple[int, int] | None = (10, 20)) -> None:
|
|
55
|
+
self.coords = coords
|
|
56
|
+
self.calls: list[tuple[str, str]] = []
|
|
57
|
+
|
|
58
|
+
async def predict_click(
|
|
59
|
+
self, *, image_b64: str, instruction: str, max_retries: int = 3
|
|
60
|
+
) -> tuple[int, int] | None:
|
|
61
|
+
self.calls.append((image_b64[:10], instruction))
|
|
62
|
+
return self.coords
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _png_b64() -> str:
|
|
66
|
+
# 1x1 transparent PNG base64 (valid minimal image)
|
|
67
|
+
return (
|
|
68
|
+
"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGMAAQAABQAB"
|
|
69
|
+
"J2n0mQAAAABJRU5ErkJggg=="
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
@pytest.mark.asyncio
|
|
74
|
+
async def test_click_action_grounds_and_calls_mcp() -> None:
|
|
75
|
+
client = FakeMCPClient()
|
|
76
|
+
grounder = FakeGrounder(coords=(123, 456))
|
|
77
|
+
tool = GroundedComputerTool(grounder=grounder, mcp_client=client) # type: ignore
|
|
78
|
+
|
|
79
|
+
blocks = await tool(
|
|
80
|
+
action="click",
|
|
81
|
+
element_description="red button",
|
|
82
|
+
screenshot_b64=_png_b64(),
|
|
83
|
+
button="left",
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
assert isinstance(blocks, list)
|
|
87
|
+
# Grounder called once
|
|
88
|
+
assert len(grounder.calls) == 1
|
|
89
|
+
# MCP called with resolved coordinates
|
|
90
|
+
assert client.calls == [("computer", {"action": "click", "x": 123, "y": 456, "button": "left"})]
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
@pytest.mark.asyncio
|
|
94
|
+
async def test_move_and_scroll_require_element_description_and_screenshot() -> None:
|
|
95
|
+
client = FakeMCPClient()
|
|
96
|
+
grounder = FakeGrounder(coords=(5, 6))
|
|
97
|
+
tool = GroundedComputerTool(grounder=grounder, mcp_client=client) # type: ignore
|
|
98
|
+
|
|
99
|
+
# Missing element_description
|
|
100
|
+
with pytest.raises(Exception) as ei:
|
|
101
|
+
await tool(action="move", screenshot_b64=_png_b64())
|
|
102
|
+
assert "element_description is required" in str(ei.value)
|
|
103
|
+
|
|
104
|
+
# Missing screenshot
|
|
105
|
+
with pytest.raises(Exception) as ei2:
|
|
106
|
+
await tool(action="scroll", element_description="list", scroll_y=100)
|
|
107
|
+
assert "No screenshot available" in str(ei2.value)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
@pytest.mark.asyncio
|
|
111
|
+
async def test_drag_grounds_both_points_and_calls_mcp() -> None:
|
|
112
|
+
client = FakeMCPClient()
|
|
113
|
+
grounder = FakeGrounder(coords=(10, 20))
|
|
114
|
+
tool = GroundedComputerTool(grounder=grounder, mcp_client=client) # type: ignore
|
|
115
|
+
|
|
116
|
+
await tool(
|
|
117
|
+
action="drag",
|
|
118
|
+
start_element_description="source",
|
|
119
|
+
end_element_description="target",
|
|
120
|
+
screenshot_b64=_png_b64(),
|
|
121
|
+
button="left",
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
# Two grounding calls (start and end)
|
|
125
|
+
assert len(grounder.calls) == 2
|
|
126
|
+
# Drag path contains two points, same coords from fake grounder
|
|
127
|
+
name, args = client.calls[0]
|
|
128
|
+
assert name == "computer"
|
|
129
|
+
assert args["action"] == "drag"
|
|
130
|
+
assert args["button"] == "left"
|
|
131
|
+
assert args["path"] == [(10, 20), (10, 20)]
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
@pytest.mark.asyncio
|
|
135
|
+
async def test_drag_requires_both_descriptions_and_screenshot() -> None:
|
|
136
|
+
client = FakeMCPClient()
|
|
137
|
+
grounder = FakeGrounder()
|
|
138
|
+
tool = GroundedComputerTool(grounder=grounder, mcp_client=client) # type: ignore
|
|
139
|
+
|
|
140
|
+
with pytest.raises(Exception) as ei:
|
|
141
|
+
await tool(action="drag", start_element_description="a", screenshot_b64=_png_b64())
|
|
142
|
+
assert "start_element_description and end_element_description" in str(ei.value)
|
|
143
|
+
|
|
144
|
+
with pytest.raises(Exception) as ei2:
|
|
145
|
+
await tool(
|
|
146
|
+
action="drag",
|
|
147
|
+
start_element_description="a",
|
|
148
|
+
end_element_description="b",
|
|
149
|
+
)
|
|
150
|
+
assert "No screenshot available" in str(ei2.value)
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@pytest.mark.asyncio
|
|
154
|
+
async def test_direct_actions_bypass_grounding_and_call_mcp() -> None:
|
|
155
|
+
client = FakeMCPClient()
|
|
156
|
+
grounder = FakeGrounder()
|
|
157
|
+
tool = GroundedComputerTool(grounder=grounder, mcp_client=client) # type: ignore
|
|
158
|
+
|
|
159
|
+
# Actions that bypass grounding
|
|
160
|
+
for action, extra in [
|
|
161
|
+
("screenshot", {}),
|
|
162
|
+
("type", {"text": "hello"}),
|
|
163
|
+
("keypress", {"keys": ["ctrl", "a"]}),
|
|
164
|
+
("wait", {}),
|
|
165
|
+
("get_current_url", {}),
|
|
166
|
+
("get_dimensions", {}),
|
|
167
|
+
("get_environment", {}),
|
|
168
|
+
]:
|
|
169
|
+
client.calls.clear()
|
|
170
|
+
_ = await tool(action=action, **extra)
|
|
171
|
+
assert client.calls and client.calls[0][0] == "computer"
|
|
172
|
+
assert client.calls[0][1]["action"] == action
|
|
173
|
+
# Grounder not invoked for these
|
|
174
|
+
assert grounder.calls == []
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@pytest.mark.asyncio
|
|
178
|
+
async def test_unsupported_action_raises() -> None:
|
|
179
|
+
client = FakeMCPClient()
|
|
180
|
+
grounder = FakeGrounder()
|
|
181
|
+
tool = GroundedComputerTool(grounder=grounder, mcp_client=client) # type: ignore
|
|
182
|
+
|
|
183
|
+
with pytest.raises(Exception) as ei:
|
|
184
|
+
await tool(action="zoom")
|
|
185
|
+
assert "Unsupported action" in str(ei.value)
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
@pytest.mark.asyncio
|
|
189
|
+
async def test_grounding_failure_propagates_as_error() -> None:
|
|
190
|
+
client = FakeMCPClient()
|
|
191
|
+
grounder = FakeGrounder(coords=None)
|
|
192
|
+
tool = GroundedComputerTool(grounder=grounder, mcp_client=client) # type: ignore
|
|
193
|
+
|
|
194
|
+
with pytest.raises(Exception) as ei:
|
|
195
|
+
await tool(action="click", element_description="x", screenshot_b64=_png_b64())
|
|
196
|
+
assert "Could not locate element" in str(ei.value)
|
|
@@ -52,7 +52,7 @@ class TestPlaywrightTool:
|
|
|
52
52
|
assert any(isinstance(b, TextContent) for b in blocks)
|
|
53
53
|
# The actual call includes wait_until parameter with a Field object
|
|
54
54
|
mock_page.goto.assert_called_once()
|
|
55
|
-
args,
|
|
55
|
+
args, _kwargs = mock_page.goto.call_args
|
|
56
56
|
assert args[0] == "https://example.com"
|
|
57
57
|
mock_ensure.assert_called_once()
|
|
58
58
|
|
|
@@ -33,7 +33,7 @@ class TestToolsInit:
|
|
|
33
33
|
"""Test lazy import with invalid attribute name."""
|
|
34
34
|
import hud.tools as tools_module
|
|
35
35
|
|
|
36
|
-
with pytest.raises(AttributeError, match="module '.*' has no attribute 'InvalidTool'"):
|
|
36
|
+
with pytest.raises(AttributeError, match=r"module '.*' has no attribute 'InvalidTool'"):
|
|
37
37
|
_ = tools_module.InvalidTool
|
|
38
38
|
|
|
39
39
|
def test_direct_imports_available(self):
|
hud/tools/tests/test_utils.py
CHANGED
|
@@ -58,7 +58,7 @@ class TestRun:
|
|
|
58
58
|
mock_proc.communicate = AsyncMock(return_value=(b"processed", b""))
|
|
59
59
|
|
|
60
60
|
with patch("asyncio.create_subprocess_shell", return_value=mock_proc):
|
|
61
|
-
return_code, stdout,
|
|
61
|
+
return_code, stdout, _stderr = await run("cat", input="test input")
|
|
62
62
|
|
|
63
63
|
assert return_code == 0
|
|
64
64
|
assert stdout == "processed"
|
|
@@ -91,7 +91,7 @@ class TestRun:
|
|
|
91
91
|
):
|
|
92
92
|
mock_wait_for.return_value = (b"done", b"")
|
|
93
93
|
|
|
94
|
-
|
|
94
|
+
_return_code, _stdout, _stderr = await run("sleep 1", timeout=5.0)
|
|
95
95
|
|
|
96
96
|
# Check that wait_for was called with the correct timeout
|
|
97
97
|
mock_wait_for.assert_called_once()
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"""Factory functions for creating agents compatible with run_dataset."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any
|
|
6
|
+
|
|
7
|
+
from openai import AsyncOpenAI
|
|
8
|
+
|
|
9
|
+
from hud.agents.grounded_openai import GroundedOpenAIChatAgent
|
|
10
|
+
from hud.agents.openai_chat_generic import GenericOpenAIChatAgent
|
|
11
|
+
from hud.tools.grounding import GrounderConfig
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def create_openai_agent(**kwargs: Any) -> GenericOpenAIChatAgent:
|
|
15
|
+
"""Factory for GenericOpenAIChatAgent with run_dataset compatibility.
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
api_key: OpenAI API key
|
|
19
|
+
base_url: Optional custom API endpoint
|
|
20
|
+
model_name: Model to use (e.g., "gpt-4o-mini")
|
|
21
|
+
**kwargs: Additional arguments passed to GenericOpenAIChatAgent
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
Configured GenericOpenAIChatAgent instance
|
|
25
|
+
|
|
26
|
+
Example:
|
|
27
|
+
>>> from hud.datasets import run_dataset
|
|
28
|
+
>>> from hud.utils.agent_factories import create_openai_agent
|
|
29
|
+
>>> results = await run_dataset(
|
|
30
|
+
... "My Eval",
|
|
31
|
+
... "hud-evals/SheetBench-50",
|
|
32
|
+
... create_openai_agent,
|
|
33
|
+
... {"api_key": "your-key", "model_name": "gpt-4o-mini"},
|
|
34
|
+
... )
|
|
35
|
+
"""
|
|
36
|
+
api_key = kwargs.pop("api_key", None)
|
|
37
|
+
base_url = kwargs.pop("base_url", None)
|
|
38
|
+
|
|
39
|
+
openai_client = AsyncOpenAI(api_key=api_key, base_url=base_url)
|
|
40
|
+
|
|
41
|
+
return GenericOpenAIChatAgent(openai_client=openai_client, **kwargs)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def create_grounded_agent(**kwargs: Any) -> GroundedOpenAIChatAgent:
|
|
45
|
+
"""Factory for GroundedOpenAIChatAgent with run_dataset compatibility.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
api_key: OpenAI API key for planning model
|
|
49
|
+
base_url: Optional custom API endpoint for planning model
|
|
50
|
+
model_name: Planning model to use (e.g., "gpt-4o-mini")
|
|
51
|
+
grounder_api_key: API key for grounding model
|
|
52
|
+
grounder_api_base: API base URL for grounding model (default: OpenRouter)
|
|
53
|
+
grounder_model: Grounding model to use (default: qwen/qwen-2.5-vl-7b-instruct)
|
|
54
|
+
**kwargs: Additional arguments passed to GroundedOpenAIChatAgent
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
Configured GroundedOpenAIChatAgent instance
|
|
58
|
+
|
|
59
|
+
Example:
|
|
60
|
+
>>> from hud.datasets import run_dataset
|
|
61
|
+
>>> from hud.utils.agent_factories import create_grounded_agent
|
|
62
|
+
>>> results = await run_dataset(
|
|
63
|
+
... "Grounded Eval",
|
|
64
|
+
... dataset,
|
|
65
|
+
... create_grounded_agent,
|
|
66
|
+
... {
|
|
67
|
+
... "api_key": "openai-key",
|
|
68
|
+
... "grounder_api_key": "openrouter-key",
|
|
69
|
+
... "model_name": "gpt-4o-mini",
|
|
70
|
+
... },
|
|
71
|
+
... )
|
|
72
|
+
"""
|
|
73
|
+
api_key = kwargs.pop("api_key", None)
|
|
74
|
+
base_url = kwargs.pop("base_url", None)
|
|
75
|
+
grounder_api_key = kwargs.pop("grounder_api_key", None)
|
|
76
|
+
grounder_api_base = kwargs.pop("grounder_api_base", "https://openrouter.ai/api/v1")
|
|
77
|
+
grounder_model = kwargs.pop("grounder_model", "qwen/qwen-2.5-vl-7b-instruct")
|
|
78
|
+
|
|
79
|
+
openai_client = AsyncOpenAI(api_key=api_key, base_url=base_url)
|
|
80
|
+
grounder_config = GrounderConfig(
|
|
81
|
+
api_base=grounder_api_base, model=grounder_model, api_key=grounder_api_key
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
return GroundedOpenAIChatAgent(
|
|
85
|
+
openai_client=openai_client, grounder_config=grounder_config, **kwargs
|
|
86
|
+
)
|
hud/utils/tests/test_version.py
CHANGED
hud/version.py
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
hud/__init__.py,sha256=KU7G-_Mj6Mjf7trXA6X0ufN6QUmqhVi19NKbnNIvD74,532
|
|
2
2
|
hud/__main__.py,sha256=YR8Dq8OhINOsVfQ55PmRXXg4fEK84Rt_-rMtJ5rvhWo,145
|
|
3
|
-
hud/settings.py,sha256=
|
|
3
|
+
hud/settings.py,sha256=bgq_zstNGlan7UDZOiElY8Aw5ZU4xL7Ds5HP_Xzph1A,2535
|
|
4
4
|
hud/types.py,sha256=DDK7-jcoI0iZbyIOfXlGJy9MpHAGcw_4napLs-v-8vY,6077
|
|
5
|
-
hud/version.py,sha256=
|
|
5
|
+
hud/version.py,sha256=T_tMaYLlvl2YQTkRh6f_ODEmmcIi1QPFX6xOChwfcCA,105
|
|
6
6
|
hud/agents/__init__.py,sha256=UoIkljWdbq4bM0LD-mSaw6w826EqdEjOk7r6glNYwYQ,286
|
|
7
|
-
hud/agents/base.py,sha256=
|
|
8
|
-
hud/agents/claude.py,sha256=
|
|
7
|
+
hud/agents/base.py,sha256=kvHimAckIMGl4mge6KajxjQKd_v1PmUYRZUNRtcggHs,30965
|
|
8
|
+
hud/agents/claude.py,sha256=Ixc05qg-r0H1OoC_DE5Ov6RtODWp7uJcTJJqpmoIob0,15478
|
|
9
|
+
hud/agents/grounded_openai.py,sha256=bUB0sOYkWPx1NfASI97gVixV6CM5GY3K61S_upCSPm8,11176
|
|
9
10
|
hud/agents/langchain.py,sha256=1EgCy8jfjunsWxlPC5XfvfLS6_XZVrIF1ZjtHcrvhYw,9584
|
|
10
11
|
hud/agents/openai.py,sha256=tvFYsZ5yaoLkfjMnHe-COxRttMsLRXBLPdSqgeipQRk,14257
|
|
11
12
|
hud/agents/openai_chat_generic.py,sha256=PQAD4GGE6sHs8R95qpgDBHEbSOJ7WXCYGYFmd3Nic1g,10628
|
|
@@ -14,7 +15,8 @@ hud/agents/misc/response_agent.py,sha256=pnaomb4H-QJm1YKU3tC1YnZXxOlDbTHIXaIH-6N
|
|
|
14
15
|
hud/agents/tests/__init__.py,sha256=W-O-_4i34d9TTyEHV-O_q1Ai1gLhzwDaaPo02_TWQIY,34
|
|
15
16
|
hud/agents/tests/test_base.py,sha256=F39ajSqASGUbPyPoWSY9KARFav62qNTK74W11Tr1Tg4,28970
|
|
16
17
|
hud/agents/tests/test_claude.py,sha256=wqEKlzEvx8obz1sSm4NY0j-Zyt1qWNfDOmRqYIuAEd0,13069
|
|
17
|
-
hud/agents/tests/test_client.py,sha256=
|
|
18
|
+
hud/agents/tests/test_client.py,sha256=uikgh6yhjPPX2RBU4XJQMz1mNox9uXjuwsP8t93id18,13337
|
|
19
|
+
hud/agents/tests/test_grounded_openai_agent.py,sha256=VK8lUvHIjWicMX00VKPE-FZyjiJqTEhb80MuRRa9fVc,5437
|
|
18
20
|
hud/agents/tests/test_openai.py,sha256=lhHowQyLp09oDVwBUjUECoPeH01F16i4O9YIHeugK6E,7028
|
|
19
21
|
hud/cli/__init__.py,sha256=W4McbKAvs8cMIYlruzjV8Z_nxkmOK9ktYWP-WBnD6xo,35804
|
|
20
22
|
hud/cli/__main__.py,sha256=fDH7XITyuDITwSDIVwRso06aouADO0CzTHKqp5TOwJE,143
|
|
@@ -23,7 +25,7 @@ hud/cli/build.py,sha256=_3rNFhNDNAChE95Ou5AqblVfD6QlUwKtcpgrPFChuq8,17742
|
|
|
23
25
|
hud/cli/clone.py,sha256=AwVDIuhr8mHb1oT2Af2HrD25SiTdwATpE6zd93vzLgA,6099
|
|
24
26
|
hud/cli/debug.py,sha256=FNzg9-_ZzUJA1nJfubmop7_2OT5mqnWsdpZyi4AVSXA,14163
|
|
25
27
|
hud/cli/dev.py,sha256=R7YJWIZCUURXzs8ovOCF9V1FwOhsAJT5D3mZQkFmTI4,31134
|
|
26
|
-
hud/cli/eval.py,sha256=
|
|
28
|
+
hud/cli/eval.py,sha256=3ASGiQ4IZPB5EdMoNtwsPmmhO7v3lRmq8uoQCIsf5dM,15770
|
|
27
29
|
hud/cli/hf.py,sha256=EYWL-fEN9SS2QJYU7iIBXs0qa9JIvmMWOMh9a8Ewt9s,15179
|
|
28
30
|
hud/cli/init.py,sha256=7Yqp3gUVmK-vVE_6A9RKhZlSTlwxxb2ylJn1H22TYSY,19573
|
|
29
31
|
hud/cli/list_func.py,sha256=ENxLL4X5uuqAASWZdQuI0k-tEzmlhUn5LATgz3QPQqQ,7065
|
|
@@ -57,7 +59,7 @@ hud/cli/utils/__init__.py,sha256=L6s0oNzY2LugGp9faodCPnjzM-ZUorUH05-HmYOq5hY,35
|
|
|
57
59
|
hud/cli/utils/cursor.py,sha256=fy850p0rVp5k_1wwOCI7rK1SggbselJrywFInSQ2gio,3009
|
|
58
60
|
hud/cli/utils/docker.py,sha256=VTUcoPqxh3uXOgvL6NSqYiSDhyCPRp3jTfFbnIDwumg,3774
|
|
59
61
|
hud/cli/utils/environment.py,sha256=-Z8UkXlRpdGsBkjw-x1EJ2IwcSCrlWaaf25ZoPDMrtw,4225
|
|
60
|
-
hud/cli/utils/interactive.py,sha256=
|
|
62
|
+
hud/cli/utils/interactive.py,sha256=qD25ZhDHI037EAhZUBFUXUpuERM979PnsxFTfpvNxhk,16523
|
|
61
63
|
hud/cli/utils/logging.py,sha256=ZgjjKVPAa7dcfJ6SMBrdfZ63d1UnnhYC-zeh7gFBXsI,8841
|
|
62
64
|
hud/cli/utils/metadata.py,sha256=VBvNNqHS5-sH97H3PhVmdOcyzZ2NGH47fVUUtHBoGLQ,7808
|
|
63
65
|
hud/cli/utils/registry.py,sha256=N49cDHOWDp85EawIhQFQItt-yvFZpfLm74m8l4-LQy4,4349
|
|
@@ -135,10 +137,16 @@ hud/tools/computer/settings.py,sha256=b1XJsEQjB9qhN1xHfVENATkzinEebe0ZPyLzMgCGkK
|
|
|
135
137
|
hud/tools/executors/__init__.py,sha256=jHxfus9SLhkL6YGtebR5RyKYyVAix3yu5EkUp2Q27Kg,732
|
|
136
138
|
hud/tools/executors/base.py,sha256=VP2SiIEBSXvklnkasGxVuy-OmDMd9rjuxZh_YuUQH7A,14481
|
|
137
139
|
hud/tools/executors/pyautogui.py,sha256=11eUQJAgFmHxwd9INAb2L9tgBmEv2Vgn0cwhwvGKlC8,22361
|
|
138
|
-
hud/tools/executors/xdo.py,sha256=
|
|
140
|
+
hud/tools/executors/xdo.py,sha256=UF53DbMX-bRGiHd-O7cCJmCrVaYuP83xiJggER7HcDk,18137
|
|
139
141
|
hud/tools/executors/tests/__init__.py,sha256=opFpGSH6cEqIZgt9izXd3Yt85pC7xkxiYmOZQTHf4AY,32
|
|
140
|
-
hud/tools/executors/tests/test_base_executor.py,sha256=
|
|
142
|
+
hud/tools/executors/tests/test_base_executor.py,sha256=ovh99to5jbQfrCKfCUnDbY-q3oDk_cMmHOVSv7Sn02E,13549
|
|
141
143
|
hud/tools/executors/tests/test_pyautogui_executor.py,sha256=Shv6pnWtlsMXBMlN5DjlttCu6rZ1H447d1QZumduOnU,6640
|
|
144
|
+
hud/tools/grounding/__init__.py,sha256=oazR_qTJqkeGtjy_0w1QW58PQ872PkVwtYI-v2KIX3k,311
|
|
145
|
+
hud/tools/grounding/config.py,sha256=Vsd5ASDZFL7kW7toKkgrYN5D-ZV6ovKZyX4nxRrHvRs,1869
|
|
146
|
+
hud/tools/grounding/grounded_tool.py,sha256=L3O8FzpDoC8ZrnT0xkjlUwAkg7mAbnhK3ju0nE2zCiQ,12679
|
|
147
|
+
hud/tools/grounding/grounder.py,sha256=DwRp7I30ldgdDjxtUJuBh3GWESNUyHbRhCXT28m3xLk,11060
|
|
148
|
+
hud/tools/grounding/tests/__init__.py,sha256=jLw4nmvvvZu2ln2_yEUUKg72IewQ4HaXCUWJuX3ECZY,33
|
|
149
|
+
hud/tools/grounding/tests/test_grounded_tool.py,sha256=kr-wOOJZcfdYfhRSNFnhv8EuIsjbwgHDQbUSH9WnxMw,6446
|
|
142
150
|
hud/tools/tests/__init__.py,sha256=eEYYkxX5Hz9woXVOBJ2H2_CQoEih0vH6nRt3sH2Z8v8,49
|
|
143
151
|
hud/tools/tests/test_base.py,sha256=m6EelJ47F_hMqvRjrr6vEdiW1AtLgz3ZH1V1IUzTxzI,8983
|
|
144
152
|
hud/tools/tests/test_bash.py,sha256=-g9a6sYgKKXRXmqYGYQBgpKEF_OlKE_uDDQXYMx6rT0,5113
|
|
@@ -147,12 +155,13 @@ hud/tools/tests/test_computer.py,sha256=BmrX2PV3wzHC4-xPJnWvenDV_kWt8LF8ia0kELBg
|
|
|
147
155
|
hud/tools/tests/test_computer_actions.py,sha256=YtUNFL7anhpXrcvg8EoUY1CqIV-TAAyaNFLZO9CiJ40,1194
|
|
148
156
|
hud/tools/tests/test_edit.py,sha256=pHw1MSs-P8mDKrwKUDW77vQfoMNwmbrEBt_MkKr2rE0,9734
|
|
149
157
|
hud/tools/tests/test_init.py,sha256=fl4Tf4IUUFOKhdSRHu9GE4mkaTDiXw-2auxj4s84HuE,698
|
|
150
|
-
hud/tools/tests/test_playwright_tool.py,sha256=
|
|
158
|
+
hud/tools/tests/test_playwright_tool.py,sha256=TG0uieerc5wXq_JX66BLfXxphbSYGlDPhSbuoeizMu4,6737
|
|
151
159
|
hud/tools/tests/test_response.py,sha256=pEv3p0k1reSKtjbA8xneu--OuCHydbHHl6YWorV4zOg,2212
|
|
152
160
|
hud/tools/tests/test_tools.py,sha256=paz28V98Am-oR7MBJPDgY-BRV14HQo_0F6X5JIC8aic,4563
|
|
153
|
-
hud/tools/tests/test_tools_init.py,sha256=
|
|
154
|
-
hud/tools/tests/test_utils.py,sha256=
|
|
161
|
+
hud/tools/tests/test_tools_init.py,sha256=aOX9IKji-4ThHEiRYULa7YlIajP0lj3eFPjgzlEg9TI,1727
|
|
162
|
+
hud/tools/tests/test_utils.py,sha256=qaujM1uyTMaKqWIeEgxty5GOFyfSUtrYCEHhmIazoy4,5500
|
|
155
163
|
hud/utils/__init__.py,sha256=ckuIzwqgTxkzASa04XTPsOu_TqsRYUKBWUYfcSi3Xnc,164
|
|
164
|
+
hud/utils/agent_factories.py,sha256=cvfXByqG6gOYHtm1VGeJjCpxoLxM4aJez8rH-AerP_A,3186
|
|
156
165
|
hud/utils/async_utils.py,sha256=5cKrJcnaHV2eJNxeyx0r7fPcdPTDBK7kM9-nLaF51X4,2409
|
|
157
166
|
hud/utils/design.py,sha256=Ymz29qdgqmnXCupDmASCqgkoW8fS6_cg5COXiFUUl50,17621
|
|
158
167
|
hud/utils/mcp.py,sha256=jvCWb5MXlMMObhrbYoiTlI-L9HNkEjLVx8GJ-HbdQ7U,2626
|
|
@@ -165,10 +174,10 @@ hud/utils/tests/test_init.py,sha256=2QLQSGgyP9wJhOvPCusm_zjJad0qApOZi1BXpxcdHXQ,
|
|
|
165
174
|
hud/utils/tests/test_mcp.py,sha256=0pUa16mL-bqbZDXp5NHBnt1gO5o10BOg7zTMHZ1DNPM,4023
|
|
166
175
|
hud/utils/tests/test_progress.py,sha256=QSF7Kpi03Ff_l3mAeqW9qs1nhK50j9vBiSobZq7T4f4,7394
|
|
167
176
|
hud/utils/tests/test_telemetry.py,sha256=5jl7bEx8C8b-FfFUko5pf4UY-mPOR-9HaeL98dGtVHM,2781
|
|
168
|
-
hud/utils/tests/test_version.py,sha256=
|
|
177
|
+
hud/utils/tests/test_version.py,sha256=rjNpZ8hUWFWMassBYVxeyCM-03Rdz8W0C7HPDQuBJfo,160
|
|
169
178
|
hud/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
170
|
-
hud_python-0.4.
|
|
171
|
-
hud_python-0.4.
|
|
172
|
-
hud_python-0.4.
|
|
173
|
-
hud_python-0.4.
|
|
174
|
-
hud_python-0.4.
|
|
179
|
+
hud_python-0.4.22.dist-info/METADATA,sha256=bX0ATTSO7oM9laQrrha-tEityugKU2JbFcAm7m5AGA0,20142
|
|
180
|
+
hud_python-0.4.22.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
181
|
+
hud_python-0.4.22.dist-info/entry_points.txt,sha256=jJbodNFg1m0-CDofe5AHvB4zKBq7sSdP97-ohaQ3ae4,63
|
|
182
|
+
hud_python-0.4.22.dist-info/licenses/LICENSE,sha256=yIzBheVUf86FC1bztAcr7RYWWNxyd3B-UJQ3uddg1HA,1078
|
|
183
|
+
hud_python-0.4.22.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|