hud-python 0.4.35__py3-none-any.whl → 0.4.36__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/tests/test_claude.py +32 -7
- hud/agents/tests/test_openai.py +29 -6
- hud/cli/__init__.py +209 -75
- hud/cli/build.py +9 -4
- hud/cli/dev.py +20 -39
- hud/cli/eval.py +3 -2
- hud/cli/flows/tasks.py +1 -0
- hud/cli/init.py +222 -629
- hud/cli/pull.py +6 -0
- hud/cli/push.py +2 -1
- hud/cli/rl/remote_runner.py +3 -1
- hud/cli/tests/test_build.py +3 -27
- hud/cli/tests/test_mcp_server.py +1 -12
- hud/cli/utils/config.py +85 -0
- hud/cli/utils/docker.py +21 -39
- hud/cli/utils/environment.py +4 -3
- hud/cli/utils/interactive.py +2 -1
- hud/cli/utils/local_runner.py +204 -0
- hud/cli/utils/metadata.py +3 -1
- hud/cli/utils/package_runner.py +292 -0
- hud/cli/utils/remote_runner.py +4 -1
- hud/clients/mcp_use.py +30 -7
- hud/datasets/parallel.py +3 -1
- hud/datasets/runner.py +4 -1
- hud/otel/context.py +38 -4
- hud/rl/buffer.py +3 -0
- hud/rl/tests/test_learner.py +1 -1
- hud/server/server.py +157 -1
- hud/settings.py +38 -0
- hud/shared/hints.py +1 -1
- hud/utils/tests/test_version.py +1 -1
- hud/version.py +1 -1
- {hud_python-0.4.35.dist-info → hud_python-0.4.36.dist-info}/METADATA +30 -12
- {hud_python-0.4.35.dist-info → hud_python-0.4.36.dist-info}/RECORD +37 -34
- {hud_python-0.4.35.dist-info → hud_python-0.4.36.dist-info}/WHEEL +0 -0
- {hud_python-0.4.35.dist-info → hud_python-0.4.36.dist-info}/entry_points.txt +0 -0
- {hud_python-0.4.35.dist-info → hud_python-0.4.36.dist-info}/licenses/LICENSE +0 -0
hud/cli/dev.py
CHANGED
|
@@ -14,7 +14,7 @@ from fastmcp import FastMCP
|
|
|
14
14
|
|
|
15
15
|
from hud.utils.hud_console import HUDConsole
|
|
16
16
|
|
|
17
|
-
from .utils.docker import get_docker_cmd
|
|
17
|
+
from .utils.docker import get_docker_cmd
|
|
18
18
|
from .utils.environment import (
|
|
19
19
|
build_environment,
|
|
20
20
|
get_image_name,
|
|
@@ -42,7 +42,7 @@ def create_proxy_server(
|
|
|
42
42
|
interactive: bool = False,
|
|
43
43
|
) -> FastMCP:
|
|
44
44
|
"""Create an HTTP proxy server that forwards to Docker container with hot-reload."""
|
|
45
|
-
|
|
45
|
+
project_path = Path(directory)
|
|
46
46
|
|
|
47
47
|
# Get the original CMD from the image
|
|
48
48
|
original_cmd = get_docker_cmd(image_name)
|
|
@@ -66,15 +66,22 @@ def create_proxy_server(
|
|
|
66
66
|
"--name",
|
|
67
67
|
container_name,
|
|
68
68
|
"-v",
|
|
69
|
-
f"{
|
|
69
|
+
f"{project_path.absolute()}:/app:rw",
|
|
70
70
|
"-e",
|
|
71
|
-
"PYTHONPATH=/app
|
|
71
|
+
"PYTHONPATH=/app",
|
|
72
|
+
"-e",
|
|
73
|
+
"PYTHONUNBUFFERED=1", # Ensure Python output is not buffered
|
|
72
74
|
]
|
|
73
75
|
|
|
74
76
|
# Add user-provided Docker arguments
|
|
75
77
|
if docker_args:
|
|
76
78
|
docker_cmd.extend(docker_args)
|
|
77
79
|
|
|
80
|
+
# Append the image name and CMD
|
|
81
|
+
docker_cmd.append(image_name)
|
|
82
|
+
if original_cmd:
|
|
83
|
+
docker_cmd.extend(original_cmd)
|
|
84
|
+
|
|
78
85
|
# Disable hot-reload if interactive mode is enabled
|
|
79
86
|
if interactive:
|
|
80
87
|
no_reload = True
|
|
@@ -84,17 +91,6 @@ def create_proxy_server(
|
|
|
84
91
|
hud_console.warning("Cannot use --full-reload with --no-reload, ignoring --full-reload")
|
|
85
92
|
full_reload = False
|
|
86
93
|
|
|
87
|
-
if not no_reload and not full_reload:
|
|
88
|
-
# Standard hot-reload: inject supervisor for server restart within container
|
|
89
|
-
modified_cmd = inject_supervisor(original_cmd)
|
|
90
|
-
docker_cmd.extend(["--entrypoint", modified_cmd[0]])
|
|
91
|
-
docker_cmd.append(image_name)
|
|
92
|
-
docker_cmd.extend(modified_cmd[1:])
|
|
93
|
-
else:
|
|
94
|
-
# No reload or full reload: use original CMD without supervisor
|
|
95
|
-
# Note: Full reload logic (container restart) would be implemented here in the future
|
|
96
|
-
docker_cmd.append(image_name)
|
|
97
|
-
|
|
98
94
|
# Create configuration following MCPConfig schema
|
|
99
95
|
config = {
|
|
100
96
|
"mcpServers": {
|
|
@@ -108,17 +104,12 @@ def create_proxy_server(
|
|
|
108
104
|
|
|
109
105
|
# Debug output - only if verbose
|
|
110
106
|
if verbose:
|
|
111
|
-
if
|
|
112
|
-
hud_console.info("Mode: Hot-reload (server restart within container)")
|
|
113
|
-
hud_console.info("Watching: /app/src for changes")
|
|
114
|
-
elif full_reload:
|
|
107
|
+
if full_reload:
|
|
115
108
|
hud_console.info("Mode: Full reload (container restart on file changes)")
|
|
116
|
-
hud_console.info(
|
|
117
|
-
"Note: Full container restart not yet implemented, using no-reload mode"
|
|
118
|
-
)
|
|
109
|
+
hud_console.info("Note: Full container restart not yet implemented")
|
|
119
110
|
else:
|
|
120
|
-
hud_console.info("Mode:
|
|
121
|
-
hud_console.info("
|
|
111
|
+
hud_console.info("Mode: Container manages its own reload")
|
|
112
|
+
hud_console.info("The container's CMD determines reload behavior")
|
|
122
113
|
hud_console.command_example(f"docker logs -f {container_name}", "View container logs")
|
|
123
114
|
|
|
124
115
|
# Show the full Docker command if there are environment variables
|
|
@@ -227,10 +218,10 @@ async def start_mcp_proxy(
|
|
|
227
218
|
stderr_handler = logging.StreamHandler(sys.stderr)
|
|
228
219
|
root_logger.addHandler(stderr_handler)
|
|
229
220
|
|
|
230
|
-
#
|
|
231
|
-
|
|
232
|
-
if not
|
|
233
|
-
hud_console.error(f"
|
|
221
|
+
# Validate project directory exists
|
|
222
|
+
project_path = Path(directory)
|
|
223
|
+
if not project_path.exists():
|
|
224
|
+
hud_console.error(f"Project directory not found: {project_path}")
|
|
234
225
|
raise click.Abort
|
|
235
226
|
|
|
236
227
|
# Extract container name from the proxy configuration (must match create_proxy_server naming)
|
|
@@ -774,16 +765,6 @@ def run_mcp_dev_server(
|
|
|
774
765
|
elif not interactive:
|
|
775
766
|
hud_console.progress_message("🧪 Run with --interactive for interactive testing mode")
|
|
776
767
|
|
|
777
|
-
# Disable logs and hot-reload if interactive mode is enabled
|
|
778
|
-
if interactive and not no_logs:
|
|
779
|
-
hud_console.warning("Docker logs disabled in interactive mode for better UI experience")
|
|
780
|
-
no_logs = True
|
|
781
|
-
# if not no_reload:
|
|
782
|
-
# hud_console.warning(
|
|
783
|
-
# "Hot-reload disabled in interactive mode to prevent output interference"
|
|
784
|
-
# )
|
|
785
|
-
# no_reload = True
|
|
786
|
-
|
|
787
768
|
# Show configuration as JSON (just the server config, not wrapped)
|
|
788
769
|
full_config = {}
|
|
789
770
|
full_config[server_name] = server_config
|
|
@@ -796,9 +777,9 @@ def run_mcp_dev_server(
|
|
|
796
777
|
"Connect to Cursor (be careful with multiple windows as that may interfere with the proxy)"
|
|
797
778
|
)
|
|
798
779
|
hud_console.link(deeplink)
|
|
780
|
+
|
|
799
781
|
hud_console.info("") # Empty line
|
|
800
782
|
|
|
801
|
-
# Start the proxy (pass original port, start_mcp_proxy will find actual port again)
|
|
802
783
|
try:
|
|
803
784
|
asyncio.run(
|
|
804
785
|
start_mcp_proxy(
|
hud/cli/eval.py
CHANGED
|
@@ -600,12 +600,12 @@ def eval_command(
|
|
|
600
600
|
if not settings.anthropic_api_key:
|
|
601
601
|
hud_console.error("ANTHROPIC_API_KEY is required for Claude agent")
|
|
602
602
|
hud_console.info(
|
|
603
|
-
"Set it in your environment or
|
|
603
|
+
"Set it in your environment or run: hud set ANTHROPIC_API_KEY=your-key-here"
|
|
604
604
|
)
|
|
605
605
|
raise typer.Exit(1)
|
|
606
606
|
elif agent == "openai" and not settings.openai_api_key:
|
|
607
607
|
hud_console.error("OPENAI_API_KEY is required for OpenAI agent")
|
|
608
|
-
hud_console.info("Set it in your environment or
|
|
608
|
+
hud_console.info("Set it in your environment or run: hud set OPENAI_API_KEY=your-key-here")
|
|
609
609
|
raise typer.Exit(1)
|
|
610
610
|
elif agent == "vllm":
|
|
611
611
|
if model:
|
|
@@ -618,6 +618,7 @@ def eval_command(
|
|
|
618
618
|
if not settings.api_key:
|
|
619
619
|
hud_console.warning("HUD_API_KEY not set. Some features may be limited.")
|
|
620
620
|
hud_console.info("Get your API key at: https://app.hud.so")
|
|
621
|
+
hud_console.info("Set it in your environment or run: hud set HUD_API_KEY=your-key-here")
|
|
621
622
|
|
|
622
623
|
# Parse allowed tools
|
|
623
624
|
allowed_tools_list = (
|
hud/cli/flows/tasks.py
CHANGED
|
@@ -171,6 +171,7 @@ def convert_tasks_to_remote(tasks_file: str) -> str:
|
|
|
171
171
|
|
|
172
172
|
if not settings.api_key or not settings.api_key.strip():
|
|
173
173
|
hud_console.error("HUD_API_KEY is not set")
|
|
174
|
+
hud_console.info("Set it in your environment or run: hud set HUD_API_KEY=your-key-here")
|
|
174
175
|
raise typer.Exit(1)
|
|
175
176
|
|
|
176
177
|
# Load tasks (supports .json and .jsonl)
|