hud-python 0.4.68__tar.gz → 0.4.70__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.4.68 → hud_python-0.4.70}/PKG-INFO +3 -3
- {hud_python-0.4.68 → hud_python-0.4.70}/README.md +2 -2
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/browser/pyproject.toml +1 -1
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/online_mind2web/pyproject.toml +1 -1
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/__init__.py +2 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/claude.py +14 -10
- hud_python-0.4.70/hud/agents/gemini.py +289 -0
- hud_python-0.4.70/hud/agents/gemini_cua.py +332 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/tests/test_claude.py +50 -10
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/tests/test_gemini.py +291 -84
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/eval.py +35 -8
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/mcp_use.py +1 -1
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/datasets/utils.py +46 -16
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/learner.py +4 -4
- hud_python-0.4.70/hud/tools/apply_patch.py +639 -0
- hud_python-0.4.70/hud/tools/shell.py +301 -0
- hud_python-0.4.70/hud/tools/tests/test_apply_patch.py +716 -0
- hud_python-0.4.70/hud/tools/tests/test_shell.py +596 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/types.py +3 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/strict_schema.py +1 -1
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/tests/test_version.py +1 -1
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/version.py +1 -1
- {hud_python-0.4.68 → hud_python-0.4.70}/pyproject.toml +2 -1
- hud_python-0.4.68/hud/agents/gemini.py +0 -492
- {hud_python-0.4.68 → hud_python-0.4.70}/.gitignore +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/LICENSE +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/blank/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/blank/environment/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/blank/environment/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/blank/server/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/blank/server/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/browser/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/browser/browser-base/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/browser/environment/2048/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/browser/environment/2048/backend/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/browser/environment/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/browser/environment/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/browser/environment/todo/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/browser/environment/todo/backend/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/browser/server/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/deepresearch/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/deepresearch/environment/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/deepresearch/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/deepresearch/server/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/jupyter/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/jupyter/server/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/online_mind2web/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/online_mind2web/src/hud_controller/providers/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/remote_browser/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/remote_browser/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/remote_browser/src/hud_controller/providers/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/rubrics/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/rubrics/environment/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/rubrics/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/rubrics/server/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/text_2048/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/environments/text_2048/pyproject.toml +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/examples/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/__main__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/base.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/grounded_openai.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/misc/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/misc/integration_test_agent.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/misc/response_agent.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/openai.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/openai_chat.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/operator.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/tests/conftest.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/tests/test_base.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/tests/test_base_runtime.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/tests/test_client.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/tests/test_grounded_openai_agent.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/tests/test_openai.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/tests/test_operator.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/agents/utils.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/__main__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/analyze.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/build.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/clone.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/debug.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/dev.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/flows/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/flows/dev.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/flows/tasks.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/get.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/init.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/list_func.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/pull.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/push.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/remove.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rft.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rft_status.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/celebrate.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/config.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/display.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/gpu.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/gpu_utils.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/local_runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/presets.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/remote_runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/rl_api.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/viewer.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/vllm.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/rl/wait_utils.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_analyze.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_analyze_metadata.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_analyze_module.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_build.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_build_failure.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_build_module.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_cli_init.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_cli_main.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_cli_more_wrappers.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_cli_root.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_clone.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_convert.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_cursor.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_debug.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_eval.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_list_func.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_main_module.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_mcp_server.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_pull.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_push.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_push_happy.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_push_wrapper.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_registry.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/tests/test_utils.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/config.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/cursor.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/docker.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/env_check.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/environment.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/interactive.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/local_runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/logging.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/metadata.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/package_runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/registry.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/remote_runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/server.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/source_hash.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tasks.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_config.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_docker.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_docker_hints.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_env_check.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_environment.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_interactive_module.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_local_runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_logging_utils.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_metadata.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_package_runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_registry_utils.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_remote_runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_runner_modules.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_source_hash.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/tests/test_tasks.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/cli/utils/version_check.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/base.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/fastmcp.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/tests/test_client_integration.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/tests/test_fastmcp.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/tests/test_mcp_use_retry.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/tests/test_protocol.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/utils/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/utils/mcp_use_retry.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/utils/retry.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/clients/utils/retry_transport.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/datasets/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/datasets/runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/datasets/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/datasets/tests/test_runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/datasets/tests/test_utils.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/misc/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/misc/claude_plays_pokemon.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/native/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/native/comparator.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/native/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/native/tests/test_comparator.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/native/tests/test_native_init.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/otel/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/otel/collector.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/otel/config.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/otel/context.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/otel/exporters.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/otel/instrumentation.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/otel/processors.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/otel/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/otel/tests/test_instrumentation.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/otel/tests/test_processors.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/py.typed +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/README.md +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/actor.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/buffer.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/chat_template.jinja +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/config.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/distributed.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/tests/test_learner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/train.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/types.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/utils/start_vllm_server.sh +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/utils.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/rl/vllm_adapter.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/samples/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/samples/browser.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/context.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/helper/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/low_level.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/router.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/server.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/tests/test_add_tool.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/tests/test_context.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/tests/test_mcp_server_handlers.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/tests/test_mcp_server_integration.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/tests/test_mcp_server_more.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/tests/test_run_wrapper.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/tests/test_server_extra.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/server/tests/test_sigterm_runner.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/settings.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/shared/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/shared/exceptions.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/shared/hints.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/shared/requests.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/shared/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/shared/tests/test_exceptions.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/shared/tests/test_hints.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/shared/tests/test_requests.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/async_context.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/instrument.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/job.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/replay.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/tests/test_async_context.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/tests/test_instrument.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/tests/test_job.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/tests/test_replay.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/tests/test_trace.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/trace.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/telemetry/utils.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/base.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/bash.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/computer/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/computer/anthropic.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/computer/gemini.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/computer/hud.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/computer/openai.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/computer/qwen.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/computer/settings.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/edit.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/executors/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/executors/base.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/executors/pyautogui.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/executors/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/executors/tests/test_base_executor.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/executors/tests/test_pyautogui_executor.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/executors/xdo.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/grounding/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/grounding/config.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/grounding/grounded_tool.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/grounding/grounder.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/grounding/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/grounding/tests/test_grounded_tool.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/jupyter.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/playwright.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/response.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/submit.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_base.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_bash.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_bash_extended.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_computer.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_computer_actions.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_edit.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_init.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_jupyter_tool.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_playwright_tool.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_response.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_submit.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_tools.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_tools_init.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_types.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/tests/test_utils.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/types.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/tools/utils.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/hud_console.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/mcp.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/pretty_errors.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/tasks.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/telemetry.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/tests/__init__.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/tests/test_init.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/tests/test_mcp.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/tests/test_pretty_errors.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/tests/test_tasks.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/tests/test_telemetry.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/tests/test_tool_shorthand.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/tool_shorthand.py +0 -0
- {hud_python-0.4.68 → hud_python-0.4.70}/hud/utils/types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hud-python
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.70
|
|
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
|
|
@@ -520,8 +520,8 @@ Thanks to all our contributors!
|
|
|
520
520
|
|
|
521
521
|
```bibtex
|
|
522
522
|
@software{hud2025agentevalplatform,
|
|
523
|
-
author = {HUD and Jay Ram and Lorenss Martinsons and Parth Patel and
|
|
524
|
-
title = {HUD: An Evaluation Platform for Agents},
|
|
523
|
+
author = {HUD and Jay Ram and Lorenss Martinsons and Parth Patel and Govind Pimpale and Dylan Bowman and Jaideep and Nguyen Nhat Minh},
|
|
524
|
+
title = {HUD: An Evaluation and RL Envrionments Platform for Agents},
|
|
525
525
|
date = {2025-04},
|
|
526
526
|
url = {https://github.com/hud-evals/hud-python},
|
|
527
527
|
langid = {en}
|
|
@@ -403,8 +403,8 @@ Thanks to all our contributors!
|
|
|
403
403
|
|
|
404
404
|
```bibtex
|
|
405
405
|
@software{hud2025agentevalplatform,
|
|
406
|
-
author = {HUD and Jay Ram and Lorenss Martinsons and Parth Patel and
|
|
407
|
-
title = {HUD: An Evaluation Platform for Agents},
|
|
406
|
+
author = {HUD and Jay Ram and Lorenss Martinsons and Parth Patel and Govind Pimpale and Dylan Bowman and Jaideep and Nguyen Nhat Minh},
|
|
407
|
+
title = {HUD: An Evaluation and RL Envrionments Platform for Agents},
|
|
408
408
|
date = {2025-04},
|
|
409
409
|
url = {https://github.com/hud-evals/hud-python},
|
|
410
410
|
langid = {en}
|
|
@@ -3,7 +3,7 @@ name = "hud-browser-controller"
|
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
description = "HUD Browser Controller - MCP interface for browser environments"
|
|
5
5
|
requires-python = ">=3.11,<3.14"
|
|
6
|
-
dependencies = [ "pydantic>=2.6,<3", "pydantic-settings>=2.2,<3", "hud-python>=0.4.
|
|
6
|
+
dependencies = [ "pydantic>=2.6,<3", "pydantic-settings>=2.2,<3", "hud-python>=0.4.69", "playwright", "pyautogui", "httpx", "typer", "fastapi>=0.104.1", "uvicorn[standard]>=0.24.0", "python-multipart>=0.0.6",]
|
|
7
7
|
|
|
8
8
|
[build-system]
|
|
9
9
|
requires = [ "hatchling",]
|
|
@@ -3,7 +3,7 @@ name = "hud-om2w"
|
|
|
3
3
|
version = "0.1.0"
|
|
4
4
|
description = "HUD Remote Browser Controller with MCP tools for cloud browser providers"
|
|
5
5
|
requires-python = ">=3.11,<3.13"
|
|
6
|
-
dependencies = [ "hud-python>=0.4.
|
|
6
|
+
dependencies = [ "hud-python>=0.4.69", "anthropic>=0.74.0", "pyautogui", "playwright", "httpx", "typer", "google-api-python-client", "google-auth",]
|
|
7
7
|
|
|
8
8
|
[build-system]
|
|
9
9
|
requires = [ "hatchling",]
|
|
@@ -3,6 +3,7 @@ from __future__ import annotations
|
|
|
3
3
|
from .base import MCPAgent
|
|
4
4
|
from .claude import ClaudeAgent
|
|
5
5
|
from .gemini import GeminiAgent
|
|
6
|
+
from .gemini_cua import GeminiCUAAgent
|
|
6
7
|
from .openai import OpenAIAgent
|
|
7
8
|
from .openai_chat import OpenAIChatAgent
|
|
8
9
|
from .operator import OperatorAgent
|
|
@@ -10,6 +11,7 @@ from .operator import OperatorAgent
|
|
|
10
11
|
__all__ = [
|
|
11
12
|
"ClaudeAgent",
|
|
12
13
|
"GeminiAgent",
|
|
14
|
+
"GeminiCUAAgent",
|
|
13
15
|
"MCPAgent",
|
|
14
16
|
"OpenAIAgent",
|
|
15
17
|
"OpenAIChatAgent",
|
|
@@ -157,22 +157,26 @@ class ClaudeAgent(MCPAgent):
|
|
|
157
157
|
|
|
158
158
|
messages_cached = self._add_prompt_caching(messages)
|
|
159
159
|
|
|
160
|
-
|
|
160
|
+
# betas to use
|
|
161
|
+
betas = ["fine-grained-tool-streaming-2025-05-14"]
|
|
162
|
+
if self.has_computer_tool:
|
|
163
|
+
betas.append("computer-use-2025-01-24")
|
|
164
|
+
|
|
165
|
+
async with self.anthropic_client.beta.messages.stream(
|
|
161
166
|
model=self.config.checkpoint_name,
|
|
162
167
|
system=self.system_prompt if self.system_prompt is not None else Omit(),
|
|
163
168
|
max_tokens=self.max_tokens,
|
|
164
169
|
messages=messages_cached,
|
|
165
170
|
tools=self.claude_tools,
|
|
166
171
|
tool_choice={"type": "auto", "disable_parallel_tool_use": True},
|
|
167
|
-
betas=
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
)
|
|
175
|
-
)
|
|
172
|
+
betas=betas,
|
|
173
|
+
) as stream:
|
|
174
|
+
# allow backend to accumulate message content
|
|
175
|
+
async for _ in stream:
|
|
176
|
+
pass
|
|
177
|
+
# get final message
|
|
178
|
+
response = await stream.get_final_message()
|
|
179
|
+
messages.append(BetaMessageParam(role="assistant", content=response.content))
|
|
176
180
|
|
|
177
181
|
# Process response
|
|
178
182
|
result = AgentResponse(content="", tool_calls=[], done=True)
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
"""Gemini MCP Agent implementation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import logging
|
|
6
|
+
from typing import TYPE_CHECKING, Any, ClassVar, cast
|
|
7
|
+
|
|
8
|
+
from google import genai
|
|
9
|
+
from google.genai import types as genai_types
|
|
10
|
+
from pydantic import ConfigDict
|
|
11
|
+
|
|
12
|
+
import hud
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from hud.datasets import Task
|
|
16
|
+
|
|
17
|
+
import mcp.types as types
|
|
18
|
+
|
|
19
|
+
from hud.settings import settings
|
|
20
|
+
from hud.types import AgentResponse, BaseAgentConfig, MCPToolCall, MCPToolResult
|
|
21
|
+
from hud.utils.hud_console import HUDConsole
|
|
22
|
+
from hud.utils.types import with_signature
|
|
23
|
+
|
|
24
|
+
from .base import BaseCreateParams, MCPAgent
|
|
25
|
+
|
|
26
|
+
logger = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class GeminiConfig(BaseAgentConfig):
|
|
30
|
+
"""Configuration for `GeminiAgent`."""
|
|
31
|
+
|
|
32
|
+
model_config = ConfigDict(arbitrary_types_allowed=True)
|
|
33
|
+
|
|
34
|
+
model_name: str = "Gemini"
|
|
35
|
+
checkpoint_name: str = "gemini-3-pro-preview"
|
|
36
|
+
model_client: genai.Client | None = None
|
|
37
|
+
temperature: float = 1.0
|
|
38
|
+
top_p: float = 0.95
|
|
39
|
+
top_k: int = 40
|
|
40
|
+
max_output_tokens: int = 8192
|
|
41
|
+
validate_api_key: bool = True
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class GeminiCreateParams(BaseCreateParams, GeminiConfig):
|
|
45
|
+
pass
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class GeminiAgent(MCPAgent):
|
|
49
|
+
"""
|
|
50
|
+
Gemini agent that uses MCP servers for tool execution.
|
|
51
|
+
|
|
52
|
+
This agent uses Gemini's native tool calling capabilities but executes
|
|
53
|
+
tools through MCP servers instead of direct implementation.
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
metadata: ClassVar[dict[str, Any] | None] = None
|
|
57
|
+
config_cls: ClassVar[type[BaseAgentConfig]] = GeminiConfig
|
|
58
|
+
|
|
59
|
+
@with_signature(GeminiCreateParams)
|
|
60
|
+
@classmethod
|
|
61
|
+
def create(cls, **kwargs: Any) -> GeminiAgent: # pyright: ignore[reportIncompatibleMethodOverride]
|
|
62
|
+
return MCPAgent.create.__func__(cls, **kwargs) # type: ignore[return-value]
|
|
63
|
+
|
|
64
|
+
def __init__(self, params: GeminiCreateParams | None = None, **kwargs: Any) -> None:
|
|
65
|
+
super().__init__(params, **kwargs)
|
|
66
|
+
self.config: GeminiConfig
|
|
67
|
+
|
|
68
|
+
model_client = self.config.model_client
|
|
69
|
+
if model_client is None:
|
|
70
|
+
api_key = settings.gemini_api_key
|
|
71
|
+
if not api_key:
|
|
72
|
+
raise ValueError("Gemini API key not found. Set GEMINI_API_KEY.")
|
|
73
|
+
model_client = genai.Client(api_key=api_key)
|
|
74
|
+
|
|
75
|
+
if self.config.validate_api_key:
|
|
76
|
+
try:
|
|
77
|
+
list(model_client.models.list(config=genai_types.ListModelsConfig(page_size=1)))
|
|
78
|
+
except Exception as e:
|
|
79
|
+
raise ValueError(f"Gemini API key is invalid: {e}") from e
|
|
80
|
+
|
|
81
|
+
self.gemini_client = model_client
|
|
82
|
+
self.temperature = self.config.temperature
|
|
83
|
+
self.top_p = self.config.top_p
|
|
84
|
+
self.top_k = self.config.top_k
|
|
85
|
+
self.max_output_tokens = self.config.max_output_tokens
|
|
86
|
+
self.hud_console = HUDConsole(logger=logger)
|
|
87
|
+
|
|
88
|
+
# Track mapping from Gemini tool names to MCP tool names
|
|
89
|
+
self._gemini_to_mcp_tool_map: dict[str, str] = {}
|
|
90
|
+
self.gemini_tools: genai_types.ToolListUnion = []
|
|
91
|
+
|
|
92
|
+
async def initialize(self, task: str | Task | None = None) -> None:
|
|
93
|
+
"""Initialize the agent and build tool mappings."""
|
|
94
|
+
await super().initialize(task)
|
|
95
|
+
# Build tool mappings after tools are discovered
|
|
96
|
+
self._convert_tools_for_gemini()
|
|
97
|
+
|
|
98
|
+
async def get_system_messages(self) -> list[Any]:
|
|
99
|
+
"""No system messages for Gemini because applied in get_response"""
|
|
100
|
+
return []
|
|
101
|
+
|
|
102
|
+
async def format_blocks(self, blocks: list[types.ContentBlock]) -> list[genai_types.Content]:
|
|
103
|
+
"""Format messages for Gemini."""
|
|
104
|
+
# Convert MCP content types to Gemini content types
|
|
105
|
+
gemini_parts: list[genai_types.Part] = []
|
|
106
|
+
|
|
107
|
+
for block in blocks:
|
|
108
|
+
if isinstance(block, types.TextContent):
|
|
109
|
+
gemini_parts.append(genai_types.Part(text=block.text))
|
|
110
|
+
elif isinstance(block, types.ImageContent):
|
|
111
|
+
# Convert MCP ImageContent to Gemini format
|
|
112
|
+
# Need to decode base64 string to bytes
|
|
113
|
+
import base64
|
|
114
|
+
|
|
115
|
+
image_bytes = base64.b64decode(block.data)
|
|
116
|
+
gemini_parts.append(
|
|
117
|
+
genai_types.Part.from_bytes(data=image_bytes, mime_type=block.mimeType)
|
|
118
|
+
)
|
|
119
|
+
else:
|
|
120
|
+
# For other types, try to handle but log a warning
|
|
121
|
+
self.hud_console.log(f"Unknown content block type: {type(block)}", level="warning")
|
|
122
|
+
|
|
123
|
+
return [genai_types.Content(role="user", parts=gemini_parts)]
|
|
124
|
+
|
|
125
|
+
@hud.instrument(
|
|
126
|
+
span_type="agent",
|
|
127
|
+
record_args=False, # Messages can be large
|
|
128
|
+
record_result=True,
|
|
129
|
+
)
|
|
130
|
+
async def get_response(self, messages: list[genai_types.Content]) -> AgentResponse:
|
|
131
|
+
"""Get response from Gemini including any tool calls."""
|
|
132
|
+
|
|
133
|
+
# Build generate content config
|
|
134
|
+
generate_config = genai_types.GenerateContentConfig(
|
|
135
|
+
temperature=self.temperature,
|
|
136
|
+
top_p=self.top_p,
|
|
137
|
+
top_k=self.top_k,
|
|
138
|
+
max_output_tokens=self.max_output_tokens,
|
|
139
|
+
tools=self.gemini_tools,
|
|
140
|
+
system_instruction=self.system_prompt,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# Make API call
|
|
144
|
+
response = self.gemini_client.models.generate_content(
|
|
145
|
+
model=self.config.checkpoint_name,
|
|
146
|
+
contents=cast("Any", messages),
|
|
147
|
+
config=generate_config,
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
# Append assistant response (including any function_call) so that
|
|
151
|
+
# subsequent FunctionResponse messages correspond to a prior FunctionCall
|
|
152
|
+
if response.candidates and len(response.candidates) > 0 and response.candidates[0].content:
|
|
153
|
+
messages.append(response.candidates[0].content)
|
|
154
|
+
|
|
155
|
+
# Process response
|
|
156
|
+
result = AgentResponse(content="", tool_calls=[], done=True)
|
|
157
|
+
collected_tool_calls: list[MCPToolCall] = []
|
|
158
|
+
|
|
159
|
+
if not response.candidates:
|
|
160
|
+
self.hud_console.warning("Response has no candidates")
|
|
161
|
+
return result
|
|
162
|
+
|
|
163
|
+
candidate = response.candidates[0]
|
|
164
|
+
|
|
165
|
+
# Extract text content and function calls
|
|
166
|
+
text_content = ""
|
|
167
|
+
thinking_content = ""
|
|
168
|
+
|
|
169
|
+
if candidate.content and candidate.content.parts:
|
|
170
|
+
for part in candidate.content.parts:
|
|
171
|
+
if part.function_call:
|
|
172
|
+
tool_call = self._extract_tool_call(part)
|
|
173
|
+
if tool_call is not None:
|
|
174
|
+
collected_tool_calls.append(tool_call)
|
|
175
|
+
elif part.text:
|
|
176
|
+
text_content += part.text
|
|
177
|
+
elif hasattr(part, "thought") and part.thought:
|
|
178
|
+
thinking_content += f"Thinking: {part.thought}\n"
|
|
179
|
+
|
|
180
|
+
# Assign collected tool calls and mark done status
|
|
181
|
+
if collected_tool_calls:
|
|
182
|
+
result.tool_calls = collected_tool_calls
|
|
183
|
+
result.done = False
|
|
184
|
+
|
|
185
|
+
# Combine text and thinking for final content
|
|
186
|
+
if thinking_content:
|
|
187
|
+
result.content = thinking_content + text_content
|
|
188
|
+
else:
|
|
189
|
+
result.content = text_content
|
|
190
|
+
|
|
191
|
+
return result
|
|
192
|
+
|
|
193
|
+
def _extract_tool_call(self, part: genai_types.Part) -> MCPToolCall | None:
|
|
194
|
+
"""Extract an MCPToolCall from a function call part.
|
|
195
|
+
|
|
196
|
+
Subclasses can override to customize tool call extraction (e.g., normalizing
|
|
197
|
+
computer use calls to a different schema).
|
|
198
|
+
"""
|
|
199
|
+
if not part.function_call:
|
|
200
|
+
return None
|
|
201
|
+
|
|
202
|
+
func_name = part.function_call.name or ""
|
|
203
|
+
mcp_tool_name = self._gemini_to_mcp_tool_map.get(func_name, func_name)
|
|
204
|
+
raw_args = dict(part.function_call.args) if part.function_call.args else {}
|
|
205
|
+
|
|
206
|
+
return MCPToolCall(
|
|
207
|
+
name=mcp_tool_name,
|
|
208
|
+
arguments=raw_args,
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
async def format_tool_results(
|
|
212
|
+
self, tool_calls: list[MCPToolCall], tool_results: list[MCPToolResult]
|
|
213
|
+
) -> list[genai_types.Content]:
|
|
214
|
+
"""Format tool results into Gemini messages."""
|
|
215
|
+
# Process each tool result
|
|
216
|
+
function_responses = []
|
|
217
|
+
|
|
218
|
+
for tool_call, result in zip(tool_calls, tool_results, strict=True):
|
|
219
|
+
# Get the Gemini function name from metadata
|
|
220
|
+
gemini_name = getattr(tool_call, "gemini_name", tool_call.name)
|
|
221
|
+
|
|
222
|
+
# Convert MCP tool results to Gemini format
|
|
223
|
+
response_dict: dict[str, Any] = {}
|
|
224
|
+
|
|
225
|
+
if result.isError:
|
|
226
|
+
# Extract error message from content
|
|
227
|
+
error_msg = "Tool execution failed"
|
|
228
|
+
for content in result.content:
|
|
229
|
+
if isinstance(content, types.TextContent):
|
|
230
|
+
error_msg = content.text
|
|
231
|
+
break
|
|
232
|
+
response_dict["error"] = error_msg
|
|
233
|
+
else:
|
|
234
|
+
# Process success content
|
|
235
|
+
response_dict["success"] = True
|
|
236
|
+
# Add text content to response
|
|
237
|
+
for content in result.content:
|
|
238
|
+
if isinstance(content, types.TextContent):
|
|
239
|
+
response_dict["output"] = content.text
|
|
240
|
+
break
|
|
241
|
+
|
|
242
|
+
# Create function response
|
|
243
|
+
function_response = genai_types.FunctionResponse(
|
|
244
|
+
name=gemini_name,
|
|
245
|
+
response=response_dict,
|
|
246
|
+
)
|
|
247
|
+
function_responses.append(function_response)
|
|
248
|
+
|
|
249
|
+
# Return as a user message containing all function responses
|
|
250
|
+
return [
|
|
251
|
+
genai_types.Content(
|
|
252
|
+
role="user",
|
|
253
|
+
parts=[genai_types.Part(function_response=fr) for fr in function_responses],
|
|
254
|
+
)
|
|
255
|
+
]
|
|
256
|
+
|
|
257
|
+
async def create_user_message(self, text: str) -> genai_types.Content:
|
|
258
|
+
"""Create a user message in Gemini's format."""
|
|
259
|
+
return genai_types.Content(role="user", parts=[genai_types.Part(text=text)])
|
|
260
|
+
|
|
261
|
+
def _convert_tools_for_gemini(self) -> genai_types.ToolListUnion:
|
|
262
|
+
"""Convert MCP tools to Gemini tool format."""
|
|
263
|
+
self._gemini_to_mcp_tool_map = {} # Reset mapping
|
|
264
|
+
self.gemini_tools = []
|
|
265
|
+
|
|
266
|
+
for tool in self.get_available_tools():
|
|
267
|
+
gemini_tool = self._to_gemini_tool(tool)
|
|
268
|
+
if gemini_tool is None:
|
|
269
|
+
continue
|
|
270
|
+
|
|
271
|
+
self._gemini_to_mcp_tool_map[tool.name] = tool.name
|
|
272
|
+
self.gemini_tools.append(gemini_tool)
|
|
273
|
+
|
|
274
|
+
return self.gemini_tools
|
|
275
|
+
|
|
276
|
+
def _to_gemini_tool(self, tool: types.Tool) -> genai_types.Tool | None:
|
|
277
|
+
"""Convert a single MCP tool to Gemini tool format.
|
|
278
|
+
|
|
279
|
+
Subclasses can override to customize tool conversion (e.g., for computer use).
|
|
280
|
+
"""
|
|
281
|
+
# Ensure parameters have proper Schema format
|
|
282
|
+
if tool.description is None or tool.inputSchema is None:
|
|
283
|
+
raise ValueError(f"MCP tool {tool.name} requires both a description and inputSchema.")
|
|
284
|
+
function_decl = genai_types.FunctionDeclaration(
|
|
285
|
+
name=tool.name,
|
|
286
|
+
description=tool.description,
|
|
287
|
+
parameters_json_schema=tool.inputSchema,
|
|
288
|
+
)
|
|
289
|
+
return genai_types.Tool(function_declarations=[function_decl])
|