hud-python 0.5.9__tar.gz → 0.5.10__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_python-0.5.9 → hud_python-0.5.10}/PKG-INFO +1 -1
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/__init__.py +5 -9
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/base.py +2 -13
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/claude.py +3 -18
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/gemini.py +3 -22
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/gemini_cua.py +3 -17
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/openai.py +4 -25
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/openai_chat.py +3 -19
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/operator.py +3 -17
- hud_python-0.5.10/hud/agents/types.py +148 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/eval.py +1 -1
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/patches/mcp_patches.py +114 -0
- hud_python-0.5.10/hud/tools/computer/__init__.py +48 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/types.py +50 -27
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/tests/test_version.py +1 -1
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/version.py +1 -1
- {hud_python-0.5.9 → hud_python-0.5.10}/pyproject.toml +1 -1
- hud_python-0.5.9/hud/tools/computer/__init__.py +0 -19
- {hud_python-0.5.9 → hud_python-0.5.10}/.gitignore +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/LICENSE +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/README.md +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/examples/README.md +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/__main__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/gateway.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/grounded_openai.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/misc/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/misc/integration_test_agent.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/misc/response_agent.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/resolver.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/conftest.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/test_base.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/test_base_runtime.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/test_claude.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/test_client.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/test_gemini.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/test_grounded_openai_agent.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/test_openai.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/test_operator.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/test_resolver.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/agents/tests/test_run_eval.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/__main__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/analyze.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/build.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/clone.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/debug.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/dev.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/flows/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/flows/dev.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/flows/init.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/flows/tasks.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/flows/templates.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/flows/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/flows/tests/test_dev.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/get.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/init.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/list_func.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/pull.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/push.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/remove.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/rft.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/rft_status.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_analyze.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_analyze_metadata.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_analyze_module.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_build.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_build_failure.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_build_module.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_cli_init.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_cli_main.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_cli_more_wrappers.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_cli_root.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_clone.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_convert.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_cursor.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_debug.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_dev.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_eval.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_eval_bedrock.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_init.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_list_func.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_main_module.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_mcp_server.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_pull.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_push.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_push_happy.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_push_wrapper.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_registry.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/tests/test_utils.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/celebrate.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/config.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/cursor.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/docker.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/env_check.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/environment.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/git.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/interactive.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/local_runner.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/logging.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/metadata.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/package_runner.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/registry.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/remote_runner.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/runner.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/server.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/source_hash.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tasks.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_config.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_docker.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_docker_hints.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_env_check.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_environment.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_git.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_interactive_module.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_local_runner.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_logging_utils.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_metadata.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_package_runner.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_registry_utils.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_remote_runner.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_runner_modules.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_source_hash.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/tests/test_tasks.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/version_check.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/cli/utils/viewer.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/README.md +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/base.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/environment.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/fastmcp.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/mcp_use.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/tests/test_analyze_scenarios.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/tests/test_client_integration.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/tests/test_fastmcp.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/tests/test_mcp_use_retry.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/tests/test_protocol.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/utils/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/utils/mcp_use_retry.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/utils/retry.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/clients/utils/retry_transport.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/datasets/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/datasets/loader.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/datasets/runner.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/datasets/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/datasets/tests/test_loader.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/datasets/tests/test_utils.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/datasets/utils.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/connection.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/connectors/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/connectors/base.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/connectors/local.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/connectors/mcp_config.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/connectors/openai.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/connectors/remote.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/environment.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/integrations/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/integrations/adk.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/integrations/anthropic.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/integrations/gemini.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/integrations/langchain.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/integrations/llamaindex.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/integrations/openai.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/mock.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/router.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/scenarios.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/tests/test_connection.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/tests/test_connectors.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/tests/test_environment.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/tests/test_integrations.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/tests/test_local_connectors.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/tests/test_scenarios.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/tests/test_tools.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/types.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/utils/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/utils/formats.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/utils/schema.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/environment/utils/tool_wrappers.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/context.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/display.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/instrument.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/manager.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/parallel.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/task.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/tests/test_context.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/tests/test_eval.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/tests/test_manager.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/tests/test_parallel.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/tests/test_task.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/types.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/eval/utils.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/native/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/native/comparator.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/native/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/native/tests/test_comparator.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/native/tests/test_native_init.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/patches/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/patches/warnings.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/py.typed +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/samples/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/samples/browser.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/context.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/helper/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/low_level.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/router.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/server.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/tests/test_add_tool.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/tests/test_context.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/tests/test_mcp_server_handlers.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/tests/test_mcp_server_integration.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/tests/test_mcp_server_more.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/tests/test_run_wrapper.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/tests/test_server_extra.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/server/tests/test_sigterm_runner.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/settings.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/shared/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/shared/exceptions.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/shared/hints.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/shared/requests.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/shared/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/shared/tests/test_exceptions.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/shared/tests/test_hints.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/shared/tests/test_requests.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/telemetry/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/telemetry/exporter.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/telemetry/instrument.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/telemetry/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/telemetry/tests/test_eval_telemetry.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/telemetry/tests/test_exporter.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/telemetry/tests/test_instrument.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/agent.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/apply_patch.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/base.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/bash.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/computer/anthropic.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/computer/gemini.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/computer/hud.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/computer/openai.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/computer/qwen.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/computer/settings.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/edit.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/executors/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/executors/base.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/executors/pyautogui.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/executors/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/executors/tests/test_base_executor.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/executors/tests/test_pyautogui_executor.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/executors/xdo.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/grounding/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/grounding/config.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/grounding/grounded_tool.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/grounding/grounder.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/grounding/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/grounding/tests/test_grounded_tool.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/jupyter.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/playwright.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/response.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/shell.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/submit.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_agent_tool.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_apply_patch.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_base.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_bash.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_bash_extended.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_computer.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_computer_actions.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_edit.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_init.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_jupyter_tool.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_playwright_tool.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_response.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_shell.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_submit.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_tools.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_tools_init.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_types.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/tests/test_utils.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/types.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/tools/utils.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/env.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/hud_console.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/mcp.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/pretty_errors.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/strict_schema.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/telemetry.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/tests/__init__.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/tests/test_init.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/tests/test_mcp.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/tests/test_pretty_errors.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/tests/test_telemetry.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/tests/test_tool_shorthand.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/tool_shorthand.py +0 -0
- {hud_python-0.5.9 → hud_python-0.5.10}/hud/utils/types.py +0 -0
|
@@ -56,15 +56,11 @@ def create_agent(model: str, **kwargs: Any) -> MCPAgent:
|
|
|
56
56
|
if gateway_info:
|
|
57
57
|
provider = gateway_info.get("provider") or "openai"
|
|
58
58
|
else:
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
ClaudeAgent: "anthropic",
|
|
65
|
-
GeminiAgent: "google",
|
|
66
|
-
}
|
|
67
|
-
provider = _AGENT_TO_PROVIDER.get(agent_cls, "openai")
|
|
59
|
+
provider = "openai"
|
|
60
|
+
if agent_cls.__name__ == "ClaudeAgent":
|
|
61
|
+
provider = "anthropic"
|
|
62
|
+
elif agent_cls.__name__ in ("GeminiAgent", "GeminiCUAAgent"):
|
|
63
|
+
provider = "gemini"
|
|
68
64
|
|
|
69
65
|
client = build_gateway_client(provider)
|
|
70
66
|
|
|
@@ -9,11 +9,12 @@ from abc import ABC, abstractmethod
|
|
|
9
9
|
from typing import TYPE_CHECKING, Any, ClassVar, Literal
|
|
10
10
|
|
|
11
11
|
import mcp.types as types
|
|
12
|
-
from pydantic import BaseModel, ConfigDict
|
|
13
12
|
|
|
14
13
|
from hud.types import AgentResponse, BaseAgentConfig, MCPToolCall, MCPToolResult, Trace
|
|
15
14
|
from hud.utils.hud_console import HUDConsole
|
|
16
15
|
|
|
16
|
+
from .types import BaseCreateParams
|
|
17
|
+
|
|
17
18
|
if TYPE_CHECKING:
|
|
18
19
|
from hud.environment import Environment
|
|
19
20
|
from hud.eval.context import EvalContext
|
|
@@ -22,18 +23,6 @@ if TYPE_CHECKING:
|
|
|
22
23
|
logger = logging.getLogger(__name__)
|
|
23
24
|
|
|
24
25
|
|
|
25
|
-
class BaseCreateParams(BaseModel):
|
|
26
|
-
"""Runtime parameters for agent creation."""
|
|
27
|
-
|
|
28
|
-
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
29
|
-
|
|
30
|
-
# Primary way to bind agent to execution context (v5)
|
|
31
|
-
ctx: Any | None = None # EvalContext or Environment - agent uses this for tool calls
|
|
32
|
-
|
|
33
|
-
auto_respond: bool = False
|
|
34
|
-
verbose: bool = False
|
|
35
|
-
|
|
36
|
-
|
|
37
26
|
class MCPAgent(ABC):
|
|
38
27
|
"""
|
|
39
28
|
Base class for MCP-enabled agents.
|
|
@@ -25,7 +25,6 @@ from anthropic.types.beta import (
|
|
|
25
25
|
BetaToolTextEditor20250728Param,
|
|
26
26
|
BetaToolUnionParam,
|
|
27
27
|
)
|
|
28
|
-
from pydantic import ConfigDict
|
|
29
28
|
|
|
30
29
|
from hud.settings import settings
|
|
31
30
|
from hud.tools.computer.settings import computer_settings
|
|
@@ -33,7 +32,8 @@ from hud.types import AgentResponse, BaseAgentConfig, MCPToolCall, MCPToolResult
|
|
|
33
32
|
from hud.utils.hud_console import HUDConsole
|
|
34
33
|
from hud.utils.types import with_signature
|
|
35
34
|
|
|
36
|
-
from .base import
|
|
35
|
+
from .base import MCPAgent
|
|
36
|
+
from .types import ClaudeConfig, ClaudeCreateParams
|
|
37
37
|
|
|
38
38
|
if TYPE_CHECKING:
|
|
39
39
|
from collections.abc import Sequence
|
|
@@ -41,21 +41,6 @@ if TYPE_CHECKING:
|
|
|
41
41
|
logger = logging.getLogger(__name__)
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
class ClaudeConfig(BaseAgentConfig):
|
|
45
|
-
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
46
|
-
|
|
47
|
-
model_name: str = "Claude"
|
|
48
|
-
model: str = "claude-sonnet-4-5"
|
|
49
|
-
model_client: AsyncAnthropic | AsyncAnthropicBedrock | None = None
|
|
50
|
-
max_tokens: int = 16384
|
|
51
|
-
use_computer_beta: bool = True
|
|
52
|
-
validate_api_key: bool = True
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
class ClaudeCreateParams(BaseCreateParams, ClaudeConfig):
|
|
56
|
-
pass
|
|
57
|
-
|
|
58
|
-
|
|
59
44
|
class ClaudeAgent(MCPAgent):
|
|
60
45
|
"""
|
|
61
46
|
Claude agent that uses MCP servers for tool execution.
|
|
@@ -94,7 +79,7 @@ class ClaudeAgent(MCPAgent):
|
|
|
94
79
|
"or ANTHROPIC_API_KEY for direct Anthropic access."
|
|
95
80
|
)
|
|
96
81
|
|
|
97
|
-
self.anthropic_client = model_client
|
|
82
|
+
self.anthropic_client: AsyncAnthropic | AsyncAnthropicBedrock = model_client
|
|
98
83
|
self.max_tokens = self.config.max_tokens
|
|
99
84
|
self.use_computer_beta = self.config.use_computer_beta
|
|
100
85
|
self.hud_console = HUDConsole(logger=logger)
|
|
@@ -8,37 +8,18 @@ from typing import Any, ClassVar, cast
|
|
|
8
8
|
import mcp.types as types
|
|
9
9
|
from google import genai
|
|
10
10
|
from google.genai import types as genai_types
|
|
11
|
-
from pydantic import ConfigDict
|
|
12
11
|
|
|
13
12
|
from hud.settings import settings
|
|
14
13
|
from hud.types import AgentResponse, BaseAgentConfig, MCPToolCall, MCPToolResult
|
|
15
14
|
from hud.utils.hud_console import HUDConsole
|
|
16
15
|
from hud.utils.types import with_signature
|
|
17
16
|
|
|
18
|
-
from .base import
|
|
17
|
+
from .base import MCPAgent
|
|
18
|
+
from .types import GeminiConfig, GeminiCreateParams
|
|
19
19
|
|
|
20
20
|
logger = logging.getLogger(__name__)
|
|
21
21
|
|
|
22
22
|
|
|
23
|
-
class GeminiConfig(BaseAgentConfig):
|
|
24
|
-
"""Configuration for `GeminiAgent`."""
|
|
25
|
-
|
|
26
|
-
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
27
|
-
|
|
28
|
-
model_name: str = "Gemini"
|
|
29
|
-
model: str = "gemini-3-pro-preview"
|
|
30
|
-
model_client: genai.Client | None = None
|
|
31
|
-
temperature: float = 1.0
|
|
32
|
-
top_p: float = 0.95
|
|
33
|
-
top_k: int = 40
|
|
34
|
-
max_output_tokens: int = 8192
|
|
35
|
-
validate_api_key: bool = True
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
class GeminiCreateParams(BaseCreateParams, GeminiConfig):
|
|
39
|
-
pass
|
|
40
|
-
|
|
41
|
-
|
|
42
23
|
class GeminiAgent(MCPAgent):
|
|
43
24
|
"""
|
|
44
25
|
Gemini agent that uses MCP servers for tool execution.
|
|
@@ -80,7 +61,7 @@ class GeminiAgent(MCPAgent):
|
|
|
80
61
|
except Exception as e:
|
|
81
62
|
raise ValueError(f"Gemini API key is invalid: {e}") from e
|
|
82
63
|
|
|
83
|
-
self.gemini_client = model_client
|
|
64
|
+
self.gemini_client: genai.Client = model_client
|
|
84
65
|
self.temperature = self.config.temperature
|
|
85
66
|
self.top_p = self.config.top_p
|
|
86
67
|
self.top_k = self.config.top_k
|
|
@@ -7,14 +7,14 @@ from typing import Any, ClassVar
|
|
|
7
7
|
|
|
8
8
|
import mcp.types as types
|
|
9
9
|
from google.genai import types as genai_types
|
|
10
|
-
from pydantic import ConfigDict, Field
|
|
11
10
|
|
|
12
11
|
from hud.tools.computer.settings import computer_settings
|
|
13
12
|
from hud.types import AgentResponse, BaseAgentConfig, MCPToolCall, MCPToolResult
|
|
14
13
|
from hud.utils.types import with_signature
|
|
15
14
|
|
|
16
|
-
from .base import
|
|
17
|
-
from .gemini import GeminiAgent
|
|
15
|
+
from .base import MCPAgent
|
|
16
|
+
from .gemini import GeminiAgent
|
|
17
|
+
from .types import GeminiCUAConfig, GeminiCUACreateParams
|
|
18
18
|
|
|
19
19
|
logger = logging.getLogger(__name__)
|
|
20
20
|
|
|
@@ -56,20 +56,6 @@ what they asked.
|
|
|
56
56
|
""".strip()
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
class GeminiCUAConfig(GeminiConfig):
|
|
60
|
-
"""Configuration for `GeminiCUAAgent`."""
|
|
61
|
-
|
|
62
|
-
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
63
|
-
|
|
64
|
-
model_name: str = "GeminiCUA"
|
|
65
|
-
model: str = "gemini-2.5-computer-use-preview-10-2025"
|
|
66
|
-
excluded_predefined_functions: list[str] = Field(default_factory=list)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
class GeminiCUACreateParams(BaseCreateParams, GeminiCUAConfig):
|
|
70
|
-
pass
|
|
71
|
-
|
|
72
|
-
|
|
73
59
|
class GeminiCUAAgent(GeminiAgent):
|
|
74
60
|
"""
|
|
75
61
|
Gemini Computer Use Agent that extends GeminiAgent with computer use capabilities.
|
|
@@ -29,39 +29,18 @@ from openai.types.responses import (
|
|
|
29
29
|
from openai.types.responses.response_create_params import ToolChoice # noqa: TC002
|
|
30
30
|
from openai.types.responses.response_input_param import FunctionCallOutput, Message
|
|
31
31
|
from openai.types.shared_params.reasoning import Reasoning # noqa: TC002
|
|
32
|
-
from pydantic import ConfigDict
|
|
33
32
|
|
|
34
33
|
from hud.settings import settings
|
|
35
34
|
from hud.types import AgentResponse, BaseAgentConfig, MCPToolCall, MCPToolResult, Trace
|
|
36
35
|
from hud.utils.strict_schema import ensure_strict_json_schema
|
|
37
36
|
from hud.utils.types import with_signature
|
|
38
37
|
|
|
39
|
-
from .base import
|
|
38
|
+
from .base import MCPAgent
|
|
39
|
+
from .types import OpenAIConfig, OpenAICreateParams
|
|
40
40
|
|
|
41
41
|
logger = logging.getLogger(__name__)
|
|
42
42
|
|
|
43
43
|
|
|
44
|
-
class OpenAIConfig(BaseAgentConfig):
|
|
45
|
-
"""Configuration model for `OpenAIAgent`."""
|
|
46
|
-
|
|
47
|
-
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
48
|
-
|
|
49
|
-
model_name: str = "OpenAI"
|
|
50
|
-
model: str = "gpt-5.1"
|
|
51
|
-
model_client: AsyncOpenAI | None = None
|
|
52
|
-
max_output_tokens: int | None = None
|
|
53
|
-
temperature: float | None = None
|
|
54
|
-
reasoning: Reasoning | None = None
|
|
55
|
-
tool_choice: ToolChoice | None = None
|
|
56
|
-
truncation: Literal["auto", "disabled"] | None = None
|
|
57
|
-
parallel_tool_calls: bool | None = None
|
|
58
|
-
validate_api_key: bool = True
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
class OpenAICreateParams(BaseCreateParams, OpenAIConfig):
|
|
62
|
-
pass
|
|
63
|
-
|
|
64
|
-
|
|
65
44
|
class OpenAIAgent(MCPAgent):
|
|
66
45
|
"""Generic OpenAI agent that can execute MCP tools through the Responses API."""
|
|
67
46
|
|
|
@@ -98,11 +77,11 @@ class OpenAIAgent(MCPAgent):
|
|
|
98
77
|
except Exception as exc: # pragma: no cover - network validation
|
|
99
78
|
raise ValueError(f"OpenAI API key is invalid: {exc}") from exc
|
|
100
79
|
|
|
101
|
-
self.openai_client = model_client
|
|
80
|
+
self.openai_client: AsyncOpenAI = model_client
|
|
102
81
|
self._model = self.config.model
|
|
103
82
|
self.max_output_tokens = self.config.max_output_tokens
|
|
104
83
|
self.temperature = self.config.temperature
|
|
105
|
-
self.reasoning = self.config.reasoning
|
|
84
|
+
self.reasoning: Reasoning | None = self.config.reasoning
|
|
106
85
|
self.tool_choice: ToolChoice | None = self.config.tool_choice
|
|
107
86
|
self.parallel_tool_calls = self.config.parallel_tool_calls
|
|
108
87
|
self.truncation: Literal["auto", "disabled"] | None = self.config.truncation
|
|
@@ -22,14 +22,14 @@ from typing import TYPE_CHECKING, Any, ClassVar, cast
|
|
|
22
22
|
|
|
23
23
|
import mcp.types as types
|
|
24
24
|
from openai import AsyncOpenAI
|
|
25
|
-
from pydantic import ConfigDict, Field
|
|
26
25
|
|
|
27
26
|
from hud.settings import settings
|
|
28
27
|
from hud.types import AgentResponse, BaseAgentConfig, MCPToolCall, MCPToolResult
|
|
29
28
|
from hud.utils.hud_console import HUDConsole
|
|
30
29
|
from hud.utils.types import with_signature
|
|
31
30
|
|
|
32
|
-
from .base import
|
|
31
|
+
from .base import MCPAgent
|
|
32
|
+
from .types import OpenAIChatConfig, OpenAIChatCreateParams
|
|
33
33
|
|
|
34
34
|
if TYPE_CHECKING:
|
|
35
35
|
from openai.types.chat import ChatCompletionToolParam
|
|
@@ -38,23 +38,6 @@ if TYPE_CHECKING:
|
|
|
38
38
|
logger = logging.getLogger(__name__)
|
|
39
39
|
|
|
40
40
|
|
|
41
|
-
class OpenAIChatConfig(BaseAgentConfig):
|
|
42
|
-
"""Configuration for `OpenAIChatAgent`."""
|
|
43
|
-
|
|
44
|
-
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
45
|
-
|
|
46
|
-
model_name: str = "OpenAI Chat"
|
|
47
|
-
model: str = "gpt-5-mini"
|
|
48
|
-
openai_client: AsyncOpenAI | None = None
|
|
49
|
-
api_key: str | None = None
|
|
50
|
-
base_url: str | None = None
|
|
51
|
-
completion_kwargs: dict[str, Any] = Field(default_factory=dict)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class OpenAIChatCreateParams(BaseCreateParams, OpenAIChatConfig):
|
|
55
|
-
pass
|
|
56
|
-
|
|
57
|
-
|
|
58
41
|
class OpenAIChatAgent(MCPAgent):
|
|
59
42
|
"""MCP-enabled agent that speaks the OpenAI *chat.completions* protocol."""
|
|
60
43
|
|
|
@@ -82,6 +65,7 @@ class OpenAIChatAgent(MCPAgent):
|
|
|
82
65
|
"Use HUD_API_KEY for gateway auth and BYOK headers for provider keys."
|
|
83
66
|
)
|
|
84
67
|
|
|
68
|
+
self.oai: AsyncOpenAI
|
|
85
69
|
if self.config.openai_client is not None:
|
|
86
70
|
self.oai = self.config.openai_client
|
|
87
71
|
elif self.config.api_key is not None or self.config.base_url is not None:
|
|
@@ -17,14 +17,14 @@ from openai.types.responses.response_input_param import (
|
|
|
17
17
|
FunctionCallOutput,
|
|
18
18
|
)
|
|
19
19
|
from openai.types.shared_params.reasoning import Reasoning
|
|
20
|
-
from pydantic import ConfigDict
|
|
21
20
|
|
|
22
21
|
from hud.tools.computer.settings import computer_settings
|
|
23
22
|
from hud.types import BaseAgentConfig, MCPToolCall, MCPToolResult
|
|
24
23
|
from hud.utils.types import with_signature
|
|
25
24
|
|
|
26
|
-
from .base import
|
|
27
|
-
from .openai import OpenAIAgent
|
|
25
|
+
from .base import MCPAgent
|
|
26
|
+
from .openai import OpenAIAgent
|
|
27
|
+
from .types import OperatorConfig, OperatorCreateParams
|
|
28
28
|
|
|
29
29
|
if TYPE_CHECKING:
|
|
30
30
|
from openai.types.responses.response_computer_tool_call import PendingSafetyCheck
|
|
@@ -50,20 +50,6 @@ what they asked.
|
|
|
50
50
|
""".strip()
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
class OperatorConfig(OpenAIConfig):
|
|
54
|
-
"""Configuration model for `OperatorAgent`."""
|
|
55
|
-
|
|
56
|
-
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
57
|
-
|
|
58
|
-
model_name: str = "Operator"
|
|
59
|
-
model: str = "computer-use-preview"
|
|
60
|
-
environment: Literal["windows", "mac", "linux", "ubuntu", "browser"] = "linux"
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class OperatorCreateParams(BaseCreateParams, OperatorConfig):
|
|
64
|
-
pass
|
|
65
|
-
|
|
66
|
-
|
|
67
53
|
class OperatorAgent(OpenAIAgent):
|
|
68
54
|
"""
|
|
69
55
|
Backwards-compatible Operator agent built on top of OpenAIAgent.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"""Agent configuration types.
|
|
2
|
+
|
|
3
|
+
Config classes are defined here separately from agent implementations
|
|
4
|
+
to allow importing them without requiring SDK dependencies (anthropic, google-genai).
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any, Literal
|
|
10
|
+
|
|
11
|
+
from pydantic import AliasChoices, BaseModel, ConfigDict, Field
|
|
12
|
+
|
|
13
|
+
from hud.types import BaseAgentConfig
|
|
14
|
+
|
|
15
|
+
# Alias to accept both 'model' and 'checkpoint_name' (backwards compat)
|
|
16
|
+
_model_alias = AliasChoices("model", "checkpoint_name")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class BaseCreateParams(BaseModel):
|
|
20
|
+
"""Runtime parameters for agent creation."""
|
|
21
|
+
|
|
22
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
23
|
+
|
|
24
|
+
ctx: Any = None # EvalContext or Environment
|
|
25
|
+
auto_respond: bool = False
|
|
26
|
+
verbose: bool = False
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
# -----------------------------------------------------------------------------
|
|
30
|
+
# Claude
|
|
31
|
+
# -----------------------------------------------------------------------------
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ClaudeConfig(BaseAgentConfig):
|
|
35
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
36
|
+
|
|
37
|
+
model_name: str = "Claude"
|
|
38
|
+
model: str = Field(default="claude-sonnet-4-5", validation_alias=_model_alias)
|
|
39
|
+
model_client: Any = None # AsyncAnthropic | AsyncAnthropicBedrock
|
|
40
|
+
max_tokens: int = 16384
|
|
41
|
+
use_computer_beta: bool = True
|
|
42
|
+
validate_api_key: bool = True
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class ClaudeCreateParams(BaseCreateParams, ClaudeConfig):
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
# -----------------------------------------------------------------------------
|
|
50
|
+
# Gemini
|
|
51
|
+
# -----------------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class GeminiConfig(BaseAgentConfig):
|
|
55
|
+
"""Configuration for GeminiAgent."""
|
|
56
|
+
|
|
57
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
58
|
+
|
|
59
|
+
model_name: str = "Gemini"
|
|
60
|
+
model: str = Field(default="gemini-3-pro-preview", validation_alias=_model_alias)
|
|
61
|
+
model_client: Any = None # genai.Client
|
|
62
|
+
temperature: float = 1.0
|
|
63
|
+
top_p: float = 0.95
|
|
64
|
+
top_k: int = 40
|
|
65
|
+
max_output_tokens: int = 8192
|
|
66
|
+
validate_api_key: bool = True
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class GeminiCreateParams(BaseCreateParams, GeminiConfig):
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
class GeminiCUAConfig(GeminiConfig):
|
|
74
|
+
"""Configuration for GeminiCUAAgent."""
|
|
75
|
+
|
|
76
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
77
|
+
|
|
78
|
+
model_name: str = "GeminiCUA"
|
|
79
|
+
model: str = Field(
|
|
80
|
+
default="gemini-2.5-computer-use-preview-10-2025", validation_alias=_model_alias
|
|
81
|
+
)
|
|
82
|
+
excluded_predefined_functions: list[str] = Field(default_factory=list)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
class GeminiCUACreateParams(BaseCreateParams, GeminiCUAConfig):
|
|
86
|
+
pass
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
# -----------------------------------------------------------------------------
|
|
90
|
+
# OpenAI
|
|
91
|
+
# -----------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
class OpenAIConfig(BaseAgentConfig):
|
|
95
|
+
"""Configuration for OpenAIAgent."""
|
|
96
|
+
|
|
97
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
98
|
+
|
|
99
|
+
model_name: str = "OpenAI"
|
|
100
|
+
model: str = Field(default="gpt-5.1", validation_alias=_model_alias)
|
|
101
|
+
model_client: Any = None # AsyncOpenAI
|
|
102
|
+
max_output_tokens: int | None = None
|
|
103
|
+
temperature: float | None = None
|
|
104
|
+
reasoning: Any = None # openai Reasoning
|
|
105
|
+
tool_choice: Any = None # openai ToolChoice
|
|
106
|
+
truncation: Literal["auto", "disabled"] | None = None
|
|
107
|
+
parallel_tool_calls: bool | None = None
|
|
108
|
+
validate_api_key: bool = True
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
class OpenAICreateParams(BaseCreateParams, OpenAIConfig):
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class OpenAIChatConfig(BaseAgentConfig):
|
|
116
|
+
"""Configuration for OpenAIChatAgent."""
|
|
117
|
+
|
|
118
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
119
|
+
|
|
120
|
+
model_name: str = "OpenAI Chat"
|
|
121
|
+
model: str = Field(default="gpt-5-mini", validation_alias=_model_alias)
|
|
122
|
+
openai_client: Any = None # AsyncOpenAI
|
|
123
|
+
api_key: str | None = None
|
|
124
|
+
base_url: str | None = None
|
|
125
|
+
completion_kwargs: dict[str, Any] = Field(default_factory=dict)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
class OpenAIChatCreateParams(BaseCreateParams, OpenAIChatConfig):
|
|
129
|
+
pass
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
# -----------------------------------------------------------------------------
|
|
133
|
+
# Operator
|
|
134
|
+
# -----------------------------------------------------------------------------
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
class OperatorConfig(OpenAIConfig):
|
|
138
|
+
"""Configuration for OperatorAgent."""
|
|
139
|
+
|
|
140
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
141
|
+
|
|
142
|
+
model_name: str = "Operator"
|
|
143
|
+
model: str = Field(default="computer-use-preview", validation_alias=_model_alias)
|
|
144
|
+
environment: Literal["windows", "mac", "linux", "ubuntu", "browser"] = "linux"
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
class OperatorCreateParams(BaseCreateParams, OperatorConfig):
|
|
148
|
+
pass
|
|
@@ -564,7 +564,7 @@ class EvalConfig(BaseModel):
|
|
|
564
564
|
table.add_row("", "")
|
|
565
565
|
table.add_row(f"[dim]{self.agent_type.value} config[/dim]", "")
|
|
566
566
|
|
|
567
|
-
config_cls = self.agent_type.
|
|
567
|
+
config_cls = self.agent_type.config_cls
|
|
568
568
|
defaults = config_cls()
|
|
569
569
|
overrides = self.agent_config.get(self.agent_type.value, {})
|
|
570
570
|
skip = {
|
|
@@ -165,6 +165,119 @@ def patch_client_session_validation() -> None:
|
|
|
165
165
|
logger.warning("Failed to patch client session: %s", e)
|
|
166
166
|
|
|
167
167
|
|
|
168
|
+
def patch_server_output_validation() -> None:
|
|
169
|
+
"""
|
|
170
|
+
Patch MCP server to skip structured output validation and auto-generate
|
|
171
|
+
structuredContent for FastMCP tools with x-fastmcp-wrap-result.
|
|
172
|
+
"""
|
|
173
|
+
try:
|
|
174
|
+
import json
|
|
175
|
+
|
|
176
|
+
import mcp.types as types
|
|
177
|
+
from mcp.server.lowlevel.server import Server
|
|
178
|
+
|
|
179
|
+
def patched_call_tool(
|
|
180
|
+
self: Any, validate_input: bool = True, validate_output: bool = False
|
|
181
|
+
) -> Any:
|
|
182
|
+
"""Patched call_tool that skips output validation."""
|
|
183
|
+
|
|
184
|
+
def decorator(func: Any) -> Any:
|
|
185
|
+
async def handler(req: types.CallToolRequest) -> Any:
|
|
186
|
+
try:
|
|
187
|
+
tool_name = req.params.name
|
|
188
|
+
arguments = req.params.arguments or {}
|
|
189
|
+
tool = await self._get_cached_tool_definition(tool_name)
|
|
190
|
+
|
|
191
|
+
if validate_input and tool:
|
|
192
|
+
try:
|
|
193
|
+
import jsonschema
|
|
194
|
+
|
|
195
|
+
jsonschema.validate(instance=arguments, schema=tool.inputSchema)
|
|
196
|
+
except jsonschema.ValidationError as e:
|
|
197
|
+
return self._make_error_result(
|
|
198
|
+
f"Input validation error: {e.message}"
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
results = await func(tool_name, arguments)
|
|
202
|
+
|
|
203
|
+
# output normalization
|
|
204
|
+
unstructured_content: list[Any]
|
|
205
|
+
maybe_structured_content: dict[str, Any] | None
|
|
206
|
+
if isinstance(results, types.CallToolResult):
|
|
207
|
+
return types.ServerResult(results)
|
|
208
|
+
elif isinstance(results, tuple) and len(results) == 2:
|
|
209
|
+
unstructured_content, maybe_structured_content = results
|
|
210
|
+
elif isinstance(results, dict):
|
|
211
|
+
maybe_structured_content = results
|
|
212
|
+
text = json.dumps(results, indent=2)
|
|
213
|
+
unstructured_content = [types.TextContent(type="text", text=text)]
|
|
214
|
+
elif results is None:
|
|
215
|
+
# None means success with no content
|
|
216
|
+
unstructured_content = []
|
|
217
|
+
maybe_structured_content = None
|
|
218
|
+
elif isinstance(results, (str, bytes, bytearray, memoryview)):
|
|
219
|
+
# Handle string/bytes explicitly before iterable check
|
|
220
|
+
# (these are iterable but should not be split into chars/ints)
|
|
221
|
+
if isinstance(results, str):
|
|
222
|
+
text = results
|
|
223
|
+
elif isinstance(results, memoryview):
|
|
224
|
+
text = bytes(results).decode("utf-8", errors="replace")
|
|
225
|
+
else:
|
|
226
|
+
text = bytes(results).decode("utf-8", errors="replace")
|
|
227
|
+
unstructured_content = [types.TextContent(type="text", text=text)]
|
|
228
|
+
maybe_structured_content = None
|
|
229
|
+
elif isinstance(results, (int, float, bool)):
|
|
230
|
+
# Primitives -> string representation
|
|
231
|
+
unstructured_content = [
|
|
232
|
+
types.TextContent(type="text", text=str(results))
|
|
233
|
+
]
|
|
234
|
+
maybe_structured_content = None
|
|
235
|
+
elif hasattr(results, "__iter__"):
|
|
236
|
+
unstructured_content = list(results)
|
|
237
|
+
maybe_structured_content = None
|
|
238
|
+
else:
|
|
239
|
+
return self._make_error_result(
|
|
240
|
+
f"Unexpected return type: {type(results).__name__}"
|
|
241
|
+
)
|
|
242
|
+
|
|
243
|
+
# Auto-generate structuredContent for FastMCP tools
|
|
244
|
+
# FastMCP generates outputSchema but doesn't populate it
|
|
245
|
+
if maybe_structured_content is None and tool:
|
|
246
|
+
output_schema = getattr(tool, "outputSchema", None)
|
|
247
|
+
if output_schema and output_schema.get("x-fastmcp-wrap-result"):
|
|
248
|
+
for item in unstructured_content:
|
|
249
|
+
if isinstance(item, types.TextContent):
|
|
250
|
+
try:
|
|
251
|
+
parsed = json.loads(item.text)
|
|
252
|
+
maybe_structured_content = {"result": parsed}
|
|
253
|
+
except json.JSONDecodeError:
|
|
254
|
+
maybe_structured_content = {"result": item.text}
|
|
255
|
+
break
|
|
256
|
+
|
|
257
|
+
return types.ServerResult(
|
|
258
|
+
types.CallToolResult(
|
|
259
|
+
content=list(unstructured_content),
|
|
260
|
+
structuredContent=maybe_structured_content,
|
|
261
|
+
isError=False,
|
|
262
|
+
)
|
|
263
|
+
)
|
|
264
|
+
except Exception as e:
|
|
265
|
+
return self._make_error_result(str(e))
|
|
266
|
+
|
|
267
|
+
self.request_handlers[types.CallToolRequest] = handler
|
|
268
|
+
return func
|
|
269
|
+
|
|
270
|
+
return decorator
|
|
271
|
+
|
|
272
|
+
Server.call_tool = patched_call_tool
|
|
273
|
+
logger.debug("Patched Server.call_tool to skip output validation")
|
|
274
|
+
|
|
275
|
+
except ImportError:
|
|
276
|
+
logger.debug("mcp.server.lowlevel.server not available, skipping patch")
|
|
277
|
+
except Exception as e:
|
|
278
|
+
logger.warning("Failed to patch server output validation: %s", e)
|
|
279
|
+
|
|
280
|
+
|
|
168
281
|
def suppress_fastmcp_logging(level: int = logging.WARNING) -> None:
|
|
169
282
|
"""
|
|
170
283
|
Suppress verbose fastmcp logging.
|
|
@@ -190,5 +303,6 @@ def apply_all_patches() -> None:
|
|
|
190
303
|
"""Apply all MCP patches."""
|
|
191
304
|
patch_streamable_http_error_handling()
|
|
192
305
|
patch_client_session_validation()
|
|
306
|
+
patch_server_output_validation()
|
|
193
307
|
suppress_fastmcp_logging()
|
|
194
308
|
logger.debug("All MCP patches applied")
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"""Computer control tools for different agent APIs."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING
|
|
6
|
+
|
|
7
|
+
from .settings import computer_settings
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from .anthropic import AnthropicComputerTool
|
|
11
|
+
from .gemini import GeminiComputerTool
|
|
12
|
+
from .hud import HudComputerTool
|
|
13
|
+
from .openai import OpenAIComputerTool
|
|
14
|
+
from .qwen import QwenComputerTool
|
|
15
|
+
|
|
16
|
+
__all__ = [
|
|
17
|
+
"AnthropicComputerTool",
|
|
18
|
+
"GeminiComputerTool",
|
|
19
|
+
"HudComputerTool",
|
|
20
|
+
"OpenAIComputerTool",
|
|
21
|
+
"QwenComputerTool",
|
|
22
|
+
"computer_settings",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def __getattr__(name: str) -> type:
|
|
27
|
+
"""Lazy import computer tools."""
|
|
28
|
+
if name == "AnthropicComputerTool":
|
|
29
|
+
from .anthropic import AnthropicComputerTool
|
|
30
|
+
|
|
31
|
+
return AnthropicComputerTool
|
|
32
|
+
elif name == "GeminiComputerTool":
|
|
33
|
+
from .gemini import GeminiComputerTool
|
|
34
|
+
|
|
35
|
+
return GeminiComputerTool
|
|
36
|
+
elif name == "HudComputerTool":
|
|
37
|
+
from .hud import HudComputerTool
|
|
38
|
+
|
|
39
|
+
return HudComputerTool
|
|
40
|
+
elif name == "OpenAIComputerTool":
|
|
41
|
+
from .openai import OpenAIComputerTool
|
|
42
|
+
|
|
43
|
+
return OpenAIComputerTool
|
|
44
|
+
elif name == "QwenComputerTool":
|
|
45
|
+
from .qwen import QwenComputerTool
|
|
46
|
+
|
|
47
|
+
return QwenComputerTool
|
|
48
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|