hud 0.6.16.dev4__tar.gz → 0.6.18.dev1__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.
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/.gitignore +2 -2
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/PKG-INFO +6 -14
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/README.md +3 -11
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/__main__.py +1 -1
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/__init__.py +35 -69
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/agent.py +11 -7
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/sdk/agent.py +18 -5
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/agent.py +5 -11
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/agent.py +43 -17
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/tools/computer.py +58 -41
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/tools/tests/test_computer.py +50 -10
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai_compatible/agent.py +1 -1
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/test_base.py +28 -6
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/test_claude_agent.py +44 -1
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/test_claude_sdk_agent.py +27 -6
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/test_openai_agent.py +158 -1
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/test_tool_agent.py +106 -2
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tool_agent.py +22 -6
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/types.py +10 -1
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/capabilities/mcp.py +27 -2
- hud-0.6.18.dev1/hud/cli/__init__.py +425 -0
- hud-0.6.18.dev1/hud/cli/__main__.py +270 -0
- hud-0.6.18.dev1/hud/cli/deploy.py +541 -0
- hud-0.6.18.dev1/hud/cli/eval.py +564 -0
- hud-0.6.18.dev1/hud/cli/init.py +195 -0
- hud-0.6.18.dev1/hud/cli/jobs.py +280 -0
- hud-0.6.18.dev1/hud/cli/models.py +262 -0
- hud-0.6.18.dev1/hud/cli/project.py +247 -0
- hud-0.6.18.dev1/hud/cli/qa.py +574 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/cli/serve.py +23 -54
- hud-0.6.18.dev1/hud/cli/sync.py +434 -0
- hud-0.6.18.dev1/hud/cli/task.py +213 -0
- hud-0.6.18.dev1/hud/cli/tests/test_cli.py +853 -0
- hud-0.6.18.dev1/hud/cli/tests/test_deploy.py +850 -0
- hud-0.6.18.dev1/hud/cli/tests/test_eval.py +687 -0
- hud-0.6.18.dev1/hud/cli/tests/test_init.py +255 -0
- hud-0.6.18.dev1/hud/cli/tests/test_jobs.py +73 -0
- hud-0.6.18.dev1/hud/cli/tests/test_main.py +26 -0
- hud-0.6.18.dev1/hud/cli/tests/test_project.py +284 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/cli/tests/test_qa.py +117 -4
- hud-0.6.18.dev1/hud/cli/tests/test_sync.py +396 -0
- hud-0.6.18.dev1/hud/cli/tests/test_task.py +149 -0
- hud-0.6.18.dev1/hud/cli/tests/test_trace.py +76 -0
- hud-0.6.18.dev1/hud/cli/trace.py +158 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/clients/client.py +22 -12
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/clients/tests/test_connect.py +17 -5
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/conftest.py +4 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/file_tracker.py +1 -1
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/server.py +54 -12
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_server.py +81 -2
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_sessions.py +23 -2
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_tunnel.py +18 -1
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_workspace.py +27 -0
- hud-0.6.18.dev1/hud/environment/utils.py +134 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/workspace.py +3 -1
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/job.py +4 -2
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/run.py +11 -7
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/runtime/hosted.py +41 -10
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/runtime/local.py +26 -8
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/sync.py +7 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/task.py +9 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/taskset.py +39 -19
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/tests/test_hosted.py +97 -2
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/tests/test_job.py +2 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/tests/test_local_runtime.py +81 -1
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/tests/test_rollout.py +120 -13
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/tests/test_sync.py +35 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/settings.py +16 -1
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/telemetry/context.py +21 -10
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/telemetry/exporter.py +4 -4
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/telemetry/robot/recorder.py +2 -2
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/telemetry/span.py +4 -9
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/telemetry/tests/test_exporter.py +10 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/train/base.py +15 -35
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/train/tests/test_client.py +26 -0
- hud-0.6.18.dev1/hud/utils/gateway.py +202 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/hud_console.py +6 -9
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/platform.py +9 -9
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/requests.py +35 -90
- hud-0.6.18.dev1/hud/utils/tests/test_gateway.py +303 -0
- hud-0.6.18.dev1/hud/utils/tests/test_naming.py +13 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/tests/test_platform.py +13 -13
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/tests/test_requests.py +45 -20
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/version.py +1 -1
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/pyproject.toml +5 -3
- hud-0.6.16.dev4/hud/cli/__init__.py +0 -175
- hud-0.6.16.dev4/hud/cli/__main__.py +0 -8
- hud-0.6.16.dev4/hud/cli/cancel.py +0 -111
- hud-0.6.16.dev4/hud/cli/client.py +0 -82
- hud-0.6.16.dev4/hud/cli/deploy.py +0 -881
- hud-0.6.16.dev4/hud/cli/eval.py +0 -1003
- hud-0.6.16.dev4/hud/cli/init.py +0 -187
- hud-0.6.16.dev4/hud/cli/jobs.py +0 -147
- hud-0.6.16.dev4/hud/cli/login.py +0 -238
- hud-0.6.16.dev4/hud/cli/models.py +0 -274
- hud-0.6.16.dev4/hud/cli/presets.py +0 -217
- hud-0.6.16.dev4/hud/cli/qa.py +0 -419
- hud-0.6.16.dev4/hud/cli/qa_analysis.py +0 -207
- hud-0.6.16.dev4/hud/cli/sync.py +0 -502
- hud-0.6.16.dev4/hud/cli/task.py +0 -210
- hud-0.6.16.dev4/hud/cli/templates.py +0 -141
- hud-0.6.16.dev4/hud/cli/tests/test_cli_init.py +0 -87
- hud-0.6.16.dev4/hud/cli/tests/test_cli_main.py +0 -27
- hud-0.6.16.dev4/hud/cli/tests/test_cli_more_wrappers.py +0 -7
- hud-0.6.16.dev4/hud/cli/tests/test_deploy.py +0 -543
- hud-0.6.16.dev4/hud/cli/tests/test_eval_bedrock.py +0 -51
- hud-0.6.16.dev4/hud/cli/tests/test_eval_config.py +0 -354
- hud-0.6.16.dev4/hud/cli/tests/test_init.py +0 -134
- hud-0.6.16.dev4/hud/cli/tests/test_jobs.py +0 -38
- hud-0.6.16.dev4/hud/cli/tests/test_main_module.py +0 -36
- hud-0.6.16.dev4/hud/cli/tests/test_qa_analysis.py +0 -87
- hud-0.6.16.dev4/hud/cli/tests/test_sync_export.py +0 -58
- hud-0.6.16.dev4/hud/cli/tests/test_trace.py +0 -26
- hud-0.6.16.dev4/hud/cli/tests/test_usage.py +0 -134
- hud-0.6.16.dev4/hud/cli/trace.py +0 -219
- hud-0.6.16.dev4/hud/cli/utils/__init__.py +0 -1
- hud-0.6.16.dev4/hud/cli/utils/api.py +0 -22
- hud-0.6.16.dev4/hud/cli/utils/build_display.py +0 -279
- hud-0.6.16.dev4/hud/cli/utils/build_logs.py +0 -230
- hud-0.6.16.dev4/hud/cli/utils/config.py +0 -115
- hud-0.6.16.dev4/hud/cli/utils/context.py +0 -282
- hud-0.6.16.dev4/hud/cli/utils/display.py +0 -100
- hud-0.6.16.dev4/hud/cli/utils/jobs.py +0 -38
- hud-0.6.16.dev4/hud/cli/utils/registry.py +0 -100
- hud-0.6.16.dev4/hud/cli/utils/source.py +0 -557
- hud-0.6.16.dev4/hud/cli/utils/tasks.py +0 -29
- hud-0.6.16.dev4/hud/cli/utils/tests/test_build_display.py +0 -49
- hud-0.6.16.dev4/hud/cli/utils/tests/test_config.py +0 -58
- hud-0.6.16.dev4/hud/cli/utils/tests/test_context.py +0 -92
- hud-0.6.16.dev4/hud/cli/utils/tests/test_registry.py +0 -76
- hud-0.6.16.dev4/hud/cli/utils/tests/test_source.py +0 -321
- hud-0.6.16.dev4/hud/cli/utils/tests/test_tasks.py +0 -80
- hud-0.6.16.dev4/hud/cli/utils/tests/test_version_check.py +0 -109
- hud-0.6.16.dev4/hud/cli/utils/usage.py +0 -179
- hud-0.6.16.dev4/hud/cli/utils/version_check.py +0 -237
- hud-0.6.16.dev4/hud/environment/utils.py +0 -84
- hud-0.6.16.dev4/hud/utils/gateway.py +0 -143
- hud-0.6.16.dev4/hud/utils/tests/__init__.py +0 -0
- hud-0.6.16.dev4/hud/utils/tests/test_gateway.py +0 -160
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/LICENSE +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/base.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/browser_use/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/browser_use/agent.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/sdk/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/sdk/computer_mcp.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/tools/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/tools/base.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/tools/coding.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/tools/computer.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/tools/hosted.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/tools/mcp_proxy.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/tools/settings.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/tools/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/claude/tools/tests/test_computer.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/settings.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/tools/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/tools/base.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/tools/coding.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/tools/computer.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/tools/filesystem.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/tools/hosted.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/tools/mcp_proxy.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/tools/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/gemini/tools/tests/test_computer.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/misc/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/misc/response_automation.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/tools/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/tools/apply_patch.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/tools/base.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/tools/coding.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/tools/hosted.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/tools/mcp_proxy.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/tools/strict_schema.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/tools/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai/tools/tests/test_strict_schema.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai_compatible/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai_compatible/tools/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai_compatible/tools/base.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai_compatible/tools/filesystem.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/openai_compatible/tools/mcp_proxy.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/robot/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/robot/adapter.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/robot/agent.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/robot/batching.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/robot/dataset.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/robot/model.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/test_apply_patch.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/test_gemini_agent.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/test_openai_compatible_agent.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/test_provider_native_tools.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/test_robot_dataset_writer.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tests/test_trace.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tools/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tools/base.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tools/hosted.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tools/mcp.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tools/rfb.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/agents/tools/ssh.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/capabilities/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/capabilities/base.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/capabilities/cdp.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/capabilities/rfb.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/capabilities/robot.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/capabilities/ssh.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/capabilities/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/capabilities/tests/test_rfb.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/capabilities/tests/test_ssh.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/cli/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/clients/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/clients/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/arguments.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/egress.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/env.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/namespace.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/robot/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/robot/bridge.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/robot/endpoint.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/robot/gym.py +0 -0
- {hud-0.6.16.dev4/hud/cli/utils → hud-0.6.18.dev1/hud/environment}/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/conftest.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_arguments.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_capability_backing.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_file_tracker.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_file_tracking.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_loader.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_manifest.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_platform.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/environment/tests/test_robot_regressions.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/chat.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/docker-seccomp.json +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/file_tracking.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/runtime/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/runtime/compose.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/runtime/core.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/runtime/daytona.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/runtime/docker.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/runtime/hud.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/runtime/modal.py +0 -0
- {hud-0.6.16.dev4/hud/environment → hud-0.6.18.dev1/hud/eval}/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/tests/test_chat.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/tests/test_docker_provider.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/tests/test_file_tracking_observer.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/tests/test_shared.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/eval/tests/test_task.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/graders/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/graders/base.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/graders/bash.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/graders/combine.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/graders/judge.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/graders/results.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/graders/text.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/Dockerfile +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/adapt.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/env.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/export.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/install.sh +0 -0
- {hud-0.6.16.dev4/hud/eval → hud-0.6.18.dev1/hud/integrations/harbor}/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/conftest.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/agent-lifecycle/environment/Dockerfile +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/agent-lifecycle/instruction.md +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/agent-lifecycle/solution/solve.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/agent-lifecycle/task.toml +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/agent-lifecycle/tests/test.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/hello-mcp/environment/Dockerfile +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/hello-mcp/environment/docker-compose.yaml +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/hello-mcp/environment/mcp-server/Dockerfile +0 -0
- {hud-0.6.16.dev4/hud/integrations/harbor/tests → hud-0.6.18.dev1/hud/integrations/harbor/tests/tasks/hello-mcp/environment/mcp-server}/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/hello-mcp/environment/mcp-server/server.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/hello-mcp/instruction.md +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/hello-mcp/solution/solve.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/hello-mcp/task.toml +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/hello-mcp/tests/test.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/phase-boundary/environment/Dockerfile +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/phase-boundary/environment/entrypoint.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/phase-boundary/instruction.md +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/phase-boundary/solution/solve.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/phase-boundary/task.toml +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/phase-boundary/tests/test.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/sidecar-reachability/environment/Dockerfile +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/sidecar-reachability/environment/docker-compose.yaml +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/sidecar-reachability/instruction.md +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/sidecar-reachability/solution/solve.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/sidecar-reachability/task.toml +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/sidecar-reachability/tests/Dockerfile +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/sidecar-reachability/tests/test.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/verifier-lifecycle/environment/Dockerfile +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/verifier-lifecycle/environment/entrypoint.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/verifier-lifecycle/instruction.md +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/verifier-lifecycle/solution/solve.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/verifier-lifecycle/task.toml +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/tasks/verifier-lifecycle/tests/test.sh +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/test_contract.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/test_harbor.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/integrations/harbor/tests/test_integration.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/patches/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/patches/mcp_patches.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/patches/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/patches/tests/test_warnings.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/patches/warnings.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/py.typed +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/telemetry/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/telemetry/instrument.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/telemetry/robot/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/telemetry/robot/video.py +0 -0
- {hud-0.6.16.dev4/hud/integrations/harbor/tests/tasks/hello-mcp/environment/mcp-server → hud-0.6.18.dev1/hud/telemetry/tests}/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/telemetry/tests/test_instrument.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/train/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/train/client.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/train/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/train/types.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/types.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/docker.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/exceptions.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/hints.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/modules.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/naming.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/process.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/serialization.py +0 -0
- {hud-0.6.16.dev4/hud/telemetry → hud-0.6.18.dev1/hud/utils}/tests/__init__.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/tests/test_exceptions.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/tests/test_hints.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/tests/test_hud_console.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/tests/test_process.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/tests/test_serialization.py +0 -0
- {hud-0.6.16.dev4 → hud-0.6.18.dev1}/hud/utils/time.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: hud
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.18.dev1
|
|
4
4
|
Summary: SDK for the HUD platform.
|
|
5
5
|
Project-URL: Homepage, https://github.com/hud-evals/hud-python
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/hud-evals/hud-python/issues
|
|
@@ -34,7 +34,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
34
34
|
Classifier: Programming Language :: Python :: 3.11
|
|
35
35
|
Classifier: Programming Language :: Python :: 3.12
|
|
36
36
|
Requires-Python: <3.13,>=3.11
|
|
37
|
-
Requires-Dist: anthropic>=0.
|
|
37
|
+
Requires-Dist: anthropic>=0.98.0
|
|
38
38
|
Requires-Dist: asyncssh>=2.23.0
|
|
39
39
|
Requires-Dist: asyncvnc>=1.3.0
|
|
40
40
|
Requires-Dist: fastmcp==3.2.0
|
|
@@ -56,7 +56,7 @@ Requires-Dist: websockets>=15.0.1
|
|
|
56
56
|
Provides-Extra: agent
|
|
57
57
|
Provides-Extra: agents
|
|
58
58
|
Provides-Extra: bedrock
|
|
59
|
-
Requires-Dist: anthropic[bedrock]>=0.
|
|
59
|
+
Requires-Dist: anthropic[bedrock]>=0.98.0; extra == 'bedrock'
|
|
60
60
|
Provides-Extra: browseruse
|
|
61
61
|
Requires-Dist: browser-use>=0.11.13; extra == 'browseruse'
|
|
62
62
|
Provides-Extra: daytona
|
|
@@ -123,10 +123,12 @@ hud set HUD_API_KEY=your-key-here
|
|
|
123
123
|
# or: export HUD_API_KEY=your-key-here
|
|
124
124
|
```
|
|
125
125
|
|
|
126
|
-
Then
|
|
126
|
+
Then start from the coding environment, or choose another example environment:
|
|
127
127
|
|
|
128
128
|
```bash
|
|
129
129
|
hud init my-env
|
|
130
|
+
hud init my-desktop-env --template cua
|
|
131
|
+
hud init my-custom-env --template blank
|
|
130
132
|
```
|
|
131
133
|
|
|
132
134
|

|
|
@@ -166,16 +168,6 @@ hud sync tasks my-taskset
|
|
|
166
168
|
hud eval my-taskset --remote
|
|
167
169
|
```
|
|
168
170
|
|
|
169
|
-
For local iteration, the same protocol works against a container on your laptop:
|
|
170
|
-
|
|
171
|
-
```bash
|
|
172
|
-
docker build -f Dockerfile.hud -t my-env .
|
|
173
|
-
docker run -d --name run1 -p 8765:8765 my-env
|
|
174
|
-
hud task start fix_bug --url tcp://127.0.0.1:8765
|
|
175
|
-
hud task grade fix_bug --url tcp://127.0.0.1:8765 --answer "..."
|
|
176
|
-
docker rm -f run1
|
|
177
|
-
```
|
|
178
|
-
|
|
179
171
|
→ [Run & deploy](https://docs.hud.ai/v6/reference/runtime)
|
|
180
172
|
|
|
181
173
|
## Environments & templates
|
|
@@ -37,10 +37,12 @@ hud set HUD_API_KEY=your-key-here
|
|
|
37
37
|
# or: export HUD_API_KEY=your-key-here
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
Then
|
|
40
|
+
Then start from the coding environment, or choose another example environment:
|
|
41
41
|
|
|
42
42
|
```bash
|
|
43
43
|
hud init my-env
|
|
44
|
+
hud init my-desktop-env --template cua
|
|
45
|
+
hud init my-custom-env --template blank
|
|
44
46
|
```
|
|
45
47
|
|
|
46
48
|

|
|
@@ -80,16 +82,6 @@ hud sync tasks my-taskset
|
|
|
80
82
|
hud eval my-taskset --remote
|
|
81
83
|
```
|
|
82
84
|
|
|
83
|
-
For local iteration, the same protocol works against a container on your laptop:
|
|
84
|
-
|
|
85
|
-
```bash
|
|
86
|
-
docker build -f Dockerfile.hud -t my-env .
|
|
87
|
-
docker run -d --name run1 -p 8765:8765 my-env
|
|
88
|
-
hud task start fix_bug --url tcp://127.0.0.1:8765
|
|
89
|
-
hud task grade fix_bug --url tcp://127.0.0.1:8765 --answer "..."
|
|
90
|
-
docker rm -f run1
|
|
91
|
-
```
|
|
92
|
-
|
|
93
85
|
→ [Run & deploy](https://docs.hud.ai/v6/reference/runtime)
|
|
94
86
|
|
|
95
87
|
## Environments & templates
|
|
@@ -10,11 +10,7 @@ from typing import TYPE_CHECKING, Any, cast
|
|
|
10
10
|
from hud.settings import settings
|
|
11
11
|
from hud.types import AgentType
|
|
12
12
|
from hud.utils.exceptions import HudAuthenticationError
|
|
13
|
-
from hud.utils.gateway import
|
|
14
|
-
gateway_model_aliases,
|
|
15
|
-
list_gateway_models,
|
|
16
|
-
normalize_gateway_model_id,
|
|
17
|
-
)
|
|
13
|
+
from hud.utils.gateway import resolve_gateway_model
|
|
18
14
|
|
|
19
15
|
if TYPE_CHECKING:
|
|
20
16
|
from typing import TypeAlias
|
|
@@ -31,10 +27,11 @@ if TYPE_CHECKING:
|
|
|
31
27
|
def create_agent(model: str, **kwargs: Any) -> GatewayAgent:
|
|
32
28
|
"""Create an agent routed through the HUD gateway.
|
|
33
29
|
|
|
34
|
-
|
|
35
|
-
gateway client locally
|
|
36
|
-
serialize the config and rebuild
|
|
37
|
-
clients remain custom/BYOK and are not
|
|
30
|
+
Sets ``gateway=True`` on the config instead of attaching a client, so the
|
|
31
|
+
provider agent builds the gateway client locally and
|
|
32
|
+
:class:`~hud.eval.runtime.HostedRuntime` can serialize the config and rebuild
|
|
33
|
+
it remotely. Explicitly supplied clients remain custom/BYOK and are not
|
|
34
|
+
serializable.
|
|
38
35
|
|
|
39
36
|
For direct API access with provider API keys, instantiate the agent classes
|
|
40
37
|
directly.
|
|
@@ -49,72 +46,40 @@ def create_agent(model: str, **kwargs: Any) -> GatewayAgent:
|
|
|
49
46
|
if not settings.api_key:
|
|
50
47
|
raise HudAuthenticationError("HUD_API_KEY is required to create a gateway agent")
|
|
51
48
|
|
|
52
|
-
|
|
53
|
-
model = normalize_gateway_model_id(model)
|
|
54
|
-
agent_type = next((candidate for candidate in AgentType if candidate.value == model), None)
|
|
55
|
-
if agent_type is not None:
|
|
56
|
-
model_id = model
|
|
57
|
-
else:
|
|
58
|
-
try:
|
|
59
|
-
gateway_models = list_gateway_models()
|
|
60
|
-
except Exception:
|
|
61
|
-
gateway_models = []
|
|
62
|
-
gateway_models = list(gateway_models)
|
|
63
|
-
for gateway_model in gateway_models:
|
|
64
|
-
if model in (
|
|
65
|
-
gateway_model.id,
|
|
66
|
-
gateway_model.name,
|
|
67
|
-
gateway_model.model_name,
|
|
68
|
-
):
|
|
69
|
-
agent_str = gateway_model.sdk_agent_type
|
|
70
|
-
if agent_str == "operator":
|
|
71
|
-
raise ValueError(
|
|
72
|
-
"Operator agent is no longer supported; use openai with a supported "
|
|
73
|
-
"OpenAI computer model."
|
|
74
|
-
)
|
|
75
|
-
if agent_str == "gemini_cua":
|
|
76
|
-
raise ValueError(
|
|
77
|
-
"Gemini CUA agent is no longer supported; use gemini with a supported "
|
|
78
|
-
"Gemini computer-use model."
|
|
79
|
-
)
|
|
80
|
-
if not isinstance(agent_str, str):
|
|
81
|
-
raise ValueError(f"Model '{model}' has invalid agent type metadata")
|
|
82
|
-
|
|
83
|
-
try:
|
|
84
|
-
agent_type = AgentType(agent_str)
|
|
85
|
-
except ValueError as exc:
|
|
86
|
-
raise ValueError(f"Model '{model}' has invalid agent type metadata") from exc
|
|
87
|
-
model_id = gateway_model.model_name or model
|
|
88
|
-
break
|
|
89
|
-
else:
|
|
90
|
-
import difflib
|
|
91
|
-
|
|
92
|
-
known = [c.value for c in AgentType] + [
|
|
93
|
-
n
|
|
94
|
-
for gm in gateway_models
|
|
95
|
-
for n in (gm.id, gm.name, gm.model_name)
|
|
96
|
-
if isinstance(n, str)
|
|
97
|
-
]
|
|
98
|
-
known.extend(gateway_model_aliases())
|
|
99
|
-
near = difflib.get_close_matches(requested_model, known, n=3, cutoff=0.5)
|
|
100
|
-
hint = (
|
|
101
|
-
f" Did you mean: {', '.join(near)}?"
|
|
102
|
-
if near
|
|
103
|
-
else " Run `hud models` to list available models."
|
|
104
|
-
)
|
|
105
|
-
source = (
|
|
106
|
-
"the HUD gateway registry"
|
|
107
|
-
if gateway_models
|
|
108
|
-
else "the HUD gateway registry (empty — is HUD_API_KEY set?)"
|
|
109
|
-
)
|
|
110
|
-
raise ValueError(f"Model {requested_model!r} not found in {source}.{hint}")
|
|
111
|
-
|
|
49
|
+
agent_type, model_id = resolve_agent_model(model)
|
|
112
50
|
kwargs.setdefault("model", model_id)
|
|
51
|
+
kwargs["gateway"] = True
|
|
113
52
|
# cls/config_cls are matched unions; the pairing is correct by construction.
|
|
114
53
|
config = agent_type.config_cls(**kwargs)
|
|
115
54
|
return agent_type.cls(cast("Any", config))
|
|
116
55
|
|
|
117
56
|
|
|
57
|
+
def resolve_agent_model(model: str) -> tuple[AgentType, str]:
|
|
58
|
+
"""Resolve a catalog id/name/slug or an agent type without constructing a client."""
|
|
59
|
+
agent_type = next((candidate for candidate in AgentType if candidate.value == model), None)
|
|
60
|
+
if agent_type is not None:
|
|
61
|
+
return agent_type, model
|
|
62
|
+
try:
|
|
63
|
+
entry = resolve_gateway_model(model)
|
|
64
|
+
except HudAuthenticationError:
|
|
65
|
+
types = ", ".join(candidate.value for candidate in AgentType)
|
|
66
|
+
raise ValueError(
|
|
67
|
+
f"Resolving {model!r} needs the HUD model catalog; set HUD_API_KEY, or pass an "
|
|
68
|
+
f"agent type ({types}) and choose the model with its config."
|
|
69
|
+
) from None
|
|
70
|
+
if entry.sdk_agent_type in ("operator", "gemini_cua"):
|
|
71
|
+
replacement = "openai" if entry.sdk_agent_type == "operator" else "gemini"
|
|
72
|
+
raise ValueError(
|
|
73
|
+
f"The {entry.sdk_agent_type} agent is no longer supported; use {replacement} with a "
|
|
74
|
+
"supported computer-use model."
|
|
75
|
+
)
|
|
76
|
+
try:
|
|
77
|
+
agent_type = AgentType(entry.sdk_agent_type)
|
|
78
|
+
except ValueError as exc:
|
|
79
|
+
raise ValueError(f"Model {model!r} has invalid agent type metadata") from exc
|
|
80
|
+
return agent_type, entry.model_name or model
|
|
81
|
+
|
|
82
|
+
|
|
118
83
|
_LAZY_EXPORTS = {
|
|
119
84
|
"ClaudeAgent": ("hud.agents.claude", "ClaudeAgent"),
|
|
120
85
|
"ClaudeSDKAgent": ("hud.agents.claude", "ClaudeSDKAgent"),
|
|
@@ -134,6 +99,7 @@ __all__ = [
|
|
|
134
99
|
"OpenAIAgent",
|
|
135
100
|
"OpenAIChatAgent",
|
|
136
101
|
"create_agent",
|
|
102
|
+
"resolve_agent_model",
|
|
137
103
|
]
|
|
138
104
|
|
|
139
105
|
|
|
@@ -38,7 +38,6 @@ from anthropic.types.beta import (
|
|
|
38
38
|
|
|
39
39
|
from hud.agents.tool_agent import RunState, ToolAgent
|
|
40
40
|
from hud.agents.types import AgentStep, Citation, ClaudeConfig, Usage
|
|
41
|
-
from hud.settings import settings
|
|
42
41
|
from hud.types import MCPToolCall, MCPToolResult
|
|
43
42
|
from hud.utils import gateway
|
|
44
43
|
|
|
@@ -108,12 +107,11 @@ class ClaudeAgent(ToolAgent[BetaMessageParam, ClaudeConfig]):
|
|
|
108
107
|
def _resolve_client(self) -> AsyncAnthropic | AsyncAnthropicBedrock:
|
|
109
108
|
if self.config.model_client is not None:
|
|
110
109
|
return cast("AsyncAnthropic | AsyncAnthropicBedrock", self.config.model_client)
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
"No API key found for Claude. Set HUD_API_KEY (gateway) or ANTHROPIC_API_KEY.",
|
|
110
|
+
return cast(
|
|
111
|
+
"AsyncAnthropic | AsyncAnthropicBedrock",
|
|
112
|
+
gateway.build_model_client(
|
|
113
|
+
"anthropic", model=self.config.model, gateway=self.config.gateway
|
|
114
|
+
),
|
|
117
115
|
)
|
|
118
116
|
|
|
119
117
|
# ─── ToolAgent hooks ──────────────────────────────────────────────
|
|
@@ -403,6 +401,12 @@ class ClaudeAgent(ToolAgent[BetaMessageParam, ClaudeConfig]):
|
|
|
403
401
|
if thinking_parts:
|
|
404
402
|
result.reasoning = "\n".join(thinking_parts)
|
|
405
403
|
result.finish_reason = response.stop_reason
|
|
404
|
+
if response.stop_reason == "refusal" and response.stop_details is not None:
|
|
405
|
+
explanation = response.stop_details.explanation
|
|
406
|
+
if explanation:
|
|
407
|
+
result.refusal = explanation
|
|
408
|
+
elif response.stop_details.category is not None:
|
|
409
|
+
result.refusal = f"This request was refused ({response.stop_details.category})."
|
|
406
410
|
return result
|
|
407
411
|
|
|
408
412
|
@staticmethod
|
|
@@ -10,6 +10,7 @@ Inspired by harbor-framework/harbor's ClaudeCode agent.
|
|
|
10
10
|
|
|
11
11
|
from __future__ import annotations
|
|
12
12
|
|
|
13
|
+
import base64
|
|
13
14
|
import json
|
|
14
15
|
import logging
|
|
15
16
|
import shlex
|
|
@@ -20,6 +21,7 @@ from typing import TYPE_CHECKING, Any, cast
|
|
|
20
21
|
from hud.agents.base import Agent
|
|
21
22
|
from hud.agents.types import AgentStep, ClaudeSDKConfig, Usage
|
|
22
23
|
from hud.settings import settings
|
|
24
|
+
from hud.telemetry.context import get_current_trace_id, get_trace_headers
|
|
23
25
|
from hud.types import Step
|
|
24
26
|
|
|
25
27
|
if TYPE_CHECKING:
|
|
@@ -83,6 +85,7 @@ class ClaudeSDKAgent(Agent):
|
|
|
83
85
|
|
|
84
86
|
async def __call__(self, run: Run) -> None:
|
|
85
87
|
mcp_servers: dict[str, dict[str, Any]] = {}
|
|
88
|
+
trace_id = get_current_trace_id()
|
|
86
89
|
manifest = run.client.manifest
|
|
87
90
|
bindings = manifest.bindings if manifest is not None else []
|
|
88
91
|
families = {c.protocol.split("/", 1)[0] for c in bindings}
|
|
@@ -100,8 +103,11 @@ class ClaudeSDKAgent(Agent):
|
|
|
100
103
|
token = cap.params.get("auth_token")
|
|
101
104
|
transport = "http" if cap.params["transport"] == "streamable-http" else "sse"
|
|
102
105
|
server_config: dict[str, Any] = {"type": transport, "url": cap.url}
|
|
106
|
+
headers = {"Trace-Id": trace_id} if trace_id is not None else {}
|
|
103
107
|
if token:
|
|
104
|
-
|
|
108
|
+
headers["Authorization"] = f"Bearer {token}"
|
|
109
|
+
if headers:
|
|
110
|
+
server_config["headers"] = headers
|
|
105
111
|
if cap.name in mcp_servers:
|
|
106
112
|
raise RuntimeError(f"duplicate MCP server name {cap.name!r}")
|
|
107
113
|
mcp_servers[cap.name] = server_config
|
|
@@ -188,6 +194,11 @@ class ClaudeSDKAgent(Agent):
|
|
|
188
194
|
if settings.api_key:
|
|
189
195
|
env["ANTHROPIC_BASE_URL"] = settings.hud_gateway_url
|
|
190
196
|
env["ANTHROPIC_API_KEY"] = settings.api_key
|
|
197
|
+
trace_headers = get_trace_headers()
|
|
198
|
+
if trace_headers:
|
|
199
|
+
env["ANTHROPIC_CUSTOM_HEADERS"] = "\n".join(
|
|
200
|
+
f"{name}: {value}" for name, value in trace_headers.items()
|
|
201
|
+
)
|
|
191
202
|
elif settings.anthropic_api_key:
|
|
192
203
|
env["ANTHROPIC_API_KEY"] = settings.anthropic_api_key
|
|
193
204
|
|
|
@@ -259,16 +270,18 @@ class ClaudeSDKAgent(Agent):
|
|
|
259
270
|
# Solution: use `cmd /c claude [args]` (no inline prompt) and feed the
|
|
260
271
|
# prompt via stdin from .hud_prompt.txt. claude --print reads stdin as
|
|
261
272
|
# the initial message when no -- argument is provided.
|
|
262
|
-
set_parts = [f"set {k}={v}" for k, v in env_vars.items()]
|
|
263
273
|
cmd_args = ["cmd", "/c", "claude"] + base_args[1:] # noqa: RUF005
|
|
264
274
|
py_args_repr = "[" + ",".join(f"'{a}'" for a in cmd_args) + "]"
|
|
275
|
+
encoded_env = base64.b64encode(json.dumps(env_vars).encode()).decode()
|
|
265
276
|
python_launcher = (
|
|
266
277
|
'python -c "'
|
|
267
|
-
"import subprocess,sys;"
|
|
268
|
-
|
|
278
|
+
"import base64,json,os,subprocess,sys;"
|
|
279
|
+
"env=os.environ.copy();"
|
|
280
|
+
f"env.update(json.loads(base64.b64decode('{encoded_env}')));"
|
|
281
|
+
f"r=subprocess.run({py_args_repr},stdin=open('.hud_prompt.txt','rb'),env=env);"
|
|
269
282
|
'sys.exit(r.returncode)"'
|
|
270
283
|
)
|
|
271
|
-
return
|
|
284
|
+
return python_launcher
|
|
272
285
|
|
|
273
286
|
# POSIX path: shell-quote everything and embed prompt inline.
|
|
274
287
|
cli_parts = [shlex.quote(a) for a in base_args]
|
|
@@ -4,18 +4,19 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
import base64
|
|
6
6
|
import logging
|
|
7
|
-
from typing import Any, cast
|
|
7
|
+
from typing import TYPE_CHECKING, Any, cast
|
|
8
8
|
|
|
9
9
|
import mcp.types as mcp_types
|
|
10
|
-
from google import genai
|
|
11
10
|
from google.genai import types as genai_types
|
|
12
11
|
|
|
13
12
|
from hud.agents.tool_agent import RunState, ToolAgent
|
|
14
13
|
from hud.agents.types import AgentStep, Citation, GeminiConfig, Usage
|
|
15
|
-
from hud.settings import settings
|
|
16
14
|
from hud.types import MCPToolCall, MCPToolResult
|
|
17
15
|
from hud.utils import gateway
|
|
18
16
|
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from google import genai
|
|
19
|
+
|
|
19
20
|
from .settings import gemini_agent_settings
|
|
20
21
|
from .tools import (
|
|
21
22
|
PREDEFINED_COMPUTER_USE_FUNCTIONS,
|
|
@@ -54,14 +55,7 @@ class GeminiAgent(ToolAgent[genai_types.Content, GeminiConfig]):
|
|
|
54
55
|
|
|
55
56
|
model_client = config.model_client
|
|
56
57
|
if model_client is None:
|
|
57
|
-
|
|
58
|
-
model_client = gateway.build_gateway_client("gemini")
|
|
59
|
-
elif settings.gemini_api_key:
|
|
60
|
-
model_client = genai.Client(api_key=settings.gemini_api_key)
|
|
61
|
-
else:
|
|
62
|
-
raise ValueError(
|
|
63
|
-
"No API key for Gemini. Set HUD_API_KEY or GEMINI_API_KEY.",
|
|
64
|
-
)
|
|
58
|
+
model_client = gateway.build_model_client("gemini", gateway=config.gateway)
|
|
65
59
|
|
|
66
60
|
self.gemini_client: genai.Client = cast("genai.Client", model_client)
|
|
67
61
|
self.temperature = config.temperature
|
|
@@ -24,9 +24,9 @@ from openai.types.responses.response_input_param import (
|
|
|
24
24
|
)
|
|
25
25
|
from openai.types.shared_params.reasoning import Reasoning # noqa: TC002
|
|
26
26
|
|
|
27
|
-
from hud.agents.tool_agent import RunState, ToolAgent
|
|
27
|
+
from hud.agents.tool_agent import DegenerateTurnError, RunState, ToolAgent
|
|
28
|
+
from hud.agents.tools.base import result_text
|
|
28
29
|
from hud.agents.types import AgentStep, Citation, OpenAIConfig, Usage
|
|
29
|
-
from hud.settings import settings
|
|
30
30
|
from hud.types import MCPToolCall, MCPToolResult
|
|
31
31
|
from hud.utils import gateway
|
|
32
32
|
|
|
@@ -41,6 +41,16 @@ if TYPE_CHECKING:
|
|
|
41
41
|
logger = logging.getLogger(__name__)
|
|
42
42
|
|
|
43
43
|
|
|
44
|
+
class EmptyShellCallError(DegenerateTurnError):
|
|
45
|
+
"""The model emitted a shell_call with an empty ``commands`` array.
|
|
46
|
+
|
|
47
|
+
OpenAI stores such a turn but returns 500 for every request that continues
|
|
48
|
+
from it via ``previous_response_id``. The turn is rejected before its
|
|
49
|
+
response id is committed, so the run state still points at the last
|
|
50
|
+
healthy response and the next sample continues from there.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
|
|
44
54
|
@dataclass
|
|
45
55
|
class OpenAIRunState(RunState[ResponseInputItemParam]):
|
|
46
56
|
last_response_id: str | None = None
|
|
@@ -62,14 +72,7 @@ class OpenAIAgent(ToolAgent[ResponseInputItemParam, OpenAIConfig]):
|
|
|
62
72
|
|
|
63
73
|
model_client = config.model_client
|
|
64
74
|
if model_client is None:
|
|
65
|
-
|
|
66
|
-
model_client = gateway.build_gateway_client("openai")
|
|
67
|
-
elif settings.openai_api_key:
|
|
68
|
-
model_client = AsyncOpenAI(api_key=settings.openai_api_key)
|
|
69
|
-
else:
|
|
70
|
-
raise ValueError(
|
|
71
|
-
"No API key for OpenAI. Set HUD_API_KEY or OPENAI_API_KEY.",
|
|
72
|
-
)
|
|
75
|
+
model_client = gateway.build_model_client("openai", gateway=config.gateway)
|
|
73
76
|
|
|
74
77
|
self.openai_client: AsyncOpenAI = cast("AsyncOpenAI", model_client)
|
|
75
78
|
self._model = config.model
|
|
@@ -106,8 +109,10 @@ class OpenAIAgent(ToolAgent[ResponseInputItemParam, OpenAIConfig]):
|
|
|
106
109
|
if isinstance(tool, OpenAIComputerTool):
|
|
107
110
|
screenshot = last_image_content(result)
|
|
108
111
|
if screenshot is None:
|
|
109
|
-
|
|
110
|
-
|
|
112
|
+
raise RuntimeError(
|
|
113
|
+
f"Computer tool result missing screenshot for call {call.id}: "
|
|
114
|
+
f"{result_text(result)}"
|
|
115
|
+
)
|
|
111
116
|
output = ComputerCallOutput(
|
|
112
117
|
type="computer_call_output",
|
|
113
118
|
call_id=call.id,
|
|
@@ -132,7 +137,17 @@ class OpenAIAgent(ToolAgent[ResponseInputItemParam, OpenAIConfig]):
|
|
|
132
137
|
acknowledged.append(raw_check)
|
|
133
138
|
if acknowledged:
|
|
134
139
|
output["acknowledged_safety_checks"] = acknowledged
|
|
135
|
-
|
|
140
|
+
if result.isError:
|
|
141
|
+
return [
|
|
142
|
+
output,
|
|
143
|
+
self._format_message(
|
|
144
|
+
"user",
|
|
145
|
+
f"Computer call {call.id} stopped with an error. "
|
|
146
|
+
"Remaining actions in this call were not executed.\n"
|
|
147
|
+
f"{result_text(result)}",
|
|
148
|
+
),
|
|
149
|
+
]
|
|
150
|
+
return output
|
|
136
151
|
|
|
137
152
|
if isinstance(tool, OpenAIShellTool):
|
|
138
153
|
structured = (
|
|
@@ -140,8 +155,6 @@ class OpenAIAgent(ToolAgent[ResponseInputItemParam, OpenAIConfig]):
|
|
|
140
155
|
)
|
|
141
156
|
output_list = structured.get("output")
|
|
142
157
|
if not isinstance(output_list, list):
|
|
143
|
-
from hud.agents.tools.base import result_text
|
|
144
|
-
|
|
145
158
|
text = result_text(result)
|
|
146
159
|
output_list = [shell_output("", text, 1 if result.isError else 0)]
|
|
147
160
|
response: dict[str, Any] = {
|
|
@@ -223,10 +236,23 @@ class OpenAIAgent(ToolAgent[ResponseInputItemParam, OpenAIConfig]):
|
|
|
223
236
|
previous_response_id=(
|
|
224
237
|
oai_state.last_response_id if oai_state.last_response_id is not None else Omit()
|
|
225
238
|
),
|
|
239
|
+
prompt_cache_key=self.config.prompt_cache_key,
|
|
226
240
|
truncation=self.truncation if self.truncation is not None else Omit(),
|
|
227
241
|
include=include_param,
|
|
228
242
|
)
|
|
229
243
|
|
|
244
|
+
empty_shell_calls = [
|
|
245
|
+
item.call_id
|
|
246
|
+
for item in response.output
|
|
247
|
+
if item.type == "shell_call" and item.action.to_dict().get("commands") == []
|
|
248
|
+
]
|
|
249
|
+
if empty_shell_calls:
|
|
250
|
+
raise EmptyShellCallError(
|
|
251
|
+
f"Model emitted shell_call(s) with an empty commands array "
|
|
252
|
+
f"({', '.join(empty_shell_calls)}); continuing from response {response.id} "
|
|
253
|
+
"would fail with OpenAI 500s, so it was not committed to the run state."
|
|
254
|
+
)
|
|
255
|
+
|
|
230
256
|
oai_state.last_response_id = response.id
|
|
231
257
|
oai_state.message_cursor = len(messages)
|
|
232
258
|
|
|
@@ -290,7 +316,7 @@ class OpenAIAgent(ToolAgent[ResponseInputItemParam, OpenAIConfig]):
|
|
|
290
316
|
elif item.action is not None:
|
|
291
317
|
arguments = item.action.to_dict()
|
|
292
318
|
else:
|
|
293
|
-
|
|
319
|
+
arguments = {"actions": []}
|
|
294
320
|
call_dict: dict[str, Any] = {
|
|
295
321
|
"name": "computer",
|
|
296
322
|
"arguments": arguments,
|
|
@@ -335,4 +361,4 @@ class OpenAIAgent(ToolAgent[ResponseInputItemParam, OpenAIConfig]):
|
|
|
335
361
|
)
|
|
336
362
|
|
|
337
363
|
|
|
338
|
-
__all__ = ["OpenAIAgent"]
|
|
364
|
+
__all__ = ["EmptyShellCallError", "OpenAIAgent"]
|