verifiers 0.2.1.dev61__tar.gz → 0.2.1.dev63__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.
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/PKG-INFO +1 -1
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/bash/program.py +143 -93
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/claude_code/harness.py +1 -1
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/codex/harness.py +1 -1
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/kimi_code/harness.py +1 -1
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/mini_swe_agent/harness.py +1 -1
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/mini_swe_agent/program.py +1 -1
- verifiers-0.2.1.dev63/verifiers/v1/harnesses/null/program.py +217 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/pi/harness.py +1 -1
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/interception/server.py +7 -4
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/mcp/__init__.py +2 -2
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/mcp/launch.py +63 -57
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/mcp/user.py +26 -2
- verifiers-0.2.1.dev61/verifiers/v1/harnesses/null/program.py +0 -168
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/.gitignore +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/LICENSE +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/README.md +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/pyproject.toml +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/AGENTS.md +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/conftest.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_browser_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_build_script.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_cli_agent_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_client_auth_errors.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_client_config.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_client_multimodal_types.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_composable_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_context_token_metrics.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_decorator_ranks.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_endpoint_registry.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_env_group.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_env_server.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_environment.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_environment_extra.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_error_chain.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_eval_display.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_eval_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_gepa_cli.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_gepa_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_gym_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_harbor_env_mcp.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_imports.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_init_script.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_install_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_interception_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_logging.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_math_rubric.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_maybe_think_parser.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_message_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_message_utils_multimodal.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_multiturn_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_nemorl_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_openai_chat_completions_token_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_openai_responses_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_opencode_rlm_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_openenv_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_parser.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_path_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_per_turn_timing.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_pricing_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_prime_plugin.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_renderer_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_renderer_e2e.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_rlm_composable_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_rubric.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_rubric_group.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_sandbox_debug_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_sandbox_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_sandbox_mixin.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_save_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_setup_script.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_singleturn_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_stateful_tool_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_think_parser.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_tool_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_tool_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_trajectory_processing.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_tui_info_formatting.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_types.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/test_xml_parser.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/conftest.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/fixtures/counter_tool_v1.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/fixtures/echo_multi_v0.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/fixtures/echo_tool_v1.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/fixtures/echo_v0.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/fixtures/echo_v1.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/fixtures/pyproject.toml +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/test_color_codeword_tasks.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/test_configs.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/test_e2e.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/test_envs.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/test_graph.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/test_judges.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/test_legacy.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/test_scoring.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/test_taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/tests/v1/test_trace.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/cli/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/cli/commands/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/cli/commands/build.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/cli/commands/eval.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/cli/commands/gepa.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/cli/commands/init.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/cli/commands/install.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/cli/commands/setup.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/cli/plugins/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/cli/plugins/prime.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/cli/tui.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/clients/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/clients/anthropic_messages_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/clients/client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/clients/nemorl_chat_completions_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/clients/openai_chat_completions_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/clients/openai_chat_completions_token_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/clients/openai_completions_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/clients/openai_responses_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/clients/renderer_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/decorators.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/AGENTS.md +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/env_group.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/environment.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/README.md +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/cli_agent_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/README.md +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/_filter.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/composable_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/harness.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/harnesses/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/harnesses/mini_swe_agent.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/harnesses/opencode.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/harnesses/prompt.txt +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/harnesses/rlm.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/sandbox_debug_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/swe_debug_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/task.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/cp/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/cp/cp_task.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/cp/test_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/harbor/cli_gym.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/harbor/harbor.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/harbor/terminal_lego.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/math/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/math/math_task.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/README.md +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/extract_fix_patch.sh +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/openswe/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/openswe/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/log_parser.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/shared/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/shared/test_patch.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/log_parsers.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_tasksets.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/gym_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/harbor_env/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/harbor_env/env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/harbor_env/mcp.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/mcp_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/opencode_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/opencode_qa_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/opencode_rlm_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/sandbox_mixin.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/utils/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/utils/file_locks.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/experimental/utils/git_checkout_cache.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/README.md +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/browser_env/README.md +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/browser_env/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/browser_env/browser_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/browser_env/modes/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/browser_env/modes/base.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/browser_env/modes/cua_mode.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/browser_env/modes/dom_mode.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/openenv_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/reasoninggym_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/integrations/textarena_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/multiturn_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/python_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/sandbox_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/singleturn_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/stateful_tool_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/envs/tool_env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/errors.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/gepa/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/gepa/adapter.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/gepa/config.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/gepa/display.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/gepa/gepa_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/parsers/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/parsers/maybe_think_parser.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/parsers/parser.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/parsers/think_parser.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/parsers/xml_parser.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/rubrics/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/rubrics/experimental/hybrid_math_rubric.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/rubrics/judge_rubric.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/rubrics/math_rubric.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/rubrics/rubric.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/rubrics/rubric_group.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/scripts/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/scripts/build.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/scripts/eval.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/scripts/gepa.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/scripts/init.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/scripts/install.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/scripts/setup.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/scripts/tui.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/serve/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/serve/client/env_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/serve/client/zmq_env_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/serve/server/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/serve/server/env_router.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/serve/server/env_server.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/serve/server/env_worker.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/serve/server/zmq_env_server.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/serve/types.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/types.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/async_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/client_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/config_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/data_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/display_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/env_config_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/env_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/error_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/eval_display.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/eval_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/heartbeat.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/import_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/install_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/interception_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/logging_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/message_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/metric_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/path_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/pricing_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/process_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/response_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/save_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/serve_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/thread_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/threaded_sandbox_client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/tool_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/usage_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/utils/version_utils.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/dashboard/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/dashboard/base.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/dashboard/eval.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/dashboard/replay.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/dashboard/validate.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/debug.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/eval/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/eval/main.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/eval/resume.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/eval/runner.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/gepa.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/init.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/replay.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/serve.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/cli/validate.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/clients/config.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/configs/debug.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/configs/eval.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/configs/init.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/configs/replay.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/configs/serve.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/configs/validate.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/decorators.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/dialects/anthropic.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/dialects/base.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/dialects/chat.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/dialects/responses.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/env.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/episode.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/errors.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/gepa/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/gepa/adapter.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/gepa/config.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/gepa/dataset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/gepa/reflection.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/gepa/runner.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/graph.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harness.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/bash/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/bash/harness.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/null/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/null/harness.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/pi/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/rlm/harness.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/interception/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/interception/base.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/interception/pool.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/interception/tunnel/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/interception/tunnel/base.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/interception/tunnel/custom.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/interception/tunnel/prime.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/judge.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/judges/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/judges/reference.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/judges/reference.txt +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/judges/rubric.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/judges/rubric.txt +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/legacy.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/loaders.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/mcp/server.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/mcp/toolset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/push.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/retries.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/rollout.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/runtimes/base.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/runtimes/docker.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/runtimes/limiters.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/runtimes/modal.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/runtimes/prime.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/runtimes/subprocess.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/scoring.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/serve/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/serve/client.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/serve/pool.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/serve/server.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/serve/types.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/session.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/state.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/task.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/tasksets/lean/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/tasksets/lean/scoring.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/tasksets/lean/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/trace.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/types.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/utils/aio.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/utils/generic.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/utils/image.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/utils/install.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/utils/interrupt.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/utils/memory.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/utils/sampling.py +0 -0
- {verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/utils/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: verifiers
|
|
3
|
-
Version: 0.2.1.
|
|
3
|
+
Version: 0.2.1.dev63
|
|
4
4
|
Summary: Verifiers: Environments for LLM Reinforcement Learning
|
|
5
5
|
Project-URL: Homepage, https://github.com/primeintellect-ai/verifiers
|
|
6
6
|
Project-URL: Documentation, https://github.com/primeintellect-ai/verifiers
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# /// script
|
|
2
2
|
# requires-python = ">=3.10"
|
|
3
|
-
# dependencies = ["openai", "mcp", "httpx"]
|
|
3
|
+
# dependencies = ["openai", "mcp", "httpx", "tenacity"]
|
|
4
4
|
# ///
|
|
5
5
|
"""Secrets arrive through argv so local tool subprocesses do not inherit them."""
|
|
6
6
|
|
|
@@ -8,14 +8,19 @@ import argparse
|
|
|
8
8
|
import asyncio
|
|
9
9
|
import json
|
|
10
10
|
import subprocess
|
|
11
|
-
from contextlib import AsyncExitStack
|
|
11
|
+
from contextlib import AsyncExitStack, asynccontextmanager, suppress
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
|
|
14
14
|
import httpx
|
|
15
15
|
from openai import AsyncOpenAI
|
|
16
|
+
from tenacity import AsyncRetrying, stop_after_attempt, wait_exponential_jitter
|
|
16
17
|
|
|
17
18
|
SERPER_URL = "https://google.serper.dev/search"
|
|
18
19
|
|
|
20
|
+
MCP_CALL_ATTEMPTS = 6
|
|
21
|
+
MCP_TIMEOUT = httpx.Timeout(600.0, connect=5.0) # the OpenAI SDK client defaults
|
|
22
|
+
|
|
23
|
+
|
|
19
24
|
BASH_TOOL = {
|
|
20
25
|
"type": "function",
|
|
21
26
|
"function": {
|
|
@@ -177,29 +182,66 @@ async def chat(
|
|
|
177
182
|
return completion.choices[0].message
|
|
178
183
|
|
|
179
184
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
+
@asynccontextmanager
|
|
186
|
+
async def mcp_session(spec: dict):
|
|
187
|
+
"""One fresh streamable-HTTP session to an MCP server, opened and closed within the caller's
|
|
188
|
+
task so AnyIO cancellation scopes stay correctly nested. A teardown failure after the body
|
|
189
|
+
completed is swallowed — the result is already in hand, and closing noise must not fail (or
|
|
190
|
+
replay) an already-answered call."""
|
|
185
191
|
from mcp import ClientSession
|
|
186
192
|
from mcp.client.streamable_http import (
|
|
187
193
|
create_mcp_http_client,
|
|
188
194
|
streamable_http_client,
|
|
189
195
|
)
|
|
190
196
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
for name, spec in config.get("mcpServers", {}).items():
|
|
197
|
+
stack = AsyncExitStack()
|
|
198
|
+
try:
|
|
194
199
|
http_client = await stack.enter_async_context(
|
|
195
|
-
create_mcp_http_client(
|
|
200
|
+
create_mcp_http_client(
|
|
201
|
+
headers=spec.get("headers") or None, timeout=MCP_TIMEOUT
|
|
202
|
+
)
|
|
196
203
|
)
|
|
197
204
|
read, write, *_ = await stack.enter_async_context(
|
|
198
205
|
streamable_http_client(spec["url"], http_client=http_client)
|
|
199
206
|
)
|
|
200
207
|
session = await stack.enter_async_context(ClientSession(read, write))
|
|
201
208
|
await session.initialize()
|
|
202
|
-
|
|
209
|
+
yield session
|
|
210
|
+
finally:
|
|
211
|
+
with suppress(Exception):
|
|
212
|
+
await stack.aclose()
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
async def with_retry(call):
|
|
216
|
+
"""Run one session-scoped operation, retrying transient failures with backoff. A call whose
|
|
217
|
+
response was lost may be replayed — MCP has no idempotency key, so tools should tolerate
|
|
218
|
+
at-least-once delivery (a tool that fails reports through its result, not an exception)."""
|
|
219
|
+
async for attempt in AsyncRetrying(
|
|
220
|
+
stop=stop_after_attempt(MCP_CALL_ATTEMPTS),
|
|
221
|
+
wait=wait_exponential_jitter(initial=0.5, max=30),
|
|
222
|
+
reraise=True,
|
|
223
|
+
):
|
|
224
|
+
with attempt:
|
|
225
|
+
return await call()
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
async def connect_mcp(
|
|
229
|
+
config: dict, reserved: set[str]
|
|
230
|
+
) -> tuple[list[dict], dict, dict]:
|
|
231
|
+
"""Enumerate each configured MCP server's tools (a streamable-HTTP `url`); return (tool schemas,
|
|
232
|
+
dispatch mapping `<server>_<tool>` -> (server name, raw tool name), servers mapping name -> spec).
|
|
233
|
+
No session is held — a stateless-HTTP server is reconnected per call."""
|
|
234
|
+
tool_schemas: list[dict] = []
|
|
235
|
+
dispatch: dict[str, tuple] = {}
|
|
236
|
+
servers: dict[str, dict] = {}
|
|
237
|
+
for name, spec in config.get("mcpServers", {}).items():
|
|
238
|
+
servers[name] = spec
|
|
239
|
+
|
|
240
|
+
async def list_tools(spec: dict = spec):
|
|
241
|
+
async with mcp_session(spec) as session:
|
|
242
|
+
return (await session.list_tools()).tools
|
|
243
|
+
|
|
244
|
+
for tool in await with_retry(list_tools):
|
|
203
245
|
# A server named "" (TOOL_PREFIX = None) advertises its tools bare.
|
|
204
246
|
full = f"{name}_{tool.name}" if name else tool.name
|
|
205
247
|
if full in reserved or full in dispatch:
|
|
@@ -216,8 +258,8 @@ async def connect_mcp(
|
|
|
216
258
|
},
|
|
217
259
|
}
|
|
218
260
|
)
|
|
219
|
-
dispatch[full] = (
|
|
220
|
-
return tool_schemas, dispatch
|
|
261
|
+
dispatch[full] = (name, tool.name)
|
|
262
|
+
return tool_schemas, dispatch, servers
|
|
221
263
|
|
|
222
264
|
|
|
223
265
|
def mcp_content_to_chat_content(blocks) -> str | list[dict]:
|
|
@@ -237,9 +279,18 @@ def mcp_content_to_chat_content(blocks) -> str | list[dict]:
|
|
|
237
279
|
return parts
|
|
238
280
|
|
|
239
281
|
|
|
240
|
-
async def call_mcp(
|
|
241
|
-
|
|
242
|
-
|
|
282
|
+
async def call_mcp(
|
|
283
|
+
servers: dict, dispatch: dict, name: str, arguments: dict
|
|
284
|
+
) -> str | list[dict]:
|
|
285
|
+
"""Call a tool on a fresh session per attempt — see `with_retry` for the replay semantics.
|
|
286
|
+
The result is converted outside the retry so a conversion failure fails once."""
|
|
287
|
+
server_name, raw = dispatch[name]
|
|
288
|
+
|
|
289
|
+
async def call():
|
|
290
|
+
async with mcp_session(servers[server_name]) as session:
|
|
291
|
+
return await session.call_tool(raw, arguments)
|
|
292
|
+
|
|
293
|
+
result = await with_retry(call)
|
|
243
294
|
return mcp_content_to_chat_content(result.content)
|
|
244
295
|
|
|
245
296
|
|
|
@@ -268,84 +319,83 @@ async def main() -> None:
|
|
|
268
319
|
initial = json.loads(payload)
|
|
269
320
|
client = AsyncOpenAI(base_url=args.base_url, api_key=args.api_key)
|
|
270
321
|
config = json.loads(args.mcp_config or "{}")
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
if not isinstance(tool_args, dict):
|
|
316
|
-
messages.append(
|
|
317
|
-
{
|
|
318
|
-
"role": "tool",
|
|
319
|
-
"tool_call_id": call.id,
|
|
320
|
-
"content": f"error: tool arguments must be a JSON object, got {type(tool_args).__name__}; resend as an object",
|
|
321
|
-
}
|
|
322
|
-
)
|
|
323
|
-
continue
|
|
324
|
-
if name in dispatch:
|
|
325
|
-
content = await call_mcp(dispatch, name, tool_args)
|
|
326
|
-
elif name == "bash":
|
|
327
|
-
content = await asyncio.to_thread(
|
|
328
|
-
run_bash, tool_args.get("command", "")
|
|
329
|
-
)
|
|
330
|
-
elif name == "edit" and args.edit:
|
|
331
|
-
content = await asyncio.to_thread(
|
|
332
|
-
run_edit,
|
|
333
|
-
tool_args.get("path"),
|
|
334
|
-
tool_args.get("old_str"),
|
|
335
|
-
tool_args.get("new_str"),
|
|
336
|
-
)
|
|
337
|
-
elif name == "search" and args.search:
|
|
338
|
-
content = await asyncio.to_thread(
|
|
339
|
-
run_search,
|
|
340
|
-
tool_args.get("query", ""),
|
|
341
|
-
args.serper_key,
|
|
342
|
-
tool_args.get("num_results", 5),
|
|
343
|
-
)
|
|
344
|
-
else:
|
|
345
|
-
content = f"error: unknown tool {name!r}"
|
|
322
|
+
tools = [BASH_TOOL]
|
|
323
|
+
reserved = {"bash"}
|
|
324
|
+
if args.edit:
|
|
325
|
+
tools.append(EDIT_TOOL)
|
|
326
|
+
reserved.add("edit")
|
|
327
|
+
if args.search:
|
|
328
|
+
tools.append(SEARCH_TOOL)
|
|
329
|
+
reserved.add("search")
|
|
330
|
+
mcp_tools, dispatch, servers = (
|
|
331
|
+
await connect_mcp(config, reserved)
|
|
332
|
+
if config.get("mcpServers")
|
|
333
|
+
else ([], {}, {})
|
|
334
|
+
)
|
|
335
|
+
tools += mcp_tools
|
|
336
|
+
messages = (
|
|
337
|
+
[{"role": "system", "content": args.system_prompt}]
|
|
338
|
+
if args.system_prompt
|
|
339
|
+
else []
|
|
340
|
+
)
|
|
341
|
+
if initial:
|
|
342
|
+
messages.extend(initial)
|
|
343
|
+
elif args.prompt:
|
|
344
|
+
messages.append({"role": "user", "content": args.prompt})
|
|
345
|
+
while True:
|
|
346
|
+
message = await chat(client, args.model, messages, tools)
|
|
347
|
+
messages.append(message.model_dump(exclude_none=True))
|
|
348
|
+
if not message.tool_calls:
|
|
349
|
+
break
|
|
350
|
+
for call in message.tool_calls:
|
|
351
|
+
name = call.function.name
|
|
352
|
+
try:
|
|
353
|
+
tool_args = json.loads(call.function.arguments or "{}")
|
|
354
|
+
except json.JSONDecodeError as e:
|
|
355
|
+
messages.append(
|
|
356
|
+
{
|
|
357
|
+
"role": "tool",
|
|
358
|
+
"tool_call_id": call.id,
|
|
359
|
+
"content": f"error: invalid JSON in tool arguments ({e}); resend the call with valid JSON",
|
|
360
|
+
}
|
|
361
|
+
)
|
|
362
|
+
continue
|
|
363
|
+
# Valid JSON can still be a non-object (`[]`, `42`, `null`); the `.get(...)` calls
|
|
364
|
+
# below assume a dict, so reject anything else as a tool error rather than crashing.
|
|
365
|
+
if not isinstance(tool_args, dict):
|
|
346
366
|
messages.append(
|
|
347
|
-
{
|
|
367
|
+
{
|
|
368
|
+
"role": "tool",
|
|
369
|
+
"tool_call_id": call.id,
|
|
370
|
+
"content": f"error: tool arguments must be a JSON object, got {type(tool_args).__name__}; resend as an object",
|
|
371
|
+
}
|
|
372
|
+
)
|
|
373
|
+
continue
|
|
374
|
+
if name in dispatch:
|
|
375
|
+
content = await call_mcp(servers, dispatch, name, tool_args)
|
|
376
|
+
elif name == "bash":
|
|
377
|
+
content = await asyncio.to_thread(
|
|
378
|
+
run_bash, tool_args.get("command", "")
|
|
348
379
|
)
|
|
380
|
+
elif name == "edit" and args.edit:
|
|
381
|
+
content = await asyncio.to_thread(
|
|
382
|
+
run_edit,
|
|
383
|
+
tool_args.get("path"),
|
|
384
|
+
tool_args.get("old_str"),
|
|
385
|
+
tool_args.get("new_str"),
|
|
386
|
+
)
|
|
387
|
+
elif name == "search" and args.search:
|
|
388
|
+
content = await asyncio.to_thread(
|
|
389
|
+
run_search,
|
|
390
|
+
tool_args.get("query", ""),
|
|
391
|
+
args.serper_key,
|
|
392
|
+
tool_args.get("num_results", 5),
|
|
393
|
+
)
|
|
394
|
+
else:
|
|
395
|
+
content = f"error: unknown tool {name!r}"
|
|
396
|
+
messages.append(
|
|
397
|
+
{"role": "tool", "tool_call_id": call.id, "content": content}
|
|
398
|
+
)
|
|
349
399
|
|
|
350
400
|
|
|
351
401
|
if __name__ == "__main__":
|
{verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/claude_code/harness.py
RENAMED
|
@@ -21,7 +21,7 @@ curl -fsSL https://claude.ai/install.sh | HOME={home} bash -s {version}
|
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class ClaudeCodeHarnessConfig(HarnessConfig):
|
|
24
|
-
version: str = Field(default="2.1.
|
|
24
|
+
version: str = Field(default="2.1.214", pattern=r"^[A-Za-z0-9._+-]+$")
|
|
25
25
|
"""Claude Code release to install; pinned for reproducibility."""
|
|
26
26
|
|
|
27
27
|
|
|
@@ -36,7 +36,7 @@ chmod +x {bin}
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
class CodexHarnessConfig(HarnessConfig):
|
|
39
|
-
version: str = "0.
|
|
39
|
+
version: str = "0.144.5"
|
|
40
40
|
"""Codex release to install (the `rust-v<version>` GitHub release); pinned for reproducibility."""
|
|
41
41
|
multi_agent: bool = False
|
|
42
42
|
"""Enable Codex's native multi-agent v2 tools."""
|
{verifiers-0.2.1.dev61 → verifiers-0.2.1.dev63}/verifiers/v1/harnesses/mini_swe_agent/harness.py
RENAMED
|
@@ -9,7 +9,7 @@ PROGRAM_SOURCE = (Path(__file__).resolve().parent / "program.py").read_text()
|
|
|
9
9
|
|
|
10
10
|
|
|
11
11
|
class MiniSWEAgentHarnessConfig(HarnessConfig):
|
|
12
|
-
version: str = "2.
|
|
12
|
+
version: str = "2.4.5"
|
|
13
13
|
"""mini-swe-agent release to install, pinned for reproducibility."""
|
|
14
14
|
|
|
15
15
|
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# /// script
|
|
2
|
+
# requires-python = ">=3.11"
|
|
3
|
+
# dependencies = ["openai", "mcp", "httpx", "tenacity"]
|
|
4
|
+
# ///
|
|
5
|
+
"""The interception endpoint and secret arrive through argv rather than the environment."""
|
|
6
|
+
|
|
7
|
+
import argparse
|
|
8
|
+
import asyncio
|
|
9
|
+
import json
|
|
10
|
+
from contextlib import AsyncExitStack, asynccontextmanager, suppress
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
|
|
13
|
+
import httpx
|
|
14
|
+
from openai import AsyncOpenAI
|
|
15
|
+
from tenacity import AsyncRetrying, stop_after_attempt, wait_exponential_jitter
|
|
16
|
+
|
|
17
|
+
MCP_CALL_ATTEMPTS = 6
|
|
18
|
+
MCP_TIMEOUT = httpx.Timeout(600.0, connect=5.0) # the OpenAI SDK client defaults
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
async def chat(
|
|
22
|
+
client: AsyncOpenAI, model: str, messages: list[dict], tools: list[dict]
|
|
23
|
+
):
|
|
24
|
+
completion = await client.chat.completions.create(
|
|
25
|
+
model=model, messages=messages, tools=tools or None
|
|
26
|
+
)
|
|
27
|
+
return completion.choices[0].message
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@asynccontextmanager
|
|
31
|
+
async def mcp_session(spec: dict):
|
|
32
|
+
"""One fresh streamable-HTTP session to an MCP server, opened and closed within the caller's
|
|
33
|
+
task so AnyIO cancellation scopes stay correctly nested. A teardown failure after the body
|
|
34
|
+
completed is swallowed — the result is already in hand, and closing noise must not fail (or
|
|
35
|
+
replay) an already-answered call."""
|
|
36
|
+
from mcp import ClientSession
|
|
37
|
+
from mcp.client.streamable_http import (
|
|
38
|
+
create_mcp_http_client,
|
|
39
|
+
streamable_http_client,
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
stack = AsyncExitStack()
|
|
43
|
+
try:
|
|
44
|
+
http_client = await stack.enter_async_context(
|
|
45
|
+
create_mcp_http_client(
|
|
46
|
+
headers=spec.get("headers") or None, timeout=MCP_TIMEOUT
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
read, write, *_ = await stack.enter_async_context(
|
|
50
|
+
streamable_http_client(spec["url"], http_client=http_client)
|
|
51
|
+
)
|
|
52
|
+
session = await stack.enter_async_context(ClientSession(read, write))
|
|
53
|
+
await session.initialize()
|
|
54
|
+
yield session
|
|
55
|
+
finally:
|
|
56
|
+
with suppress(Exception):
|
|
57
|
+
await stack.aclose()
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
async def with_retry(call):
|
|
61
|
+
"""Run one session-scoped operation, retrying transient failures with backoff. A call whose
|
|
62
|
+
response was lost may be replayed — MCP has no idempotency key, so tools should tolerate
|
|
63
|
+
at-least-once delivery (a tool that fails reports through its result, not an exception)."""
|
|
64
|
+
async for attempt in AsyncRetrying(
|
|
65
|
+
stop=stop_after_attempt(MCP_CALL_ATTEMPTS),
|
|
66
|
+
wait=wait_exponential_jitter(initial=0.5, max=30),
|
|
67
|
+
reraise=True,
|
|
68
|
+
):
|
|
69
|
+
with attempt:
|
|
70
|
+
return await call()
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
async def connect_mcp(config: dict) -> tuple[list[dict], dict, dict]:
|
|
74
|
+
"""Enumerate each configured MCP server's tools (a streamable-HTTP `url`); return (tool schemas,
|
|
75
|
+
dispatch mapping advertised name -> (server name, raw tool name), servers mapping name -> spec).
|
|
76
|
+
No session is held — a stateless-HTTP server is reconnected per call. Tools are advertised as
|
|
77
|
+
`<server>_<tool>`; a server named `""` (TOOL_PREFIX = None) advertises its tools bare, so names
|
|
78
|
+
must be unique across the rollout's servers."""
|
|
79
|
+
tool_schemas: list[dict] = []
|
|
80
|
+
dispatch: dict[str, tuple] = {}
|
|
81
|
+
servers: dict[str, dict] = {}
|
|
82
|
+
for name, spec in config.get("mcpServers", {}).items():
|
|
83
|
+
servers[name] = spec
|
|
84
|
+
|
|
85
|
+
async def list_tools(spec: dict = spec):
|
|
86
|
+
async with mcp_session(spec) as session:
|
|
87
|
+
return (await session.list_tools()).tools
|
|
88
|
+
|
|
89
|
+
for tool in await with_retry(list_tools):
|
|
90
|
+
full = f"{name}_{tool.name}" if name else tool.name
|
|
91
|
+
if full in dispatch:
|
|
92
|
+
raise ValueError(
|
|
93
|
+
f"duplicate tool name {full!r} across servers; keep qualified names"
|
|
94
|
+
)
|
|
95
|
+
tool_schemas.append(
|
|
96
|
+
{
|
|
97
|
+
"type": "function",
|
|
98
|
+
"function": {
|
|
99
|
+
"name": full,
|
|
100
|
+
"description": tool.description or "",
|
|
101
|
+
"parameters": tool.inputSchema,
|
|
102
|
+
},
|
|
103
|
+
}
|
|
104
|
+
)
|
|
105
|
+
dispatch[full] = (name, tool.name)
|
|
106
|
+
return tool_schemas, dispatch, servers
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def mcp_content_to_chat_content(blocks) -> str | list[dict]:
|
|
110
|
+
parts = []
|
|
111
|
+
for block in blocks:
|
|
112
|
+
if block.type == "text":
|
|
113
|
+
parts.append({"type": "text", "text": block.text})
|
|
114
|
+
elif block.type == "image":
|
|
115
|
+
url = f"data:{block.mimeType};base64,{block.data}"
|
|
116
|
+
parts.append({"type": "image_url", "image_url": {"url": url}})
|
|
117
|
+
else:
|
|
118
|
+
parts.append({"type": "text", "text": str(block)})
|
|
119
|
+
if not parts:
|
|
120
|
+
return str(blocks)
|
|
121
|
+
if all(part["type"] == "text" for part in parts):
|
|
122
|
+
return "\n".join(part["text"] for part in parts)
|
|
123
|
+
return parts
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
async def call_mcp(
|
|
127
|
+
servers: dict, dispatch: dict, name: str, arguments: dict
|
|
128
|
+
) -> str | list[dict]:
|
|
129
|
+
"""Call a tool on a fresh session per attempt — see `with_retry` for the replay semantics.
|
|
130
|
+
The result is converted outside the retry so a conversion failure fails once."""
|
|
131
|
+
server_name, raw = dispatch[name]
|
|
132
|
+
|
|
133
|
+
async def call():
|
|
134
|
+
async with mcp_session(servers[server_name]) as session:
|
|
135
|
+
return await session.call_tool(raw, arguments)
|
|
136
|
+
|
|
137
|
+
result = await with_retry(call)
|
|
138
|
+
return mcp_content_to_chat_content(result.content)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def parse_args() -> argparse.Namespace:
|
|
142
|
+
parser = argparse.ArgumentParser()
|
|
143
|
+
parser.add_argument("--base-url", required=True)
|
|
144
|
+
parser.add_argument("--api-key", required=True)
|
|
145
|
+
parser.add_argument("--model", required=True)
|
|
146
|
+
parser.add_argument("--system-prompt", default="")
|
|
147
|
+
parser.add_argument("--prompt", default="")
|
|
148
|
+
parser.add_argument("--initial-messages-file", default="")
|
|
149
|
+
parser.add_argument("--mcp-config", default="")
|
|
150
|
+
return parser.parse_args()
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
async def main() -> None:
|
|
154
|
+
args = parse_args()
|
|
155
|
+
initial = []
|
|
156
|
+
if args.initial_messages_file:
|
|
157
|
+
path = Path(args.initial_messages_file)
|
|
158
|
+
payload = path.read_bytes()
|
|
159
|
+
path.unlink()
|
|
160
|
+
initial = json.loads(payload)
|
|
161
|
+
client = AsyncOpenAI(base_url=args.base_url, api_key=args.api_key)
|
|
162
|
+
config = json.loads(args.mcp_config or "{}")
|
|
163
|
+
if config.get("mcpServers"):
|
|
164
|
+
# Bound only tool enumeration; each session is opened and closed within this task.
|
|
165
|
+
async with asyncio.timeout(60):
|
|
166
|
+
tools, dispatch, servers = await connect_mcp(config)
|
|
167
|
+
else:
|
|
168
|
+
tools, dispatch, servers = [], {}, {}
|
|
169
|
+
messages = (
|
|
170
|
+
[{"role": "system", "content": args.system_prompt}]
|
|
171
|
+
if args.system_prompt
|
|
172
|
+
else []
|
|
173
|
+
)
|
|
174
|
+
if initial:
|
|
175
|
+
messages.extend(initial)
|
|
176
|
+
elif args.prompt:
|
|
177
|
+
messages.append({"role": "user", "content": args.prompt})
|
|
178
|
+
while True:
|
|
179
|
+
message = await chat(client, args.model, messages, tools)
|
|
180
|
+
messages.append(message.model_dump(exclude_none=True))
|
|
181
|
+
if not message.tool_calls:
|
|
182
|
+
break
|
|
183
|
+
for call in message.tool_calls:
|
|
184
|
+
name = call.function.name
|
|
185
|
+
try:
|
|
186
|
+
tool_args = json.loads(call.function.arguments or "{}")
|
|
187
|
+
except json.JSONDecodeError as e:
|
|
188
|
+
messages.append(
|
|
189
|
+
{
|
|
190
|
+
"role": "tool",
|
|
191
|
+
"tool_call_id": call.id,
|
|
192
|
+
"content": f"error: invalid JSON in tool arguments ({e}); resend the call with valid JSON",
|
|
193
|
+
}
|
|
194
|
+
)
|
|
195
|
+
continue
|
|
196
|
+
# Valid JSON can still be a non-object (`[]`, `42`, `null`); the MCP dispatch
|
|
197
|
+
# assumes a dict, so reject anything else as a tool error rather than crashing.
|
|
198
|
+
if not isinstance(tool_args, dict):
|
|
199
|
+
messages.append(
|
|
200
|
+
{
|
|
201
|
+
"role": "tool",
|
|
202
|
+
"tool_call_id": call.id,
|
|
203
|
+
"content": f"error: tool arguments must be a JSON object, got {type(tool_args).__name__}; resend as an object",
|
|
204
|
+
}
|
|
205
|
+
)
|
|
206
|
+
continue
|
|
207
|
+
if name in dispatch:
|
|
208
|
+
content = await call_mcp(servers, dispatch, name, tool_args)
|
|
209
|
+
else:
|
|
210
|
+
content = f"error: unknown tool {name!r}"
|
|
211
|
+
messages.append(
|
|
212
|
+
{"role": "tool", "tool_call_id": call.id, "content": content}
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
|
|
216
|
+
if __name__ == "__main__":
|
|
217
|
+
asyncio.run(main())
|
|
@@ -346,10 +346,10 @@ class InterceptionServer(Interception):
|
|
|
346
346
|
if (
|
|
347
347
|
session.user is not None
|
|
348
348
|
and session.trace.task.data.prompt is None
|
|
349
|
-
and
|
|
349
|
+
and all(m.role != "assistant" for m in prompt)
|
|
350
350
|
):
|
|
351
351
|
if session.opening is None:
|
|
352
|
-
session.opening = await session.user("")
|
|
352
|
+
session.opening = await session.user("", len(prompt))
|
|
353
353
|
body = dialect.extend(body, None, session.opening)
|
|
354
354
|
prompt = [*prompt, *session.opening]
|
|
355
355
|
# If the simulator ended at the open (its task's `@stop` now fires), the loop's
|
|
@@ -498,8 +498,11 @@ class InterceptionServer(Interception):
|
|
|
498
498
|
# when there's no user simulator to keep the conversation going.
|
|
499
499
|
if response.message.tool_calls or session.user is None:
|
|
500
500
|
return serve(response)
|
|
501
|
+
prompt = [*prompt, response.message]
|
|
501
502
|
try:
|
|
502
|
-
user_messages = await session.user(
|
|
503
|
+
user_messages = await session.user(
|
|
504
|
+
response.message.content or "", len(prompt)
|
|
505
|
+
)
|
|
503
506
|
except RolloutError as e:
|
|
504
507
|
return self._fail(session, dialect, e)
|
|
505
508
|
except Exception as e:
|
|
@@ -515,7 +518,7 @@ class InterceptionServer(Interception):
|
|
|
515
518
|
# `self.state`), caught by `refused()` at the top of the next iteration — the
|
|
516
519
|
# interception server holds no opinion about the state's contents.
|
|
517
520
|
body = dialect.extend(body, response.raw, user_messages)
|
|
518
|
-
prompt = [*prompt,
|
|
521
|
+
prompt = [*prompt, *user_messages]
|
|
519
522
|
# The simulator changed the payload, so this is a new operation not a retry.
|
|
520
523
|
headers.popall("idempotency-key", None)
|
|
521
524
|
headers.popall("x-idempotency-key", None)
|
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from verifiers.v1.mcp.launch import (
|
|
4
4
|
Respond,
|
|
5
|
-
connect_user,
|
|
6
5
|
serve,
|
|
7
6
|
SharedToolServer,
|
|
8
7
|
serve_shared,
|
|
9
8
|
serve_tools,
|
|
10
9
|
serve_user,
|
|
10
|
+
user_respond,
|
|
11
11
|
)
|
|
12
12
|
from verifiers.v1.mcp.server import ServerBase
|
|
13
13
|
from verifiers.v1.mcp.toolset import SharedToolsetConfig, Toolset, ToolsetConfig
|
|
@@ -21,10 +21,10 @@ __all__ = [
|
|
|
21
21
|
"User",
|
|
22
22
|
"UserConfig",
|
|
23
23
|
"Respond",
|
|
24
|
-
"connect_user",
|
|
25
24
|
"serve",
|
|
26
25
|
"SharedToolServer",
|
|
27
26
|
"serve_shared",
|
|
28
27
|
"serve_tools",
|
|
29
28
|
"serve_user",
|
|
29
|
+
"user_respond",
|
|
30
30
|
]
|