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/docker_utils.py
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
|
-
"""Docker utilities for HUD CLI."""
|
|
2
|
-
|
|
3
|
-
from __future__ import annotations
|
|
4
|
-
|
|
5
|
-
import json
|
|
6
|
-
import subprocess
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def get_docker_cmd(image: str) -> list[str] | None:
|
|
10
|
-
"""
|
|
11
|
-
Extract the CMD from a Docker image.
|
|
12
|
-
|
|
13
|
-
Args:
|
|
14
|
-
image: Docker image name
|
|
15
|
-
|
|
16
|
-
Returns:
|
|
17
|
-
List of command parts or None if not found
|
|
18
|
-
"""
|
|
19
|
-
try:
|
|
20
|
-
result = subprocess.run( # noqa: S603
|
|
21
|
-
["docker", "inspect", image], # noqa: S607
|
|
22
|
-
capture_output=True,
|
|
23
|
-
text=True,
|
|
24
|
-
check=True,
|
|
25
|
-
)
|
|
26
|
-
|
|
27
|
-
inspect_data = json.loads(result.stdout)
|
|
28
|
-
if inspect_data and len(inspect_data) > 0 and isinstance(inspect_data[0], dict):
|
|
29
|
-
config = inspect_data[0].get("Config", {})
|
|
30
|
-
cmd = config.get("Cmd", [])
|
|
31
|
-
return cmd if cmd else None
|
|
32
|
-
|
|
33
|
-
except (subprocess.CalledProcessError, json.JSONDecodeError, KeyError):
|
|
34
|
-
return None
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def inject_supervisor(cmd: list[str]) -> list[str]:
|
|
38
|
-
"""
|
|
39
|
-
Inject watchfiles CLI supervisor into a Docker CMD.
|
|
40
|
-
|
|
41
|
-
For shell commands, we inject before the last exec command.
|
|
42
|
-
For direct commands, we wrap the entire command.
|
|
43
|
-
|
|
44
|
-
Args:
|
|
45
|
-
cmd: Original Docker CMD
|
|
46
|
-
|
|
47
|
-
Returns:
|
|
48
|
-
Modified CMD with watchfiles supervisor injected
|
|
49
|
-
"""
|
|
50
|
-
if not cmd:
|
|
51
|
-
return cmd
|
|
52
|
-
|
|
53
|
-
# Handle shell commands that might have background processes
|
|
54
|
-
if cmd[0] in ["sh", "bash"] and len(cmd) >= 3 and cmd[1] == "-c":
|
|
55
|
-
shell_cmd = cmd[2]
|
|
56
|
-
|
|
57
|
-
# Look for 'exec' in the shell command - this is the last command
|
|
58
|
-
if " exec " in shell_cmd:
|
|
59
|
-
# Replace only the exec'd command with watchfiles
|
|
60
|
-
parts = shell_cmd.rsplit(" exec ", 1)
|
|
61
|
-
if len(parts) == 2:
|
|
62
|
-
# Extract the actual command after exec
|
|
63
|
-
last_cmd = parts[1].strip()
|
|
64
|
-
# Use watchfiles with logs redirected to stderr (which won't interfere with MCP on stdout) # noqa: E501
|
|
65
|
-
new_shell_cmd = f"{parts[0]} exec watchfiles --verbose '{last_cmd}' /app/src"
|
|
66
|
-
return [cmd[0], cmd[1], new_shell_cmd]
|
|
67
|
-
else:
|
|
68
|
-
# No exec, the whole thing is the command
|
|
69
|
-
return ["sh", "-c", f"watchfiles --verbose '{shell_cmd}' /app/src"]
|
|
70
|
-
|
|
71
|
-
# Direct command - wrap with watchfiles
|
|
72
|
-
watchfiles_cmd = " ".join(cmd)
|
|
73
|
-
return ["sh", "-c", f"watchfiles --verbose '{watchfiles_cmd}' /app/src"]
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
def image_exists(image_name: str) -> bool:
|
|
77
|
-
"""Check if a Docker image exists locally."""
|
|
78
|
-
result = subprocess.run( # noqa: S603
|
|
79
|
-
["docker", "image", "inspect", image_name], # noqa: S607
|
|
80
|
-
stdout=subprocess.DEVNULL,
|
|
81
|
-
stderr=subprocess.DEVNULL,
|
|
82
|
-
)
|
|
83
|
-
return result.returncode == 0
|
|
1
|
+
"""Docker utilities for HUD CLI."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
import subprocess
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def get_docker_cmd(image: str) -> list[str] | None:
|
|
10
|
+
"""
|
|
11
|
+
Extract the CMD from a Docker image.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
image: Docker image name
|
|
15
|
+
|
|
16
|
+
Returns:
|
|
17
|
+
List of command parts or None if not found
|
|
18
|
+
"""
|
|
19
|
+
try:
|
|
20
|
+
result = subprocess.run( # noqa: S603
|
|
21
|
+
["docker", "inspect", image], # noqa: S607
|
|
22
|
+
capture_output=True,
|
|
23
|
+
text=True,
|
|
24
|
+
check=True,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
inspect_data = json.loads(result.stdout)
|
|
28
|
+
if inspect_data and len(inspect_data) > 0 and isinstance(inspect_data[0], dict):
|
|
29
|
+
config = inspect_data[0].get("Config", {})
|
|
30
|
+
cmd = config.get("Cmd", [])
|
|
31
|
+
return cmd if cmd else None
|
|
32
|
+
|
|
33
|
+
except (subprocess.CalledProcessError, json.JSONDecodeError, KeyError):
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def inject_supervisor(cmd: list[str]) -> list[str]:
|
|
38
|
+
"""
|
|
39
|
+
Inject watchfiles CLI supervisor into a Docker CMD.
|
|
40
|
+
|
|
41
|
+
For shell commands, we inject before the last exec command.
|
|
42
|
+
For direct commands, we wrap the entire command.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
cmd: Original Docker CMD
|
|
46
|
+
|
|
47
|
+
Returns:
|
|
48
|
+
Modified CMD with watchfiles supervisor injected
|
|
49
|
+
"""
|
|
50
|
+
if not cmd:
|
|
51
|
+
return cmd
|
|
52
|
+
|
|
53
|
+
# Handle shell commands that might have background processes
|
|
54
|
+
if cmd[0] in ["sh", "bash"] and len(cmd) >= 3 and cmd[1] == "-c":
|
|
55
|
+
shell_cmd = cmd[2]
|
|
56
|
+
|
|
57
|
+
# Look for 'exec' in the shell command - this is the last command
|
|
58
|
+
if " exec " in shell_cmd:
|
|
59
|
+
# Replace only the exec'd command with watchfiles
|
|
60
|
+
parts = shell_cmd.rsplit(" exec ", 1)
|
|
61
|
+
if len(parts) == 2:
|
|
62
|
+
# Extract the actual command after exec
|
|
63
|
+
last_cmd = parts[1].strip()
|
|
64
|
+
# Use watchfiles with logs redirected to stderr (which won't interfere with MCP on stdout) # noqa: E501
|
|
65
|
+
new_shell_cmd = f"{parts[0]} exec watchfiles --verbose '{last_cmd}' /app/src"
|
|
66
|
+
return [cmd[0], cmd[1], new_shell_cmd]
|
|
67
|
+
else:
|
|
68
|
+
# No exec, the whole thing is the command
|
|
69
|
+
return ["sh", "-c", f"watchfiles --verbose '{shell_cmd}' /app/src"]
|
|
70
|
+
|
|
71
|
+
# Direct command - wrap with watchfiles
|
|
72
|
+
watchfiles_cmd = " ".join(cmd)
|
|
73
|
+
return ["sh", "-c", f"watchfiles --verbose '{watchfiles_cmd}' /app/src"]
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def image_exists(image_name: str) -> bool:
|
|
77
|
+
"""Check if a Docker image exists locally."""
|
|
78
|
+
result = subprocess.run( # noqa: S603
|
|
79
|
+
["docker", "image", "inspect", image_name], # noqa: S607
|
|
80
|
+
stdout=subprocess.DEVNULL,
|
|
81
|
+
stderr=subprocess.DEVNULL,
|
|
82
|
+
)
|
|
83
|
+
return result.returncode == 0
|