hud-python 0.5.12__tar.gz → 0.5.13__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.12 → hud_python-0.5.13}/PKG-INFO +2 -2
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/__init__.py +14 -1
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/build.py +27 -4
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/eval.py +33 -1
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_build.py +2 -2
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/datasets/runner.py +2 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/scenarios.py +13 -8
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/manager.py +79 -12
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/types.py +2 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/tests/test_version.py +1 -1
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/version.py +1 -1
- {hud_python-0.5.12 → hud_python-0.5.13}/pyproject.toml +2 -2
- {hud_python-0.5.12 → hud_python-0.5.13}/.gitignore +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/LICENSE +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/README.md +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/examples/README.md +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/__main__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/base.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/claude.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/gateway.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/gemini.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/gemini_cua.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/grounded_openai.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/misc/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/misc/integration_test_agent.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/misc/response_agent.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/openai.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/openai_chat.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/operator.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/resolver.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/conftest.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/test_base.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/test_base_runtime.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/test_claude.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/test_client.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/test_gemini.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/test_grounded_openai_agent.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/test_openai.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/test_operator.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/test_resolver.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/tests/test_run_eval.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/agents/types.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/__main__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/analyze.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/clone.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/debug.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/dev.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/flows/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/flows/dev.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/flows/init.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/flows/tasks.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/flows/templates.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/flows/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/flows/tests/test_dev.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/get.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/init.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/list_func.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/pull.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/push.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/remove.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/rft.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/rft_status.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_analyze.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_analyze_metadata.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_analyze_module.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_build_failure.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_build_module.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_cli_init.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_cli_main.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_cli_more_wrappers.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_cli_root.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_clone.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_convert.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_cursor.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_debug.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_dev.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_eval.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_eval_bedrock.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_init.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_list_func.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_main_module.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_mcp_server.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_pull.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_push.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_push_happy.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_push_wrapper.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_registry.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/tests/test_utils.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/celebrate.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/config.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/cursor.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/docker.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/env_check.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/environment.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/git.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/interactive.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/local_runner.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/logging.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/metadata.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/package_runner.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/registry.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/remote_runner.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/runner.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/server.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/source_hash.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tasks.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_config.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_docker.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_docker_hints.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_env_check.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_environment.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_git.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_interactive_module.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_local_runner.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_logging_utils.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_metadata.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_package_runner.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_registry_utils.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_remote_runner.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_runner_modules.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_source_hash.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/tests/test_tasks.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/version_check.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/cli/utils/viewer.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/README.md +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/base.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/environment.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/fastmcp.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/mcp_use.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/tests/test_analyze_scenarios.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/tests/test_client_integration.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/tests/test_fastmcp.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/tests/test_mcp_use_retry.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/tests/test_protocol.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/utils/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/utils/mcp_use_retry.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/utils/retry.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/clients/utils/retry_transport.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/datasets/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/datasets/loader.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/datasets/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/datasets/tests/test_loader.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/datasets/tests/test_utils.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/datasets/utils.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/connection.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/connectors/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/connectors/base.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/connectors/local.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/connectors/mcp_config.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/connectors/openai.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/connectors/remote.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/environment.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/integrations/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/integrations/adk.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/integrations/anthropic.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/integrations/gemini.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/integrations/langchain.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/integrations/llamaindex.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/integrations/openai.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/mock.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/router.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/tests/test_connection.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/tests/test_connectors.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/tests/test_environment.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/tests/test_integrations.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/tests/test_local_connectors.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/tests/test_scenarios.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/tests/test_tools.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/types.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/utils/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/utils/formats.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/utils/schema.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/environment/utils/tool_wrappers.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/context.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/display.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/instrument.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/parallel.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/task.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/tests/test_context.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/tests/test_eval.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/tests/test_manager.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/tests/test_parallel.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/tests/test_task.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/eval/utils.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/native/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/native/comparator.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/native/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/native/tests/test_comparator.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/native/tests/test_native_init.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/patches/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/patches/mcp_patches.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/patches/warnings.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/py.typed +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/samples/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/samples/browser.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/context.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/helper/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/low_level.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/router.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/server.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/tests/test_add_tool.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/tests/test_context.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/tests/test_mcp_server_handlers.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/tests/test_mcp_server_integration.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/tests/test_mcp_server_more.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/tests/test_run_wrapper.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/tests/test_server_extra.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/server/tests/test_sigterm_runner.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/settings.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/shared/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/shared/exceptions.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/shared/hints.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/shared/requests.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/shared/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/shared/tests/test_exceptions.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/shared/tests/test_hints.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/shared/tests/test_requests.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/telemetry/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/telemetry/exporter.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/telemetry/instrument.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/telemetry/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/telemetry/tests/test_eval_telemetry.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/telemetry/tests/test_exporter.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/telemetry/tests/test_instrument.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/agent.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/apply_patch.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/base.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/bash.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/computer/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/computer/anthropic.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/computer/gemini.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/computer/hud.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/computer/openai.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/computer/qwen.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/computer/settings.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/edit.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/executors/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/executors/base.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/executors/pyautogui.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/executors/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/executors/tests/test_base_executor.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/executors/tests/test_pyautogui_executor.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/executors/xdo.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/grounding/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/grounding/config.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/grounding/grounded_tool.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/grounding/grounder.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/grounding/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/grounding/tests/test_grounded_tool.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/jupyter.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/playwright.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/response.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/shell.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/submit.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_agent_tool.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_apply_patch.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_base.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_bash.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_bash_extended.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_computer.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_computer_actions.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_edit.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_init.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_jupyter_tool.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_playwright_tool.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_response.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_shell.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_submit.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_tools.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_tools_init.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_types.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/tests/test_utils.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/types.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/tools/utils.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/types.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/env.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/hud_console.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/mcp.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/pretty_errors.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/strict_schema.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/telemetry.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/tests/__init__.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/tests/test_init.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/tests/test_mcp.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/tests/test_pretty_errors.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/tests/test_telemetry.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/tests/test_tool_shorthand.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/tool_shorthand.py +0 -0
- {hud_python-0.5.12 → hud_python-0.5.13}/hud/utils/types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hud-python
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.13
|
|
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
|
|
@@ -91,7 +91,7 @@ Requires-Dist: pyright==1.1.407; extra == 'dev'
|
|
|
91
91
|
Requires-Dist: pytest-asyncio; extra == 'dev'
|
|
92
92
|
Requires-Dist: pytest-cov; extra == 'dev'
|
|
93
93
|
Requires-Dist: pytest-mock; extra == 'dev'
|
|
94
|
-
Requires-Dist: pytest
|
|
94
|
+
Requires-Dist: pytest>=8.1.1; extra == 'dev'
|
|
95
95
|
Requires-Dist: ruff>=0.11.8; extra == 'dev'
|
|
96
96
|
Requires-Dist: tornado>=6.5.2; extra == 'dev'
|
|
97
97
|
Description-Content-Type: text/markdown
|
|
@@ -741,6 +741,11 @@ def build(
|
|
|
741
741
|
platform: str | None = typer.Option(
|
|
742
742
|
None, "--platform", help="Set Docker target platform (e.g., linux/amd64)"
|
|
743
743
|
),
|
|
744
|
+
secrets: list[str] | None = typer.Option( # noqa: B008
|
|
745
|
+
None,
|
|
746
|
+
"--secret",
|
|
747
|
+
help=("Docker build secret (repeatable), e.g. --secret id=GITHUB_TOKEN,env=GITHUB_TOKEN"),
|
|
748
|
+
),
|
|
744
749
|
remote_cache: str | None = typer.Option(
|
|
745
750
|
None, "--remote-cache", help="Enable remote cache using Amazon ECR with specified repo name"
|
|
746
751
|
),
|
|
@@ -812,7 +817,15 @@ def build(
|
|
|
812
817
|
i += 1
|
|
813
818
|
|
|
814
819
|
build_command(
|
|
815
|
-
directory,
|
|
820
|
+
directory,
|
|
821
|
+
tag,
|
|
822
|
+
no_cache,
|
|
823
|
+
verbose,
|
|
824
|
+
env_vars,
|
|
825
|
+
platform,
|
|
826
|
+
secrets,
|
|
827
|
+
remote_cache,
|
|
828
|
+
build_args or None,
|
|
816
829
|
)
|
|
817
830
|
|
|
818
831
|
|
|
@@ -555,11 +555,13 @@ def build_docker_image(
|
|
|
555
555
|
verbose: bool = False,
|
|
556
556
|
build_args: dict[str, str] | None = None,
|
|
557
557
|
platform: str | None = None,
|
|
558
|
+
secrets: list[str] | None = None,
|
|
558
559
|
remote_cache: str | None = None,
|
|
559
560
|
) -> bool:
|
|
560
561
|
"""Build a Docker image from a directory."""
|
|
561
562
|
hud_console = HUDConsole()
|
|
562
563
|
build_args = build_args or {}
|
|
564
|
+
secrets = secrets or []
|
|
563
565
|
|
|
564
566
|
# Check if Dockerfile exists (prefer Dockerfile.hud)
|
|
565
567
|
dockerfile = find_dockerfile(directory)
|
|
@@ -629,6 +631,10 @@ def build_docker_image(
|
|
|
629
631
|
for key, value in build_args.items():
|
|
630
632
|
cmd.extend(["--build-arg", f"{key}={value}"])
|
|
631
633
|
|
|
634
|
+
# Add secrets
|
|
635
|
+
for secret in secrets:
|
|
636
|
+
cmd.extend(["--secret", secret])
|
|
637
|
+
|
|
632
638
|
cmd.append(str(directory))
|
|
633
639
|
|
|
634
640
|
# Always show build output
|
|
@@ -636,7 +642,10 @@ def build_docker_image(
|
|
|
636
642
|
|
|
637
643
|
try:
|
|
638
644
|
# Use Docker's native output formatting - no capture, let Docker handle display
|
|
639
|
-
|
|
645
|
+
env = os.environ.copy()
|
|
646
|
+
if secrets:
|
|
647
|
+
env["DOCKER_BUILDKIT"] = "1"
|
|
648
|
+
result = subprocess.run(cmd, check=False, env=env) # noqa: S603
|
|
640
649
|
return result.returncode == 0
|
|
641
650
|
except Exception as e:
|
|
642
651
|
hud_console.error(f"Build error: {e}")
|
|
@@ -650,6 +659,7 @@ def build_environment(
|
|
|
650
659
|
verbose: bool = False,
|
|
651
660
|
env_vars: dict[str, str] | None = None,
|
|
652
661
|
platform: str | None = None,
|
|
662
|
+
secrets: list[str] | None = None,
|
|
653
663
|
remote_cache: str | None = None,
|
|
654
664
|
build_args: dict[str, str] | None = None,
|
|
655
665
|
) -> None:
|
|
@@ -725,6 +735,7 @@ def build_environment(
|
|
|
725
735
|
verbose,
|
|
726
736
|
build_args=build_args or None,
|
|
727
737
|
platform=platform,
|
|
738
|
+
secrets=secrets,
|
|
728
739
|
remote_cache=remote_cache,
|
|
729
740
|
):
|
|
730
741
|
hud_console.error("Docker build failed")
|
|
@@ -1008,16 +1019,23 @@ def build_environment(
|
|
|
1008
1019
|
for key, value in build_args.items():
|
|
1009
1020
|
label_cmd.extend(["--build-arg", f"{key}={value}"])
|
|
1010
1021
|
|
|
1022
|
+
# Add secrets to final image build (same as initial build)
|
|
1023
|
+
for secret in secrets or []:
|
|
1024
|
+
label_cmd.extend(["--secret", secret])
|
|
1025
|
+
|
|
1011
1026
|
label_cmd.append(str(env_dir))
|
|
1012
1027
|
|
|
1013
1028
|
# Run rebuild using Docker's native output formatting
|
|
1029
|
+
env = os.environ.copy()
|
|
1030
|
+
if secrets:
|
|
1031
|
+
env["DOCKER_BUILDKIT"] = "1"
|
|
1014
1032
|
if verbose:
|
|
1015
1033
|
# Show Docker's native output when verbose
|
|
1016
|
-
result = subprocess.run(label_cmd, check=False) # noqa: S603
|
|
1034
|
+
result = subprocess.run(label_cmd, check=False, env=env) # noqa: S603
|
|
1017
1035
|
else:
|
|
1018
1036
|
# Capture output for error reporting, but don't show unless it fails
|
|
1019
1037
|
result = subprocess.run( # noqa: S603
|
|
1020
|
-
label_cmd, capture_output=True, text=True, check=False
|
|
1038
|
+
label_cmd, capture_output=True, text=True, check=False, env=env
|
|
1021
1039
|
)
|
|
1022
1040
|
|
|
1023
1041
|
if result.returncode != 0:
|
|
@@ -1111,10 +1129,15 @@ def build_command(
|
|
|
1111
1129
|
verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed output"),
|
|
1112
1130
|
env_vars: dict[str, str] | None = None,
|
|
1113
1131
|
platform: str | None = None,
|
|
1132
|
+
secrets: list[str] | None = typer.Option( # noqa: B008
|
|
1133
|
+
None,
|
|
1134
|
+
"--secret",
|
|
1135
|
+
help=("Docker build secret (repeatable), e.g. --secret id=GITHUB_TOKEN,env=GITHUB_TOKEN"),
|
|
1136
|
+
),
|
|
1114
1137
|
remote_cache: str | None = None,
|
|
1115
1138
|
build_args: dict[str, str] | None = None,
|
|
1116
1139
|
) -> None:
|
|
1117
1140
|
"""Build a HUD environment and generate lock file."""
|
|
1118
1141
|
build_environment(
|
|
1119
|
-
directory, tag, no_cache, verbose, env_vars, platform, remote_cache, build_args
|
|
1142
|
+
directory, tag, no_cache, verbose, env_vars, platform, secrets, remote_cache, build_args
|
|
1120
1143
|
)
|
|
@@ -164,6 +164,7 @@ class EvalConfig(BaseModel):
|
|
|
164
164
|
"auto_respond",
|
|
165
165
|
"quiet",
|
|
166
166
|
"gateway",
|
|
167
|
+
"taskset",
|
|
167
168
|
}
|
|
168
169
|
# Fields loaded from [agent] section
|
|
169
170
|
_AGENT_FIELDS: ClassVar[set[str]] = {"allowed_tools", "disallowed_tools"}
|
|
@@ -184,6 +185,7 @@ class EvalConfig(BaseModel):
|
|
|
184
185
|
remote: bool = False
|
|
185
186
|
quiet: bool = False # Suppress opening browser for eval links
|
|
186
187
|
gateway: bool = False # Use HUD Gateway for LLM API calls
|
|
188
|
+
taskset: str | None = None # Taskset slug to associate job with
|
|
187
189
|
|
|
188
190
|
# Base agent config (these merge with task's agent_config)
|
|
189
191
|
allowed_tools: list[str] | None = None
|
|
@@ -655,16 +657,41 @@ async def _run_evaluation(cfg: EvalConfig) -> tuple[list[Any], list[Any]]:
|
|
|
655
657
|
agent_kwargs = {
|
|
656
658
|
k: v for k, v in agent_kwargs.items() if k not in ("api_key", "model_client")
|
|
657
659
|
}
|
|
658
|
-
# Create a job ID for tracking
|
|
659
660
|
import uuid
|
|
660
661
|
|
|
661
662
|
from hud.datasets.utils import submit_rollouts
|
|
663
|
+
from hud.eval.manager import _send_job_enter
|
|
662
664
|
|
|
663
665
|
job_id = str(uuid.uuid4())
|
|
664
666
|
hud_console.info(
|
|
665
667
|
f"Submitting {len(tasks)} task(s) for remote execution (job_id: {job_id})…"
|
|
666
668
|
)
|
|
667
669
|
|
|
670
|
+
if cfg.taskset:
|
|
671
|
+
tasks_to_create = [t for t in tasks if not t.id]
|
|
672
|
+
tasks_data = (
|
|
673
|
+
[t.model_dump(mode="json", exclude_none=True) for t in tasks_to_create]
|
|
674
|
+
if tasks_to_create
|
|
675
|
+
else None
|
|
676
|
+
)
|
|
677
|
+
ids = await _send_job_enter(
|
|
678
|
+
job_id=job_id,
|
|
679
|
+
name=f"eval ({cfg.source})" if cfg.source else "eval",
|
|
680
|
+
variants=None,
|
|
681
|
+
group=cfg.group_size,
|
|
682
|
+
api_key=None,
|
|
683
|
+
taskset=cfg.taskset,
|
|
684
|
+
tasks=tasks_data,
|
|
685
|
+
)
|
|
686
|
+
if ids:
|
|
687
|
+
if len(ids) != len(tasks_to_create):
|
|
688
|
+
hud_console.warning(
|
|
689
|
+
f"Task count mismatch: sent {len(tasks_to_create)} tasks, "
|
|
690
|
+
f"received {len(ids)} IDs. Some tasks may not be linked."
|
|
691
|
+
)
|
|
692
|
+
for task_obj, task_version_id in zip(tasks_to_create, ids, strict=False):
|
|
693
|
+
task_obj.id = task_version_id
|
|
694
|
+
|
|
668
695
|
await submit_rollouts(
|
|
669
696
|
tasks=tasks,
|
|
670
697
|
job_id=job_id,
|
|
@@ -701,6 +728,7 @@ async def _run_evaluation(cfg: EvalConfig) -> tuple[list[Any], list[Any]]:
|
|
|
701
728
|
max_concurrent=cfg.max_concurrent,
|
|
702
729
|
group_size=cfg.group_size,
|
|
703
730
|
quiet=cfg.quiet,
|
|
731
|
+
taskset=cfg.taskset,
|
|
704
732
|
)
|
|
705
733
|
|
|
706
734
|
# Show reward for single task
|
|
@@ -767,6 +795,9 @@ def eval_command(
|
|
|
767
795
|
gateway: bool = typer.Option(
|
|
768
796
|
False, "--gateway", "-g", help="Route LLM API calls through HUD Gateway"
|
|
769
797
|
),
|
|
798
|
+
taskset: str | None = typer.Option(
|
|
799
|
+
None, "--taskset", "-t", help="Taskset slug to associate job with"
|
|
800
|
+
),
|
|
770
801
|
) -> None:
|
|
771
802
|
"""🚀 Run evaluation on datasets or individual tasks with agents.
|
|
772
803
|
|
|
@@ -801,6 +832,7 @@ def eval_command(
|
|
|
801
832
|
byok=byok,
|
|
802
833
|
quiet=quiet,
|
|
803
834
|
gateway=gateway,
|
|
835
|
+
taskset=taskset,
|
|
804
836
|
)
|
|
805
837
|
|
|
806
838
|
# Find source if not provided
|
|
@@ -60,12 +60,12 @@ class TestIncrementVersion:
|
|
|
60
60
|
def test_increment_minor(self):
|
|
61
61
|
"""Test incrementing minor version."""
|
|
62
62
|
assert increment_version("1.2.3", "minor") == "1.3.0"
|
|
63
|
-
assert increment_version("0.5.
|
|
63
|
+
assert increment_version("0.5.13", "minor") == "0.6.0"
|
|
64
64
|
|
|
65
65
|
def test_increment_major(self):
|
|
66
66
|
"""Test incrementing major version."""
|
|
67
67
|
assert increment_version("1.2.3", "major") == "2.0.0"
|
|
68
|
-
assert increment_version("0.5.
|
|
68
|
+
assert increment_version("0.5.13", "major") == "1.0.0"
|
|
69
69
|
|
|
70
70
|
def test_increment_with_v_prefix(self):
|
|
71
71
|
"""Test incrementing version with v prefix."""
|
|
@@ -29,6 +29,7 @@ async def run_dataset(
|
|
|
29
29
|
max_concurrent: int = 30,
|
|
30
30
|
group_size: int = 1,
|
|
31
31
|
quiet: bool = True,
|
|
32
|
+
taskset: str | None = None,
|
|
32
33
|
) -> list[EvalContext]:
|
|
33
34
|
"""Run an agent on a dataset of tasks.
|
|
34
35
|
|
|
@@ -96,6 +97,7 @@ async def run_dataset(
|
|
|
96
97
|
group=group_size,
|
|
97
98
|
max_concurrent=max_concurrent,
|
|
98
99
|
quiet=quiet,
|
|
100
|
+
taskset=taskset,
|
|
99
101
|
) as ctx:
|
|
100
102
|
# Build agent params - use system_prompt from ctx (set from task.agent_config)
|
|
101
103
|
final_agent_params = dict(agent_params or {})
|
|
@@ -382,6 +382,7 @@ class ScenarioMixin:
|
|
|
382
382
|
self,
|
|
383
383
|
name: str | None = None,
|
|
384
384
|
description: str | None = None,
|
|
385
|
+
required_env_vars: list[str] | None = None,
|
|
385
386
|
) -> Callable[
|
|
386
387
|
[Callable[..., AsyncGenerator[Any, None]]],
|
|
387
388
|
Callable[..., AsyncGenerator[Any, None]],
|
|
@@ -396,19 +397,21 @@ class ScenarioMixin:
|
|
|
396
397
|
Args:
|
|
397
398
|
name: Optional name for the scenario (defaults to function name)
|
|
398
399
|
description: Optional description of what the scenario does
|
|
400
|
+
required_env_vars: Optional list of environment variable names this scenario requires.
|
|
401
|
+
These are used by the HUD platform to check if users have configured the
|
|
402
|
+
necessary API keys/credentials before running this specific scenario.
|
|
399
403
|
|
|
400
404
|
Example:
|
|
401
|
-
@env.scenario()
|
|
402
|
-
async def
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
yield float(result > 0)
|
|
405
|
+
@env.scenario(required_env_vars=["OPENAI_API_KEY"])
|
|
406
|
+
async def chat(query: str):
|
|
407
|
+
yield f"Answer this question: {query}"
|
|
408
|
+
# ... evaluate
|
|
409
|
+
yield 1.0
|
|
407
410
|
|
|
408
411
|
# MCP client usage:
|
|
409
|
-
# 1. get_prompt("{env_name}:
|
|
412
|
+
# 1. get_prompt("{env_name}:chat", {query: "..."}) -> prompt messages
|
|
410
413
|
# 2. agent runs...
|
|
411
|
-
# 3. read_resource("{env_name}:
|
|
414
|
+
# 3. read_resource("{env_name}:chat") -> {"reward": 0.95}
|
|
412
415
|
"""
|
|
413
416
|
|
|
414
417
|
def decorator(
|
|
@@ -568,6 +571,8 @@ class ScenarioMixin:
|
|
|
568
571
|
scenario_meta["code"] = source_code
|
|
569
572
|
if prompt_args:
|
|
570
573
|
scenario_meta["arguments"] = prompt_args
|
|
574
|
+
if required_env_vars:
|
|
575
|
+
scenario_meta["required_env_vars"] = required_env_vars
|
|
571
576
|
|
|
572
577
|
prompt = FunctionPrompt(
|
|
573
578
|
name=scenario_id,
|
|
@@ -56,14 +56,16 @@ def _get_eval_name(tasks: list[Task] | None = None) -> str:
|
|
|
56
56
|
return "eval"
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
def _send_job_enter(
|
|
59
|
+
async def _send_job_enter(
|
|
60
60
|
job_id: str,
|
|
61
61
|
name: str,
|
|
62
62
|
variants: dict[str, Any] | None,
|
|
63
63
|
group: int,
|
|
64
64
|
api_key: str | None,
|
|
65
|
-
|
|
66
|
-
|
|
65
|
+
taskset: str | None = None,
|
|
66
|
+
tasks: list[dict[str, Any]] | None = None,
|
|
67
|
+
) -> list[str] | None:
|
|
68
|
+
"""Send job enter payload (async request before traces start)."""
|
|
67
69
|
import httpx
|
|
68
70
|
|
|
69
71
|
from hud.eval.types import JobEnterPayload
|
|
@@ -71,23 +73,35 @@ def _send_job_enter(
|
|
|
71
73
|
|
|
72
74
|
api_key = api_key or settings.api_key
|
|
73
75
|
if not settings.telemetry_enabled or not api_key:
|
|
74
|
-
return
|
|
76
|
+
return None
|
|
75
77
|
|
|
76
78
|
payload = JobEnterPayload(
|
|
77
79
|
name=name,
|
|
78
80
|
variants=variants,
|
|
79
81
|
group=group,
|
|
82
|
+
taskset=taskset,
|
|
83
|
+
tasks=tasks if taskset else None, # only send tasks if taskset specified
|
|
80
84
|
)
|
|
81
85
|
|
|
82
86
|
try:
|
|
83
|
-
httpx.
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
87
|
+
async with httpx.AsyncClient(timeout=10.0) as client:
|
|
88
|
+
resp = await client.post(
|
|
89
|
+
f"{settings.hud_api_url}/trace/job/{job_id}/enter",
|
|
90
|
+
json=payload.model_dump(exclude_none=True),
|
|
91
|
+
headers={"Authorization": f"Bearer {api_key}"},
|
|
92
|
+
)
|
|
93
|
+
if resp.is_success:
|
|
94
|
+
try:
|
|
95
|
+
data = resp.json()
|
|
96
|
+
except Exception:
|
|
97
|
+
return None
|
|
98
|
+
if isinstance(data, dict):
|
|
99
|
+
ids = data.get("task_version_ids")
|
|
100
|
+
if isinstance(ids, list) and all(isinstance(x, str) for x in ids):
|
|
101
|
+
return ids
|
|
89
102
|
except Exception as e:
|
|
90
103
|
logger.warning("Failed to send job enter: %s", e)
|
|
104
|
+
return None
|
|
91
105
|
|
|
92
106
|
|
|
93
107
|
@asynccontextmanager
|
|
@@ -105,6 +119,7 @@ async def run_eval(
|
|
|
105
119
|
max_concurrent: int | None = None,
|
|
106
120
|
trace: bool = True,
|
|
107
121
|
quiet: bool = False,
|
|
122
|
+
taskset: str | None = None,
|
|
108
123
|
) -> AsyncGenerator[EvalContext, None]:
|
|
109
124
|
"""Standalone eval context manager.
|
|
110
125
|
|
|
@@ -235,13 +250,37 @@ async def run_eval(
|
|
|
235
250
|
|
|
236
251
|
if total_evals == 1:
|
|
237
252
|
if tasks:
|
|
253
|
+
# Even for single-task evals, --taskset requires a job_enter call so the run
|
|
254
|
+
# and task are linked to the taskset (via job_id + task_version_id).
|
|
255
|
+
job_id_for_run = job_id
|
|
256
|
+
if taskset:
|
|
257
|
+
eval_name = _get_eval_name(tasks=tasks)
|
|
258
|
+
if job_id_for_run is None:
|
|
259
|
+
job_id_for_run = str(uuid.uuid4())
|
|
260
|
+
|
|
261
|
+
task_data = None
|
|
262
|
+
if not tasks[0].id:
|
|
263
|
+
task_data = [tasks[0].model_dump(mode="json", exclude_none=True)]
|
|
264
|
+
|
|
265
|
+
created_task_version_ids = await _send_job_enter(
|
|
266
|
+
job_id=job_id_for_run,
|
|
267
|
+
name=eval_name,
|
|
268
|
+
variants=variants,
|
|
269
|
+
group=group,
|
|
270
|
+
api_key=api_key,
|
|
271
|
+
taskset=taskset,
|
|
272
|
+
tasks=task_data,
|
|
273
|
+
)
|
|
274
|
+
if created_task_version_ids and not tasks[0].id:
|
|
275
|
+
tasks[0].id = created_task_version_ids[0]
|
|
276
|
+
|
|
238
277
|
# Single task - use EvalContext.from_task()
|
|
239
278
|
ctx = EvalContext.from_task(
|
|
240
279
|
tasks[0],
|
|
241
280
|
name=name,
|
|
242
281
|
trace_id=trace_id,
|
|
243
282
|
api_key=api_key,
|
|
244
|
-
job_id=
|
|
283
|
+
job_id=job_id_for_run,
|
|
245
284
|
group_id=group_id,
|
|
246
285
|
variants=variant_combos[0],
|
|
247
286
|
code_snippet=code_snippet,
|
|
@@ -273,13 +312,41 @@ async def run_eval(
|
|
|
273
312
|
job_url = f"https://hud.ai/jobs/{implicit_job_id}"
|
|
274
313
|
|
|
275
314
|
# Send job enter (sync request before traces start)
|
|
276
|
-
|
|
315
|
+
# Serialize tasks for auto-add to taskset (only tasks without existing backend id).
|
|
316
|
+
# For v5 scenario tasks, the backend task_version_id is carried in Task.id.
|
|
317
|
+
tasks_data = None
|
|
318
|
+
tasks_to_create: list[Task] = []
|
|
319
|
+
if taskset and tasks:
|
|
320
|
+
tasks_to_create = [t for t in tasks if not t.id]
|
|
321
|
+
tasks_data = (
|
|
322
|
+
[t.model_dump(mode="json", exclude_none=True) for t in tasks_to_create]
|
|
323
|
+
if tasks_to_create
|
|
324
|
+
else None
|
|
325
|
+
)
|
|
326
|
+
created_task_version_ids = await _send_job_enter(
|
|
277
327
|
job_id=implicit_job_id,
|
|
278
328
|
name=eval_name,
|
|
279
329
|
variants=variants,
|
|
280
330
|
group=group,
|
|
281
331
|
api_key=api_key,
|
|
332
|
+
taskset=taskset,
|
|
333
|
+
tasks=tasks_data,
|
|
282
334
|
)
|
|
335
|
+
if created_task_version_ids and tasks_to_create:
|
|
336
|
+
# Assign backend IDs back onto the in-memory tasks so trace enter includes
|
|
337
|
+
# task_version_id.
|
|
338
|
+
# Platform guarantees ordered one-to-one mapping, but warn if counts differ.
|
|
339
|
+
if len(created_task_version_ids) != len(tasks_to_create):
|
|
340
|
+
logger.warning(
|
|
341
|
+
"Task count mismatch: sent %d tasks, received %d IDs. "
|
|
342
|
+
"Some tasks may not be linked to the taskset.",
|
|
343
|
+
len(tasks_to_create),
|
|
344
|
+
len(created_task_version_ids),
|
|
345
|
+
)
|
|
346
|
+
for task_obj, task_version_id in zip(
|
|
347
|
+
tasks_to_create, created_task_version_ids, strict=False
|
|
348
|
+
):
|
|
349
|
+
task_obj.id = task_version_id
|
|
283
350
|
|
|
284
351
|
# Print job URL (not individual trace URLs)
|
|
285
352
|
if not quiet:
|
|
@@ -53,6 +53,8 @@ class JobEnterPayload(BaseModel):
|
|
|
53
53
|
name: str | None = None
|
|
54
54
|
variants: dict[str, Any] | None = None # Full variant config
|
|
55
55
|
group: int | None = None
|
|
56
|
+
taskset: str | None = None # taskset slug to associate job with
|
|
57
|
+
tasks: list[dict[str, Any]] | None = None # task definitions to add to taskset
|
|
56
58
|
|
|
57
59
|
|
|
58
60
|
__all__ = [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "hud-python"
|
|
3
|
-
version = "0.5.
|
|
3
|
+
version = "0.5.13"
|
|
4
4
|
description = "SDK for the HUD platform."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11, <3.13"
|
|
@@ -140,7 +140,7 @@ dev = [
|
|
|
140
140
|
"dotenv>=0.9.9",
|
|
141
141
|
# Testing and linting
|
|
142
142
|
"ruff >=0.11.8",
|
|
143
|
-
"pytest >=8.1.1
|
|
143
|
+
"pytest >=8.1.1",
|
|
144
144
|
"pytest-asyncio",
|
|
145
145
|
"pytest-mock",
|
|
146
146
|
"pytest-cov",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|