verifiers 0.2.2.dev61__tar.gz → 0.2.2.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.2.dev61 → verifiers-0.2.2.dev63}/PKG-INFO +1 -1
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/agent.py +4 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/env.py +7 -1
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/interception/__init__.py +7 -4
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/interception/base.py +3 -5
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/interception/pool.py +14 -6
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/interception/server.py +39 -27
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/mcp/launch.py +85 -25
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/mcp/server.py +51 -14
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/rollout.py +14 -4
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/.gitignore +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/LICENSE +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/README.md +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/pyproject.toml +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/conftest.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_browser_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_build_script.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_cli_agent_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_client_auth_errors.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_client_config.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_client_multimodal_types.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_composable_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_context_token_metrics.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_decorator_ranks.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_endpoint_registry.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_env_group.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_env_server.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_environment.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_environment_extra.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_error_chain.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_eval_display.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_eval_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_gepa_cli.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_gepa_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_gym_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_harbor_env_mcp.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_imports.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_init_script.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_install_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_interception_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_logging.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_math_rubric.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_maybe_think_parser.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_message_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_message_utils_multimodal.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_multiturn_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_nemorl_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_openai_chat_completions_token_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_openai_responses_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_opencode_rlm_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_openenv_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_parser.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_path_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_per_turn_timing.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_pricing_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_prime_plugin.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_renderer_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_renderer_e2e.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_rlm_composable_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_rubric.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_rubric_group.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_sandbox_debug_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_sandbox_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_sandbox_mixin.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_save_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_setup_script.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_singleturn_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_stateful_tool_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_think_parser.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_tool_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_tool_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_trajectory_processing.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_tui_info_formatting.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_types.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/test_xml_parser.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/conftest.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/fixtures/counter_tool_v1.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/fixtures/duet_v1.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/fixtures/echo_acp_resume_v1.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/fixtures/echo_multi_v0.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/fixtures/echo_tool_v1.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/fixtures/echo_v0.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/fixtures/echo_v1.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/fixtures/pyproject.toml +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/test_color_codeword_tasks.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/test_configs.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/test_e2e.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/test_envs.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/test_graph.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/test_judges.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/test_legacy.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/test_scoring.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/test_taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/tests/v1/test_trace.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/cli/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/cli/commands/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/cli/commands/build.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/cli/commands/eval.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/cli/commands/gepa.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/cli/commands/init.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/cli/commands/install.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/cli/commands/setup.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/cli/plugins/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/cli/plugins/prime.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/cli/tui.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/clients/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/clients/anthropic_messages_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/clients/client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/clients/nemorl_chat_completions_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/clients/openai_chat_completions_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/clients/openai_chat_completions_token_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/clients/openai_completions_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/clients/openai_responses_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/clients/renderer_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/decorators.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/env_group.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/environment.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/README.md +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/cli_agent_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/README.md +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/_filter.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/composable_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/harnesses/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/harnesses/mini_swe_agent.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/harnesses/opencode.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/harnesses/prompt.txt +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/harnesses/rlm.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/sandbox_debug_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/swe_debug_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/task.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/cp/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/cp/cp_task.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/cp/test_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/harbor/cli_gym.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/harbor/harbor.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/harbor/terminal_lego.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/math/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/math/math_task.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/README.md +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/extract_fix_patch.sh +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/openswe/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/openswe/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/log_parser.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/shared/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/shared/test_patch.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/log_parsers.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/composable/tasksets/swe/swe_tasksets.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/gym_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/harbor_env/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/harbor_env/env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/harbor_env/mcp.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/mcp_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/opencode_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/opencode_qa_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/opencode_rlm_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/sandbox_mixin.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/utils/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/utils/file_locks.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/experimental/utils/git_checkout_cache.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/README.md +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/browser_env/README.md +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/browser_env/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/browser_env/browser_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/browser_env/modes/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/browser_env/modes/base.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/browser_env/modes/cua_mode.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/browser_env/modes/dom_mode.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/openenv_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/reasoninggym_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/integrations/textarena_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/multiturn_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/python_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/sandbox_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/singleturn_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/stateful_tool_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/envs/tool_env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/errors.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/gepa/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/gepa/adapter.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/gepa/config.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/gepa/display.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/gepa/gepa_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/parsers/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/parsers/maybe_think_parser.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/parsers/parser.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/parsers/think_parser.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/parsers/xml_parser.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/rubrics/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/rubrics/experimental/hybrid_math_rubric.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/rubrics/judge_rubric.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/rubrics/math_rubric.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/rubrics/rubric.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/rubrics/rubric_group.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/scripts/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/scripts/build.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/scripts/eval.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/scripts/gepa.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/scripts/init.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/scripts/install.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/scripts/setup.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/scripts/tui.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/serve/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/serve/client/env_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/serve/client/zmq_env_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/serve/server/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/serve/server/env_router.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/serve/server/env_server.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/serve/server/env_worker.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/serve/server/zmq_env_server.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/serve/types.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/types.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/async_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/client_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/config_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/data_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/display_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/env_config_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/env_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/error_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/eval_display.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/eval_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/heartbeat.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/import_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/install_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/interception_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/logging_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/message_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/metric_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/path_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/pricing_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/process_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/response_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/save_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/serve_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/thread_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/threaded_sandbox_client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/tool_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/usage_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/utils/version_utils.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/acp/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/acp/_runner.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/artifacts.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/dashboard/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/dashboard/base.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/dashboard/eval.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/dashboard/replay.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/dashboard/validate.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/debug.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/eval/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/eval/main.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/eval/resume.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/eval/runner.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/gepa.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/init.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/replay.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/serve.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/cli/validate.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/clients/config.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/agent.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/cli/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/cli/debug.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/cli/env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/cli/eval.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/cli/init.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/cli/replay.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/cli/serve.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/cli/validate.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/judge.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/legacy.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/retries.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/serve.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/task.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/configs/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/decorators.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/dialects/anthropic.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/dialects/base.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/dialects/chat.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/dialects/responses.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/envs/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/envs/agentic_judge/env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/envs/best_of_n/env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/envs/single_agent/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/envs/single_agent/env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/envs/user_sim/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/envs/user_sim/env.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/episode.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/errors.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/gepa/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/gepa/adapter.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/gepa/config.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/gepa/dataset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/gepa/reflection.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/gepa/runner.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/graph.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/bash/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/bash/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/bash/program.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/browser_use/program.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/codex/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/null/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/null/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/null/program.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/pi/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/pi/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/pool/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/pool/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/rlm/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/interception/tunnel/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/interception/tunnel/base.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/interception/tunnel/custom.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/interception/tunnel/prime.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/judge.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/judges/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/judges/reference.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/judges/reference.txt +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/judges/rubric.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/judges/rubric.txt +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/legacy.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/loaders.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/mcp/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/mcp/toolset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/push.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/retries.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/runtimes/base.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/runtimes/docker/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/runtimes/docker/egress.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/runtimes/limiters.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/runtimes/modal.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/runtimes/prime.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/runtimes/subprocess.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/scoring.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/serve/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/serve/client.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/serve/pool.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/serve/server.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/serve/types.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/session.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/state.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/task.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/tasksets/lean/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/tasksets/lean/scoring.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/tasksets/lean/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/trace.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/types.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/aio.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/compile.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/generic.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/git.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/image.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/install.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/interrupt.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/memory.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.dev63}/verifiers/v1/utils/sampling.py +0 -0
- {verifiers-0.2.2.dev61 → verifiers-0.2.2.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.2.
|
|
3
|
+
Version: 0.2.2.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
|
|
@@ -334,6 +334,10 @@ class Agent:
|
|
|
334
334
|
return self.interception
|
|
335
335
|
if self._server is None:
|
|
336
336
|
return None
|
|
337
|
+
if any(tool.state_secret for tool in shared_tools.values()):
|
|
338
|
+
# Shared state credentials are attached per run, after this owned
|
|
339
|
+
# server was created; let the rollout size a scoped server instead.
|
|
340
|
+
return None
|
|
337
341
|
if self._server.tunnel is not None or (
|
|
338
342
|
run_is_local and not shared_tools and not task.toolsets(task.config)
|
|
339
343
|
):
|
|
@@ -350,7 +350,13 @@ class Env(ABC, Generic[ConfigT]):
|
|
|
350
350
|
run slots inside. Torn down on exit (`teardown()`, then the framework's)."""
|
|
351
351
|
async with self.shared_tools() as shared:
|
|
352
352
|
interception = make_interception(
|
|
353
|
-
self.config.interception,
|
|
353
|
+
self.config.interception,
|
|
354
|
+
requires_tunnel=self._requires_tunnel(shared),
|
|
355
|
+
state_service_secrets=tuple(
|
|
356
|
+
server.state_secret
|
|
357
|
+
for server in shared.values()
|
|
358
|
+
if server.state_secret
|
|
359
|
+
),
|
|
354
360
|
)
|
|
355
361
|
async with interception:
|
|
356
362
|
self._shared_tools = shared
|
|
@@ -54,16 +54,19 @@ def requires_tunnel(
|
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
def make_interception(
|
|
57
|
-
config: InterceptionConfig,
|
|
57
|
+
config: InterceptionConfig,
|
|
58
|
+
*,
|
|
59
|
+
requires_tunnel: bool,
|
|
60
|
+
state_service_secrets: tuple[str, ...] = (),
|
|
58
61
|
) -> Interception:
|
|
59
62
|
"""The interception for a config, picked by type (the host-side counterpart to
|
|
60
63
|
`make_runtime`). With `requires_tunnel`, each server is exposed through its configured
|
|
61
64
|
tunnel; otherwise it remains on host loopback. The caller computes this requirement."""
|
|
62
65
|
if isinstance(config, InterceptionServerConfig):
|
|
63
|
-
return InterceptionServer(config, requires_tunnel)
|
|
66
|
+
return InterceptionServer(config, requires_tunnel, state_service_secrets)
|
|
64
67
|
if isinstance(config, StaticInterceptionPoolConfig):
|
|
65
|
-
return StaticInterceptionPool(config, requires_tunnel)
|
|
66
|
-
return ElasticInterceptionPool(config, requires_tunnel)
|
|
68
|
+
return StaticInterceptionPool(config, requires_tunnel, state_service_secrets)
|
|
69
|
+
return ElasticInterceptionPool(config, requires_tunnel, state_service_secrets)
|
|
67
70
|
|
|
68
71
|
|
|
69
72
|
__all__ = [
|
|
@@ -26,12 +26,10 @@ class BaseInterceptionConfig(BaseConfig):
|
|
|
26
26
|
`multiplex`)."""
|
|
27
27
|
|
|
28
28
|
|
|
29
|
-
# (base_url,
|
|
30
|
-
#
|
|
31
|
-
# `{base_url}/v1`; tool servers reach this rollout's shared state at `{base_url}/state`
|
|
32
|
-
# + `/task`. `base_url` is universally reachable — the interception is exposed (tunnel)
|
|
29
|
+
# (base_url, model_secret, state_secret): model inference and task state deliberately use
|
|
30
|
+
# separate capabilities. `base_url` is universally reachable — the interception is exposed
|
|
33
31
|
# whenever any consumer is remote.
|
|
34
|
-
Slot = tuple[str, str]
|
|
32
|
+
Slot = tuple[str, str, str]
|
|
35
33
|
|
|
36
34
|
|
|
37
35
|
class Interception(ABC):
|
|
@@ -48,12 +48,16 @@ class StaticInterceptionPool(Interception):
|
|
|
48
48
|
operator's call (it's the shape for pre-provisioned/bring-your-own endpoints)."""
|
|
49
49
|
|
|
50
50
|
def __init__(
|
|
51
|
-
self,
|
|
51
|
+
self,
|
|
52
|
+
config: StaticInterceptionPoolConfig,
|
|
53
|
+
requires_tunnel: bool = False,
|
|
54
|
+
state_service_secrets: tuple[str, ...] = (),
|
|
52
55
|
) -> None:
|
|
53
56
|
super().__init__()
|
|
54
57
|
self.config = config
|
|
55
58
|
self.servers = [
|
|
56
|
-
InterceptionServer(server, requires_tunnel)
|
|
59
|
+
InterceptionServer(server, requires_tunnel, state_service_secrets)
|
|
60
|
+
for server in config.servers
|
|
57
61
|
]
|
|
58
62
|
|
|
59
63
|
async def start(self) -> None:
|
|
@@ -89,10 +93,12 @@ class ElasticInterceptionPool(Interception):
|
|
|
89
93
|
self,
|
|
90
94
|
config: ElasticInterceptionPoolConfig | None = None,
|
|
91
95
|
requires_tunnel: bool = False,
|
|
96
|
+
state_service_secrets: tuple[str, ...] = (),
|
|
92
97
|
) -> None:
|
|
93
98
|
super().__init__()
|
|
94
99
|
self.config = config or ElasticInterceptionPoolConfig()
|
|
95
100
|
self.requires_tunnel = requires_tunnel
|
|
101
|
+
self.state_service_secrets = state_service_secrets
|
|
96
102
|
self.servers: list[InterceptionServer] = []
|
|
97
103
|
self._lock = asyncio.Lock()
|
|
98
104
|
self._warm_task: asyncio.Task[InterceptionServer] | None = None
|
|
@@ -116,7 +122,9 @@ class ElasticInterceptionPool(Interception):
|
|
|
116
122
|
return server
|
|
117
123
|
# Pin prime explicitly — the only tunnel kind that can be minted on demand.
|
|
118
124
|
server = InterceptionServer(
|
|
119
|
-
InterceptionServerConfig(tunnel=PrimeTunnelConfig()),
|
|
125
|
+
InterceptionServerConfig(tunnel=PrimeTunnelConfig()),
|
|
126
|
+
self.requires_tunnel,
|
|
127
|
+
self.state_service_secrets,
|
|
120
128
|
)
|
|
121
129
|
await self.stack.enter_async_context(server)
|
|
122
130
|
self.servers.append(server)
|
|
@@ -136,8 +144,8 @@ class ElasticInterceptionPool(Interception):
|
|
|
136
144
|
# Register under the lock so concurrent acquires see each other's load.
|
|
137
145
|
async with self._lock:
|
|
138
146
|
server = await self._server()
|
|
139
|
-
|
|
147
|
+
model_secret, state_secret = server.register(session)
|
|
140
148
|
try:
|
|
141
|
-
yield server.base_url,
|
|
149
|
+
yield server.base_url, model_secret, state_secret
|
|
142
150
|
finally:
|
|
143
|
-
server.unregister(
|
|
151
|
+
server.unregister(model_secret, state_secret)
|
|
@@ -6,10 +6,10 @@ into the trace's message graph, and returns the result in OpenAI shape. We injec
|
|
|
6
6
|
`OPENAI_BASE_URL`/`OPENAI_API_KEY` so the program's SDK talks to us. Both non-streaming and
|
|
7
7
|
SSE requests are supported.
|
|
8
8
|
|
|
9
|
-
One server multiplexes many rollouts: each rollout registers
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
One server multiplexes many rollouts: each rollout registers separate model and state
|
|
10
|
+
capabilities, and the server routes each to the right session. So N rollouts need one
|
|
11
|
+
server (and, behind a remote runtime, one tunnel) per pool member rather than one each —
|
|
12
|
+
see `interception.pool`.
|
|
13
13
|
|
|
14
14
|
The server is a pure model boundary: one request, one turn — refusal checks (limits,
|
|
15
15
|
`@stop`s), the model call, the graph commit, retry atomicity. A run's user exchange
|
|
@@ -25,7 +25,7 @@ import logging
|
|
|
25
25
|
import secrets
|
|
26
26
|
import time
|
|
27
27
|
import traceback
|
|
28
|
-
from collections.abc import AsyncIterator
|
|
28
|
+
from collections.abc import AsyncIterator, Collection
|
|
29
29
|
from contextlib import asynccontextmanager
|
|
30
30
|
from typing import Literal
|
|
31
31
|
|
|
@@ -126,9 +126,13 @@ class InterceptionServer(Interception):
|
|
|
126
126
|
self,
|
|
127
127
|
config: InterceptionServerConfig | None = None,
|
|
128
128
|
requires_tunnel: bool = False,
|
|
129
|
+
state_service_secrets: Collection[str] = (),
|
|
129
130
|
) -> None:
|
|
130
131
|
super().__init__()
|
|
131
132
|
self.sessions: dict[str, RolloutSession] = {}
|
|
133
|
+
self.state_sessions: dict[str, RolloutSession] = {}
|
|
134
|
+
self.state_routes: dict[str, RolloutSession] = {}
|
|
135
|
+
self.state_service_secrets = frozenset(state_service_secrets)
|
|
132
136
|
self.config = config or InterceptionServerConfig()
|
|
133
137
|
self.tunnel: Tunnel | None = (
|
|
134
138
|
make_tunnel(self.config.tunnel) if requires_tunnel else None
|
|
@@ -143,16 +147,20 @@ class InterceptionServer(Interception):
|
|
|
143
147
|
"""Rollouts currently registered — what the pools balance on."""
|
|
144
148
|
return len(self.sessions)
|
|
145
149
|
|
|
146
|
-
def register(self, session: RolloutSession) -> str:
|
|
147
|
-
"""
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
self.sessions[
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
150
|
+
def register(self, session: RolloutSession) -> tuple[str, str]:
|
|
151
|
+
"""Register separate capabilities for model inference and private task state."""
|
|
152
|
+
model_secret = secrets.token_urlsafe(16)
|
|
153
|
+
state_secret = secrets.token_urlsafe(16)
|
|
154
|
+
self.sessions[model_secret] = session
|
|
155
|
+
self.state_sessions[state_secret] = session
|
|
156
|
+
self.state_routes[session.trace.id] = session
|
|
157
|
+
return model_secret, state_secret
|
|
158
|
+
|
|
159
|
+
def unregister(self, model_secret: str, state_secret: str) -> None:
|
|
160
|
+
session = self.sessions.pop(model_secret, None)
|
|
161
|
+
self.state_sessions.pop(state_secret, None)
|
|
155
162
|
if session is not None:
|
|
163
|
+
self.state_routes.pop(session.trace.id, None)
|
|
156
164
|
# The rollout concluded; its trace is sealed. Cancel straggler handlers
|
|
157
165
|
# (aiohttp keeps them alive past client death) so a slow upstream call
|
|
158
166
|
# can't commit a late turn onto the concluded trace.
|
|
@@ -160,11 +168,11 @@ class InterceptionServer(Interception):
|
|
|
160
168
|
|
|
161
169
|
@asynccontextmanager
|
|
162
170
|
async def acquire(self, session: RolloutSession) -> AsyncIterator[Slot]:
|
|
163
|
-
|
|
171
|
+
model_secret, state_secret = self.register(session)
|
|
164
172
|
try:
|
|
165
|
-
yield self.base_url,
|
|
173
|
+
yield self.base_url, model_secret, state_secret
|
|
166
174
|
finally:
|
|
167
|
-
self.unregister(
|
|
175
|
+
self.unregister(model_secret, state_secret)
|
|
168
176
|
|
|
169
177
|
def _handler_for(self, dialect: Dialect):
|
|
170
178
|
"""Bind a route's dialect to the request handler — the route the SDK posts to is what
|
|
@@ -188,12 +196,11 @@ class InterceptionServer(Interception):
|
|
|
188
196
|
app.router.add_post(route, self._handler_for(dialect))
|
|
189
197
|
for aux in dialect.aux_routes:
|
|
190
198
|
app.router.add_post(aux, self._aux_handler_for(dialect, aux))
|
|
191
|
-
#
|
|
192
|
-
# GET/PUT their `self.state` here, keyed by the same bearer secret as the model routes.
|
|
199
|
+
# Tool servers use a state-only capability; the model bearer cannot reach these.
|
|
193
200
|
app.router.add_get("/state", self.handle_state_get)
|
|
194
201
|
app.router.add_put("/state", self.handle_state_put)
|
|
195
202
|
# A launched tool server fetches its rollout's task here to run `setup_task` — the task
|
|
196
|
-
# is never passed via env, only over this channel, keyed by the
|
|
203
|
+
# is never passed via env, only over this channel, keyed by the state bearer.
|
|
197
204
|
app.router.add_get("/task", self.handle_task_get)
|
|
198
205
|
self.runner = web.AppRunner(app)
|
|
199
206
|
await self.runner.setup()
|
|
@@ -705,12 +712,17 @@ class InterceptionServer(Interception):
|
|
|
705
712
|
return web.json_response(dialect.error_body(str(e)), status=502)
|
|
706
713
|
return web.json_response(result)
|
|
707
714
|
|
|
708
|
-
def _session_for(
|
|
709
|
-
|
|
710
|
-
|
|
715
|
+
def _session_for(
|
|
716
|
+
self, request: web.Request, *, allow_service: bool = False
|
|
717
|
+
) -> RolloutSession | None:
|
|
718
|
+
"""Resolve a private state bearer, or a trusted shared server plus route id."""
|
|
711
719
|
auth = request.headers.get("Authorization", "")
|
|
712
720
|
secret = auth[len("Bearer ") :] if auth.startswith("Bearer ") else ""
|
|
713
|
-
session = self.
|
|
721
|
+
session = self.state_sessions.get(secret)
|
|
722
|
+
if session is None and allow_service and secret in self.state_service_secrets:
|
|
723
|
+
session = self.state_routes.get(
|
|
724
|
+
request.headers.get("X-Verifiers-State-Route", "")
|
|
725
|
+
)
|
|
714
726
|
if session is not None: # state writes must not land on a sealed trace either
|
|
715
727
|
session.adopt(asyncio.current_task())
|
|
716
728
|
return session
|
|
@@ -718,7 +730,7 @@ class InterceptionServer(Interception):
|
|
|
718
730
|
async def handle_state_get(self, request: web.Request) -> web.Response:
|
|
719
731
|
"""Hand a rollout's tool server the current shared `trace.state` (it pulls before each
|
|
720
732
|
`@vf.tool` call, so it sees writes from the other servers)."""
|
|
721
|
-
session = self._session_for(request)
|
|
733
|
+
session = self._session_for(request, allow_service=True)
|
|
722
734
|
if session is None:
|
|
723
735
|
return web.json_response({"error": "unauthorized"}, status=401)
|
|
724
736
|
logger.debug("intercept GET /state: id=%s", session.trace.id)
|
|
@@ -732,7 +744,7 @@ class InterceptionServer(Interception):
|
|
|
732
744
|
|
|
733
745
|
async def handle_task_get(self, request: web.Request) -> web.Response:
|
|
734
746
|
"""Hand a launched tool server the rollout's task (class ref + JSON) so it can run
|
|
735
|
-
`setup_task` for this rollout — keyed by
|
|
747
|
+
`setup_task` for this rollout — keyed by its private state bearer."""
|
|
736
748
|
session = self._session_for(request)
|
|
737
749
|
if session is None:
|
|
738
750
|
return web.json_response({"error": "unauthorized"}, status=401)
|
|
@@ -749,7 +761,7 @@ class InterceptionServer(Interception):
|
|
|
749
761
|
"""Replace a rollout's shared `trace.state` with a server's pushed copy (validated into the
|
|
750
762
|
trace's `State` type). Last write wins per call. A task ends the trajectory from state via
|
|
751
763
|
its own `@stop` (run in `RolloutSession.refused` before each model call)."""
|
|
752
|
-
session = self._session_for(request)
|
|
764
|
+
session = self._session_for(request, allow_service=True)
|
|
753
765
|
if session is None:
|
|
754
766
|
return web.json_response({"error": "unauthorized"}, status=401)
|
|
755
767
|
logger.debug("intercept PUT /state: id=%s", session.trace.id)
|
|
@@ -5,12 +5,13 @@ import contextlib
|
|
|
5
5
|
import importlib.metadata
|
|
6
6
|
import io
|
|
7
7
|
import logging
|
|
8
|
+
import secrets
|
|
8
9
|
import shlex
|
|
9
10
|
import sys
|
|
10
11
|
import tarfile
|
|
11
12
|
import uuid
|
|
12
13
|
from collections.abc import AsyncIterator
|
|
13
|
-
from dataclasses import dataclass
|
|
14
|
+
from dataclasses import dataclass, field
|
|
14
15
|
from functools import cache
|
|
15
16
|
from pathlib import Path
|
|
16
17
|
from typing import TYPE_CHECKING
|
|
@@ -18,14 +19,20 @@ from urllib.parse import parse_qsl, urlencode, urlsplit, urlunsplit
|
|
|
18
19
|
|
|
19
20
|
from verifiers.v1.errors import ToolsetError
|
|
20
21
|
from verifiers.v1.interception.tunnel import PrimeTunnel
|
|
21
|
-
from verifiers.v1.mcp.server import
|
|
22
|
+
from verifiers.v1.mcp.server import (
|
|
23
|
+
STATE_ROUTE_PARAM,
|
|
24
|
+
STATE_SIGNATURE_PARAM,
|
|
25
|
+
STATE_URL_PARAM,
|
|
26
|
+
ServerBase,
|
|
27
|
+
state_signature,
|
|
28
|
+
)
|
|
22
29
|
from verifiers.v1.runtimes import (
|
|
23
30
|
NetworkPolicyConfig,
|
|
24
31
|
Runtime,
|
|
25
32
|
make_runtime,
|
|
26
|
-
runtime_is_local,
|
|
27
33
|
)
|
|
28
34
|
from verifiers.v1.runtimes.base import _ENSURE_UV
|
|
35
|
+
from verifiers.v1.state import State
|
|
29
36
|
|
|
30
37
|
if TYPE_CHECKING:
|
|
31
38
|
from verifiers.v1.mcp.toolset import Toolset
|
|
@@ -170,14 +177,17 @@ async def serve_in_runtime(
|
|
|
170
177
|
the OS choose and report the result through a file. With a state channel, the server fetches
|
|
171
178
|
the current rollout task from the adjacent `/task` endpoint rather than a launch argument.
|
|
172
179
|
"""
|
|
173
|
-
|
|
180
|
+
# A shared server has a private service secret but no fixed state URL. Set
|
|
181
|
+
# both controls explicitly so a subprocess cannot inherit stale host values.
|
|
182
|
+
env = {
|
|
183
|
+
"VF_CONFIG": server.config.model_dump_json(),
|
|
184
|
+
"VF_STATE_URL": state_url or "",
|
|
185
|
+
"VF_STATE_SECRET": state_secret,
|
|
186
|
+
}
|
|
174
187
|
if runtime.type == "subprocess":
|
|
175
188
|
# Keep provider temp files in the runtime workdir so cleanup removes them.
|
|
176
189
|
assert runtime.info.id is not None
|
|
177
190
|
env["TMPDIR"] = runtime.info.id
|
|
178
|
-
if state_url:
|
|
179
|
-
env["VF_STATE_URL"] = state_url
|
|
180
|
-
env["VF_STATE_SECRET"] = state_secret
|
|
181
191
|
if runtime.published_port is not None:
|
|
182
192
|
env["MCP_HOST"] = "0.0.0.0"
|
|
183
193
|
fixed = runtime.published_port if exposed else None
|
|
@@ -240,8 +250,14 @@ async def reachable_url(
|
|
|
240
250
|
yield url
|
|
241
251
|
|
|
242
252
|
|
|
253
|
+
@dataclass(frozen=True)
|
|
254
|
+
class _ServedServer:
|
|
255
|
+
url: str
|
|
256
|
+
runtime: Runtime
|
|
257
|
+
|
|
258
|
+
|
|
243
259
|
@contextlib.asynccontextmanager
|
|
244
|
-
async def
|
|
260
|
+
async def _serve(
|
|
245
261
|
server: ServerBase,
|
|
246
262
|
harness_runtime: Runtime | None = None,
|
|
247
263
|
harness_is_local: bool = True,
|
|
@@ -307,7 +323,27 @@ async def serve(
|
|
|
307
323
|
base = base.replace("127.0.0.1", "localhost", 1)
|
|
308
324
|
elif not colocated and harness_runtime is not None:
|
|
309
325
|
base = harness_runtime.host_url(base)
|
|
310
|
-
yield f"{base.rstrip('/')}/mcp"
|
|
326
|
+
yield _ServedServer(f"{base.rstrip('/')}/mcp", runtime)
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
@contextlib.asynccontextmanager
|
|
330
|
+
async def serve(
|
|
331
|
+
server: ServerBase,
|
|
332
|
+
harness_runtime: Runtime | None = None,
|
|
333
|
+
harness_is_local: bool = True,
|
|
334
|
+
*,
|
|
335
|
+
state_secret: str = "",
|
|
336
|
+
state_base: str | None = None,
|
|
337
|
+
):
|
|
338
|
+
"""Serve one MCP server and yield the URL visible to its consumer."""
|
|
339
|
+
async with _serve(
|
|
340
|
+
server,
|
|
341
|
+
harness_runtime,
|
|
342
|
+
harness_is_local,
|
|
343
|
+
state_secret=state_secret,
|
|
344
|
+
state_base=state_base,
|
|
345
|
+
) as served:
|
|
346
|
+
yield served.url
|
|
311
347
|
|
|
312
348
|
|
|
313
349
|
@dataclass(frozen=True)
|
|
@@ -315,7 +351,8 @@ class SharedToolServer:
|
|
|
315
351
|
"""One live taskset-scoped (shared) server, as the rollouts see it: its eval-level
|
|
316
352
|
`url` plus whether its runtime is `local` (host-reachable) — a remote one is an
|
|
317
353
|
interception consumer, so the interception must be exposed for it to reach the
|
|
318
|
-
`/state` channel (see `Env._requires_tunnel`).
|
|
354
|
+
`/state` channel (see `Env._requires_tunnel`). `runtime` is retained for translating
|
|
355
|
+
that channel into the server's network. An `external` server (a
|
|
319
356
|
config-`url` endpoint) was not launched by the framework and sits outside its state
|
|
320
357
|
machinery entirely: rollouts get its URL bare — no state tag (and no per-rollout
|
|
321
358
|
secret sent to a third party)."""
|
|
@@ -323,6 +360,8 @@ class SharedToolServer:
|
|
|
323
360
|
url: str
|
|
324
361
|
local: bool
|
|
325
362
|
external: bool = False
|
|
363
|
+
runtime: Runtime | None = field(default=None, repr=False)
|
|
364
|
+
state_secret: str = field(default="", repr=False)
|
|
326
365
|
|
|
327
366
|
|
|
328
367
|
@contextlib.asynccontextmanager
|
|
@@ -359,24 +398,45 @@ async def serve_shared(toolsets: list[Toolset], harness_is_local: bool = True):
|
|
|
359
398
|
url=cfg.url, local=False, external=True
|
|
360
399
|
)
|
|
361
400
|
else:
|
|
362
|
-
|
|
363
|
-
|
|
401
|
+
state_secret = (
|
|
402
|
+
secrets.token_urlsafe(24) if toolset._state_cls is not State else ""
|
|
403
|
+
)
|
|
404
|
+
served = await stack.enter_async_context(
|
|
405
|
+
_serve(
|
|
406
|
+
toolset,
|
|
407
|
+
harness_is_local=harness_is_local,
|
|
408
|
+
state_secret=state_secret,
|
|
409
|
+
)
|
|
364
410
|
)
|
|
365
411
|
servers[name] = SharedToolServer(
|
|
366
|
-
url=url,
|
|
412
|
+
url=served.url,
|
|
413
|
+
local=served.runtime.is_local,
|
|
414
|
+
runtime=served.runtime,
|
|
415
|
+
state_secret=state_secret,
|
|
367
416
|
)
|
|
368
417
|
logger.info("shared tool server '%s': %s", name, servers[name].url)
|
|
369
418
|
yield servers
|
|
370
419
|
|
|
371
420
|
|
|
372
|
-
def _shared_url_for_rollout(
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
421
|
+
def _shared_url_for_rollout(
|
|
422
|
+
server: SharedToolServer,
|
|
423
|
+
visible_url: str,
|
|
424
|
+
state_base: str | None,
|
|
425
|
+
state_route: str,
|
|
426
|
+
) -> str:
|
|
427
|
+
"""Attach signed state coordinates; the shared server keeps its bearer private."""
|
|
428
|
+
if not state_base or not server.state_secret:
|
|
429
|
+
return visible_url
|
|
430
|
+
state_url = f"{state_base.rstrip('/')}/state"
|
|
431
|
+
if server.runtime is not None:
|
|
432
|
+
state_url = server.runtime.host_url(state_url)
|
|
433
|
+
parts = urlsplit(visible_url)
|
|
377
434
|
query = dict(parse_qsl(parts.query))
|
|
378
|
-
query[STATE_URL_PARAM] =
|
|
379
|
-
query[
|
|
435
|
+
query[STATE_URL_PARAM] = state_url
|
|
436
|
+
query[STATE_ROUTE_PARAM] = state_route
|
|
437
|
+
query[STATE_SIGNATURE_PARAM] = state_signature(
|
|
438
|
+
server.state_secret, state_url, state_route
|
|
439
|
+
)
|
|
380
440
|
return urlunsplit(parts._replace(query=urlencode(query)))
|
|
381
441
|
|
|
382
442
|
|
|
@@ -387,6 +447,7 @@ async def serve_tools(
|
|
|
387
447
|
shared: dict[str, SharedToolServer] | None = None,
|
|
388
448
|
*,
|
|
389
449
|
state_secret: str = "",
|
|
450
|
+
state_route: str = "",
|
|
390
451
|
state_base: str | None = None,
|
|
391
452
|
):
|
|
392
453
|
"""Bring up a rollout's tool servers and yield `{name: url}` the harness reaches: the
|
|
@@ -394,9 +455,9 @@ async def serve_tools(
|
|
|
394
455
|
server fetches its task over the interception `/task` channel), and the
|
|
395
456
|
taskset-scoped `shared` servers — already
|
|
396
457
|
running eval-level (see `serve_shared`) — join under their per-rollout state tag.
|
|
397
|
-
`
|
|
398
|
-
|
|
399
|
-
`
|
|
458
|
+
`state_secret` is private to task-scoped servers; shared servers keep an
|
|
459
|
+
eval-level service secret and receive only signed `state_route` coordinates.
|
|
460
|
+
`state_base` is universally reachable from either placement."""
|
|
400
461
|
urls: dict[str, str] = {}
|
|
401
462
|
async with contextlib.AsyncExitStack() as stack:
|
|
402
463
|
for name, server in (shared or {}).items():
|
|
@@ -408,8 +469,7 @@ async def serve_tools(
|
|
|
408
469
|
logger.info("tool server '%s' (shared, external): %s", name, server.url)
|
|
409
470
|
continue
|
|
410
471
|
url = harness_runtime.host_url(server.url) if server.local else server.url
|
|
411
|
-
urls[name] = _shared_url_for_rollout(url, state_base,
|
|
412
|
-
# The tagged URL contains the bearer secret; log only the untagged base URL.
|
|
472
|
+
urls[name] = _shared_url_for_rollout(server, url, state_base, state_route)
|
|
413
473
|
logger.info("tool server '%s' (shared): %s", name, server.url)
|
|
414
474
|
for toolset in toolsets:
|
|
415
475
|
name = toolset.server_name
|
|
@@ -3,6 +3,8 @@ from __future__ import annotations
|
|
|
3
3
|
import contextlib
|
|
4
4
|
import contextvars
|
|
5
5
|
import functools
|
|
6
|
+
import hashlib
|
|
7
|
+
import hmac
|
|
6
8
|
import inspect
|
|
7
9
|
import logging
|
|
8
10
|
import os
|
|
@@ -32,6 +34,7 @@ async def _channel_request(
|
|
|
32
34
|
url: str,
|
|
33
35
|
secret: str,
|
|
34
36
|
*,
|
|
37
|
+
route: str | None = None,
|
|
35
38
|
content: bytes | None = None,
|
|
36
39
|
client: AsyncClient | None = None,
|
|
37
40
|
) -> Response:
|
|
@@ -57,6 +60,8 @@ async def _channel_request(
|
|
|
57
60
|
)
|
|
58
61
|
async with manager as request_client:
|
|
59
62
|
headers = {"Authorization": f"Bearer {secret}"}
|
|
63
|
+
if route:
|
|
64
|
+
headers["X-Verifiers-State-Route"] = route
|
|
60
65
|
if content is not None:
|
|
61
66
|
headers["Content-Type"] = "application/json"
|
|
62
67
|
resp = await request_client.request(
|
|
@@ -76,7 +81,15 @@ async def _channel_request(
|
|
|
76
81
|
# Shared servers receive the calling rollout's state channel in URL parameters because one
|
|
77
82
|
# process cannot carry a single rollout's channel in its environment.
|
|
78
83
|
STATE_URL_PARAM = "vf_state_url"
|
|
79
|
-
|
|
84
|
+
STATE_ROUTE_PARAM = "vf_state_route"
|
|
85
|
+
STATE_SIGNATURE_PARAM = "vf_state_signature"
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def state_signature(secret: str, url: str, route: str) -> str:
|
|
89
|
+
"""Authenticate one exact shared-server state destination."""
|
|
90
|
+
message = f"vf-state-v1\0{url}\0{route}".encode()
|
|
91
|
+
return hmac.new(secret.encode(), message, hashlib.sha256).hexdigest()
|
|
92
|
+
|
|
80
93
|
|
|
81
94
|
# A context variable isolates the state seen by concurrent calls on one shared server.
|
|
82
95
|
_call_state: contextvars.ContextVar[State | None] = contextvars.ContextVar(
|
|
@@ -91,7 +104,12 @@ def _request_query(name: str) -> str | None:
|
|
|
91
104
|
request = request_ctx.get().request
|
|
92
105
|
except LookupError:
|
|
93
106
|
return None
|
|
94
|
-
|
|
107
|
+
if request is None:
|
|
108
|
+
return None
|
|
109
|
+
values = request.query_params.getlist(name)
|
|
110
|
+
if len(values) > 1:
|
|
111
|
+
raise ValueError(f"duplicate {name!r} state coordinate")
|
|
112
|
+
return values[0] if values else None
|
|
95
113
|
|
|
96
114
|
|
|
97
115
|
def _die_with_parent() -> None:
|
|
@@ -135,19 +153,32 @@ class ServerBase(Generic[ConfigT, StateT]):
|
|
|
135
153
|
current = _call_state.get()
|
|
136
154
|
return current if current is not None else self._inert_state # type: ignore[return-value]
|
|
137
155
|
|
|
138
|
-
def _state_channel(self) -> tuple[str | None, str]:
|
|
139
|
-
"""
|
|
140
|
-
url =
|
|
141
|
-
secret =
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
156
|
+
def _state_channel(self) -> tuple[str | None, str, str | None]:
|
|
157
|
+
"""Use an env channel, or authenticate the exact coordinates of a shared call."""
|
|
158
|
+
url = os.environ.get("VF_STATE_URL")
|
|
159
|
+
secret = os.environ.get("VF_STATE_SECRET", "")
|
|
160
|
+
if url:
|
|
161
|
+
return url, secret, None
|
|
162
|
+
shared_url = _request_query(STATE_URL_PARAM)
|
|
163
|
+
route = _request_query(STATE_ROUTE_PARAM)
|
|
164
|
+
signature = _request_query(STATE_SIGNATURE_PARAM)
|
|
165
|
+
if not any((shared_url, route, signature)):
|
|
166
|
+
return None, "", None
|
|
167
|
+
if not secret or not shared_url or not route or not signature:
|
|
168
|
+
raise ValueError("invalid shared state coordinates")
|
|
169
|
+
if not hmac.compare_digest(
|
|
170
|
+
signature, state_signature(secret, shared_url, route)
|
|
171
|
+
):
|
|
172
|
+
raise ValueError("invalid shared state coordinates")
|
|
173
|
+
return shared_url, secret, route
|
|
145
174
|
|
|
146
175
|
async def _pull_state(self) -> State:
|
|
147
|
-
url, secret = self._state_channel()
|
|
176
|
+
url, secret, route = self._state_channel()
|
|
148
177
|
if not url:
|
|
149
178
|
return self._state_cls()
|
|
150
|
-
response = await _channel_request(
|
|
179
|
+
response = await _channel_request(
|
|
180
|
+
"GET", url, secret, route=route, client=self._state_client
|
|
181
|
+
)
|
|
151
182
|
try:
|
|
152
183
|
return self._state_adapter.validate_json(response.content)
|
|
153
184
|
except ValidationError as e:
|
|
@@ -157,7 +188,7 @@ class ServerBase(Generic[ConfigT, StateT]):
|
|
|
157
188
|
raise
|
|
158
189
|
|
|
159
190
|
async def _push_state(self, before: bytes) -> None:
|
|
160
|
-
url, secret = self._state_channel()
|
|
191
|
+
url, secret, route = self._state_channel()
|
|
161
192
|
if not url:
|
|
162
193
|
return
|
|
163
194
|
state = _call_state.get()
|
|
@@ -166,7 +197,12 @@ class ServerBase(Generic[ConfigT, StateT]):
|
|
|
166
197
|
if after == before:
|
|
167
198
|
return
|
|
168
199
|
await _channel_request(
|
|
169
|
-
"PUT",
|
|
200
|
+
"PUT",
|
|
201
|
+
url,
|
|
202
|
+
secret,
|
|
203
|
+
route=route,
|
|
204
|
+
content=after,
|
|
205
|
+
client=self._state_client,
|
|
170
206
|
)
|
|
171
207
|
|
|
172
208
|
async def _fetch_task(self, state_url: str | None, secret: str):
|
|
@@ -263,7 +299,8 @@ class ServerBase(Generic[ConfigT, StateT]):
|
|
|
263
299
|
):
|
|
264
300
|
self._state_client = client
|
|
265
301
|
await self.setup()
|
|
266
|
-
|
|
302
|
+
state_url, secret, _ = self._state_channel()
|
|
303
|
+
await self._setup_task_from_channel(state_url, secret)
|
|
267
304
|
# These servers are reached through localhost or a tunnel, never a browser.
|
|
268
305
|
security = TransportSecuritySettings(
|
|
269
306
|
enable_dns_rebinding_protection=False
|
|
@@ -97,7 +97,12 @@ async def _serve_interception(
|
|
|
97
97
|
[server.config for server in servers],
|
|
98
98
|
shared_tools.values(),
|
|
99
99
|
)
|
|
100
|
-
server = InterceptionServer(
|
|
100
|
+
server = InterceptionServer(
|
|
101
|
+
requires_tunnel=tunneled,
|
|
102
|
+
state_service_secrets=tuple(
|
|
103
|
+
tool.state_secret for tool in shared_tools.values() if tool.state_secret
|
|
104
|
+
),
|
|
105
|
+
)
|
|
101
106
|
async with server, server.acquire(session) as slot:
|
|
102
107
|
yield slot
|
|
103
108
|
|
|
@@ -271,7 +276,11 @@ class RolloutRun:
|
|
|
271
276
|
# The harness reaches the model at `{base_url}/v1`; tool servers reach this
|
|
272
277
|
# rollout's `/state` + `/task` at `base_url` — it's universally reachable
|
|
273
278
|
# (the interception is exposed whenever any consumer is remote).
|
|
274
|
-
|
|
279
|
+
(
|
|
280
|
+
base_url,
|
|
281
|
+
model_secret,
|
|
282
|
+
state_secret,
|
|
283
|
+
) = await self._stack.enter_async_context(
|
|
275
284
|
_serve_interception(
|
|
276
285
|
self._interception,
|
|
277
286
|
runtime,
|
|
@@ -281,13 +290,14 @@ class RolloutRun:
|
|
|
281
290
|
)
|
|
282
291
|
)
|
|
283
292
|
self._endpoint = f"{runtime.host_url(base_url)}/v1"
|
|
284
|
-
self._secret =
|
|
293
|
+
self._secret = model_secret
|
|
285
294
|
self._urls = await self._stack.enter_async_context(
|
|
286
295
|
serve_tools(
|
|
287
296
|
toolsets,
|
|
288
297
|
runtime,
|
|
289
298
|
shared=self._shared_tools,
|
|
290
|
-
state_secret=
|
|
299
|
+
state_secret=state_secret,
|
|
300
|
+
state_route=self.trace.id,
|
|
291
301
|
state_base=base_url,
|
|
292
302
|
)
|
|
293
303
|
)
|