verifiers 0.2.2.dev94__tar.gz → 0.2.2.dev96__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.dev94 → verifiers-0.2.2.dev96}/PKG-INFO +1 -1
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/harnesses/rlm.py +2 -3
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/utils/git_checkout_cache.py +2 -1
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/path_utils.py +12 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/eval/main.py +3 -2
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/eval/resume.py +1 -38
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/eval/runner.py +7 -7
- verifiers-0.2.2.dev96/verifiers/v1/cli/resume.py +42 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/validate.py +253 -27
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/cli/validate.py +14 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/interception/tunnel/prime.py +2 -2
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/runtimes/limiters.py +19 -15
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/runtimes/modal.py +1 -1
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/runtimes/prime.py +1 -1
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/.gitignore +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/LICENSE +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/README.md +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/pyproject.toml +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/conftest.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_browser_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_build_script.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_cli_agent_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_client_auth_errors.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_client_config.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_client_multimodal_types.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_composable_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_context_token_metrics.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_decorator_ranks.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_endpoint_registry.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_env_group.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_env_server.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_environment.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_environment_extra.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_error_chain.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_eval_display.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_eval_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_gepa_cli.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_gepa_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_gym_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_harbor_env_mcp.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_imports.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_init_script.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_install_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_interception_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_logging.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_math_rubric.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_maybe_think_parser.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_message_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_message_utils_multimodal.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_multiturn_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_nemorl_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_openai_chat_completions_token_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_openai_responses_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_opencode_rlm_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_openenv_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_parser.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_path_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_per_turn_timing.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_pricing_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_prime_plugin.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_renderer_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_renderer_e2e.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_rlm_composable_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_rubric.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_rubric_group.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_sandbox_debug_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_sandbox_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_sandbox_mixin.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_save_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_setup_script.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_singleturn_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_stateful_tool_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_think_parser.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_tool_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_tool_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_trajectory_processing.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_tui_info_formatting.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_types.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/test_xml_parser.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/conftest.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/fixtures/counter_tool_v1.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/fixtures/duet_v1.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/fixtures/echo_acp_resume_v1.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/fixtures/echo_multi_v0.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/fixtures/echo_tool_v1.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/fixtures/echo_v0.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/fixtures/echo_v1.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/fixtures/pyproject.toml +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/test_color_codeword_tasks.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/test_configs.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/test_e2e.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/test_envs.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/test_graph.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/test_judges.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/test_legacy.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/test_scoring.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/test_taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/tests/v1/test_trace.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/cli/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/cli/commands/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/cli/commands/build.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/cli/commands/eval.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/cli/commands/gepa.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/cli/commands/init.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/cli/commands/install.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/cli/commands/setup.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/cli/plugins/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/cli/plugins/prime.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/cli/tui.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/clients/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/clients/anthropic_messages_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/clients/client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/clients/nemorl_chat_completions_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/clients/openai_chat_completions_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/clients/openai_chat_completions_token_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/clients/openai_completions_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/clients/openai_responses_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/clients/renderer_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/decorators.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/env_group.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/environment.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/README.md +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/cli_agent_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/README.md +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/_filter.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/composable_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/harnesses/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/harnesses/mini_swe_agent.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/harnesses/opencode.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/harnesses/prompt.txt +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/sandbox_debug_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/swe_debug_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/task.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/cp/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/cp/cp_task.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/cp/test_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/harbor/cli_gym.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/harbor/harbor.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/harbor/terminal_lego.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/math/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/math/math_task.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/README.md +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/extract_fix_patch.sh +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/multi_swe/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/openswe/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/openswe/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/log_parser.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/r2e_gym/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/scale_swe/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/shared/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/shared/test_patch.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/swe_bench/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/swe_lego/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/log_parsers.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/swe_rebench_v2/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/swe_smith/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/composable/tasksets/swe/swe_tasksets.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/gym_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/harbor_env/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/harbor_env/env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/harbor_env/mcp.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/mcp_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/opencode_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/opencode_qa_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/opencode_rlm_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/sandbox_mixin.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/utils/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/experimental/utils/file_locks.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/README.md +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/browser_env/README.md +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/browser_env/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/browser_env/browser_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/browser_env/modes/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/browser_env/modes/base.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/browser_env/modes/cua_mode.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/browser_env/modes/dom_mode.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/openenv_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/reasoninggym_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/integrations/textarena_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/multiturn_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/python_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/sandbox_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/singleturn_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/stateful_tool_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/envs/tool_env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/errors.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/gepa/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/gepa/adapter.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/gepa/config.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/gepa/display.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/gepa/gepa_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/parsers/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/parsers/maybe_think_parser.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/parsers/parser.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/parsers/think_parser.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/parsers/xml_parser.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/rubrics/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/rubrics/experimental/hybrid_math_rubric.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/rubrics/judge_rubric.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/rubrics/math_rubric.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/rubrics/rubric.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/rubrics/rubric_group.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/scripts/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/scripts/build.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/scripts/eval.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/scripts/gepa.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/scripts/init.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/scripts/install.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/scripts/setup.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/scripts/tui.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/serve/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/serve/client/env_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/serve/client/zmq_env_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/serve/server/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/serve/server/env_router.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/serve/server/env_server.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/serve/server/env_worker.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/serve/server/zmq_env_server.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/serve/types.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/types.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/async_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/client_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/config_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/data_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/display_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/env_config_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/env_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/error_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/eval_display.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/eval_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/heartbeat.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/import_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/install_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/interception_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/logging_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/message_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/metric_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/pricing_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/process_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/response_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/save_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/serve_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/thread_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/threaded_sandbox_client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/tool_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/usage_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/utils/version_utils.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/acp/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/acp/runner.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/agent.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/dashboard/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/dashboard/base.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/dashboard/eval.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/dashboard/replay.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/dashboard/validate.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/debug.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/eval/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/gepa.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/init.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/replay.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/clients/base.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/agent.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/cli/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/cli/debug.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/cli/env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/cli/eval.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/cli/init.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/cli/replay.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/judge.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/legacy.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/retries.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/serve.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/task.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/configs/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/dialects/anthropic.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/dialects/base.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/dialects/chat.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/dialects/responses.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/envs/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/envs/agentic_judge/env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/envs/best_of_n/env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/envs/shared_agentic_judge/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/envs/single_agent/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/envs/single_agent/env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/envs/user_sim/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/envs/user_sim/env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/episode.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/errors.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/gepa/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/gepa/adapter.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/gepa/config.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/gepa/dataset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/gepa/reflection.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/gepa/runner.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/graph.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/bash/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/bash/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/bash/program.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/browser_use/program.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/codex/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/node.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/null/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/null/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/null/program.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/pi/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/pi/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/pool/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/pool/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/rlm/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/interception/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/interception/base.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/interception/pool.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/interception/server.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/interception/tunnel/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/interception/tunnel/base.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/interception/tunnel/custom.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/judge.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/judges/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/judges/reference.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/judges/reference.txt +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/judges/rubric.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/judges/rubric.txt +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/legacy.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/mcp/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/mcp/launch.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/mcp/server.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/mcp/toolset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/rollout.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/runtimes/base.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/runtimes/docker/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/runtimes/docker/egress.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/runtimes/subprocess.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/serve/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/serve/client.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/serve/pool.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/serve/server.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/serve/types.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/session.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/state.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/task.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/tasksets/harbor/env.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/tasksets/lean/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/tasksets/lean/scoring.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/tasksets/lean/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/trace.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/types.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/aio.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/artifacts.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/compile.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/decorators.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/generic.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/git.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/image.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/install.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/interrupt.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/loaders.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/memory.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/platform.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/retries.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/verifiers/v1/utils/score.py +0 -0
- {verifiers-0.2.2.dev94 → verifiers-0.2.2.dev96}/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.dev96
|
|
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
|
|
@@ -15,6 +15,7 @@ from verifiers.envs.experimental.utils.git_checkout_cache import (
|
|
|
15
15
|
validate_git_checkout,
|
|
16
16
|
)
|
|
17
17
|
from verifiers.types import Messages, State, SystemMessage, TrajectoryStep
|
|
18
|
+
from verifiers.utils.path_utils import CACHE_DIR
|
|
18
19
|
|
|
19
20
|
DEFAULT_RLM_REPO_URL = "github.com/PrimeIntellect-ai/rlm-harness.git"
|
|
20
21
|
DEFAULT_RLM_REF = "main"
|
|
@@ -24,9 +25,7 @@ DEFAULT_RLM_MAX_DEPTH = 0
|
|
|
24
25
|
DEFAULT_APPEND_TO_SYSTEM_PROMPT_PATH = "/task/append_to_system_prompt.txt"
|
|
25
26
|
DEFAULT_RLM_CHECKOUT_PATH = "/tmp/rlm-checkout"
|
|
26
27
|
DEFAULT_RLM_CHECKOUT_UPLOAD_NAME = "rlm_checkout"
|
|
27
|
-
DEFAULT_RLM_LOCAL_CHECKOUT_CACHE_ROOT =
|
|
28
|
-
Path.home() / ".cache" / "verifiers" / "rlm-checkouts"
|
|
29
|
-
)
|
|
28
|
+
DEFAULT_RLM_LOCAL_CHECKOUT_CACHE_ROOT = CACHE_DIR / "rlm-checkouts"
|
|
30
29
|
_REQUIRED_CHECKOUT_FILES = ("install.sh", "pyproject.toml")
|
|
31
30
|
|
|
32
31
|
COMPACTION_BOUNDARY_MARKER = "--- context compacted ---"
|
|
@@ -16,6 +16,7 @@ from verifiers.envs.experimental.utils.file_locks import (
|
|
|
16
16
|
exclusive_path_lock,
|
|
17
17
|
sibling_lock_path,
|
|
18
18
|
)
|
|
19
|
+
from verifiers.utils.path_utils import CACHE_DIR
|
|
19
20
|
|
|
20
21
|
_IN_USE_LOCK_SUFFIX = ".in-use.lock"
|
|
21
22
|
|
|
@@ -23,7 +24,7 @@ _IN_USE_LOCK_SUFFIX = ".in-use.lock"
|
|
|
23
24
|
# resolved checkout's in-use lock file. See ``_acquire_in_use_lock``.
|
|
24
25
|
_held_in_use_locks: dict[Path, IO] = {}
|
|
25
26
|
|
|
26
|
-
DEFAULT_GIT_CHECKOUT_CACHE_ROOT =
|
|
27
|
+
DEFAULT_GIT_CHECKOUT_CACHE_ROOT = CACHE_DIR / "git-checkouts"
|
|
27
28
|
_FULL_COMMIT_SHA_RE = re.compile(r"^[0-9a-fA-F]{40}$")
|
|
28
29
|
|
|
29
30
|
logger = logging.getLogger(__name__)
|
|
@@ -9,6 +9,18 @@ from verifiers.types import EvalConfig
|
|
|
9
9
|
logger = logging.getLogger(__name__)
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
def home_dir() -> Path:
|
|
13
|
+
"""Best-effort home directory; fall back to the temp dir so import never fails."""
|
|
14
|
+
try:
|
|
15
|
+
return Path.home()
|
|
16
|
+
except RuntimeError:
|
|
17
|
+
return Path(tempfile.gettempdir())
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
CACHE_DIR = home_dir() / ".cache" / "verifiers"
|
|
21
|
+
"""User-local cache root for verifiers-managed state."""
|
|
22
|
+
|
|
23
|
+
|
|
12
24
|
def write_temp_file(content: str, suffix: str = ".txt") -> str:
|
|
13
25
|
"""Write content to a named temporary file and return its path.
|
|
14
26
|
|
|
@@ -7,7 +7,7 @@ import sys
|
|
|
7
7
|
from pydantic_config import cli
|
|
8
8
|
|
|
9
9
|
import verifiers.v1 as vf
|
|
10
|
-
from verifiers.v1.cli.eval.resume import load_resume_config
|
|
10
|
+
from verifiers.v1.cli.eval.resume import load_resume_config
|
|
11
11
|
from verifiers.v1.cli.eval.runner import run_eval
|
|
12
12
|
from verifiers.v1.cli.output import output_path, write_config
|
|
13
13
|
from verifiers.v1.cli.resolve import (
|
|
@@ -17,6 +17,7 @@ from verifiers.v1.cli.resolve import (
|
|
|
17
17
|
references_config_file,
|
|
18
18
|
with_positional_taskset,
|
|
19
19
|
)
|
|
20
|
+
from verifiers.v1.cli.resume import split_resume
|
|
20
21
|
from verifiers.v1.configs.cli.eval import EvalConfig
|
|
21
22
|
from verifiers.v1.utils.interrupt import install_interrupt
|
|
22
23
|
from verifiers.v1.utils.logging import setup_logging
|
|
@@ -40,7 +41,7 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
40
41
|
narrow_config(EvalConfig, argv)
|
|
41
42
|
) # full option help, narrowed to the given ids
|
|
42
43
|
return
|
|
43
|
-
resume_dir, rest = split_resume(argv)
|
|
44
|
+
resume_dir, rest = split_resume(argv, "eval")
|
|
44
45
|
# re-run a previous run's missing/errored rollouts, in place
|
|
45
46
|
if resume_dir is not None:
|
|
46
47
|
if rest:
|
|
@@ -11,7 +11,6 @@ changed since the interrupted run re-runs, and nothing depends on `data.idx`. Th
|
|
|
11
11
|
legacy (v0) bridge still matches by row index (`key_of`).
|
|
12
12
|
"""
|
|
13
13
|
|
|
14
|
-
import hashlib
|
|
15
14
|
import json
|
|
16
15
|
import tomllib
|
|
17
16
|
from collections import Counter, defaultdict
|
|
@@ -22,6 +21,7 @@ from typing import TypeVar
|
|
|
22
21
|
from pydantic_core import from_json
|
|
23
22
|
|
|
24
23
|
from verifiers.v1.cli.output import CONFIG_FILE, TRACES_FILE, sniff_episode
|
|
24
|
+
from verifiers.v1.cli.resume import task_key
|
|
25
25
|
from verifiers.v1.configs.cli.eval import EvalConfig
|
|
26
26
|
from verifiers.v1.episode import Episode, WireEpisode
|
|
27
27
|
from verifiers.v1.trace import WireTrace
|
|
@@ -29,43 +29,6 @@ from verifiers.v1.trace import WireTrace
|
|
|
29
29
|
K = TypeVar("K", bound=Hashable)
|
|
30
30
|
|
|
31
31
|
|
|
32
|
-
def task_key(data: Mapping) -> str:
|
|
33
|
-
"""Content identity of one task's wire data — an `exclude_none` dump, the shape
|
|
34
|
-
saved rows already have on disk. `sort_keys` so field order can't split identity."""
|
|
35
|
-
return hashlib.sha256(json.dumps(data, sort_keys=True).encode()).hexdigest()
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def distribute(
|
|
39
|
-
selected_keys: list[K], owed: dict[K, int], num_rollouts: int
|
|
40
|
-
) -> list[int]:
|
|
41
|
-
"""Spread each key's owed rollouts over its selection instances, in order —
|
|
42
|
-
content-identical tasks are interchangeable, so any instance can absorb the
|
|
43
|
-
debt (capped at `num_rollouts` each). Returns one count per selection."""
|
|
44
|
-
remaining = dict(owed)
|
|
45
|
-
counts: list[int] = []
|
|
46
|
-
for key in selected_keys:
|
|
47
|
-
take = min(num_rollouts, remaining.get(key, 0))
|
|
48
|
-
if take:
|
|
49
|
-
remaining[key] -= take
|
|
50
|
-
counts.append(take)
|
|
51
|
-
return counts
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
def split_resume(argv: list[str]) -> tuple[Path | None, list[str]]:
|
|
55
|
-
"""Pull `--resume <dir>` / `--resume=<dir>` out of argv, returning (dir, the other args).
|
|
56
|
-
The caller rejects any leftover args, since resume re-runs the saved config verbatim."""
|
|
57
|
-
for i, arg in enumerate(argv):
|
|
58
|
-
if arg == "--resume":
|
|
59
|
-
if i + 1 >= len(argv):
|
|
60
|
-
raise SystemExit(
|
|
61
|
-
"--resume needs an output dir: uv run eval --resume <dir>"
|
|
62
|
-
)
|
|
63
|
-
return Path(argv[i + 1]), argv[:i] + argv[i + 2 :]
|
|
64
|
-
if arg.startswith("--resume="):
|
|
65
|
-
return Path(arg.split("=", 1)[1]), argv[:i] + argv[i + 1 :]
|
|
66
|
-
return None, argv
|
|
67
|
-
|
|
68
|
-
|
|
69
32
|
def load_resume_config(resume_dir: Path) -> EvalConfig:
|
|
70
33
|
"""Rebuild the run's `EvalConfig` from its saved `config.toml`, pointed back at its own
|
|
71
34
|
output dir so the resumed rollouts append to the same `traces.jsonl`."""
|
|
@@ -14,6 +14,7 @@ from verifiers.v1.cli.output import (
|
|
|
14
14
|
output_path,
|
|
15
15
|
save_config,
|
|
16
16
|
)
|
|
17
|
+
from verifiers.v1.cli.resume import distribute, task_key
|
|
17
18
|
from verifiers.v1.clients import ModelContext
|
|
18
19
|
from verifiers.v1.configs.cli.eval import EvalConfig
|
|
19
20
|
from verifiers.v1.env import Env, RunSlot
|
|
@@ -48,14 +49,13 @@ async def run_eval(env: Env, config: EvalConfig) -> list[Episode]:
|
|
|
48
49
|
finished: list[Episode] = []
|
|
49
50
|
if config.resume is not None:
|
|
50
51
|
keys = [
|
|
51
|
-
|
|
52
|
-
for t in tasks
|
|
52
|
+
task_key(t.data.model_dump(mode="json", exclude_none=True)) for t in tasks
|
|
53
53
|
]
|
|
54
54
|
finished, owed = resume.load(out, keys, config.num_rollouts, env.complete)
|
|
55
55
|
if not owed: # already complete - report it and exit successfully
|
|
56
56
|
print(resume.nothing_to_resume_msg(out, len(tasks), config.num_rollouts))
|
|
57
57
|
raise SystemExit(0)
|
|
58
|
-
counts =
|
|
58
|
+
counts = distribute(keys, owed, config.num_rollouts)
|
|
59
59
|
plan = [(task, n) for task, n in zip(tasks, counts) if n]
|
|
60
60
|
logger.info(
|
|
61
61
|
"resuming %s: %d task(s), %d rollout(s) owed",
|
|
@@ -179,7 +179,7 @@ async def run_eval_server(config: EvalConfig) -> list[Episode]:
|
|
|
179
179
|
client = EnvClient(address=address)
|
|
180
180
|
await client.wait_for_server_startup(timeout=600)
|
|
181
181
|
# A v1 run dispatches — and resumes — tasks by content: the client owns them,
|
|
182
|
-
# and `
|
|
182
|
+
# and `task_key` is their identity. Only the legacy bridge is addressed
|
|
183
183
|
# by dataset row (its dataset lives server-side, reported via `info`), and
|
|
184
184
|
# only a legacy env group-scores; a v1 env scores siblings in its own rollout.
|
|
185
185
|
if legacy:
|
|
@@ -209,14 +209,14 @@ async def run_eval_server(config: EvalConfig) -> list[Episode]:
|
|
|
209
209
|
whole_task=group_scored,
|
|
210
210
|
key_of=lambda data: data.get("idx"),
|
|
211
211
|
)
|
|
212
|
-
counts =
|
|
212
|
+
counts = distribute(idxs, owed, config.num_rollouts)
|
|
213
213
|
else:
|
|
214
214
|
keys = [
|
|
215
|
-
|
|
215
|
+
task_key(t.data.model_dump(mode="json", exclude_none=True))
|
|
216
216
|
for t in tasks
|
|
217
217
|
]
|
|
218
218
|
finished, owed = resume.load(out, keys, config.num_rollouts)
|
|
219
|
-
counts =
|
|
219
|
+
counts = distribute(keys, owed, config.num_rollouts)
|
|
220
220
|
if not owed: # already complete - report it and exit successfully
|
|
221
221
|
print(resume.nothing_to_resume_msg(out, len(plan), config.num_rollouts))
|
|
222
222
|
raise SystemExit(0)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Resume primitives shared by eval-like CLIs."""
|
|
2
|
+
|
|
3
|
+
import hashlib
|
|
4
|
+
import json
|
|
5
|
+
from collections.abc import Hashable, Mapping
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import TypeVar
|
|
8
|
+
|
|
9
|
+
K = TypeVar("K", bound=Hashable)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def task_key(data: Mapping) -> str:
|
|
13
|
+
"""Content identity for task wire data, independent of field order."""
|
|
14
|
+
return hashlib.sha256(json.dumps(data, sort_keys=True).encode()).hexdigest()
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def distribute(
|
|
18
|
+
selected_keys: list[K], owed: dict[K, int], num_results: int
|
|
19
|
+
) -> list[int]:
|
|
20
|
+
"""Spread each key's owed results over its selected instances, in order."""
|
|
21
|
+
remaining = dict(owed)
|
|
22
|
+
counts: list[int] = []
|
|
23
|
+
for key in selected_keys:
|
|
24
|
+
take = min(num_results, remaining.get(key, 0))
|
|
25
|
+
if take:
|
|
26
|
+
remaining[key] -= take
|
|
27
|
+
counts.append(take)
|
|
28
|
+
return counts
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def split_resume(argv: list[str], command: str) -> tuple[Path | None, list[str]]:
|
|
32
|
+
"""Pull ``--resume <dir>`` from argv, returning the dir and other arguments."""
|
|
33
|
+
for i, arg in enumerate(argv):
|
|
34
|
+
if arg == "--resume":
|
|
35
|
+
if i + 1 >= len(argv):
|
|
36
|
+
raise SystemExit(
|
|
37
|
+
f"--resume needs an output dir: uv run {command} --resume <dir>"
|
|
38
|
+
)
|
|
39
|
+
return Path(argv[i + 1]), argv[:i] + argv[i + 2 :]
|
|
40
|
+
if arg.startswith("--resume="):
|
|
41
|
+
return Path(arg.split("=", 1)[1]), argv[:i] + argv[i + 1 :]
|
|
42
|
+
return None, argv
|
|
@@ -2,16 +2,23 @@
|
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import contextlib
|
|
5
|
+
import json
|
|
5
6
|
import logging
|
|
6
7
|
import sys
|
|
7
8
|
import time
|
|
9
|
+
import tomllib
|
|
10
|
+
from collections import Counter, defaultdict
|
|
11
|
+
from collections.abc import Mapping, Sequence
|
|
12
|
+
from pathlib import Path
|
|
8
13
|
from typing import Any
|
|
9
14
|
from uuid import uuid4
|
|
10
15
|
|
|
11
16
|
from pydantic_config import cli
|
|
17
|
+
from pydantic_core import from_json
|
|
12
18
|
|
|
13
19
|
import verifiers.v1 as vf
|
|
14
20
|
from verifiers.v1.cli.dashboard import TaskProgress, validate_dashboard
|
|
21
|
+
from verifiers.v1.cli.output import CONFIG_FILE, write_config
|
|
15
22
|
from verifiers.v1.cli.resolve import (
|
|
16
23
|
extract_id,
|
|
17
24
|
narrow_taskset_config,
|
|
@@ -19,11 +26,13 @@ from verifiers.v1.cli.resolve import (
|
|
|
19
26
|
references_config_file,
|
|
20
27
|
with_positional_taskset,
|
|
21
28
|
)
|
|
29
|
+
from verifiers.v1.cli.resume import distribute, split_resume, task_key
|
|
22
30
|
from verifiers.v1.configs.cli.validate import ValidateConfig
|
|
23
31
|
from verifiers.v1.runtimes import make_runtime
|
|
24
32
|
from verifiers.v1.state import state_cls
|
|
25
33
|
from verifiers.v1.task import Task
|
|
26
34
|
from verifiers.v1.trace import Trace, TraceTask
|
|
35
|
+
from verifiers.v1.utils.aio import run_shielded
|
|
27
36
|
from verifiers.v1.utils.compile import resolve_runtime_config
|
|
28
37
|
from verifiers.v1.utils.decorators import invoke
|
|
29
38
|
from verifiers.v1.utils.interrupt import install_interrupt
|
|
@@ -31,10 +40,19 @@ from verifiers.v1.utils.logging import setup_logging
|
|
|
31
40
|
|
|
32
41
|
logger = logging.getLogger(__name__)
|
|
33
42
|
|
|
43
|
+
RESULTS_FILE = "results.jsonl"
|
|
44
|
+
SUMMARY_FILE = "summary.json"
|
|
45
|
+
LOG_FILE = "validate.log"
|
|
46
|
+
FINAL_REASONS = frozenset({"valid", "invalid"})
|
|
47
|
+
REASONS = ("valid", "invalid", "error", "timeout")
|
|
48
|
+
|
|
49
|
+
ResultRow = dict[str, Any]
|
|
50
|
+
|
|
34
51
|
USAGE = (
|
|
35
52
|
"usage: uv run validate [<taskset-id>] [--only-setup | --only-gold] "
|
|
36
|
-
"[--runtime.type subprocess] [options] [@ file.toml]\n"
|
|
37
|
-
"
|
|
53
|
+
"[-o <output-dir>] [--runtime.type subprocess] [options] [@ file.toml]\n"
|
|
54
|
+
" uv run validate --resume <output-dir>\n"
|
|
55
|
+
" runs persisted gold and setup-only checks per task (no model)"
|
|
38
56
|
)
|
|
39
57
|
|
|
40
58
|
|
|
@@ -45,7 +63,149 @@ def _narrow(argv: list[str]) -> type[ValidateConfig]:
|
|
|
45
63
|
return narrow_taskset_config(ValidateConfig, extract_id(argv, "taskset"))
|
|
46
64
|
|
|
47
65
|
|
|
48
|
-
|
|
66
|
+
def validation_mode(config: ValidateConfig) -> str:
|
|
67
|
+
if config.only_gold:
|
|
68
|
+
return "gold"
|
|
69
|
+
if config.only_setup:
|
|
70
|
+
return "setup"
|
|
71
|
+
return "all"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def output_path(config: ValidateConfig) -> Path:
|
|
75
|
+
if config.output_dir is not None:
|
|
76
|
+
return config.output_dir
|
|
77
|
+
return Path("outputs") / f"{config.name}--validate" / config.uuid
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _write_rows(path: Path, rows: Sequence[ResultRow]) -> None:
|
|
81
|
+
tmp = path.with_suffix(f"{path.suffix}.tmp")
|
|
82
|
+
with tmp.open("w", encoding="utf-8") as f:
|
|
83
|
+
for row in rows:
|
|
84
|
+
f.write(json.dumps(row, sort_keys=True, separators=(",", ":")) + "\n")
|
|
85
|
+
tmp.replace(path)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def append_result(results_dir: Path, row: ResultRow) -> None:
|
|
89
|
+
data = json.dumps(row, sort_keys=True, separators=(",", ":")).encode()
|
|
90
|
+
with (results_dir / RESULTS_FILE).open("ab") as f:
|
|
91
|
+
f.write(data + b"\n")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _is_final(row: object, key: str, mode: str) -> bool:
|
|
95
|
+
if not isinstance(row, dict):
|
|
96
|
+
return False
|
|
97
|
+
reason = row.get("reason")
|
|
98
|
+
return (
|
|
99
|
+
row.get("task_key") == key
|
|
100
|
+
and row.get("mode") == mode
|
|
101
|
+
and reason in FINAL_REASONS
|
|
102
|
+
and row.get("valid") is (reason == "valid")
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def load_results(
|
|
107
|
+
results_dir: Path, selected_keys: list[str], mode: str
|
|
108
|
+
) -> tuple[list[ResultRow], dict[str, int]]:
|
|
109
|
+
"""Keep final rows by eval task-content key; return counts owed per key."""
|
|
110
|
+
path = results_dir / RESULTS_FILE
|
|
111
|
+
targets = Counter(selected_keys)
|
|
112
|
+
good: dict[str, list[ResultRow]] = defaultdict(list)
|
|
113
|
+
if path.exists():
|
|
114
|
+
with path.open("rb") as f:
|
|
115
|
+
for line in f:
|
|
116
|
+
if not line.strip():
|
|
117
|
+
continue
|
|
118
|
+
try:
|
|
119
|
+
row = from_json(line)
|
|
120
|
+
except ValueError:
|
|
121
|
+
try:
|
|
122
|
+
row = json.loads(line)
|
|
123
|
+
except (json.JSONDecodeError, UnicodeDecodeError):
|
|
124
|
+
continue
|
|
125
|
+
if not isinstance(row, dict):
|
|
126
|
+
continue
|
|
127
|
+
key = row.get("task_key")
|
|
128
|
+
if (
|
|
129
|
+
isinstance(key, str)
|
|
130
|
+
and key in targets
|
|
131
|
+
and len(good[key]) < targets[key]
|
|
132
|
+
and _is_final(row, key, mode)
|
|
133
|
+
):
|
|
134
|
+
good[key].append(row)
|
|
135
|
+
|
|
136
|
+
owed = {
|
|
137
|
+
key: target - len(good.get(key, []))
|
|
138
|
+
for key, target in targets.items()
|
|
139
|
+
if len(good.get(key, [])) < target
|
|
140
|
+
}
|
|
141
|
+
# Eval spreads debt over content-identical selected tasks in order. Assign the
|
|
142
|
+
# interchangeable kept rows to the remaining positions so reporting positions
|
|
143
|
+
# stay unique even when duplicate task content exists.
|
|
144
|
+
counts = distribute(selected_keys, owed, 1)
|
|
145
|
+
rows = []
|
|
146
|
+
used = Counter()
|
|
147
|
+
for position, (key, count) in enumerate(zip(selected_keys, counts)):
|
|
148
|
+
if count:
|
|
149
|
+
continue
|
|
150
|
+
row = good[key][used[key]]
|
|
151
|
+
used[key] += 1
|
|
152
|
+
rows.append({**row, "task_position": position})
|
|
153
|
+
_write_rows(path, rows)
|
|
154
|
+
return rows, owed
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def summarize(rows: Sequence[ResultRow], total: int, mode: str) -> dict[str, Any]:
|
|
158
|
+
counts = Counter(row.get("reason") for row in rows)
|
|
159
|
+
missing = max(0, total - len(rows))
|
|
160
|
+
outcomes = {reason: counts[reason] for reason in REASONS}
|
|
161
|
+
outcomes["missing"] = missing
|
|
162
|
+
terminal = outcomes["valid"] + outcomes["invalid"]
|
|
163
|
+
summary: dict[str, Any] = {
|
|
164
|
+
"mode": mode,
|
|
165
|
+
"total": total,
|
|
166
|
+
"recorded": len(rows),
|
|
167
|
+
"terminal": terminal,
|
|
168
|
+
"owed": missing + outcomes["error"] + outcomes["timeout"],
|
|
169
|
+
"outcomes": outcomes,
|
|
170
|
+
"valid_rate": round(outcomes["valid"] / total, 6) if total else None,
|
|
171
|
+
}
|
|
172
|
+
if mode == "all":
|
|
173
|
+
checks: dict[str, dict[str, int]] = {}
|
|
174
|
+
for check in ("gold", "setup"):
|
|
175
|
+
check_counts = Counter(
|
|
176
|
+
row.get(check, {}).get("reason")
|
|
177
|
+
for row in rows
|
|
178
|
+
if isinstance(row.get(check), dict)
|
|
179
|
+
)
|
|
180
|
+
checks[check] = {reason: check_counts[reason] for reason in REASONS}
|
|
181
|
+
checks[check]["missing"] = missing
|
|
182
|
+
summary["checks"] = checks
|
|
183
|
+
return summary
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def write_summary(results_dir: Path, summary: Mapping[str, Any]) -> None:
|
|
187
|
+
path = results_dir / SUMMARY_FILE
|
|
188
|
+
tmp = path.with_suffix(f"{path.suffix}.tmp")
|
|
189
|
+
tmp.write_text(json.dumps(summary, indent=2, sort_keys=True) + "\n")
|
|
190
|
+
tmp.replace(path)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def save_run(config: ValidateConfig, results_dir: Path, total: int) -> None:
|
|
194
|
+
write_config(config, results_dir)
|
|
195
|
+
(results_dir / RESULTS_FILE).write_text("")
|
|
196
|
+
write_summary(results_dir, summarize([], total, validation_mode(config)))
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
def load_resume_config(resume_dir: Path) -> ValidateConfig:
|
|
200
|
+
path = resume_dir / CONFIG_FILE
|
|
201
|
+
if not path.exists():
|
|
202
|
+
raise SystemExit(
|
|
203
|
+
f"--resume: no config.toml in {resume_dir} - not a validate output dir"
|
|
204
|
+
)
|
|
205
|
+
config = ValidateConfig.model_validate(tomllib.loads(path.read_text()))
|
|
206
|
+
config.resume = resume_dir
|
|
207
|
+
config.output_dir = resume_dir
|
|
208
|
+
return config
|
|
49
209
|
|
|
50
210
|
|
|
51
211
|
def _classify(valid: bool, exc: BaseException | None) -> str:
|
|
@@ -217,27 +377,64 @@ async def run_validate(config: ValidateConfig) -> list[dict]:
|
|
|
217
377
|
raise SystemExit(
|
|
218
378
|
"taskset needs a container runtime to validate - pass --runtime.type docker (or prime)"
|
|
219
379
|
)
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
)
|
|
380
|
+
mode = validation_mode(config)
|
|
381
|
+
checks = "gold+setup" if mode == "all" else mode
|
|
382
|
+
out = output_path(config)
|
|
383
|
+
selected_keys = [
|
|
384
|
+
task_key(task.data.model_dump(mode="json", exclude_none=True)) for task in tasks
|
|
385
|
+
]
|
|
386
|
+
if config.resume is None:
|
|
387
|
+
save_run(config, out, len(tasks))
|
|
388
|
+
rows: list[ResultRow] = []
|
|
389
|
+
counts = [1] * len(tasks)
|
|
390
|
+
else:
|
|
391
|
+
rows, owed = load_results(out, selected_keys, mode)
|
|
392
|
+
counts = distribute(selected_keys, owed, 1)
|
|
393
|
+
write_summary(out, summarize(rows, len(tasks), mode))
|
|
394
|
+
plan = [
|
|
395
|
+
(position, task, key)
|
|
396
|
+
for position, (task, key, count) in enumerate(zip(tasks, selected_keys, counts))
|
|
397
|
+
if count
|
|
398
|
+
]
|
|
223
399
|
logger.info(
|
|
224
|
-
"
|
|
400
|
+
"%s %d/%d task(s) from %s on the %s runtime (%s)",
|
|
401
|
+
"resuming" if config.resume is not None else "validating",
|
|
402
|
+
len(plan),
|
|
225
403
|
len(tasks),
|
|
226
404
|
config.name,
|
|
227
405
|
config.runtime.type,
|
|
228
406
|
checks,
|
|
229
407
|
)
|
|
408
|
+
logger.info("results: %s", out)
|
|
230
409
|
|
|
231
410
|
sem = asyncio.Semaphore(config.max_concurrent) if config.max_concurrent else None
|
|
232
411
|
states = [TaskProgress(idx=t.data.idx, name=t.data.name) for t in tasks]
|
|
233
|
-
|
|
412
|
+
for row in rows:
|
|
413
|
+
state = states[row["task_position"]]
|
|
414
|
+
state.state = row["reason"]
|
|
415
|
+
|
|
416
|
+
write_lock = asyncio.Lock()
|
|
234
417
|
|
|
235
|
-
async def _one(task) ->
|
|
236
|
-
st =
|
|
418
|
+
async def _one(position: int, task: Task, key: str) -> ResultRow:
|
|
419
|
+
st = states[position]
|
|
237
420
|
async with sem or contextlib.nullcontext():
|
|
238
421
|
st.start = time.time()
|
|
239
422
|
st.state = "running"
|
|
240
423
|
row = await _validate_task(task, config)
|
|
424
|
+
row["task_position"] = position
|
|
425
|
+
row["task_key"] = key
|
|
426
|
+
|
|
427
|
+
async def persist() -> None:
|
|
428
|
+
async with write_lock:
|
|
429
|
+
await asyncio.to_thread(append_result, out, row)
|
|
430
|
+
rows.append(row)
|
|
431
|
+
await asyncio.to_thread(
|
|
432
|
+
write_summary,
|
|
433
|
+
out,
|
|
434
|
+
summarize(rows, len(tasks), mode),
|
|
435
|
+
)
|
|
436
|
+
|
|
437
|
+
await run_shielded(persist())
|
|
241
438
|
st.end, st.state = time.time(), row["reason"]
|
|
242
439
|
if not config.rich: # the dashboard shows this live; otherwise log each task
|
|
243
440
|
detail = f" - {row['error']}" if row["error"] else ""
|
|
@@ -257,7 +454,17 @@ async def run_validate(config: ValidateConfig) -> list[dict]:
|
|
|
257
454
|
else contextlib.nullcontext()
|
|
258
455
|
)
|
|
259
456
|
async with display:
|
|
260
|
-
|
|
457
|
+
if not plan:
|
|
458
|
+
logger.info(
|
|
459
|
+
"nothing to resume: all %d task(s) are valid or invalid", len(tasks)
|
|
460
|
+
)
|
|
461
|
+
return rows
|
|
462
|
+
await asyncio.gather(
|
|
463
|
+
*(_one(position, task, key) for position, task, key in plan)
|
|
464
|
+
)
|
|
465
|
+
rows.sort(key=lambda row: row["task_position"])
|
|
466
|
+
write_summary(out, summarize(rows, len(tasks), mode))
|
|
467
|
+
return rows
|
|
261
468
|
|
|
262
469
|
|
|
263
470
|
def main(argv: list[str] | None = None) -> None:
|
|
@@ -271,27 +478,46 @@ def main(argv: list[str] | None = None) -> None:
|
|
|
271
478
|
with plugin_errors():
|
|
272
479
|
cli(_narrow(argv)) # full option help, narrowed to the given taskset
|
|
273
480
|
return
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
481
|
+
resume_dir, rest = split_resume(argv, "validate")
|
|
482
|
+
if resume_dir is not None:
|
|
483
|
+
if rest:
|
|
484
|
+
raise SystemExit(
|
|
485
|
+
f"{USAGE}\n--resume replays the saved config and takes no other arguments"
|
|
486
|
+
)
|
|
487
|
+
with plugin_errors():
|
|
488
|
+
config = load_resume_config(resume_dir)
|
|
489
|
+
else:
|
|
490
|
+
if not extract_id(argv, "taskset") and not references_config_file(argv):
|
|
491
|
+
raise SystemExit(
|
|
492
|
+
USAGE
|
|
493
|
+
) # need a taskset (positional / --taskset.id) or a @ file.toml
|
|
494
|
+
|
|
495
|
+
with plugin_errors():
|
|
496
|
+
config_type = _narrow(argv)
|
|
497
|
+
sys.argv = [
|
|
498
|
+
sys.argv[0],
|
|
499
|
+
*argv,
|
|
500
|
+
] # let prime-pydantic-config render help/errors
|
|
501
|
+
config = cli(config_type)
|
|
502
|
+
out = output_path(config)
|
|
503
|
+
setup_logging(
|
|
504
|
+
"DEBUG" if config.verbose else "INFO",
|
|
505
|
+
log_file=str(out / LOG_FILE),
|
|
506
|
+
console=not config.rich,
|
|
507
|
+
)
|
|
289
508
|
if config.rich:
|
|
290
509
|
logging.lastResort = None # drop stdlib records that bypass loguru
|
|
291
510
|
# Graceful shutdown: first Ctrl-C/SIGTERM unwinds each task's teardown `finally`
|
|
292
511
|
# (containers/sandboxes); a second is swallowed so it can't orphan them mid-cleanup.
|
|
293
512
|
install_interrupt()
|
|
294
|
-
|
|
513
|
+
try:
|
|
514
|
+
asyncio.run(run_validate(config))
|
|
515
|
+
except KeyboardInterrupt:
|
|
516
|
+
print(f"interrupted; partial results: {out}", file=sys.stderr)
|
|
517
|
+
raise SystemExit(130)
|
|
518
|
+
summary = json.loads((out / SUMMARY_FILE).read_text())
|
|
519
|
+
print(f"results: {out}")
|
|
520
|
+
print(json.dumps(summary, indent=2, sort_keys=True))
|
|
295
521
|
|
|
296
522
|
|
|
297
523
|
if __name__ == "__main__":
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
"""Configuration for model-free task validation."""
|
|
2
2
|
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from uuid import uuid4
|
|
5
|
+
|
|
3
6
|
from pydantic import AliasChoices, Field, SerializeAsAny, model_validator
|
|
4
7
|
from pydantic_config import BaseConfig
|
|
5
8
|
|
|
@@ -16,6 +19,9 @@ class CheckTimeoutConfig(BaseConfig):
|
|
|
16
19
|
|
|
17
20
|
|
|
18
21
|
class ValidateConfig(BaseConfig):
|
|
22
|
+
uuid: str = Field(default_factory=lambda: str(uuid4()), exclude=True)
|
|
23
|
+
"""Auto-generated run id — the default output directory leaf. Excluded from the
|
|
24
|
+
saved config so re-running it starts a fresh run."""
|
|
19
25
|
taskset: SerializeAsAny[TasksetConfig] = TasksetConfig()
|
|
20
26
|
runtime: RuntimeConfig = DockerConfig()
|
|
21
27
|
"""Where each task's validation hooks run."""
|
|
@@ -40,6 +46,14 @@ class ValidateConfig(BaseConfig):
|
|
|
40
46
|
"""Log at debug level instead of the default info."""
|
|
41
47
|
rich: bool = True
|
|
42
48
|
"""Show a live dashboard (one row per task) instead of per-task log lines."""
|
|
49
|
+
output_dir: Path | None = Field(
|
|
50
|
+
None, validation_alias=AliasChoices("output_dir", "o")
|
|
51
|
+
)
|
|
52
|
+
"""Where to write config.toml, results.jsonl, summary.json, and validate.log. None
|
|
53
|
+
creates a fresh run under outputs/<taskset>--validate/<uuid>."""
|
|
54
|
+
resume: Path | None = Field(None, exclude=True)
|
|
55
|
+
"""Set by --resume: re-run missing, errored, and timed-out tasks in this directory.
|
|
56
|
+
The saved config is replayed verbatim, so resume takes no other arguments."""
|
|
43
57
|
|
|
44
58
|
@property
|
|
45
59
|
def name(self) -> str:
|
|
@@ -13,7 +13,7 @@ from verifiers.v1.runtimes.limiters import creation_limiter
|
|
|
13
13
|
from verifiers.v1.utils.aio import run_shielded
|
|
14
14
|
|
|
15
15
|
# The prime_tunnel service caps tunnel starts at 512/min per API token — a property of the
|
|
16
|
-
# tunnel service, shared by every process
|
|
16
|
+
# tunnel service, shared by every process for the user that opens one. One user-global
|
|
17
17
|
# limiter, not a per-runtime config knob.
|
|
18
18
|
_TUNNELS_PER_MIN = 512
|
|
19
19
|
TUNNEL_LIMITER = creation_limiter(_TUNNELS_PER_MIN / 60, "prime-tunnel")
|
|
@@ -30,7 +30,7 @@ class PrimeTunnel(Tunnel[PrimeTunnelConfig]):
|
|
|
30
30
|
@contextlib.asynccontextmanager
|
|
31
31
|
async def expose(self, port: int) -> AsyncIterator[str]:
|
|
32
32
|
"""Bridge the host `port` to a public URL via prime_tunnel (frpc). Tunnel creation
|
|
33
|
-
is network-bound and globally rate-capped (512/min,
|
|
33
|
+
is network-bound and globally rate-capped (512/min, user-wide via the shared
|
|
34
34
|
`TUNNEL_LIMITER`), so transient failures are retried; a terminal one raises
|
|
35
35
|
`TunnelError`. The tunnel is torn down on exit."""
|
|
36
36
|
from prime_tunnel import Tunnel as TunnelClient
|