hud-python 0.4.1__py3-none-any.whl → 0.4.3__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/__init__.py +22 -22
- hud/agents/__init__.py +13 -15
- hud/agents/base.py +599 -599
- hud/agents/claude.py +373 -373
- hud/agents/langchain.py +261 -250
- hud/agents/misc/__init__.py +7 -7
- hud/agents/misc/response_agent.py +82 -80
- hud/agents/openai.py +352 -352
- hud/agents/openai_chat_generic.py +154 -154
- hud/agents/tests/__init__.py +1 -1
- hud/agents/tests/test_base.py +742 -742
- hud/agents/tests/test_claude.py +324 -324
- hud/agents/tests/test_client.py +363 -363
- hud/agents/tests/test_openai.py +237 -237
- hud/cli/__init__.py +617 -617
- hud/cli/__main__.py +8 -8
- hud/cli/analyze.py +371 -371
- hud/cli/analyze_metadata.py +230 -230
- hud/cli/build.py +498 -427
- hud/cli/clone.py +185 -185
- hud/cli/cursor.py +92 -92
- hud/cli/debug.py +392 -392
- hud/cli/docker_utils.py +83 -83
- hud/cli/init.py +280 -281
- hud/cli/interactive.py +353 -353
- hud/cli/mcp_server.py +764 -756
- hud/cli/pull.py +330 -336
- hud/cli/push.py +404 -370
- hud/cli/remote_runner.py +311 -311
- hud/cli/runner.py +160 -160
- hud/cli/tests/__init__.py +3 -3
- hud/cli/tests/test_analyze.py +284 -284
- hud/cli/tests/test_cli_init.py +265 -265
- hud/cli/tests/test_cli_main.py +27 -27
- hud/cli/tests/test_clone.py +142 -142
- hud/cli/tests/test_cursor.py +253 -253
- hud/cli/tests/test_debug.py +453 -453
- hud/cli/tests/test_mcp_server.py +139 -139
- hud/cli/tests/test_utils.py +388 -388
- hud/cli/utils.py +263 -263
- hud/clients/README.md +143 -143
- hud/clients/__init__.py +16 -16
- hud/clients/base.py +378 -379
- hud/clients/fastmcp.py +222 -222
- hud/clients/mcp_use.py +298 -278
- hud/clients/tests/__init__.py +1 -1
- hud/clients/tests/test_client_integration.py +111 -111
- hud/clients/tests/test_fastmcp.py +342 -342
- hud/clients/tests/test_protocol.py +188 -188
- hud/clients/utils/__init__.py +1 -1
- hud/clients/utils/retry_transport.py +160 -160
- hud/datasets.py +327 -322
- hud/misc/__init__.py +1 -1
- hud/misc/claude_plays_pokemon.py +292 -292
- hud/otel/__init__.py +35 -35
- hud/otel/collector.py +142 -142
- hud/otel/config.py +164 -164
- hud/otel/context.py +536 -536
- hud/otel/exporters.py +366 -366
- hud/otel/instrumentation.py +97 -97
- hud/otel/processors.py +118 -118
- hud/otel/tests/__init__.py +1 -1
- hud/otel/tests/test_processors.py +197 -197
- hud/server/__init__.py +5 -5
- hud/server/context.py +114 -114
- hud/server/helper/__init__.py +5 -5
- hud/server/low_level.py +132 -132
- hud/server/server.py +170 -166
- hud/server/tests/__init__.py +3 -3
- hud/settings.py +73 -73
- hud/shared/__init__.py +5 -5
- hud/shared/exceptions.py +180 -180
- hud/shared/requests.py +264 -264
- hud/shared/tests/test_exceptions.py +157 -157
- hud/shared/tests/test_requests.py +275 -275
- hud/telemetry/__init__.py +25 -25
- hud/telemetry/instrument.py +379 -379
- hud/telemetry/job.py +309 -309
- hud/telemetry/replay.py +74 -74
- hud/telemetry/trace.py +83 -83
- hud/tools/__init__.py +33 -33
- hud/tools/base.py +365 -365
- hud/tools/bash.py +161 -161
- hud/tools/computer/__init__.py +15 -15
- hud/tools/computer/anthropic.py +437 -437
- hud/tools/computer/hud.py +376 -376
- hud/tools/computer/openai.py +295 -295
- hud/tools/computer/settings.py +82 -82
- hud/tools/edit.py +314 -314
- hud/tools/executors/__init__.py +30 -30
- hud/tools/executors/base.py +539 -539
- hud/tools/executors/pyautogui.py +621 -621
- hud/tools/executors/tests/__init__.py +1 -1
- hud/tools/executors/tests/test_base_executor.py +338 -338
- hud/tools/executors/tests/test_pyautogui_executor.py +165 -165
- hud/tools/executors/xdo.py +511 -511
- hud/tools/playwright.py +412 -412
- hud/tools/tests/__init__.py +3 -3
- hud/tools/tests/test_base.py +282 -282
- hud/tools/tests/test_bash.py +158 -158
- hud/tools/tests/test_bash_extended.py +197 -197
- hud/tools/tests/test_computer.py +425 -425
- hud/tools/tests/test_computer_actions.py +34 -34
- hud/tools/tests/test_edit.py +259 -259
- hud/tools/tests/test_init.py +27 -27
- hud/tools/tests/test_playwright_tool.py +183 -183
- hud/tools/tests/test_tools.py +145 -145
- hud/tools/tests/test_utils.py +156 -156
- hud/tools/types.py +72 -72
- hud/tools/utils.py +50 -50
- hud/types.py +136 -136
- hud/utils/__init__.py +10 -10
- hud/utils/async_utils.py +65 -65
- hud/utils/design.py +236 -168
- hud/utils/mcp.py +55 -55
- hud/utils/progress.py +149 -149
- hud/utils/telemetry.py +66 -66
- hud/utils/tests/test_async_utils.py +173 -173
- hud/utils/tests/test_init.py +17 -17
- hud/utils/tests/test_progress.py +261 -261
- hud/utils/tests/test_telemetry.py +82 -82
- hud/utils/tests/test_version.py +8 -8
- hud/version.py +7 -7
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/METADATA +10 -8
- hud_python-0.4.3.dist-info/RECORD +131 -0
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/licenses/LICENSE +21 -21
- hud/agents/art.py +0 -101
- hud_python-0.4.1.dist-info/RECORD +0 -132
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/WHEEL +0 -0
- {hud_python-0.4.1.dist-info → hud_python-0.4.3.dist-info}/entry_points.txt +0 -0
hud/cli/tests/test_mcp_server.py
CHANGED
|
@@ -1,139 +1,139 @@
|
|
|
1
|
-
"""Tests for hud.cli.mcp_server module."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
from typing import TYPE_CHECKING
|
|
6
|
-
from unittest.mock import MagicMock, patch
|
|
7
|
-
|
|
8
|
-
import pytest
|
|
9
|
-
|
|
10
|
-
from hud.cli.mcp_server import (
|
|
11
|
-
create_proxy_server,
|
|
12
|
-
get_docker_cmd,
|
|
13
|
-
get_image_name,
|
|
14
|
-
inject_supervisor,
|
|
15
|
-
run_mcp_dev_server,
|
|
16
|
-
update_pyproject_toml,
|
|
17
|
-
)
|
|
18
|
-
|
|
19
|
-
if TYPE_CHECKING:
|
|
20
|
-
from pathlib import Path
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
class TestCreateMCPServer:
|
|
24
|
-
"""Test MCP server creation."""
|
|
25
|
-
|
|
26
|
-
def test_create_mcp_server(self) -> None:
|
|
27
|
-
"""Test that MCP server is created with correct configuration."""
|
|
28
|
-
mcp = create_proxy_server(".", "test-image:latest")
|
|
29
|
-
assert mcp._mcp_server.name == "HUD Dev Proxy - test-image:latest"
|
|
30
|
-
# Proxy server doesn't define its own tools, it forwards to Docker containers
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class TestDockerUtils:
|
|
34
|
-
"""Test Docker utility functions."""
|
|
35
|
-
|
|
36
|
-
def test_get_docker_cmd(self) -> None:
|
|
37
|
-
"""Test extracting CMD from Docker image."""
|
|
38
|
-
with patch("subprocess.run") as mock_run:
|
|
39
|
-
mock_result = MagicMock()
|
|
40
|
-
mock_result.returncode = 0
|
|
41
|
-
mock_result.stdout = '["python", "-m", "server"]'
|
|
42
|
-
mock_run.return_value = mock_result
|
|
43
|
-
|
|
44
|
-
cmd = get_docker_cmd("test-image:latest")
|
|
45
|
-
assert cmd is None
|
|
46
|
-
|
|
47
|
-
def test_get_docker_cmd_failure(self) -> None:
|
|
48
|
-
"""Test handling when Docker inspect fails."""
|
|
49
|
-
import subprocess
|
|
50
|
-
|
|
51
|
-
with patch("subprocess.run") as mock_run:
|
|
52
|
-
# check=True causes CalledProcessError on non-zero return
|
|
53
|
-
mock_run.side_effect = subprocess.CalledProcessError(1, "docker inspect")
|
|
54
|
-
|
|
55
|
-
cmd = get_docker_cmd("test-image:latest")
|
|
56
|
-
assert cmd is None
|
|
57
|
-
|
|
58
|
-
def test_inject_supervisor(self) -> None:
|
|
59
|
-
"""Test supervisor injection into Docker CMD."""
|
|
60
|
-
original_cmd = ["python", "-m", "server"]
|
|
61
|
-
modified = inject_supervisor(original_cmd)
|
|
62
|
-
|
|
63
|
-
assert modified[0] == "sh"
|
|
64
|
-
assert modified[1] == "-c"
|
|
65
|
-
assert "watchfiles" in modified[2]
|
|
66
|
-
assert "python -m server" in modified[2]
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class TestImageResolution:
|
|
70
|
-
"""Test image name resolution."""
|
|
71
|
-
|
|
72
|
-
def test_get_image_name_override(self) -> None:
|
|
73
|
-
"""Test image name with override."""
|
|
74
|
-
name, source = get_image_name(".", "custom-image:v1")
|
|
75
|
-
assert name == "custom-image:v1"
|
|
76
|
-
assert source == "override"
|
|
77
|
-
|
|
78
|
-
def test_get_image_name_from_pyproject(self, tmp_path: Path) -> None:
|
|
79
|
-
"""Test image name from pyproject.toml."""
|
|
80
|
-
pyproject = tmp_path / "pyproject.toml"
|
|
81
|
-
pyproject.write_text("""
|
|
82
|
-
[tool.hud]
|
|
83
|
-
image = "my-project:latest"
|
|
84
|
-
""")
|
|
85
|
-
|
|
86
|
-
name, source = get_image_name(str(tmp_path))
|
|
87
|
-
assert name == "my-project:latest"
|
|
88
|
-
assert source == "cache"
|
|
89
|
-
|
|
90
|
-
def test_get_image_name_auto_generate(self, tmp_path: Path) -> None:
|
|
91
|
-
"""Test auto-generated image name."""
|
|
92
|
-
test_dir = tmp_path / "my_test_project"
|
|
93
|
-
test_dir.mkdir()
|
|
94
|
-
|
|
95
|
-
name, source = get_image_name(str(test_dir))
|
|
96
|
-
assert name == "hud-my-test-project:dev"
|
|
97
|
-
assert source == "auto"
|
|
98
|
-
|
|
99
|
-
def test_update_pyproject_toml(self, tmp_path: Path) -> None:
|
|
100
|
-
"""Test updating pyproject.toml with image name."""
|
|
101
|
-
pyproject = tmp_path / "pyproject.toml"
|
|
102
|
-
pyproject.write_text("""
|
|
103
|
-
[project]
|
|
104
|
-
name = "test"
|
|
105
|
-
""")
|
|
106
|
-
|
|
107
|
-
update_pyproject_toml(str(tmp_path), "new-image:v1", silent=True)
|
|
108
|
-
|
|
109
|
-
content = pyproject.read_text()
|
|
110
|
-
assert "[tool.hud]" in content
|
|
111
|
-
assert 'image = "new-image:v1"' in content
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
class TestRunMCPDevServer:
|
|
115
|
-
"""Test the main server runner."""
|
|
116
|
-
|
|
117
|
-
def test_run_dev_server_image_not_found(self) -> None:
|
|
118
|
-
"""Test handling when Docker image doesn't exist."""
|
|
119
|
-
import click
|
|
120
|
-
|
|
121
|
-
with (
|
|
122
|
-
patch("hud.cli.mcp_server.image_exists", return_value=False),
|
|
123
|
-
patch("click.confirm", return_value=False),
|
|
124
|
-
pytest.raises(click.Abort),
|
|
125
|
-
):
|
|
126
|
-
run_mcp_dev_server(
|
|
127
|
-
directory=".",
|
|
128
|
-
image="missing:latest",
|
|
129
|
-
build=False,
|
|
130
|
-
no_cache=False,
|
|
131
|
-
transport="http",
|
|
132
|
-
port=8765,
|
|
133
|
-
no_reload=False,
|
|
134
|
-
verbose=False,
|
|
135
|
-
inspector=False,
|
|
136
|
-
no_logs=False,
|
|
137
|
-
docker_args=[],
|
|
138
|
-
interactive=False,
|
|
139
|
-
)
|
|
1
|
+
"""Tests for hud.cli.mcp_server module."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
from unittest.mock import MagicMock, patch
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
|
|
10
|
+
from hud.cli.mcp_server import (
|
|
11
|
+
create_proxy_server,
|
|
12
|
+
get_docker_cmd,
|
|
13
|
+
get_image_name,
|
|
14
|
+
inject_supervisor,
|
|
15
|
+
run_mcp_dev_server,
|
|
16
|
+
update_pyproject_toml,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class TestCreateMCPServer:
|
|
24
|
+
"""Test MCP server creation."""
|
|
25
|
+
|
|
26
|
+
def test_create_mcp_server(self) -> None:
|
|
27
|
+
"""Test that MCP server is created with correct configuration."""
|
|
28
|
+
mcp = create_proxy_server(".", "test-image:latest")
|
|
29
|
+
assert mcp._mcp_server.name == "HUD Dev Proxy - test-image:latest"
|
|
30
|
+
# Proxy server doesn't define its own tools, it forwards to Docker containers
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TestDockerUtils:
|
|
34
|
+
"""Test Docker utility functions."""
|
|
35
|
+
|
|
36
|
+
def test_get_docker_cmd(self) -> None:
|
|
37
|
+
"""Test extracting CMD from Docker image."""
|
|
38
|
+
with patch("subprocess.run") as mock_run:
|
|
39
|
+
mock_result = MagicMock()
|
|
40
|
+
mock_result.returncode = 0
|
|
41
|
+
mock_result.stdout = '["python", "-m", "server"]'
|
|
42
|
+
mock_run.return_value = mock_result
|
|
43
|
+
|
|
44
|
+
cmd = get_docker_cmd("test-image:latest")
|
|
45
|
+
assert cmd is None
|
|
46
|
+
|
|
47
|
+
def test_get_docker_cmd_failure(self) -> None:
|
|
48
|
+
"""Test handling when Docker inspect fails."""
|
|
49
|
+
import subprocess
|
|
50
|
+
|
|
51
|
+
with patch("subprocess.run") as mock_run:
|
|
52
|
+
# check=True causes CalledProcessError on non-zero return
|
|
53
|
+
mock_run.side_effect = subprocess.CalledProcessError(1, "docker inspect")
|
|
54
|
+
|
|
55
|
+
cmd = get_docker_cmd("test-image:latest")
|
|
56
|
+
assert cmd is None
|
|
57
|
+
|
|
58
|
+
def test_inject_supervisor(self) -> None:
|
|
59
|
+
"""Test supervisor injection into Docker CMD."""
|
|
60
|
+
original_cmd = ["python", "-m", "server"]
|
|
61
|
+
modified = inject_supervisor(original_cmd)
|
|
62
|
+
|
|
63
|
+
assert modified[0] == "sh"
|
|
64
|
+
assert modified[1] == "-c"
|
|
65
|
+
assert "watchfiles" in modified[2]
|
|
66
|
+
assert "python -m server" in modified[2]
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class TestImageResolution:
|
|
70
|
+
"""Test image name resolution."""
|
|
71
|
+
|
|
72
|
+
def test_get_image_name_override(self) -> None:
|
|
73
|
+
"""Test image name with override."""
|
|
74
|
+
name, source = get_image_name(".", "custom-image:v1")
|
|
75
|
+
assert name == "custom-image:v1"
|
|
76
|
+
assert source == "override"
|
|
77
|
+
|
|
78
|
+
def test_get_image_name_from_pyproject(self, tmp_path: Path) -> None:
|
|
79
|
+
"""Test image name from pyproject.toml."""
|
|
80
|
+
pyproject = tmp_path / "pyproject.toml"
|
|
81
|
+
pyproject.write_text("""
|
|
82
|
+
[tool.hud]
|
|
83
|
+
image = "my-project:latest"
|
|
84
|
+
""")
|
|
85
|
+
|
|
86
|
+
name, source = get_image_name(str(tmp_path))
|
|
87
|
+
assert name == "my-project:latest"
|
|
88
|
+
assert source == "cache"
|
|
89
|
+
|
|
90
|
+
def test_get_image_name_auto_generate(self, tmp_path: Path) -> None:
|
|
91
|
+
"""Test auto-generated image name."""
|
|
92
|
+
test_dir = tmp_path / "my_test_project"
|
|
93
|
+
test_dir.mkdir()
|
|
94
|
+
|
|
95
|
+
name, source = get_image_name(str(test_dir))
|
|
96
|
+
assert name == "hud-my-test-project:dev"
|
|
97
|
+
assert source == "auto"
|
|
98
|
+
|
|
99
|
+
def test_update_pyproject_toml(self, tmp_path: Path) -> None:
|
|
100
|
+
"""Test updating pyproject.toml with image name."""
|
|
101
|
+
pyproject = tmp_path / "pyproject.toml"
|
|
102
|
+
pyproject.write_text("""
|
|
103
|
+
[project]
|
|
104
|
+
name = "test"
|
|
105
|
+
""")
|
|
106
|
+
|
|
107
|
+
update_pyproject_toml(str(tmp_path), "new-image:v1", silent=True)
|
|
108
|
+
|
|
109
|
+
content = pyproject.read_text()
|
|
110
|
+
assert "[tool.hud]" in content
|
|
111
|
+
assert 'image = "new-image:v1"' in content
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
class TestRunMCPDevServer:
|
|
115
|
+
"""Test the main server runner."""
|
|
116
|
+
|
|
117
|
+
def test_run_dev_server_image_not_found(self) -> None:
|
|
118
|
+
"""Test handling when Docker image doesn't exist."""
|
|
119
|
+
import click
|
|
120
|
+
|
|
121
|
+
with (
|
|
122
|
+
patch("hud.cli.mcp_server.image_exists", return_value=False),
|
|
123
|
+
patch("click.confirm", return_value=False),
|
|
124
|
+
pytest.raises(click.Abort),
|
|
125
|
+
):
|
|
126
|
+
run_mcp_dev_server(
|
|
127
|
+
directory=".",
|
|
128
|
+
image="missing:latest",
|
|
129
|
+
build=False,
|
|
130
|
+
no_cache=False,
|
|
131
|
+
transport="http",
|
|
132
|
+
port=8765,
|
|
133
|
+
no_reload=False,
|
|
134
|
+
verbose=False,
|
|
135
|
+
inspector=False,
|
|
136
|
+
no_logs=False,
|
|
137
|
+
docker_args=[],
|
|
138
|
+
interactive=False,
|
|
139
|
+
)
|