verifiers 0.1.15.dev416__tar.gz → 0.1.15.dev418__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.1.15.dev416 → verifiers-0.1.15.dev418}/PKG-INFO +1 -1
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/test_e2e.py +9 -25
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/GUIDE.md +6 -8
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/interception/server.py +3 -3
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/mcp/launch.py +7 -37
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/mcp/server.py +5 -14
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/mcp/toolset.py +0 -15
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/tasksets/harbor/taskset.py +19 -1
- verifiers-0.1.15.dev416/verifiers/v1/mcp/multiplex.py +0 -302
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/.gitignore +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/LICENSE +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/pyproject.toml +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/AGENTS.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/conftest.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_browser_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_build_script.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_cli_agent_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_client_auth_errors.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_client_config.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_client_multimodal_types.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_composable_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_context_token_metrics.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_decorator_ranks.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_endpoint_registry.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_env_group.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_env_server.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_environment.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_environment_extra.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_envs.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_error_chain.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_eval_display.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_eval_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_gepa_cli.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_gepa_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_gym_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_harbor_env_mcp.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_imports.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_init_script.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_install_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_interception_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_logging.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_math_rubric.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_maybe_think_parser.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_message_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_message_utils_multimodal.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_multiturn_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_nemorl_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_openai_chat_completions_token_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_openai_responses_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_opencode_rlm_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_openenv_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_parser.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_path_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_per_turn_timing.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_pricing_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_prime_plugin.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_renderer_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_renderer_e2e.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_rlm_composable_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_rubric.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_rubric_group.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_sandbox_debug_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_sandbox_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_sandbox_mixin.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_save_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_setup_script.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_singleturn_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_stateful_tool_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_think_parser.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_tool_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_tool_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_trajectory_processing.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_tui_info_formatting.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_types.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_wordle_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/test_xml_parser.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/conftest.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/fixtures/counter_tool_v1.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/fixtures/echo_multi_v0.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/fixtures/echo_tool_v1.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/fixtures/echo_v0.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/fixtures/echo_v1.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/fixtures/pyproject.toml +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/test_color_codeword_tasks.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/test_configs.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/test_envs.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/test_graph.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/test_legacy.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/test_scoring.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/tests/v1/test_trace.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/AGENTS.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/cli/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/cli/commands/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/cli/commands/build.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/cli/commands/eval.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/cli/commands/gepa.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/cli/commands/init.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/cli/commands/install.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/cli/commands/setup.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/cli/plugins/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/cli/plugins/prime.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/cli/tui.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/clients/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/clients/anthropic_messages_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/clients/client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/clients/nemorl_chat_completions_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/clients/openai_chat_completions_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/clients/openai_chat_completions_token_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/clients/openai_completions_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/clients/openai_responses_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/clients/renderer_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/decorators.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/AGENTS.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/env_group.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/environment.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/cli_agent_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/_filter.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/composable_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/harness.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/harnesses/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/harnesses/mini_swe_agent.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/harnesses/opencode.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/harnesses/prompt.txt +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/harnesses/rlm.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/sandbox_debug_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/swe_debug_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/task.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/cp/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/cp/cp_task.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/cp/test_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/harbor/cli_gym.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/harbor/harbor.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/harbor/terminal_lego.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/math/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/math/math_task.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/openseeker/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/openseeker/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/openseeker/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/api_tools/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/api_tools/tool_pdf.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/eval_toolkit.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/evaluator.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/llm_client/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/llm_client/base_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/prompts/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/prompts/cache_prompts.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/cache_filesys.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/load_eval_script.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/misc.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/tool_visit.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/utils/url_tools.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/obj_task_eval/verification_tree.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/open_ended.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/quest/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/redsearcher/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/search/search_tasksets.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/extract_fix_patch.sh +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/openswe/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/openswe/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/log_parser.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/shared/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/shared/test_patch.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/log_parsers.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/composable/tasksets/swe/swe_tasksets.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/gym_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/harbor_env/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/harbor_env/env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/harbor_env/mcp.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/mcp_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/opencode_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/opencode_qa_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/opencode_rlm_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/sandbox_mixin.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/utils/file_locks.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/experimental/utils/git_checkout_cache.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/browser_env/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/browser_env/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/browser_env/browser_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/browser_env/modes/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/browser_env/modes/base.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/browser_env/modes/cua_mode.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/browser_env/modes/dom_mode.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/openenv_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/reasoninggym_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/integrations/textarena_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/multiturn_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/python_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/sandbox_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/singleturn_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/stateful_tool_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/envs/tool_env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/errors.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/gepa/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/gepa/adapter.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/gepa/config.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/gepa/display.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/gepa/gepa_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/parsers/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/parsers/maybe_think_parser.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/parsers/parser.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/parsers/think_parser.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/parsers/xml_parser.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rl/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rl/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rl/inference/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rl/inference/client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rl/inference/server.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rl/trainer/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rl/trainer/config.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rl/trainer/orchestrator.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rl/trainer/trainer.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rl/trainer/utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rubrics/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rubrics/experimental/hybrid_math_rubric.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rubrics/judge_rubric.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rubrics/math_rubric.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rubrics/rubric.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/rubrics/rubric_group.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/scripts/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/scripts/build.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/scripts/eval.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/scripts/gepa.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/scripts/init.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/scripts/install.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/scripts/rl.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/scripts/setup.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/scripts/train.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/scripts/tui.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/scripts/vllm.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/serve/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/serve/client/env_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/serve/client/zmq_env_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/serve/server/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/serve/server/env_router.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/serve/server/env_server.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/serve/server/env_worker.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/serve/server/zmq_env_server.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/serve/types.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/types.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/async_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/client_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/config_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/data_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/display_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/env_config_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/env_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/error_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/eval_display.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/eval_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/heartbeat.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/import_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/install_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/interception_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/logging_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/message_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/metric_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/path_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/pricing_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/process_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/response_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/save_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/serve_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/thread_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/threaded_sandbox_client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/tool_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/usage_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/utils/version_utils.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/ARCHITECTURE.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/README.md +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/dashboard/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/dashboard/base.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/dashboard/eval.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/dashboard/validate.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/eval/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/eval/main.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/eval/resume.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/eval/runner.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/init.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/serve.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/cli/validate.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/clients/config.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/configs/eval.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/configs/init.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/configs/serve.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/configs/validate.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/decorators.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/dialects/anthropic.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/dialects/base.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/dialects/chat.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/dialects/responses.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/env.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/episode.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/errors.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/graph.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harness.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/codex/harness.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/default/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/default/harness.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/default/program.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/null/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/null/harness.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/null/program.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/rlm/harness.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/interception/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/interception/pool.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/judge.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/legacy.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/loaders.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/mcp/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/mcp/user.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/retries.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/rollout.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/runtimes/base.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/runtimes/docker.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/runtimes/limiters.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/runtimes/modal.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/runtimes/prime.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/runtimes/subprocess.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/scoring.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/serve/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/serve/client.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/serve/pool.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/serve/server.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/serve/types.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/state.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/task.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/tasksets/lean/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/tasksets/lean/scoring.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/tasksets/lean/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/trace.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/types.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/utils/install.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.1.15.dev416 → verifiers-0.1.15.dev418}/verifiers/v1/utils/memory.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: verifiers
|
|
3
|
-
Version: 0.1.15.
|
|
3
|
+
Version: 0.1.15.dev418
|
|
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
|
|
@@ -9,8 +9,8 @@ carries a pytest mark, so subsets select with `-m` (see `conftest.py`).
|
|
|
9
9
|
`test_user` and `test_tool` fan a server's own runtime against the harness runtime (the full
|
|
10
10
|
reachability matrix); `test_single_turn`/`test_agentic` fan the harness against the harness runtime.
|
|
11
11
|
`test_shared_tool_isolation` runs two concurrent rollouts against one SHARED writable tool server
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
across the full `harness_runtime` x (shared server's own) `tool_runtime` matrix — incl. mixed-locality
|
|
13
|
+
combos — asserting each keeps its own `self.state`.
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
import pytest
|
|
@@ -126,23 +126,16 @@ async def test_tool_state(run_v1, harness_runtime, tool_runtime, tmp_path):
|
|
|
126
126
|
|
|
127
127
|
|
|
128
128
|
@pytest.mark.e2e
|
|
129
|
-
@pytest.mark.parametrize(
|
|
130
|
-
"fork",
|
|
131
|
-
[pytest.param(False, id="fork-off"), pytest.param(True, id="fork-on")],
|
|
132
|
-
)
|
|
133
129
|
async def test_shared_tool_isolation(
|
|
134
|
-
run_v1_server, harness_runtime, tool_runtime,
|
|
130
|
+
run_v1_server, harness_runtime, tool_runtime, tmp_path
|
|
135
131
|
):
|
|
136
|
-
"""A SHARED, writable tool server keeps each rollout's state isolated across concurrent
|
|
137
|
-
over the FULL `harness_runtime` x (shared server's own) `tool_runtime`
|
|
132
|
+
"""A SHARED, writable tool server keeps each rollout's `self.state` isolated across concurrent
|
|
133
|
+
rollouts, over the FULL `harness_runtime` x (shared server's own) `tool_runtime` matrix — including
|
|
138
134
|
the mixed-locality combos (e.g. a local harness with a remote shared tool), which is exactly where
|
|
139
|
-
the rollout's `/state`
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
`isolate=True` (the per-rollout `self.state` channel); fork=on sets `isolate=False` (the server
|
|
144
|
-
writes a process-global slot), so ONLY the forked-child process isolation can keep it correct.
|
|
145
|
-
`isolate` is a config field (not an env var), so it reaches the shared server in any runtime.
|
|
135
|
+
the rollout's `/state` channel must be bridged to the tool's runtime. `scratchpad-v1` gives each
|
|
136
|
+
task a unique word and rewards 1.0 iff the rollout reads back its OWN word, so two concurrent
|
|
137
|
+
rollouts (two distinct words on the ONE shared instance) both scoring 1.0 proves the per-rollout
|
|
138
|
+
`self.state` channel keeps them isolated with no cross-rollout corruption.
|
|
146
139
|
|
|
147
140
|
Placement is fixed to `shared`, so only the own-runtime cases of `tool_runtime` apply (the
|
|
148
141
|
colocated/shared params have no distinct runtime to fan — skipped). Runs through the env-server
|
|
@@ -158,13 +151,6 @@ async def test_shared_tool_isolation(
|
|
|
158
151
|
pytest.skip(
|
|
159
152
|
"tool server in a prime sandbox needs prime port exposure (unreachable from host here)"
|
|
160
153
|
)
|
|
161
|
-
# A prime harness relays every model call through the sandbox, so two concurrent rollouts driving
|
|
162
|
-
# the EXPERIMENTAL fork-per-rollout server can't finish within the rollout cap (reward stays 0).
|
|
163
|
-
# The fork-isolation path is covered by the subprocess/docker harness cases.
|
|
164
|
-
if harness_runtime == "prime" and fork:
|
|
165
|
-
pytest.skip(
|
|
166
|
-
"prime harness + experimental fork-per-rollout is too slow under concurrency to finish in the rollout cap"
|
|
167
|
-
)
|
|
168
154
|
traces = await run_v1_server(
|
|
169
155
|
"scratchpad-v1",
|
|
170
156
|
harness="null",
|
|
@@ -176,8 +162,6 @@ async def test_shared_tool_isolation(
|
|
|
176
162
|
taskset_overrides={
|
|
177
163
|
"tools": {
|
|
178
164
|
"shared": True,
|
|
179
|
-
"fork": fork,
|
|
180
|
-
"isolate": not fork, # fork=on: write a global slot so ONLY fork can isolate it
|
|
181
165
|
**tool_runtime, # the shared tool's own runtime ({"runtime": {"type": ...}})
|
|
182
166
|
}
|
|
183
167
|
},
|
|
@@ -511,19 +511,17 @@ the default is the cheapest correct thing; the rest trade setup cost for isolati
|
|
|
511
511
|
| **own runtime** *(default)* | *(nothing; `runtime = {type = "docker"\|"prime"}` for a sandbox)* | own runtime per rollout — `subprocess` on the host (default), or a `docker`/`prime` sandbox over a tunnel | full per-rollout isolation; a sandbox also isolates untrusted code / deps / network | pays `setup` every rollout (a sandbox adds spin-up + env install) |
|
|
512
512
|
| **colocated** | `colocated = true` | inside the harness's runtime, one per rollout (no tunnel) | no extra runtime/tunnel; can touch the harness's filesystem | couples to the harness; `setup` per rollout |
|
|
513
513
|
| **shared** | `shared = true` | one instance for the whole eval | `setup` once; writable per-rollout if state lives in `self.state` | state outside `self.state` corrupts across rollouts; `setup_task` skipped |
|
|
514
|
-
| **shared + fork** | `shared = true, fork = true` | warm parent + forked child per rollout (copy-on-write) | `setup` once **and** isolates arbitrary in-process/on-disk state; runs `setup_task` per child | a process per concurrent rollout; Linux only |
|
|
515
514
|
| **remote** *(tools only)* | `url = "https://…"` | connects to an already-running MCP endpoint | zero hosting; use a public/third-party server | no isolation, state, or lifecycle control |
|
|
516
515
|
|
|
517
|
-
`shared`
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
memory.
|
|
516
|
+
`shared` works on any runtime — the framework makes the rollout's `/state` channel reachable from the
|
|
517
|
+
shared server (localhost, or a host tunnel when remote). Keep big shared data off the Python heap
|
|
518
|
+
(numpy / mmap / an on-disk index) so one instance scales across rollouts.
|
|
521
519
|
|
|
522
520
|
**Choosing per-rollout state:** read-only resource → `shared`; state that fits a `State` model →
|
|
523
521
|
`shared` + `self.state` (no extra process, the scalable default); state that can't (module globals,
|
|
524
|
-
on-disk scratch, a stateful C library) →
|
|
525
|
-
`setup` each time; cheap `setup` → just use the default. **User simulators** support only the
|
|
526
|
-
per-rollout placements (own runtime or `colocated`); `shared` / `
|
|
522
|
+
on-disk scratch, a stateful C library) → a per-rollout placement (own runtime or `colocated`) that
|
|
523
|
+
pays `setup` each time; cheap `setup` → just use the default. **User simulators** support only the
|
|
524
|
+
per-rollout placements (own runtime or `colocated`); `shared` / `url` are tools-only.
|
|
527
525
|
|
|
528
526
|
## Learn from the examples
|
|
529
527
|
|
|
@@ -216,8 +216,8 @@ class InterceptionServer:
|
|
|
216
216
|
# GET/PUT their `self.state` here, keyed by the same bearer secret as the model routes.
|
|
217
217
|
app.router.add_get("/state", self.handle_state_get)
|
|
218
218
|
app.router.add_put("/state", self.handle_state_put)
|
|
219
|
-
# A
|
|
220
|
-
#
|
|
219
|
+
# A launched tool/user server fetches its rollout's task here to run `setup_task` — the task
|
|
220
|
+
# is never passed via env, only over this channel, keyed by the same bearer secret.
|
|
221
221
|
app.router.add_get("/task", self.handle_task_get)
|
|
222
222
|
self.runner = web.AppRunner(app)
|
|
223
223
|
await self.runner.setup()
|
|
@@ -585,7 +585,7 @@ class InterceptionServer:
|
|
|
585
585
|
)
|
|
586
586
|
|
|
587
587
|
async def handle_task_get(self, request: web.Request) -> web.Response:
|
|
588
|
-
"""Hand a
|
|
588
|
+
"""Hand a launched tool/user server the rollout's task (class ref + JSON) so it can run
|
|
589
589
|
`setup_task` for this rollout — keyed by the same bearer secret as the state channel."""
|
|
590
590
|
session = self._session_for(request)
|
|
591
591
|
if session is None:
|
|
@@ -287,23 +287,11 @@ async def serve(
|
|
|
287
287
|
"is built once for the whole eval and must be task-agnostic — it receives no task. "
|
|
288
288
|
"Drop `shared` to run it per-rollout (with the task), or make its `setup` task-independent."
|
|
289
289
|
)
|
|
290
|
-
if (
|
|
291
|
-
shared
|
|
292
|
-
and not getattr(cfg, "fork", False)
|
|
293
|
-
and type(server).setup_task is not ServerBase.setup_task
|
|
294
|
-
):
|
|
290
|
+
if shared and type(server).setup_task is not ServerBase.setup_task:
|
|
295
291
|
logger.warning(
|
|
296
292
|
"shared server %r overrides `setup_task`, but `setup_task` is NEVER called for a shared "
|
|
297
293
|
"server (it's built once, task-agnostic) — its per-task logic will not run. Move "
|
|
298
|
-
"task-agnostic work into `setup`, drop `shared` to run it per-rollout,
|
|
299
|
-
"(each rollout gets a forked child that runs `setup_task`).",
|
|
300
|
-
server.server_name,
|
|
301
|
-
)
|
|
302
|
-
if shared and getattr(cfg, "fork", False):
|
|
303
|
-
# `serve_tools` makes the rollout's /state + /task channel reachable from the shared server's
|
|
304
|
-
# runtime (a host tunnel when it's remote), so any harness/runtime combo works.
|
|
305
|
-
logger.warning(
|
|
306
|
-
"shared server %r uses fork-per-rollout isolation, which is EXPERIMENTAL",
|
|
294
|
+
"task-agnostic work into `setup`, or drop `shared` to run it per-rollout.",
|
|
307
295
|
server.server_name,
|
|
308
296
|
)
|
|
309
297
|
async with contextlib.AsyncExitStack() as stack:
|
|
@@ -383,11 +371,11 @@ async def serve_shared(toolsets: list[Toolset], harness_is_local: bool = True):
|
|
|
383
371
|
|
|
384
372
|
def _shared_url_for_rollout(url: str, state_base: str | None, state_secret: str) -> str:
|
|
385
373
|
"""Tag a `shared` server's eval-level URL with this rollout's state-channel coordinates, so the
|
|
386
|
-
one shared process serves each rollout its OWN `self.state`
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
374
|
+
one shared process serves each rollout its OWN `self.state`. `state_base` is the interception
|
|
375
|
+
server's reachable base for THIS rollout, chosen by the caller to be reachable from the shared
|
|
376
|
+
server's runtime (localhost, or a host tunnel for a remote runtime). The secret is the bearer the
|
|
377
|
+
harness already holds, so it's no new exposure — but it must not be logged (callers log the
|
|
378
|
+
untagged base)."""
|
|
391
379
|
if not state_base:
|
|
392
380
|
return url
|
|
393
381
|
parts = urlsplit(url)
|
|
@@ -397,19 +385,6 @@ def _shared_url_for_rollout(url: str, state_base: str | None, state_secret: str)
|
|
|
397
385
|
return urlunsplit(parts._replace(query=urlencode(query)))
|
|
398
386
|
|
|
399
387
|
|
|
400
|
-
async def reap_forked_child(shared_url: str, secret: str) -> None:
|
|
401
|
-
"""Best-effort: POST `/vf/close` to reap this rollout's forked child on teardown (a `fork` shared
|
|
402
|
-
server, see `multiplex`); the multiplexer otherwise only reaps a child when it exits."""
|
|
403
|
-
close_url = (
|
|
404
|
-
f"{shared_url.rsplit('/mcp', 1)[0]}/vf/close?{STATE_SECRET_PARAM}={secret}"
|
|
405
|
-
)
|
|
406
|
-
with contextlib.suppress(Exception):
|
|
407
|
-
import httpx
|
|
408
|
-
|
|
409
|
-
async with httpx.AsyncClient(timeout=10.0) as client:
|
|
410
|
-
await client.post(close_url)
|
|
411
|
-
|
|
412
|
-
|
|
413
388
|
@contextlib.asynccontextmanager
|
|
414
389
|
async def serve_tools(
|
|
415
390
|
toolsets: list[Toolset],
|
|
@@ -456,11 +431,6 @@ async def serve_tools(
|
|
|
456
431
|
# log the untagged base, NOT urls[name] — the per-rollout tag carries the rollout's
|
|
457
432
|
# bearer secret (`vf_state_secret`), which must not reach a log sink
|
|
458
433
|
logger.info("tool server '%s' (shared): %s", name, shared_urls[name])
|
|
459
|
-
if getattr(cfg, "fork", False) and state_secret:
|
|
460
|
-
# reap this rollout's forked child when the rollout's tool-serving scope exits
|
|
461
|
-
stack.push_async_callback(
|
|
462
|
-
reap_forked_child, shared_urls[name], state_secret
|
|
463
|
-
)
|
|
464
434
|
else:
|
|
465
435
|
urls[name] = await stack.enter_async_context(
|
|
466
436
|
serve(
|
|
@@ -118,8 +118,7 @@ def _request_query(name: str) -> str | None:
|
|
|
118
118
|
def _die_with_parent() -> None:
|
|
119
119
|
"""Ask the kernel to SIGKILL this process when its parent (the launcher) dies, so a server is
|
|
120
120
|
never orphaned if its launcher is torn down without stopping it (a backstop to the runtime's
|
|
121
|
-
own cleanup). Linux-only; a no-op elsewhere.
|
|
122
|
-
it again."""
|
|
121
|
+
own cleanup). Linux-only; a no-op elsewhere."""
|
|
123
122
|
import ctypes
|
|
124
123
|
import signal
|
|
125
124
|
|
|
@@ -241,9 +240,8 @@ class ServerBase(Generic[ConfigT, StateT]):
|
|
|
241
240
|
self, state_url: str | None, secret: str
|
|
242
241
|
) -> None:
|
|
243
242
|
"""Fetch this rollout's task over the state channel and run `setup_task` for it — a no-op
|
|
244
|
-
without a channel or task (a shared, task-agnostic server).
|
|
245
|
-
|
|
246
|
-
channel (see `verifiers.v1.mcp.multiplex`)."""
|
|
243
|
+
without a channel or task (a shared, task-agnostic server). Called by `_serve` with the
|
|
244
|
+
per-rollout env channel a launched server carries."""
|
|
247
245
|
task = await self._fetch_task(state_url, secret)
|
|
248
246
|
if task is not None:
|
|
249
247
|
await self.setup_task(task)
|
|
@@ -332,8 +330,8 @@ class ServerBase(Generic[ConfigT, StateT]):
|
|
|
332
330
|
async def _setup() -> None:
|
|
333
331
|
await self.setup()
|
|
334
332
|
# Per-rollout servers carry the rollout's state channel in their env; fetch this rollout's
|
|
335
|
-
# task over it and run `setup_task`. A shared server has no env channel
|
|
336
|
-
#
|
|
333
|
+
# task over it and run `setup_task`. A shared server has no env channel, so this is a
|
|
334
|
+
# no-op for it (it's task-agnostic — one instance for the whole eval).
|
|
337
335
|
await self._setup_task_from_channel(*self._state_channel())
|
|
338
336
|
|
|
339
337
|
asyncio.run(_setup())
|
|
@@ -369,13 +367,6 @@ class ServerBase(Generic[ConfigT, StateT]):
|
|
|
369
367
|
self._state_client = None
|
|
370
368
|
|
|
371
369
|
app.router.lifespan_context = serving_lifespan
|
|
372
|
-
if getattr(self.config, "fork", False):
|
|
373
|
-
# `setup` ran once above (warm); fork a child per rollout that inherits it and runs
|
|
374
|
-
# `setup_task` for the rollout's task (see multiplex).
|
|
375
|
-
from verifiers.v1.mcp.multiplex import serve_forked
|
|
376
|
-
|
|
377
|
-
serve_forked(app, sock, self)
|
|
378
|
-
return
|
|
379
370
|
server = uvicorn.Server(uvicorn.Config(app, log_level="critical"))
|
|
380
371
|
asyncio.run(server.serve(sockets=[sock]))
|
|
381
372
|
|
|
@@ -32,8 +32,6 @@ class ToolsetConfig(BaseConfig):
|
|
|
32
32
|
costs a per-rollout install.
|
|
33
33
|
- shared: one instance for the whole eval, in its own `runtime` (pays `setup` once; per-rollout
|
|
34
34
|
writable state stays isolated via `self.state`).
|
|
35
|
-
- shared + fork: like shared, but a forked child per rollout (copy-on-write) also isolates
|
|
36
|
-
state that can't live in `self.state`.
|
|
37
35
|
See the placement/isolation section of `verifiers/v1/GUIDE.md` for the trade-offs of each.
|
|
38
36
|
Subclass to add the server's own knobs (the data its `@tool` methods read). The server name is
|
|
39
37
|
the class's `TOOL_PREFIX` ClassVar, not a field here — it's an identity (the model sees
|
|
@@ -51,15 +49,6 @@ class ToolsetConfig(BaseConfig):
|
|
|
51
49
|
server's URL), so concurrent rollouts don't corrupt each other — provided the shared server runs
|
|
52
50
|
on a local runtime (the default), which can reach the host's interception server. Mutually
|
|
53
51
|
exclusive with `colocated`."""
|
|
54
|
-
fork: bool = False
|
|
55
|
-
"""For a `shared` server: fork a child process per rollout (copy-on-write memory + a private
|
|
56
|
-
working dir), so per-rollout state that can't live in `self.state` — module globals, a mutated
|
|
57
|
-
in-memory object, relative-path on-disk writes — is isolated per rollout automatically. The
|
|
58
|
-
expensive `setup` runs once in the parent; each child inherits it warm and runs `setup_task` for
|
|
59
|
-
its rollout's task (see `verifiers.v1.mcp.multiplex`) — so a stateful per-rollout server pays its
|
|
60
|
-
`setup` once yet stays isolated. Requires `shared`; works on any runtime (a remote one reaches the
|
|
61
|
-
rollout's state/task channel over a host tunnel). Linux/fork only; not for CUDA/GPU state or
|
|
62
|
-
background threads in the server."""
|
|
63
52
|
runtime: RuntimeConfig = SubprocessConfig()
|
|
64
53
|
"""The server's own runtime, used unless `colocated` (host/subprocess by default — always
|
|
65
54
|
reachable from any harness runtime; set docker/prime to isolate it in its own sandbox)."""
|
|
@@ -72,10 +61,6 @@ class ToolsetConfig(BaseConfig):
|
|
|
72
61
|
def _validate_placement(self) -> "ToolsetConfig":
|
|
73
62
|
if self.colocated and self.shared:
|
|
74
63
|
raise ValueError("colocated and shared are mutually exclusive")
|
|
75
|
-
if self.fork and not self.shared:
|
|
76
|
-
raise ValueError(
|
|
77
|
-
"fork requires shared — a per-rollout server already runs in its own process"
|
|
78
|
-
)
|
|
79
64
|
return self
|
|
80
65
|
|
|
81
66
|
|
|
@@ -90,6 +90,10 @@ class HarborTask(Task):
|
|
|
90
90
|
tags: list[str] = []
|
|
91
91
|
task_dir: str = Field(exclude=True)
|
|
92
92
|
"""Host path to the task dir; used to stage tests/ to verify, not serialized."""
|
|
93
|
+
verifier_env: dict[str, str] = {}
|
|
94
|
+
"""Raw [verifier.env] entries (literals or `${VAR}`/`${VAR:-default}` templates).
|
|
95
|
+
Resolved against the host environment at scoring time, like `harbor run` — so a
|
|
96
|
+
verifier that needs judge API keys or configuration actually receives them."""
|
|
93
97
|
|
|
94
98
|
|
|
95
99
|
def harbor_cli() -> str:
|
|
@@ -268,9 +272,23 @@ def parse_task(task_dir: Path, idx: int, harbor_config: HarborConfig) -> HarborT
|
|
|
268
272
|
category=meta.get("category"),
|
|
269
273
|
tags=meta.get("tags", []),
|
|
270
274
|
task_dir=str(task_dir),
|
|
275
|
+
verifier_env=config.get("verifier", {}).get("env", {}),
|
|
271
276
|
)
|
|
272
277
|
|
|
273
278
|
|
|
279
|
+
def verifier_env(task: HarborTask) -> dict[str, str]:
|
|
280
|
+
"""The env a task's verifier runs with: its [verifier.env] templates resolved against
|
|
281
|
+
the host environment (`${VAR}` / `${VAR:-default}`, harbor's own semantics). Resolution
|
|
282
|
+
is deferred to scoring time so resolved secrets never land on the serialized task."""
|
|
283
|
+
if not task.verifier_env:
|
|
284
|
+
return {}
|
|
285
|
+
# Lazy: `harbor` is the optional extra, but scoring implies the dataset was
|
|
286
|
+
# downloaded, which already required it.
|
|
287
|
+
from harbor.utils.env import resolve_env_vars
|
|
288
|
+
|
|
289
|
+
return resolve_env_vars(task.verifier_env)
|
|
290
|
+
|
|
291
|
+
|
|
274
292
|
# Harbor test directories are immutable after download, so repeated rollouts can reuse
|
|
275
293
|
# the latest archive. One entry bounds retained memory to one task.
|
|
276
294
|
@lru_cache(maxsize=1)
|
|
@@ -315,7 +333,7 @@ class HarborTaskset(Taskset[HarborTask, HarborConfig]):
|
|
|
315
333
|
],
|
|
316
334
|
{},
|
|
317
335
|
)
|
|
318
|
-
await runtime.run(["sh", "-c", "cd /tests && bash test.sh"],
|
|
336
|
+
await runtime.run(["sh", "-c", "cd /tests && bash test.sh"], verifier_env(task))
|
|
319
337
|
try:
|
|
320
338
|
reward = (await runtime.read("/logs/verifier/reward.txt")).decode().strip()
|
|
321
339
|
return float(reward or 0)
|
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
"""Fork-per-rollout isolation for a SHARED tool server.
|
|
2
|
-
|
|
3
|
-
A `shared` server is one process for the whole eval; `self.state` isolates its per-rollout state over
|
|
4
|
-
the interception channel (see `server`), but state that DOESN'T live in `self.state` — module globals,
|
|
5
|
-
a mutated in-memory object (an index the tool edits), relative-path on-disk writes — is still shared
|
|
6
|
-
across rollouts. `ToolsetConfig(fork=True)` isolates those too: the expensive `setup` runs ONCE in a
|
|
7
|
-
parent process, then a child is forked per rollout on first contact — the child inherits the warm
|
|
8
|
-
state copy-on-write (in-memory state isolated on write), runs in a private working directory
|
|
9
|
-
(relative-path writes isolated), and runs `setup_task` for its rollout's task (fetched from the
|
|
10
|
-
interception server's `/task` channel — a shared server gets no task via env). The parent is a thin
|
|
11
|
-
async reverse proxy that pins each rollout to its child and streams MCP traffic (so SSE works). So an
|
|
12
|
-
ordinary stateful per-rollout server (expensive `setup` + per-rollout `setup_task`) is isolated
|
|
13
|
-
per rollout with no rollout-aware code.
|
|
14
|
-
|
|
15
|
-
The rollout key is the per-rollout secret the framework tags onto a shared server's URL
|
|
16
|
-
(`STATE_SECRET_PARAM`, see `serve_tools`), alongside the reachable interception base
|
|
17
|
-
(`STATE_URL_PARAM`) for this rollout's `/state` + `/task`. The proxy routes by the key (intra-sandbox,
|
|
18
|
-
no host needed); the child reaches `/state` + `/task` over that base, which `serve_tools` makes
|
|
19
|
-
reachable from the shared server's runtime (localhost, or a host tunnel when it's remote) — so fork
|
|
20
|
-
works on any harness/runtime combo. A child lives for its whole rollout: it is reaped on a `POST
|
|
21
|
-
/vf/close?<key>` from rollout teardown, and on parent exit (each child also dies with the parent via
|
|
22
|
-
`PR_SET_PDEATHSIG`). There is no idle reaper — idle time can't tell a slow-but-live rollout from a
|
|
23
|
-
leaked one, and reaping a live rollout's child would re-run `setup_task` on the next call and wipe its
|
|
24
|
-
in-process state.
|
|
25
|
-
|
|
26
|
-
Caveats: Linux/fork only; do NOT use with CUDA/GPU state or background threads in the server (fork
|
|
27
|
-
copies neither safely) — the fork here is from a single-threaded loop, before any such state. Writes
|
|
28
|
-
to absolute paths outside the private CWD are not isolated.
|
|
29
|
-
"""
|
|
30
|
-
|
|
31
|
-
from __future__ import annotations
|
|
32
|
-
|
|
33
|
-
import asyncio
|
|
34
|
-
import concurrent.futures
|
|
35
|
-
import contextlib
|
|
36
|
-
import hashlib
|
|
37
|
-
import logging
|
|
38
|
-
import os
|
|
39
|
-
import shutil
|
|
40
|
-
import signal
|
|
41
|
-
import socket
|
|
42
|
-
import tempfile
|
|
43
|
-
import time
|
|
44
|
-
from urllib.parse import parse_qs
|
|
45
|
-
|
|
46
|
-
from verifiers.v1.mcp.server import (
|
|
47
|
-
STATE_SECRET_PARAM,
|
|
48
|
-
STATE_URL_PARAM,
|
|
49
|
-
_die_with_parent,
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
logger = logging.getLogger(__name__)
|
|
53
|
-
|
|
54
|
-
CLOSE_PATH = "/vf/close"
|
|
55
|
-
"""The framework POSTs here (with the rollout key) on rollout teardown to reap that child promptly."""
|
|
56
|
-
|
|
57
|
-
_HOP_BY_HOP = {
|
|
58
|
-
"connection",
|
|
59
|
-
"keep-alive",
|
|
60
|
-
"transfer-encoding",
|
|
61
|
-
"content-length",
|
|
62
|
-
"host",
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
class _Child:
|
|
67
|
-
def __init__(self, pid: int, port: int, cwd: str) -> None:
|
|
68
|
-
self.pid, self.port, self.cwd = pid, port, cwd
|
|
69
|
-
# set once the child is serving; reap() also sets it, to wake any waiter
|
|
70
|
-
self.ready = asyncio.Event()
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def _serve_child(
|
|
74
|
-
app, sock: socket.socket, cwd: str, server, state_url: str, secret: str
|
|
75
|
-
) -> None:
|
|
76
|
-
"""In the forked child: die with the parent, move to a private CWD, run `setup_task` for this
|
|
77
|
-
rollout's task (over the per-request state channel), and serve `app` on the inherited (already
|
|
78
|
-
bound) `sock` with a fresh event loop (the inherited parent loop is abandoned). Never returns."""
|
|
79
|
-
import uvicorn
|
|
80
|
-
|
|
81
|
-
_die_with_parent() # SIGKILL this child when the parent multiplexer dies (cleared by fork)
|
|
82
|
-
os.chdir(cwd)
|
|
83
|
-
loop = asyncio.new_event_loop()
|
|
84
|
-
asyncio.set_event_loop(loop)
|
|
85
|
-
try:
|
|
86
|
-
loop.run_until_complete(server._setup_task_from_channel(state_url, secret))
|
|
87
|
-
loop.run_until_complete(
|
|
88
|
-
uvicorn.Server(
|
|
89
|
-
uvicorn.Config(
|
|
90
|
-
app,
|
|
91
|
-
log_level="critical",
|
|
92
|
-
# exit promptly on SIGTERM at teardown — don't hang waiting on the long-lived
|
|
93
|
-
# MCP SSE connection to close (the parent SIGKILLs us / PR_SET_PDEATHSIG fires).
|
|
94
|
-
timeout_graceful_shutdown=0,
|
|
95
|
-
)
|
|
96
|
-
).serve(sockets=[sock])
|
|
97
|
-
)
|
|
98
|
-
finally:
|
|
99
|
-
os._exit(0)
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
async def _wait_up(port: int, timeout: float = 30.0) -> None:
|
|
103
|
-
deadline = time.monotonic() + timeout
|
|
104
|
-
while time.monotonic() < deadline:
|
|
105
|
-
try:
|
|
106
|
-
_, writer = await asyncio.open_connection("127.0.0.1", port)
|
|
107
|
-
writer.close()
|
|
108
|
-
return
|
|
109
|
-
except OSError:
|
|
110
|
-
await asyncio.sleep(0.05)
|
|
111
|
-
raise RuntimeError(f"fork child on port {port} did not come up")
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
def serve_forked(app, sock: socket.socket, server) -> None:
|
|
115
|
-
"""Serve `app` on the bound `sock` as a fork-per-rollout multiplexer (see module docstring).
|
|
116
|
-
`app` is the warm MCP ASGI app, built once in the parent after `setup`; forked children inherit
|
|
117
|
-
it copy-on-write. `server` is the `ServerBase` whose tools the app exposes — each child runs its
|
|
118
|
-
`setup_task` for the rollout's task. `sock` is the socket the launcher reads the port back from."""
|
|
119
|
-
import httpx
|
|
120
|
-
import uvicorn
|
|
121
|
-
|
|
122
|
-
base = tempfile.mkdtemp(prefix="vf_fork_")
|
|
123
|
-
children: dict[str, _Child] = {}
|
|
124
|
-
forking = asyncio.Lock()
|
|
125
|
-
client = httpx.AsyncClient(timeout=None)
|
|
126
|
-
|
|
127
|
-
def _spawn(key: str, state_url: str) -> _Child:
|
|
128
|
-
# Bind the child's port HERE and keep it bound across the fork — the child serves on this exact
|
|
129
|
-
# (inherited) socket, so the port is never released: no TOCTOU window. Fully synchronous (no
|
|
130
|
-
# await), so it runs entirely under `forking`, which serializes the fork() from a single loop.
|
|
131
|
-
child_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
132
|
-
child_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
|
133
|
-
child_sock.bind(("127.0.0.1", 0)) # 0 = an OS-assigned free port
|
|
134
|
-
port = child_sock.getsockname()[1]
|
|
135
|
-
# name the private dir by a hash, not `key` — `key` is the rollout's bearer secret, which
|
|
136
|
-
# shouldn't appear as a filesystem path
|
|
137
|
-
slug = hashlib.sha256(key.encode()).hexdigest()[:16] if key else "_default"
|
|
138
|
-
cwd = os.path.join(base, slug)
|
|
139
|
-
os.makedirs(cwd, exist_ok=True)
|
|
140
|
-
pid = os.fork()
|
|
141
|
-
if pid == 0:
|
|
142
|
-
# child: serves on the inherited socket (setup_task first); never returns
|
|
143
|
-
_serve_child(app, child_sock, cwd, server, state_url, key)
|
|
144
|
-
child_sock.close() # parent: the child owns the socket fd now
|
|
145
|
-
return _Child(pid, port, cwd)
|
|
146
|
-
|
|
147
|
-
async def ensure(key: str, state_url: str) -> _Child:
|
|
148
|
-
# Fast path: a live child — no lock, no readiness probe.
|
|
149
|
-
child = children.get(key)
|
|
150
|
-
if child is not None and child.ready.is_set():
|
|
151
|
-
return child
|
|
152
|
-
# Readiness waits stay outside the lock, so traffic to ready children remains lock-free.
|
|
153
|
-
async with forking:
|
|
154
|
-
child = children.get(key)
|
|
155
|
-
creating = child is None
|
|
156
|
-
if creating:
|
|
157
|
-
children[key] = child = _spawn(key, state_url)
|
|
158
|
-
if not creating:
|
|
159
|
-
# Another task is bringing this key up — wait for it, don't re-fork.
|
|
160
|
-
await child.ready.wait()
|
|
161
|
-
if (
|
|
162
|
-
children.get(key) is not child
|
|
163
|
-
): # reaped / failed to start meanwhile → retry
|
|
164
|
-
return await ensure(key, state_url)
|
|
165
|
-
return child
|
|
166
|
-
# We created it: wait for it to serve OUTSIDE the lock, so other keys fork in parallel.
|
|
167
|
-
try:
|
|
168
|
-
await _wait_up(child.port)
|
|
169
|
-
except BaseException:
|
|
170
|
-
await reap(
|
|
171
|
-
key
|
|
172
|
-
) # dead on arrival: drop it (wakes any waiter to re-fork), then propagate
|
|
173
|
-
raise
|
|
174
|
-
child.ready.set()
|
|
175
|
-
# log only the pid (it correlates spawn<->reap) — the key is the rollout's bearer secret
|
|
176
|
-
logger.info("fork: spawned child pid=%d", child.pid)
|
|
177
|
-
return child
|
|
178
|
-
|
|
179
|
-
async def reap(key: str) -> None:
|
|
180
|
-
# Keep fork() out of the cleanup thread's lifetime; ready children bypass this lock.
|
|
181
|
-
async with forking:
|
|
182
|
-
child = children.pop(key, None)
|
|
183
|
-
if not child:
|
|
184
|
-
return
|
|
185
|
-
child.ready.set() # wake waiters; they re-check `children` before re-forking
|
|
186
|
-
with contextlib.suppress(Exception):
|
|
187
|
-
os.kill(child.pid, signal.SIGKILL)
|
|
188
|
-
|
|
189
|
-
def cleanup() -> None:
|
|
190
|
-
with contextlib.suppress(Exception):
|
|
191
|
-
os.waitpid(child.pid, 0)
|
|
192
|
-
shutil.rmtree(child.cwd, ignore_errors=True)
|
|
193
|
-
|
|
194
|
-
# One worker keeps cleanup ordered and lets it finish if this task is cancelled.
|
|
195
|
-
loop = asyncio.get_running_loop()
|
|
196
|
-
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as executor:
|
|
197
|
-
future = loop.run_in_executor(executor, cleanup)
|
|
198
|
-
try:
|
|
199
|
-
await asyncio.shield(future)
|
|
200
|
-
except asyncio.CancelledError:
|
|
201
|
-
await future
|
|
202
|
-
raise
|
|
203
|
-
logger.info("fork: reaped child pid=%d", child.pid)
|
|
204
|
-
|
|
205
|
-
async def _respond(send, status: int, body: bytes) -> None:
|
|
206
|
-
await send({"type": "http.response.start", "status": status, "headers": []})
|
|
207
|
-
await send({"type": "http.response.body", "body": body})
|
|
208
|
-
|
|
209
|
-
async def proxy(scope, receive, send) -> None:
|
|
210
|
-
if scope["type"] == "lifespan":
|
|
211
|
-
# Drive the proxy app's own (empty) lifespan; each child runs the real app's lifespan.
|
|
212
|
-
while True:
|
|
213
|
-
msg = await receive()
|
|
214
|
-
if msg["type"] == "lifespan.startup":
|
|
215
|
-
await send({"type": "lifespan.startup.complete"})
|
|
216
|
-
elif msg["type"] == "lifespan.shutdown":
|
|
217
|
-
await send({"type": "lifespan.shutdown.complete"})
|
|
218
|
-
return
|
|
219
|
-
if scope["type"] != "http":
|
|
220
|
-
return
|
|
221
|
-
params = parse_qs(scope.get("query_string", b"").decode())
|
|
222
|
-
key = (params.get(STATE_SECRET_PARAM) or [""])[0]
|
|
223
|
-
state_url = (params.get(STATE_URL_PARAM) or [""])[0]
|
|
224
|
-
if scope["path"] == CLOSE_PATH:
|
|
225
|
-
await reap(key)
|
|
226
|
-
await _respond(send, 200, b"closed")
|
|
227
|
-
return
|
|
228
|
-
body: list[bytes] = []
|
|
229
|
-
more = True
|
|
230
|
-
while more: # read the request body, then forward to the rollout's child
|
|
231
|
-
msg = await receive()
|
|
232
|
-
body.append(msg.get("body", b""))
|
|
233
|
-
more = msg.get("more_body", False)
|
|
234
|
-
# Bring the child up and stream its response back. Any failure here (child never came up,
|
|
235
|
-
# `ensure` timed out, upstream errored mid-stream) must not leave the ASGI caller hanging:
|
|
236
|
-
# send a clean 502 if nothing was sent yet, else end the started body so the client stops.
|
|
237
|
-
started = False
|
|
238
|
-
try:
|
|
239
|
-
child = await ensure(key, state_url)
|
|
240
|
-
headers = [
|
|
241
|
-
(k.decode(), v.decode())
|
|
242
|
-
for k, v in scope["headers"]
|
|
243
|
-
if k.decode().lower() not in _HOP_BY_HOP
|
|
244
|
-
]
|
|
245
|
-
qs = scope.get("query_string", b"").decode()
|
|
246
|
-
url = f"http://127.0.0.1:{child.port}{scope['path']}" + (
|
|
247
|
-
f"?{qs}" if qs else ""
|
|
248
|
-
)
|
|
249
|
-
req = client.build_request(
|
|
250
|
-
scope["method"], url, headers=headers, content=b"".join(body)
|
|
251
|
-
)
|
|
252
|
-
resp = await client.send(req, stream=True)
|
|
253
|
-
try:
|
|
254
|
-
out = [
|
|
255
|
-
(k.encode(), v.encode())
|
|
256
|
-
for k, v in resp.headers.items()
|
|
257
|
-
if k.lower() not in _HOP_BY_HOP
|
|
258
|
-
]
|
|
259
|
-
await send(
|
|
260
|
-
{
|
|
261
|
-
"type": "http.response.start",
|
|
262
|
-
"status": resp.status_code,
|
|
263
|
-
"headers": out,
|
|
264
|
-
}
|
|
265
|
-
)
|
|
266
|
-
started = True
|
|
267
|
-
async for chunk in resp.aiter_raw():
|
|
268
|
-
await send(
|
|
269
|
-
{"type": "http.response.body", "body": chunk, "more_body": True}
|
|
270
|
-
)
|
|
271
|
-
await send(
|
|
272
|
-
{"type": "http.response.body", "body": b"", "more_body": False}
|
|
273
|
-
)
|
|
274
|
-
finally:
|
|
275
|
-
await resp.aclose()
|
|
276
|
-
except Exception as exc:
|
|
277
|
-
logger.warning("fork: proxy error forwarding to child: %s", exc)
|
|
278
|
-
if started:
|
|
279
|
-
with contextlib.suppress(Exception):
|
|
280
|
-
await send(
|
|
281
|
-
{"type": "http.response.body", "body": b"", "more_body": False}
|
|
282
|
-
)
|
|
283
|
-
else:
|
|
284
|
-
await _respond(send, 502, b"fork proxy error")
|
|
285
|
-
|
|
286
|
-
async def _serve() -> None:
|
|
287
|
-
# timeout_graceful_shutdown=0: exit promptly on SIGTERM (the runtime's teardown) instead of
|
|
288
|
-
# hanging on the long-lived proxied SSE — so `finally` below SIGKILLs the children.
|
|
289
|
-
try:
|
|
290
|
-
await uvicorn.Server(
|
|
291
|
-
uvicorn.Config(proxy, log_level="critical", timeout_graceful_shutdown=0)
|
|
292
|
-
).serve(sockets=[sock])
|
|
293
|
-
finally:
|
|
294
|
-
await client.aclose()
|
|
295
|
-
|
|
296
|
-
try:
|
|
297
|
-
asyncio.run(_serve())
|
|
298
|
-
finally:
|
|
299
|
-
for key in list(children):
|
|
300
|
-
with contextlib.suppress(Exception):
|
|
301
|
-
os.kill(children[key].pid, signal.SIGKILL)
|
|
302
|
-
shutil.rmtree(base, ignore_errors=True)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|