verifiers 0.4.1.dev29__tar.gz → 0.4.1.dev30__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 (268) hide show
  1. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/PKG-INFO +1 -1
  2. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/pyproject.toml +1 -0
  3. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/conftest.py +3 -1
  4. verifiers-0.4.1.dev30/tests/integration/fixtures/echo_tool_compose/docker-compose.yaml +7 -0
  5. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/echo_tool_v1.py +12 -3
  6. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/grid.py +11 -2
  7. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_multi_turn_tool.py +28 -6
  8. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/mcp/launch.py +36 -2
  9. verifiers-0.4.1.dev30/verifiers/v1/mcp/toolset.py +55 -0
  10. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/rollout.py +16 -1
  11. verifiers-0.4.1.dev29/verifiers/v1/mcp/toolset.py +0 -34
  12. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/.gitignore +0 -0
  13. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/LICENSE +0 -0
  14. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/README.md +0 -0
  15. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/agent_user_harness_v1.py +0 -0
  16. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/agent_user_v1.py +0 -0
  17. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/counter_tool_v1.py +0 -0
  18. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/duet_v1.py +0 -0
  19. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/echo_acp_resume_v1.py +0 -0
  20. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/echo_agentic_v1.py +0 -0
  21. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/echo_user_sim_v1.py +0 -0
  22. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/echo_v1.py +0 -0
  23. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/network_policy_v1.py +0 -0
  24. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/pyproject.toml +0 -0
  25. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/skill_codeword_v1.py +0 -0
  26. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/skills/project-codeword/SKILL.md +0 -0
  27. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/fixtures/tool_response_image_v1.py +0 -0
  28. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_agent_user.py +0 -0
  29. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_agentic_judge.py +0 -0
  30. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_compose_scoring.py +0 -0
  31. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_examples.py +0 -0
  32. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_limits.py +0 -0
  33. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_multi_agent.py +0 -0
  34. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_multi_turn.py +0 -0
  35. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_multimodal_tool.py +0 -0
  36. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_network_policy.py +0 -0
  37. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_resume_tool.py +0 -0
  38. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_rubric_judge.py +0 -0
  39. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_sampling.py +0 -0
  40. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_shared_tool.py +0 -0
  41. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_single_turn.py +0 -0
  42. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_skills.py +0 -0
  43. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_stateful_tool.py +0 -0
  44. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_user_echo.py +0 -0
  45. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/integration/test_user_sim.py +0 -0
  46. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/cli/test_replay.py +0 -0
  47. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/conftest.py +0 -0
  48. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/harnesses/test_core.py +0 -0
  49. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/harnesses/test_rlm.py +0 -0
  50. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/interception/test_tunnel.py +0 -0
  51. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/judges/conftest.py +0 -0
  52. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/judges/test_judge.py +0 -0
  53. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/judges/test_reference.py +0 -0
  54. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/judges/test_rubric.py +0 -0
  55. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/runtimes/test_e2b.py +0 -0
  56. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/serve/test_client.py +0 -0
  57. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/serve/test_delta.py +0 -0
  58. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/serve/test_pool.py +0 -0
  59. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/test_agent.py +0 -0
  60. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/test_dialects.py +0 -0
  61. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/test_graph.py +0 -0
  62. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/test_semantic.py +0 -0
  63. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/test_task.py +0 -0
  64. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/test_taskset.py +0 -0
  65. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/test_trace.py +0 -0
  66. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/utils/test_compile.py +0 -0
  67. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/utils/test_loaders.py +0 -0
  68. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/utils/test_platform.py +0 -0
  69. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/tests/unit/utils/test_score.py +0 -0
  70. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/__init__.py +0 -0
  71. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/__init__.py +0 -0
  72. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/acp/__init__.py +0 -0
  73. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/acp/runner.py +0 -0
  74. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/agent.py +0 -0
  75. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/__init__.py +0 -0
  76. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/dashboard/__init__.py +0 -0
  77. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/dashboard/base.py +0 -0
  78. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/dashboard/eval.py +0 -0
  79. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/dashboard/replay.py +0 -0
  80. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/dashboard/validate.py +0 -0
  81. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/debug.py +0 -0
  82. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/eval/__init__.py +0 -0
  83. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/eval/hint.py +0 -0
  84. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/eval/main.py +0 -0
  85. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/eval/resume.py +0 -0
  86. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/eval/runner.py +0 -0
  87. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/gepa.py +0 -0
  88. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/output.py +0 -0
  89. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/replay.py +0 -0
  90. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/resolve.py +0 -0
  91. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/resume.py +0 -0
  92. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/cli/validate.py +0 -0
  93. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/clients/__init__.py +0 -0
  94. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/clients/base.py +0 -0
  95. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/clients/client.py +0 -0
  96. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/clients/eval.py +0 -0
  97. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/clients/train.py +0 -0
  98. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/__init__.py +0 -0
  99. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/agent.py +0 -0
  100. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/cli/__init__.py +0 -0
  101. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/cli/debug.py +0 -0
  102. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/cli/env.py +0 -0
  103. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/cli/eval.py +0 -0
  104. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/cli/replay.py +0 -0
  105. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/cli/validate.py +0 -0
  106. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/client.py +0 -0
  107. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/env.py +0 -0
  108. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/harness.py +0 -0
  109. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/judge.py +0 -0
  110. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/retries.py +0 -0
  111. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/runtime.py +0 -0
  112. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/scoring.py +0 -0
  113. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/select.py +0 -0
  114. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/serve.py +0 -0
  115. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/task.py +0 -0
  116. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/configs/taskset.py +0 -0
  117. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/dialects/__init__.py +0 -0
  118. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/dialects/anthropic.py +0 -0
  119. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/dialects/base.py +0 -0
  120. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/dialects/chat.py +0 -0
  121. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/dialects/responses.py +0 -0
  122. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/env.py +0 -0
  123. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/envs/__init__.py +0 -0
  124. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
  125. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/envs/agentic_judge/env.py +0 -0
  126. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
  127. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/envs/best_of_n/env.py +0 -0
  128. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/envs/single_agent/__init__.py +0 -0
  129. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/envs/single_agent/env.py +0 -0
  130. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/envs/user_sim/__init__.py +0 -0
  131. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/envs/user_sim/env.py +0 -0
  132. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/episode.py +0 -0
  133. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/errors.py +0 -0
  134. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/gepa/__init__.py +0 -0
  135. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/gepa/adapter.py +0 -0
  136. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/gepa/config.py +0 -0
  137. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/gepa/dataset.py +0 -0
  138. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/gepa/reflection.py +0 -0
  139. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/gepa/runner.py +0 -0
  140. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/grading.py +0 -0
  141. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/graph.py +0 -0
  142. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harness.py +0 -0
  143. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/__init__.py +0 -0
  144. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/bash/__init__.py +0 -0
  145. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/bash/harness.py +0 -0
  146. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
  147. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
  148. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/browser_use/program.py +0 -0
  149. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
  150. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
  151. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/codex/__init__.py +0 -0
  152. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
  153. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/codex/harness.py +0 -0
  154. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
  155. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
  156. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
  157. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
  158. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
  159. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
  160. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
  161. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
  162. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/node.py +0 -0
  163. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/null/__init__.py +0 -0
  164. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/null/harness.py +0 -0
  165. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
  166. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
  167. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/opencode/__init__.py +0 -0
  168. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/opencode/harness.py +0 -0
  169. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/opencode/mcp-ready.js +0 -0
  170. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/pi/__init__.py +0 -0
  171. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
  172. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/pi/harness.py +0 -0
  173. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
  174. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
  175. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
  176. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/rlm/harness.py +0 -0
  177. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
  178. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
  179. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
  180. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/utils/__init__.py +0 -0
  181. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/utils/compaction.py +0 -0
  182. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/utils/core.py +0 -0
  183. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/utils/install.py +0 -0
  184. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/utils/launch.py +0 -0
  185. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/utils/mcp.py +0 -0
  186. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/harnesses/utils/replay.py +0 -0
  187. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/interception/__init__.py +0 -0
  188. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/interception/base.py +0 -0
  189. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/interception/pool.py +0 -0
  190. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/interception/server.py +0 -0
  191. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/interception/tunnel/__init__.py +0 -0
  192. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/interception/tunnel/base.py +0 -0
  193. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/interception/tunnel/custom.py +0 -0
  194. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/interception/tunnel/prime.py +0 -0
  195. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/judge.py +0 -0
  196. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/judges/__init__.py +0 -0
  197. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/judges/decision.py +0 -0
  198. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/judges/reference.py +0 -0
  199. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/judges/reference.txt +0 -0
  200. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/judges/rubric.py +0 -0
  201. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/judges/rubric.txt +0 -0
  202. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/mcp/__init__.py +0 -0
  203. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/mcp/server.py +0 -0
  204. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/__init__.py +0 -0
  205. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/apptainer.py +0 -0
  206. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/base.py +0 -0
  207. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/compose.py +0 -0
  208. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/container.py +0 -0
  209. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/deployment.py +0 -0
  210. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/docker/__init__.py +0 -0
  211. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/docker/egress.py +0 -0
  212. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/e2b.py +0 -0
  213. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/limiters.py +0 -0
  214. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/modal.py +0 -0
  215. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/prime.py +0 -0
  216. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/runtime.py +0 -0
  217. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/strategies.py +0 -0
  218. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/runtimes/subprocess.py +0 -0
  219. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/semantic.py +0 -0
  220. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/serve/__init__.py +0 -0
  221. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/serve/client.py +0 -0
  222. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/serve/delta.py +0 -0
  223. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/serve/encoding.py +0 -0
  224. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/serve/pool.py +0 -0
  225. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/serve/server.py +0 -0
  226. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/serve/types.py +0 -0
  227. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/session.py +0 -0
  228. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/state.py +0 -0
  229. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/task.py +0 -0
  230. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/taskset.py +0 -0
  231. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/__init__.py +0 -0
  232. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
  233. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
  234. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
  235. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
  236. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
  237. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
  238. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
  239. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
  240. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
  241. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
  242. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
  243. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
  244. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/trace.py +0 -0
  245. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/types.py +0 -0
  246. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/__init__.py +0 -0
  247. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/aio.py +0 -0
  248. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/artifacts.py +0 -0
  249. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/compile.py +0 -0
  250. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/decorators.py +0 -0
  251. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/env.py +0 -0
  252. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/eval.py +0 -0
  253. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/format.py +0 -0
  254. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/generic.py +0 -0
  255. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/git.py +0 -0
  256. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/image.py +0 -0
  257. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/interrupt.py +0 -0
  258. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/loaders.py +0 -0
  259. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/logging.py +0 -0
  260. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/memory.py +0 -0
  261. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/paths.py +0 -0
  262. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/platform.py +0 -0
  263. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/prime.py +0 -0
  264. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/retries.py +0 -0
  265. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/scope.py +0 -0
  266. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/score.py +0 -0
  267. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/trace_store.py +0 -0
  268. {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev30}/verifiers/v1/utils/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: verifiers
3
- Version: 0.4.1.dev29
3
+ Version: 0.4.1.dev30
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
@@ -231,6 +231,7 @@ markers = [
231
231
  "modal: integration cells touching the modal runtime (external sandbox; local-only, excluded in CI)",
232
232
  "e2b: integration cells touching the e2b runtime (external sandbox; local-only, excluded in CI)",
233
233
  "colocated: integration cells with a tool server colocated in the harness runtime",
234
+ "service: integration cells with a tool server in a Compose service beside the harness",
234
235
  "null: integration cells on the null harness",
235
236
  "bash: integration cells on the bash harness",
236
237
  "claude_code: integration cells on the claude-code harness",
@@ -46,9 +46,11 @@ def harness_runtime(request) -> dict:
46
46
  @pytest.fixture
47
47
  def tool_runtime(request) -> dict:
48
48
  """A `taskset.task.tools` override placing the tool server: `colocated` (inside the harness's
49
- runtime) or its own runtime, by type."""
49
+ runtime), `service` (in the task's `tools` Compose service) or its own runtime, by type."""
50
50
  if request.param == "colocated":
51
51
  return {"colocated": True}
52
+ if request.param == "service":
53
+ return {"service": "tools"}
52
54
  return {"runtime": {"type": request.param}}
53
55
 
54
56
 
@@ -0,0 +1,7 @@
1
+ # echo-tool-v1 with its tool server placed in a Compose service: the server runs in
2
+ # `tools`, beside the workspace (`main`, the runtime's image), and the harness reaches it
3
+ # over the Compose network by the service's name.
4
+ services:
5
+ tools:
6
+ image: python:3.11-slim
7
+ command: [sleep, infinity]
@@ -2,19 +2,23 @@
2
2
 
3
3
  The v1 tool fixture for the integration grid. The task constructs an `EchoToolset`
4
4
  (`vf.Toolset`) in `Task.toolsets`, with one `@vf.tool` method whose placement is
5
- CLI-tunable (`--taskset.task.tools.colocated`, `--taskset.task.tools.runtime.type`):
6
- it runs colocated in the harness's runtime or in its own runtime, and the harness
7
- must reach it wherever it lives. The tool stamps its output with a token the prompt
5
+ CLI-tunable (`--taskset.task.tools.colocated`, `--taskset.task.tools.service`,
6
+ `--taskset.task.tools.runtime.type`): it runs colocated in the harness's runtime, in the
7
+ task's `tools` Compose service (echo_tool_compose), or in its own runtime, and the
8
+ harness must reach it wherever it lives. The tool stamps its output with a token the prompt
8
9
  never reveals, so the reward is 1.0 only if the model actually called the tool —
9
10
  trivial when the infra works, impossible when it doesn't. The tool is task-agnostic,
10
11
  so it would also serve taskset-scoped (`Taskset.toolsets`).
11
12
  """
12
13
 
14
+ from pathlib import Path
15
+
13
16
  import verifiers.v1 as vf
14
17
  from verifiers.v1.types import content_text
15
18
 
16
19
  PHRASE = "hello world"
17
20
  ECHO_TOKEN = "ok-7f3" # the tool stamps this; only a real tool call can surface it
21
+ COMPOSE = Path(__file__).with_name("echo_tool_compose")
18
22
 
19
23
 
20
24
  class EchoToolset(vf.Toolset[vf.ToolsetConfig]):
@@ -35,6 +39,11 @@ class EchoToolTask(vf.Task[vf.TaskData, vf.State, EchoToolTaskConfig]):
35
39
  def toolsets(cls, config: EchoToolTaskConfig) -> list[vf.Toolset]:
36
40
  return [EchoToolset(config.tools)]
37
41
 
42
+ def deployment_spec(self) -> vf.ComposeSpec | None:
43
+ if self.config.tools.service is None:
44
+ return None
45
+ return vf.ComposeSpec(directory=str(COMPOSE), file="docker-compose.yaml")
46
+
38
47
  @vf.reward(weight=1.0)
39
48
  async def echoed(self, trace: vf.Trace) -> float:
40
49
  # A stamped TOOL result proves the tool really ran with the phrase.
@@ -59,6 +59,8 @@ HARNESSES: list[str | dict] = [
59
59
  RUNTIMES = ["subprocess", "docker", "podman", "apptainer", "prime", "modal", "e2b"]
60
60
  ENGINES = ("podman", "apptainer")
61
61
  HARNESS_RUNTIMES = [runtime for runtime in RUNTIMES if runtime not in ENGINES]
62
+ # Runtimes whose VMs run a task's Compose services.
63
+ COMPOSE_VMS = ("prime", "modal")
62
64
 
63
65
  # Harnesses that cannot run against the CI model yet.
64
66
  # TODO: drop each entry once its fix lands.
@@ -208,7 +210,7 @@ def placements(
208
210
  tool_runtimes: tuple[str, ...] = ("colocated", *RUNTIMES),
209
211
  ) -> list:
210
212
  """`(harness_runtime, tool_runtime)` cells for a tool server placed colocated in the
211
- harness's box or in its own runtime."""
213
+ harness's box, in a Compose service beside it (`service`), or in its own runtime."""
212
214
  cells = []
213
215
  for harness_runtime in harness_runtimes:
214
216
  for tool_runtime in tool_runtimes:
@@ -220,8 +222,15 @@ def placements(
220
222
  ]
221
223
  if missing:
222
224
  marks.append(pytest.mark.skip(reason=f"needs {missing[0]} on the host"))
225
+ elif tool_runtime == "service" and harness_runtime not in COMPOSE_VMS:
226
+ marks.append(
227
+ pytest.mark.skip(
228
+ reason="a tool server in a Compose service needs Compose on a "
229
+ "Prime or Modal VM"
230
+ )
231
+ )
223
232
  elif (
224
- tool_runtime != "colocated"
233
+ tool_runtime not in ("colocated", "service")
225
234
  and not runtime_cls(tool_runtime).supports_expose
226
235
  ):
227
236
  marks.append(
@@ -1,11 +1,13 @@
1
1
  """One task, one MCP tool: the model calls a tool whose output carries a stamp the prompt
2
2
  never reveals (echo-tool-v1), so reward 1.0 proves the tool ran. Every MCP harness reaches
3
3
  it colocated across the harness x runtime grid; the chat loop reaches it across its
4
- placements (colocated in the harness's box, or its own runtime) on the runtime x runtime
5
- grid."""
4
+ placements (colocated in the harness's box, in a Compose service beside it, or its own
5
+ runtime) on the runtime x runtime grid."""
6
6
 
7
7
  import pytest
8
- from grid import grid, placements
8
+ from grid import RUNTIMES, grid, placements
9
+
10
+ import verifiers.v1 as vf
9
11
 
10
12
 
11
13
  @pytest.mark.parametrize("harness,harness_runtime", grid(needs=("mcp",)), indirect=True)
@@ -29,11 +31,16 @@ async def test_tool(run, harness, harness_runtime):
29
31
  assert trace.reward == 1.0
30
32
 
31
33
 
32
- @pytest.mark.parametrize("harness_runtime,tool_runtime", placements(), indirect=True)
34
+ @pytest.mark.parametrize(
35
+ "harness_runtime,tool_runtime",
36
+ placements(tool_runtimes=("colocated", "service", *RUNTIMES)),
37
+ indirect=True,
38
+ )
33
39
  async def test_tool_placement(run, harness_runtime, tool_runtime):
34
40
  """A `vf.Toolset` across its placement (`tool_runtime`: colocated in the harness's
35
- runtime, or its own runtime) x the harness `runtime`, on the chat loop. Eval-wide SHARED servers
36
- are a different scope (`Taskset.toolsets`), covered by `test_shared_tool`."""
41
+ runtime, in a Compose service beside it, or its own runtime) x the harness `runtime`,
42
+ on the chat loop. Eval-wide SHARED servers are a different scope (`Taskset.toolsets`),
43
+ covered by `test_shared_tool`."""
37
44
  (episode,) = await run(
38
45
  "echo-tool-v1",
39
46
  harness="null",
@@ -51,3 +58,18 @@ async def test_tool_placement(run, harness_runtime, tool_runtime):
51
58
  assert trace.tools
52
59
  (echo_tool,) = [tool for tool in trace.tools if tool.name.endswith("back")]
53
60
  assert "message" in echo_tool.parameters.get("properties", {})
61
+
62
+
63
+ @pytest.mark.parametrize(
64
+ "placement",
65
+ [
66
+ {"colocated": True},
67
+ {"url": "http://example.com/mcp"},
68
+ {"runtime": {"type": "prime"}},
69
+ ],
70
+ )
71
+ def test_service_placement_is_exclusive(placement):
72
+ """A server in a Compose service runs there: not colocated, remote or in a runtime of
73
+ its own."""
74
+ with pytest.raises(ValueError):
75
+ vf.ToolsetConfig(service="tools", **placement)
@@ -11,7 +11,7 @@ import sys
11
11
  import sysconfig
12
12
  import tempfile
13
13
  import uuid
14
- from collections.abc import AsyncIterator
14
+ from collections.abc import AsyncIterator, Mapping
15
15
  from dataclasses import dataclass, field
16
16
  from functools import cache
17
17
  from importlib.metadata import PathDistribution, distribution, packages_distributions
@@ -325,6 +325,7 @@ async def serve_in_runtime(
325
325
  runtime: Runtime,
326
326
  *,
327
327
  exposed: bool,
328
+ listen_all: bool = False,
328
329
  state_url: str | None = None,
329
330
  state_secret: str = "",
330
331
  ) -> int:
@@ -345,7 +346,7 @@ async def serve_in_runtime(
345
346
  # Keep provider temp files in the runtime workdir so cleanup removes them.
346
347
  assert runtime.info.id is not None
347
348
  env["TMPDIR"] = runtime.info.id
348
- if exposed and runtime.published_port is not None:
349
+ if listen_all or (exposed and runtime.published_port is not None):
349
350
  env["MCP_HOST"] = "0.0.0.0"
350
351
  fixed = runtime.published_port if exposed else None
351
352
  port_file = None
@@ -432,9 +433,38 @@ async def _serve(
432
433
  *,
433
434
  state_secret: str = "",
434
435
  state_base: str | None = None,
436
+ services: Mapping[str, Runtime] | None = None,
435
437
  ):
436
438
  cfg = server.config
437
439
  colocated = getattr(cfg, "colocated", False)
440
+ if (service := getattr(cfg, "service", None)) is not None:
441
+ # The harness reaches the server over the deployment's Compose network.
442
+ if services is None or service not in services:
443
+ raise ToolsetError(
444
+ f"server {server.server_name!r} runs in Compose service {service!r}, "
445
+ "which needs a task whose Compose services define it"
446
+ )
447
+ runtime = services[service]
448
+ if runtime.is_local:
449
+ # A local service cannot reach the host-loopback state channel.
450
+ raise ToolsetError(
451
+ f"server {server.server_name!r} runs in Compose service {service!r}, "
452
+ "which needs Compose on a Prime or Modal VM"
453
+ )
454
+ port = await serve_in_runtime(
455
+ server,
456
+ runtime,
457
+ exposed=False,
458
+ listen_all=True,
459
+ state_url=(
460
+ runtime.host_url(f"{state_base.rstrip('/')}/state")
461
+ if state_base
462
+ else None
463
+ ),
464
+ state_secret=state_secret,
465
+ )
466
+ yield _ServedServer(f"http://{service}:{port}/mcp", runtime)
467
+ return
438
468
  async with contextlib.AsyncExitStack() as stack:
439
469
  # Colocated servers inherit the harness cut. A separately provisioned filtered
440
470
  # server has neither that lifecycle nor a published port after isolation;
@@ -501,6 +531,7 @@ async def serve(
501
531
  *,
502
532
  state_secret: str = "",
503
533
  state_base: str | None = None,
534
+ services: Mapping[str, Runtime] | None = None,
504
535
  ):
505
536
  """Serve one MCP server and yield the URL visible to its consumer."""
506
537
  async with _serve(
@@ -509,6 +540,7 @@ async def serve(
509
540
  harness_is_local,
510
541
  state_secret=state_secret,
511
542
  state_base=state_base,
543
+ services=services,
512
544
  ) as served:
513
545
  yield served.url
514
546
 
@@ -616,6 +648,7 @@ async def serve_tools(
616
648
  state_secret: str = "",
617
649
  state_route: str = "",
618
650
  state_base: str | None = None,
651
+ services: Mapping[str, Runtime] | None = None,
619
652
  ):
620
653
  """Bring up a rollout's tool servers and yield `{name: url}` the harness reaches: the
621
654
  task-scoped `toolsets` are launched by `serve` (placement off each one's `config`; the
@@ -656,6 +689,7 @@ async def serve_tools(
656
689
  harness_runtime,
657
690
  state_secret=state_secret,
658
691
  state_base=state_base,
692
+ services=services,
659
693
  )
660
694
  )
661
695
  logger.info("tool server '%s': %s", name, urls[name])
@@ -0,0 +1,55 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from pydantic import model_validator
6
+ from pydantic_config import BaseConfig
7
+
8
+ from verifiers.v1.mcp.server import ConfigT, ServerBase
9
+ from verifiers.v1.runtimes import RuntimeConfig, SubprocessConfig
10
+ from verifiers.v1.state import StateT
11
+ from verifiers.v1.utils.decorators import discover_decorated
12
+
13
+ if TYPE_CHECKING:
14
+ from mcp.server.mcpserver import MCPServer
15
+
16
+
17
+ class ToolsetConfig(BaseConfig):
18
+ colocated: bool = False
19
+ runtime: RuntimeConfig = SubprocessConfig()
20
+ url: str | None = None
21
+ service: str | None = None
22
+ """Run the server in this service of the task's Compose services (on a Prime or
23
+ Modal VM). The harness reaches it over the Compose network by the service's name,
24
+ so the workspace needs no access to whatever the server fronts."""
25
+
26
+ @model_validator(mode="after")
27
+ def _one_placement(self):
28
+ if self.service is None:
29
+ return self
30
+ if self.colocated or self.url:
31
+ raise ValueError(
32
+ "a tool server placed in a Compose service is neither colocated nor remote"
33
+ )
34
+ # The service is the server's runtime; another one, or its policy, would go unused.
35
+ if not isinstance(self.runtime, SubprocessConfig):
36
+ raise ValueError( # noqa: TRY004 - Pydantic validators must raise ValueError
37
+ "a tool server placed in a Compose service runs in that service and "
38
+ f"takes no runtime of its own (got {self.runtime.type})"
39
+ )
40
+ return self
41
+
42
+
43
+ class SharedToolsetConfig(BaseConfig):
44
+ runtime: RuntimeConfig = SubprocessConfig()
45
+ url: str | None = None
46
+
47
+
48
+ class Toolset(ServerBase[ConfigT, StateT]):
49
+ def register(self, mcp: MCPServer) -> None:
50
+ for fn in discover_decorated(self, "tool"):
51
+ mcp.add_tool(
52
+ self._with_state(fn),
53
+ name=getattr(fn, "tool_name", None) or fn.__name__,
54
+ description=(fn.__doc__ or "").strip() or None,
55
+ )
@@ -7,6 +7,7 @@ import time
7
7
  from collections.abc import Awaitable, Callable
8
8
  from contextlib import AsyncExitStack
9
9
  from dataclasses import dataclass
10
+ from urllib.parse import urlsplit
10
11
 
11
12
  from verifiers.v1.clients import ModelContext
12
13
  from verifiers.v1.configs.agent import AgentConfig
@@ -364,6 +365,14 @@ class Rollout:
364
365
  )
365
366
  self._endpoint = runtime.host_url(f"{base_url.rstrip('/')}/v1")
366
367
  self._secret = model_secret
368
+ services = (
369
+ {
370
+ name: self.deployment.target(name)
371
+ for name in self.deployment.target_backends
372
+ }
373
+ if self.deployment.spec is not None
374
+ else {}
375
+ )
367
376
  self._urls = await self._stack.enter_async_context(
368
377
  serve_tools(
369
378
  toolsets,
@@ -372,12 +381,18 @@ class Rollout:
372
381
  state_secret=state_secret,
373
382
  state_route=self.trace.id,
374
383
  state_base=base_url,
384
+ services=services,
375
385
  )
376
386
  )
377
387
  # Setup and service provisioning are complete. Apply the runtime's
378
388
  # execution policy while preserving the framework routes the agent uses.
389
+ # Compose service names resolve inside the deployment, not as egress.
379
390
  await self.deployment.prepare_execution(
380
- [self._endpoint, *self._urls.values()]
391
+ [
392
+ url
393
+ for url in [self._endpoint, *self._urls.values()]
394
+ if urlsplit(url).hostname not in services
395
+ ]
381
396
  )
382
397
  async with (
383
398
  boundary(HarnessError, "opening harness session"),
@@ -1,34 +0,0 @@
1
- from __future__ import annotations
2
-
3
- from typing import TYPE_CHECKING
4
-
5
- from pydantic_config import BaseConfig
6
-
7
- from verifiers.v1.mcp.server import ConfigT, ServerBase
8
- from verifiers.v1.runtimes import RuntimeConfig, SubprocessConfig
9
- from verifiers.v1.state import StateT
10
- from verifiers.v1.utils.decorators import discover_decorated
11
-
12
- if TYPE_CHECKING:
13
- from mcp.server.mcpserver import MCPServer
14
-
15
-
16
- class ToolsetConfig(BaseConfig):
17
- colocated: bool = False
18
- runtime: RuntimeConfig = SubprocessConfig()
19
- url: str | None = None
20
-
21
-
22
- class SharedToolsetConfig(BaseConfig):
23
- runtime: RuntimeConfig = SubprocessConfig()
24
- url: str | None = None
25
-
26
-
27
- class Toolset(ServerBase[ConfigT, StateT]):
28
- def register(self, mcp: MCPServer) -> None:
29
- for fn in discover_decorated(self, "tool"):
30
- mcp.add_tool(
31
- self._with_state(fn),
32
- name=getattr(fn, "tool_name", None) or fn.__name__,
33
- description=(fn.__doc__ or "").strip() or None,
34
- )
File without changes