hud-python 0.4.18__tar.gz → 0.4.20__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.
Potentially problematic release.
This version of hud-python might be problematic. Click here for more details.
- {hud_python-0.4.18 → hud_python-0.4.20}/PKG-INFO +1 -1
- {hud_python-0.4.18 → hud_python-0.4.20}/examples/README.md +20 -30
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/base.py +30 -11
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/claude.py +41 -27
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/openai_chat_generic.py +11 -12
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/clients/base.py +10 -22
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/datasets/task.py +5 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/playwright.py +1 -1
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/tests/test_version.py +1 -1
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/version.py +1 -1
- {hud_python-0.4.18 → hud_python-0.4.20}/pyproject.toml +1 -1
- {hud_python-0.4.18 → hud_python-0.4.20}/.gitignore +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/LICENSE +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/browser/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/browser/apps/2048/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/browser/apps/2048/backend/pyproject.toml +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/browser/apps/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/browser/apps/todo/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/browser/apps/todo/backend/pyproject.toml +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/browser/pyproject.toml +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/remote_browser/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/remote_browser/pyproject.toml +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/remote_browser/src/hud_controller/providers/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/text_2048/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/environments/text_2048/pyproject.toml +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/__main__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/langchain.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/misc/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/misc/response_agent.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/openai.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/tests/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/tests/test_base.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/tests/test_claude.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/tests/test_client.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/agents/tests/test_openai.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/__main__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/analyze.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/build.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/clone.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/debug.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/dev.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/eval.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/hf.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/init.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/list_func.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/pull.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/push.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/remove.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/rl/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/rl/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/rl/init.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/rl/pod.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/rl/ssh.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/rl/train.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/rl/utils.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_analyze.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_analyze_metadata.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_build.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_cli_init.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_cli_main.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_clone.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_cursor.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_debug.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_list_func.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_main_module.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_mcp_server.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_pull.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_push.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_registry.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/tests/test_utils.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/utils/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/utils/cursor.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/utils/docker.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/utils/environment.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/utils/interactive.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/utils/logging.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/utils/metadata.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/utils/registry.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/utils/remote_runner.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/utils/runner.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/cli/utils/server.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/clients/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/clients/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/clients/fastmcp.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/clients/mcp_use.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/clients/tests/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/clients/tests/test_client_integration.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/clients/tests/test_fastmcp.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/clients/tests/test_protocol.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/clients/utils/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/clients/utils/retry_transport.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/datasets/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/datasets/execution/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/datasets/execution/parallel.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/datasets/execution/runner.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/datasets/utils.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/misc/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/misc/claude_plays_pokemon.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/otel/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/otel/collector.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/otel/config.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/otel/context.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/otel/exporters.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/otel/instrumentation.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/otel/processors.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/otel/tests/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/otel/tests/test_processors.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/py.typed +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/server/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/server/context.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/server/helper/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/server/low_level.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/server/server.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/server/tests/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/settings.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/shared/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/shared/exceptions.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/shared/requests.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/shared/tests/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/shared/tests/test_exceptions.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/shared/tests/test_requests.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/telemetry/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/telemetry/instrument.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/telemetry/job.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/telemetry/replay.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/telemetry/tests/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/telemetry/tests/test_replay.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/telemetry/tests/test_trace.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/telemetry/trace.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/base.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/bash.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/computer/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/computer/anthropic.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/computer/hud.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/computer/openai.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/computer/settings.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/edit.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/executors/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/executors/base.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/executors/pyautogui.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/executors/tests/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/executors/tests/test_base_executor.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/executors/tests/test_pyautogui_executor.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/executors/xdo.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/response.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_base.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_bash.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_bash_extended.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_computer.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_computer_actions.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_edit.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_init.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_playwright_tool.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_response.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_tools.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_tools_init.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/tests/test_utils.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/types.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/utils.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/types.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/async_utils.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/design.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/mcp.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/progress.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/telemetry.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/tests/__init__.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/tests/test_async_utils.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/tests/test_init.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/tests/test_mcp.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/tests/test_progress.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/hud/utils/tests/test_telemetry.py +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/rl/README.md +0 -0
- {hud_python-0.4.18 → hud_python-0.4.20}/rl/pyproject.toml +0 -0
|
@@ -20,6 +20,19 @@ python examples/01_hello_2048.py
|
|
|
20
20
|
|
|
21
21
|
> | Requires Docker and `ANTHROPIC_API_KEY` environment variable.
|
|
22
22
|
|
|
23
|
+
### 03_browser_agent_loop.py
|
|
24
|
+
Quick start for the browser environment (Claude). Supports multiple demo apps.
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# 2048 (default)
|
|
28
|
+
python examples/03_browser_agent_loop.py
|
|
29
|
+
|
|
30
|
+
# Todo app
|
|
31
|
+
python examples/03_browser_agent_loop.py --app todo
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
> | Requires Docker (exposes port 8080) and `ANTHROPIC_API_KEY`.
|
|
35
|
+
|
|
23
36
|
## Core Patterns
|
|
24
37
|
|
|
25
38
|
### 02_agent_lifecycle.py
|
|
@@ -50,35 +63,12 @@ Using the legacy `mcp_use` client for multi-server setups.
|
|
|
50
63
|
### integration_otel.py
|
|
51
64
|
Custom OpenTelemetry backend integration (e.g., Jaeger).
|
|
52
65
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
| Requirement | Used For |
|
|
56
|
-
|-------------|----------|
|
|
57
|
-
| Docker | Running environment containers |
|
|
58
|
-
| `HUD_API_KEY` | Cloud deployments and telemetry |
|
|
59
|
-
| `ANTHROPIC_API_KEY` | Claude agent examples |
|
|
66
|
+
### openai_compatible_agent.py
|
|
67
|
+
OpenAI-compatible chat.completions agent with both text and browser 2048 environments.
|
|
60
68
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
import asyncio, hud
|
|
67
|
-
from hud.datasets import Task
|
|
68
|
-
from hud.agents import ClaudeAgent
|
|
69
|
-
|
|
70
|
-
async def main():
|
|
71
|
-
with hud.trace("example-name"):
|
|
72
|
-
task = Task(
|
|
73
|
-
prompt="Your task here",
|
|
74
|
-
mcp_config={...}
|
|
75
|
-
)
|
|
76
|
-
|
|
77
|
-
agent = ClaudeAgent()
|
|
78
|
-
result = await agent.run(task)
|
|
79
|
-
print(f"Reward: {result.reward}")
|
|
80
|
-
|
|
81
|
-
asyncio.run(main())
|
|
69
|
+
```bash
|
|
70
|
+
export OPENAI_API_KEY=your-key # or dummy value for local servers
|
|
71
|
+
# export OPENAI_BASE_URL=http://localhost:8000/v1 # e.g., vllm
|
|
72
|
+
python examples/openai_compatible_agent.py --mode text # text environment
|
|
73
|
+
python examples/openai_compatible_agent.py --mode browser # browser environment
|
|
82
74
|
```
|
|
83
|
-
|
|
84
|
-
> | The agent automatically creates an MCP client from `task.mcp_config` if none is provided.
|
|
@@ -30,9 +30,19 @@ class MCPAgent(ABC):
|
|
|
30
30
|
"""
|
|
31
31
|
Base class for MCP-enabled agents.
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
Provides common behavior for agents that interact with MCP servers, including:
|
|
34
|
+
- Client management: accepts an `AgentMCPClient` or auto-creates one at
|
|
35
|
+
runtime when `run()` is called with a `Task` that includes `mcp_config`.
|
|
36
|
+
- Tool lifecycle: discovery, filtering (`allowed_tools`, `disallowed_tools`),
|
|
37
|
+
and automatic marking of lifecycle tools (setup/evaluate) from a `Task`.
|
|
38
|
+
- Messaging: system prompt handling, optional inclusion of setup output on
|
|
39
|
+
the first turn, and control over initial screenshots.
|
|
40
|
+
- Telemetry & UX: standardized logging/printing via `HUDDesign` and optional
|
|
41
|
+
automatic tracing (`auto_trace`).
|
|
42
|
+
|
|
43
|
+
Subclasses implement provider-specific formatting and response fetching
|
|
44
|
+
by overriding these abstract methods: `get_system_messages`, `get_response`,
|
|
45
|
+
`format_blocks`, and `format_tool_results`.
|
|
36
46
|
"""
|
|
37
47
|
|
|
38
48
|
metadata: dict[str, Any]
|
|
@@ -59,14 +69,23 @@ class MCPAgent(ABC):
|
|
|
59
69
|
Initialize the base MCP agent.
|
|
60
70
|
|
|
61
71
|
Args:
|
|
62
|
-
mcp_client:
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
mcp_client: Client for connecting to MCP servers. If None, a client
|
|
73
|
+
is auto-created at runtime when `run()` is called with a `Task`
|
|
74
|
+
that provides `mcp_config`.
|
|
75
|
+
allowed_tools: Names of tools to allow (None means allow all).
|
|
76
|
+
disallowed_tools: Names of tools to always exclude.
|
|
77
|
+
lifecycle_tools: Tools reserved for lifecycle phases (e.g., setup,
|
|
78
|
+
evaluate). These are hidden from normal tool calling.
|
|
79
|
+
system_prompt: System prompt to seed the conversation.
|
|
80
|
+
append_setup_output: Whether to append setup tool output to the
|
|
81
|
+
first turn's messages.
|
|
82
|
+
initial_screenshot: Whether to include an initial screenshot before
|
|
83
|
+
the first prompt (when supported by the environment).
|
|
84
|
+
model_name: Label used in telemetry/logging to identify the model.
|
|
85
|
+
response_agent: Optional automation that can respond to the model's
|
|
86
|
+
outputs to keep the loop going (e.g., auto-continue/stop).
|
|
87
|
+
auto_trace: If True, automatically creates a trace/span for runs.
|
|
88
|
+
verbose: If True, increases logging verbosity for developer UX.
|
|
70
89
|
"""
|
|
71
90
|
|
|
72
91
|
self.mcp_client = mcp_client
|
|
@@ -306,35 +306,49 @@ class ClaudeAgent(MCPAgent):
|
|
|
306
306
|
"""Convert MCP tools to Claude tool format."""
|
|
307
307
|
claude_tools = []
|
|
308
308
|
self._claude_to_mcp_tool_map = {} # Reset mapping
|
|
309
|
-
|
|
309
|
+
|
|
310
|
+
# Find computer tool by priority
|
|
311
|
+
computer_tool_priority = ["anthropic_computer", "computer_anthropic", "computer"]
|
|
312
|
+
selected_computer_tool = None
|
|
313
|
+
|
|
314
|
+
for priority_name in computer_tool_priority:
|
|
315
|
+
for tool in self._available_tools:
|
|
316
|
+
if tool.name == priority_name:
|
|
317
|
+
selected_computer_tool = tool
|
|
318
|
+
break
|
|
319
|
+
if selected_computer_tool:
|
|
320
|
+
break
|
|
321
|
+
|
|
322
|
+
# Add the selected computer tool if found
|
|
323
|
+
if selected_computer_tool:
|
|
324
|
+
claude_tool = {
|
|
325
|
+
"type": "computer_20250124",
|
|
326
|
+
"name": "computer",
|
|
327
|
+
"display_width_px": self.metadata["display_width"],
|
|
328
|
+
"display_height_px": self.metadata["display_height"],
|
|
329
|
+
}
|
|
330
|
+
# Map Claude's "computer" back to the actual MCP tool name
|
|
331
|
+
self._claude_to_mcp_tool_map["computer"] = selected_computer_tool.name
|
|
332
|
+
claude_tools.append(claude_tool)
|
|
333
|
+
logger.debug(f"Using {selected_computer_tool.name} as computer tool for Claude")
|
|
334
|
+
|
|
335
|
+
# Add other non-computer tools
|
|
310
336
|
for tool in self._available_tools:
|
|
311
|
-
#
|
|
312
|
-
if tool.name in
|
|
313
|
-
# Use Claude's native computer use format with configurable dimensions
|
|
314
|
-
claude_tool = {
|
|
315
|
-
"type": "computer_20250124",
|
|
316
|
-
"name": "computer",
|
|
317
|
-
"display_width_px": self.metadata["display_width"],
|
|
318
|
-
"display_height_px": self.metadata["display_height"],
|
|
319
|
-
}
|
|
320
|
-
# Map Claude's "computer" back to the actual MCP tool name
|
|
321
|
-
self._claude_to_mcp_tool_map["computer"] = tool.name
|
|
322
|
-
elif tool.name not in self.lifecycle_tools:
|
|
323
|
-
# Convert regular tools
|
|
324
|
-
claude_tool = {
|
|
325
|
-
"name": tool.name,
|
|
326
|
-
"description": tool.description or f"Execute {tool.name}",
|
|
327
|
-
"input_schema": tool.inputSchema
|
|
328
|
-
or {
|
|
329
|
-
"type": "object",
|
|
330
|
-
"properties": {},
|
|
331
|
-
},
|
|
332
|
-
}
|
|
333
|
-
# Direct mapping for non-computer tools
|
|
334
|
-
self._claude_to_mcp_tool_map[tool.name] = tool.name
|
|
335
|
-
else:
|
|
337
|
+
# Skip computer tools (already handled) and lifecycle tools
|
|
338
|
+
if tool.name in computer_tool_priority or tool.name in self.lifecycle_tools:
|
|
336
339
|
continue
|
|
337
|
-
|
|
340
|
+
|
|
341
|
+
claude_tool = {
|
|
342
|
+
"name": tool.name,
|
|
343
|
+
"description": tool.description or f"Execute {tool.name}",
|
|
344
|
+
"input_schema": tool.inputSchema
|
|
345
|
+
or {
|
|
346
|
+
"type": "object",
|
|
347
|
+
"properties": {},
|
|
348
|
+
},
|
|
349
|
+
}
|
|
350
|
+
# Direct mapping for non-computer tools
|
|
351
|
+
self._claude_to_mcp_tool_map[tool.name] = tool.name
|
|
338
352
|
claude_tools.append(claude_tool)
|
|
339
353
|
|
|
340
354
|
self.claude_tools = claude_tools
|
|
@@ -7,7 +7,7 @@ through the existing :class:`hud.agent.MCPAgent` scaffolding.
|
|
|
7
7
|
Key points:
|
|
8
8
|
- Stateless, no special server-side conversation state is assumed.
|
|
9
9
|
- Accepts an :class:`openai.AsyncOpenAI` client, caller can supply their own
|
|
10
|
-
base_url / api_key (e.g.
|
|
10
|
+
base_url / api_key (e.g. llama.cpp, together.ai, …)
|
|
11
11
|
- All HUD features (step_count, OTel spans, tool filtering, screenshots, …)
|
|
12
12
|
come from the ``MCPAgent`` base class, we only implement the three abstract
|
|
13
13
|
methods
|
|
@@ -30,8 +30,6 @@ if TYPE_CHECKING:
|
|
|
30
30
|
from openai import AsyncOpenAI
|
|
31
31
|
from openai.types.chat import ChatCompletionToolParam
|
|
32
32
|
|
|
33
|
-
from hud.clients import AgentMCPClient
|
|
34
|
-
|
|
35
33
|
logger = logging.getLogger(__name__)
|
|
36
34
|
|
|
37
35
|
|
|
@@ -40,19 +38,19 @@ class GenericOpenAIChatAgent(MCPAgent):
|
|
|
40
38
|
|
|
41
39
|
def __init__(
|
|
42
40
|
self,
|
|
43
|
-
mcp_client: AgentMCPClient,
|
|
44
41
|
*,
|
|
45
42
|
openai_client: AsyncOpenAI,
|
|
46
43
|
model_name: str = "gpt-4o-mini",
|
|
47
44
|
parallel_tool_calls: bool = False,
|
|
48
|
-
|
|
45
|
+
completion_kwargs: dict[str, Any] | None = None,
|
|
49
46
|
**agent_kwargs: Any,
|
|
50
47
|
) -> None:
|
|
51
|
-
|
|
48
|
+
# Accept base-agent settings via **agent_kwargs (e.g., mcp_client, system_prompt, etc.)
|
|
49
|
+
super().__init__(**agent_kwargs)
|
|
52
50
|
self.oai = openai_client
|
|
53
51
|
self.model_name = model_name
|
|
54
52
|
self.parallel_tool_calls = parallel_tool_calls
|
|
55
|
-
self.
|
|
53
|
+
self.completion_kwargs: dict[str, Any] = completion_kwargs or {}
|
|
56
54
|
self.conversation_history = []
|
|
57
55
|
|
|
58
56
|
@staticmethod
|
|
@@ -177,12 +175,15 @@ class GenericOpenAIChatAgent(MCPAgent):
|
|
|
177
175
|
# Convert MCP tool schemas to OpenAI format
|
|
178
176
|
mcp_schemas = self.get_tool_schemas()
|
|
179
177
|
|
|
178
|
+
protected_keys = {"model", "messages", "tools", "parallel_tool_calls"}
|
|
179
|
+
extra = {k: v for k, v in (self.completion_kwargs or {}).items() if k not in protected_keys}
|
|
180
|
+
|
|
180
181
|
response = await self.oai.chat.completions.create(
|
|
181
182
|
model=self.model_name,
|
|
182
183
|
messages=messages,
|
|
183
184
|
tools=cast("list[ChatCompletionToolParam]", mcp_schemas),
|
|
184
185
|
parallel_tool_calls=self.parallel_tool_calls,
|
|
185
|
-
|
|
186
|
+
**extra,
|
|
186
187
|
)
|
|
187
188
|
|
|
188
189
|
choice = response.choices[0]
|
|
@@ -247,9 +248,7 @@ class GenericOpenAIChatAgent(MCPAgent):
|
|
|
247
248
|
image_parts.append(
|
|
248
249
|
{
|
|
249
250
|
"type": "image_url",
|
|
250
|
-
"image_url": {
|
|
251
|
-
"url": f"data:{mime_type};base64,{data}"
|
|
252
|
-
},
|
|
251
|
+
"image_url": {"url": f"data:{mime_type};base64,{data}"},
|
|
253
252
|
}
|
|
254
253
|
)
|
|
255
254
|
elif isinstance(item, types.TextContent):
|
|
@@ -276,7 +275,7 @@ class GenericOpenAIChatAgent(MCPAgent):
|
|
|
276
275
|
# Add a user message with the images
|
|
277
276
|
content_with_images = [
|
|
278
277
|
{"type": "text", "text": "Tool returned the following:"},
|
|
279
|
-
*image_parts
|
|
278
|
+
*image_parts,
|
|
280
279
|
]
|
|
281
280
|
rendered.append(
|
|
282
281
|
{
|
|
@@ -130,31 +130,19 @@ class BaseHUDClient(AgentMCPClient):
|
|
|
130
130
|
logger.debug("Initializing MCP client...")
|
|
131
131
|
|
|
132
132
|
try:
|
|
133
|
+
# Check if API key is set for HUD API
|
|
134
|
+
for server_config in self._mcp_config.values():
|
|
135
|
+
url = server_config.get("url", "")
|
|
136
|
+
headers = server_config.get("headers", {})
|
|
137
|
+
if "mcp.hud.so" in url and len(headers.get("Authorization", "")) < 10:
|
|
138
|
+
raise RuntimeError(
|
|
139
|
+
"Please ensure your HUD_API_KEY environment variable is set correctly."
|
|
140
|
+
"You can get an API key at https://app.hud.so"
|
|
141
|
+
)
|
|
133
142
|
# Subclasses implement connection
|
|
134
143
|
await self._connect(self._mcp_config)
|
|
135
|
-
except RuntimeError as e:
|
|
136
|
-
# Re-raise authentication errors with clear message
|
|
137
|
-
if "Authentication failed" in str(e):
|
|
138
|
-
raise
|
|
139
|
-
raise
|
|
140
144
|
except Exception as e:
|
|
141
|
-
|
|
142
|
-
error_msg = str(e)
|
|
143
|
-
if "401" in error_msg or "Unauthorized" in error_msg:
|
|
144
|
-
# Check if connecting to HUD API
|
|
145
|
-
for server_config in self._mcp_config.values():
|
|
146
|
-
url = server_config.get("url", "")
|
|
147
|
-
if "mcp.hud.so" in url:
|
|
148
|
-
raise RuntimeError(
|
|
149
|
-
"Authentication failed for HUD API. "
|
|
150
|
-
"Please ensure your HUD_API_KEY environment variable is set correctly. "
|
|
151
|
-
"You can get an API key at https://app.hud.so"
|
|
152
|
-
) from e
|
|
153
|
-
raise RuntimeError(
|
|
154
|
-
"Authentication failed (401 Unauthorized). "
|
|
155
|
-
"Please check your credentials or API key."
|
|
156
|
-
) from e
|
|
157
|
-
raise
|
|
145
|
+
raise e
|
|
158
146
|
|
|
159
147
|
# Common hud behavior - fetch telemetry
|
|
160
148
|
await self._fetch_telemetry()
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import json
|
|
6
|
+
import logging
|
|
6
7
|
from collections import defaultdict
|
|
7
8
|
from string import Template
|
|
8
9
|
from typing import Any
|
|
@@ -12,6 +13,8 @@ from pydantic import BaseModel, Field, field_validator
|
|
|
12
13
|
from hud.settings import settings
|
|
13
14
|
from hud.types import MCPToolCall
|
|
14
15
|
|
|
16
|
+
logger = logging.getLogger(__name__)
|
|
17
|
+
|
|
15
18
|
|
|
16
19
|
class Task(BaseModel):
|
|
17
20
|
"""
|
|
@@ -90,6 +93,8 @@ class Task(BaseModel):
|
|
|
90
93
|
|
|
91
94
|
if settings.api_key:
|
|
92
95
|
mapping["HUD_API_KEY"] = settings.api_key
|
|
96
|
+
else:
|
|
97
|
+
logger.error("HUD_API_KEY is not set, tracing and remote training will not work")
|
|
93
98
|
|
|
94
99
|
def substitute_in_value(obj: Any) -> Any:
|
|
95
100
|
"""Recursively substitute variables in nested structures."""
|
|
@@ -153,7 +153,7 @@ class PlaywrightTool(BaseTool):
|
|
|
153
153
|
"""Ensure browser is launched and ready."""
|
|
154
154
|
if self._browser is None or not self._browser.is_connected():
|
|
155
155
|
if self._cdp_url:
|
|
156
|
-
logger.info("Connecting to remote browser via CDP
|
|
156
|
+
logger.info("Connecting to remote browser via CDP")
|
|
157
157
|
else:
|
|
158
158
|
logger.info("Launching Playwright browser...")
|
|
159
159
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hud_python-0.4.18 → hud_python-0.4.20}/environments/browser/apps/2048/backend/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hud_python-0.4.18 → hud_python-0.4.20}/environments/browser/apps/todo/backend/pyproject.toml
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hud_python-0.4.18 → hud_python-0.4.20}/hud/tools/executors/tests/test_pyautogui_executor.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|