verifiers 0.4.1.dev29__tar.gz → 0.4.1.dev31__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/PKG-INFO +1 -1
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/pyproject.toml +1 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/conftest.py +3 -1
- verifiers-0.4.1.dev31/tests/integration/fixtures/echo_tool_compose/docker-compose.yaml +7 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/echo_tool_v1.py +12 -3
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/grid.py +11 -2
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_multi_turn_tool.py +28 -6
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/dialects/anthropic.py +26 -1
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/dialects/base.py +1 -1
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/dialects/responses.py +1 -1
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/interception/server.py +3 -1
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/mcp/launch.py +36 -2
- verifiers-0.4.1.dev31/verifiers/v1/mcp/toolset.py +55 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/rollout.py +16 -1
- verifiers-0.4.1.dev29/verifiers/v1/mcp/toolset.py +0 -34
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/.gitignore +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/LICENSE +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/README.md +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/agent_user_harness_v1.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/agent_user_v1.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/counter_tool_v1.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/duet_v1.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/echo_acp_resume_v1.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/echo_agentic_v1.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/echo_user_sim_v1.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/echo_v1.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/network_policy_v1.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/pyproject.toml +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/skill_codeword_v1.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/skills/project-codeword/SKILL.md +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/tool_response_image_v1.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_agent_user.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_agentic_judge.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_compose_scoring.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_examples.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_limits.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_multi_agent.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_multi_turn.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_multimodal_tool.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_network_policy.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_resume_tool.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_rubric_judge.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_sampling.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_shared_tool.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_single_turn.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_skills.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_stateful_tool.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_user_echo.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/test_user_sim.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/cli/test_replay.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/conftest.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/harnesses/test_core.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/harnesses/test_rlm.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/interception/test_tunnel.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/judges/conftest.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/judges/test_judge.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/judges/test_reference.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/judges/test_rubric.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/runtimes/test_e2b.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/serve/test_client.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/serve/test_delta.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/serve/test_pool.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/test_agent.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/test_dialects.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/test_graph.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/test_semantic.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/test_task.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/test_taskset.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/test_trace.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/utils/test_compile.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/utils/test_loaders.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/utils/test_platform.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/unit/utils/test_score.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/acp/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/acp/runner.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/agent.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/dashboard/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/dashboard/base.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/dashboard/eval.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/dashboard/replay.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/dashboard/validate.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/debug.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/eval/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/eval/hint.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/eval/main.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/eval/resume.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/eval/runner.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/gepa.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/replay.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/resume.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/cli/validate.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/clients/base.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/agent.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/cli/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/cli/debug.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/cli/env.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/cli/eval.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/cli/replay.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/cli/validate.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/client.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/env.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/judge.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/retries.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/runtime.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/scoring.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/select.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/serve.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/task.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/configs/taskset.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/dialects/chat.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/env.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/envs/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/envs/agentic_judge/env.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/envs/best_of_n/env.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/envs/single_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/envs/single_agent/env.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/envs/user_sim/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/envs/user_sim/env.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/episode.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/errors.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/gepa/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/gepa/adapter.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/gepa/config.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/gepa/dataset.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/gepa/reflection.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/gepa/runner.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/grading.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/graph.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/bash/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/bash/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/browser_use/program.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/codex/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/node.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/null/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/null/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/opencode/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/opencode/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/opencode/mcp-ready.js +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/pi/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/pi/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/rlm/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/utils/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/utils/compaction.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/utils/core.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/utils/install.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/utils/launch.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/utils/mcp.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/harnesses/utils/replay.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/interception/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/interception/base.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/interception/pool.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/interception/tunnel/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/interception/tunnel/base.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/interception/tunnel/custom.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/interception/tunnel/prime.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/judge.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/judges/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/judges/decision.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/judges/reference.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/judges/reference.txt +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/judges/rubric.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/judges/rubric.txt +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/mcp/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/mcp/server.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/apptainer.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/base.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/compose.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/container.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/deployment.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/docker/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/docker/egress.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/e2b.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/limiters.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/modal.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/prime.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/runtime.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/strategies.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/runtimes/subprocess.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/semantic.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/serve/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/serve/client.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/serve/delta.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/serve/encoding.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/serve/pool.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/serve/server.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/serve/types.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/session.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/state.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/task.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/harbor/taskset.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/trace.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/types.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/aio.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/artifacts.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/compile.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/decorators.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/env.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/eval.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/generic.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/git.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/image.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/interrupt.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/loaders.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/memory.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/paths.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/platform.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/prime.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/retries.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/scope.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/score.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/verifiers/v1/utils/trace_store.py +0 -0
- {verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/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.
|
|
3
|
+
Version: 0.4.1.dev31
|
|
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.
|
|
6
|
-
it runs colocated in the harness's runtime
|
|
7
|
-
|
|
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
|
|
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,
|
|
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(
|
|
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`,
|
|
36
|
-
are a different scope (`Taskset.toolsets`),
|
|
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)
|
|
@@ -24,6 +24,7 @@ from verifiers.v1.dialects.base import (
|
|
|
24
24
|
parse_sse_event,
|
|
25
25
|
provider_domains,
|
|
26
26
|
)
|
|
27
|
+
from verifiers.v1.errors import ProviderError
|
|
27
28
|
from verifiers.v1.types import (
|
|
28
29
|
AssistantMessage,
|
|
29
30
|
ContentPart,
|
|
@@ -51,6 +52,18 @@ STOP_REASONS: dict[str, FinishReason] = {
|
|
|
51
52
|
"tool_use": "tool_calls",
|
|
52
53
|
"stop_sequence": "stop",
|
|
53
54
|
}
|
|
55
|
+
ERROR_TYPES = {
|
|
56
|
+
400: "invalid_request_error",
|
|
57
|
+
401: "authentication_error",
|
|
58
|
+
403: "permission_error",
|
|
59
|
+
404: "not_found_error",
|
|
60
|
+
413: "request_too_large",
|
|
61
|
+
429: "rate_limit_error",
|
|
62
|
+
502: "api_error",
|
|
63
|
+
529: "overloaded_error",
|
|
64
|
+
}
|
|
65
|
+
ERROR_STATUSES = {kind: status for status, kind in ERROR_TYPES.items()}
|
|
66
|
+
|
|
54
67
|
# Claude may reorder mixed thinking block types between a response and its replay.
|
|
55
68
|
# Native tool events share the final rank, preserving their relative order.
|
|
56
69
|
THINKING_ORDER = {"redacted_thinking": 0, "thinking": 1}
|
|
@@ -356,6 +369,11 @@ class AnthropicStreamParser(StreamParser):
|
|
|
356
369
|
if event is None:
|
|
357
370
|
return
|
|
358
371
|
kind = event.get("type")
|
|
372
|
+
if kind == "error":
|
|
373
|
+
# HTTP 200 streams can fail in-band; preserve the provider's cause and IDs.
|
|
374
|
+
detail = event.get("error") or {}
|
|
375
|
+
status = ERROR_STATUSES.get(detail.get("type"), 502)
|
|
376
|
+
raise ProviderError(json.dumps(event), status_code=status)
|
|
359
377
|
if kind == "message_start":
|
|
360
378
|
self.message = event.get("message") or {}
|
|
361
379
|
elif kind == "content_block_start":
|
|
@@ -516,7 +534,14 @@ class AnthropicDialect(Dialect[AnthropicMessage]):
|
|
|
516
534
|
# Anthropic's own keepalive; its SDKs skip it anywhere in the stream.
|
|
517
535
|
return b'event: ping\ndata: {"type": "ping"}\n\n'
|
|
518
536
|
|
|
519
|
-
def stream_error(self, error: dict) -> bytes:
|
|
537
|
+
def stream_error(self, error: dict, *, status_code: int | None = None) -> bytes:
|
|
538
|
+
# Once HTTP 200 is committed, clients classify retries from the SSE error type.
|
|
539
|
+
if status_code is not None:
|
|
540
|
+
kind = ERROR_TYPES.get(
|
|
541
|
+
status_code,
|
|
542
|
+
"api_error" if status_code >= 500 else "invalid_request_error",
|
|
543
|
+
)
|
|
544
|
+
error = {**error, "error": {**error.get("error", {}), "type": kind}}
|
|
520
545
|
# The Anthropic SDKs raise only on a named `error` event.
|
|
521
546
|
return b"event: error\ndata: " + json.dumps(error).encode() + b"\n\n"
|
|
522
547
|
|
|
@@ -318,7 +318,7 @@ class Dialect(ABC, Generic[RespT]):
|
|
|
318
318
|
# Don't terminate an empty event; some SSE clients try to JSON-decode it.
|
|
319
319
|
return b": keepalive\n"
|
|
320
320
|
|
|
321
|
-
def stream_error(self, error: dict) -> bytes:
|
|
321
|
+
def stream_error(self, error: dict, *, status_code: int | None = None) -> bytes:
|
|
322
322
|
"""An `error_body` as an SSE event, for a failure after the stream is committed.
|
|
323
323
|
OpenAI SDKs raise on any event carrying `error`."""
|
|
324
324
|
return b"data: " + json.dumps(error).encode() + b"\n\n"
|
|
@@ -687,7 +687,7 @@ class ResponsesDialect(Dialect[OpenAIResponse]):
|
|
|
687
687
|
payload = {"type": kind, "sequence_number": 0, "response": _KEEPALIVE_RESPONSE}
|
|
688
688
|
return f"event: {kind}\ndata: {json.dumps(payload)}\n\n".encode()
|
|
689
689
|
|
|
690
|
-
def stream_error(self, error: dict) -> bytes:
|
|
690
|
+
def stream_error(self, error: dict, *, status_code: int | None = None) -> bytes:
|
|
691
691
|
# `response.failed` is what Responses clients (codex) act on; the `error` key is what
|
|
692
692
|
# the OpenAI SDK raises on.
|
|
693
693
|
message = error["error"]["message"]
|
|
@@ -288,7 +288,9 @@ async def _buffered_stream(
|
|
|
288
288
|
await stream.write(
|
|
289
289
|
replay.body
|
|
290
290
|
if response.status < 400
|
|
291
|
-
else dialect.stream_error(
|
|
291
|
+
else dialect.stream_error(
|
|
292
|
+
from_json(replay.body), status_code=response.status
|
|
293
|
+
)
|
|
292
294
|
)
|
|
293
295
|
await stream.write_eof()
|
|
294
296
|
except ConnectionResetError:
|
|
@@ -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
|
-
[
|
|
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
|
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/agent_user_harness_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/counter_tool_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/echo_acp_resume_v1.py
RENAMED
|
File without changes
|
{verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/echo_agentic_v1.py
RENAMED
|
File without changes
|
{verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/echo_user_sim_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/network_policy_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/skill_codeword_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
{verifiers-0.4.1.dev29 → verifiers-0.4.1.dev31}/tests/integration/fixtures/tool_response_image_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|