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