verifiers 0.3.2.dev168__tar.gz → 0.3.2.dev170__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.3.2.dev168 → verifiers-0.3.2.dev170}/PKG-INFO +2 -2
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/pyproject.toml +1 -1
- verifiers-0.3.2.dev170/tests/v1/fixtures/agent_user_v1.py +82 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/test_e2e.py +29 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/rollout.py +35 -1
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/runtimes/base.py +19 -1
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/runtimes/docker/__init__.py +2 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/runtimes/prime.py +5 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/task.py +4 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/harbor/taskset.py +1 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/artifacts.py +37 -1
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/.gitignore +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/LICENSE +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/README.md +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/conftest.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/fixtures/counter_tool_v1.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/fixtures/duet_v1.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/fixtures/echo_acp_resume_v1.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/fixtures/echo_agentic_v1.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/fixtures/echo_tool_v1.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/fixtures/echo_user_sim_v1.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/fixtures/echo_v1.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/fixtures/pyproject.toml +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/fixtures/tool_response_image_v1.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/test_color_codeword_tasks.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/test_configs.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/test_envs.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/test_graph.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/test_judges.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/test_platform_run.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/test_scoring.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/test_serve_delta.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/test_taskset.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/test_trace.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/acp/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/acp/runner.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/agent.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/dashboard/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/dashboard/base.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/dashboard/eval.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/dashboard/replay.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/dashboard/validate.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/debug.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/eval/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/eval/hint.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/eval/main.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/eval/resume.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/eval/runner.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/gepa.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/init.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/output.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/replay.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/resolve.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/resume.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/cli/validate.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/clients/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/clients/base.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/clients/client.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/clients/eval.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/clients/train.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/agent.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/cli/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/cli/debug.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/cli/env.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/cli/eval.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/cli/init.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/cli/replay.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/cli/validate.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/client.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/env.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/judge.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/retries.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/runtime.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/select.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/serve.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/task.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/configs/taskset.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/dialects/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/dialects/anthropic.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/dialects/base.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/dialects/chat.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/dialects/responses.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/env.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/agentic_judge/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/agentic_judge/env.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/best_of_n/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/best_of_n/env.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/isolated_verifier/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/isolated_verifier/env.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/shared_agentic_judge/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/single_agent/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/single_agent/env.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/user_sim/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/user_sim/env.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/episode.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/errors.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/gepa/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/gepa/adapter.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/gepa/config.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/gepa/dataset.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/gepa/reflection.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/gepa/runner.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/graph.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/bash/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/bash/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/browser_use/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/browser_use/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/browser_use/program.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/claude_code/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/claude_code/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/codex/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/codex/gate.mjs +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/codex/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/hermes_agent/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/hermes_agent/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/hermes_agent/program.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/kimi_code/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/kimi_code/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/mini_swe_agent/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/mini_swe_agent/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/mini_swe_agent/program.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/node.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/null/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/null/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/openclaw/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/openclaw/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/pi/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/pi/gate.mjs +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/pi/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/prime_agent/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/prime_agent/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/rlm/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/rlm/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/terminus_2/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/terminus_2/harness.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/terminus_2/program.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/utils/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/utils/compaction.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/utils/core.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/utils/install.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/utils/launch.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/harnesses/utils/mcp.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/interception/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/interception/base.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/interception/pool.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/interception/server.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/interception/tunnel/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/interception/tunnel/base.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/interception/tunnel/custom.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/interception/tunnel/prime.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/judge.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/judges/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/judges/reference.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/judges/reference.txt +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/judges/rubric.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/judges/rubric.txt +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/mcp/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/mcp/launch.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/mcp/server.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/mcp/toolset.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/runtimes/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/runtimes/apptainer.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/runtimes/container.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/runtimes/docker/egress.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/runtimes/e2b.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/runtimes/limiters.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/runtimes/modal.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/runtimes/subprocess.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/semantic.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/serve/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/serve/client.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/serve/delta.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/serve/encoding.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/serve/pool.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/serve/server.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/serve/types.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/session.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/state.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/taskset.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/harbor/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/harbor/compose.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/harbor/env.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/harbor/toolset.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/nemo_gym/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/nemo_gym/response.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/nemo_gym/server.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/nemo_gym/taskset.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/nemo_gym/toolset.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/openenv/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/openenv/taskset.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/textarena/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/tasksets/textarena/taskset.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/trace.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/types.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/__init__.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/aio.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/compile.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/decorators.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/format.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/generic.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/git.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/image.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/interrupt.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/loaders.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/logging.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/memory.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/paths.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/platform.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/prime.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/retries.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/scope.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/score.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/trace_store.py +0 -0
- {verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/utils/version.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: verifiers
|
|
3
|
-
Version: 0.3.2.
|
|
3
|
+
Version: 0.3.2.dev170
|
|
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
|
|
@@ -36,7 +36,7 @@ Requires-Dist: numpy>=2.1.0
|
|
|
36
36
|
Requires-Dist: openai<3.0.0,>=2.54.0
|
|
37
37
|
Requires-Dist: prime-pydantic-config[toml]>=0.4.3
|
|
38
38
|
Requires-Dist: prime-runs>=0.1.3
|
|
39
|
-
Requires-Dist: prime-sandboxes>=0.
|
|
39
|
+
Requires-Dist: prime-sandboxes>=0.4.1
|
|
40
40
|
Requires-Dist: prime-tunnel>=0.1.8
|
|
41
41
|
Requires-Dist: pydantic>=2.12.3
|
|
42
42
|
Requires-Dist: pyzmq>=27.1.0
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"""agent-user-v1: a scripted, model-free agent that runs as a non-root user and tries root actions.
|
|
2
|
+
|
|
3
|
+
Task setup runs as root: it creates the task's `agent_user` (images normally ship one),
|
|
4
|
+
plants a root-only secret, and hands the workdir to that user. The scripted harness then runs
|
|
5
|
+
as that user, attempts four actions only root may take, and records each outcome in the
|
|
6
|
+
workdir. The reward is 1 only if every root action was denied while the agent still saw the
|
|
7
|
+
secret and could write its workspace.
|
|
8
|
+
Needs a runtime that can switch users (docker or prime).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import json
|
|
12
|
+
|
|
13
|
+
import verifiers.v1 as vf
|
|
14
|
+
from verifiers.v1.clients import ModelContext
|
|
15
|
+
from verifiers.v1.configs.harness import HarnessConfig
|
|
16
|
+
from verifiers.v1.harness import Harness
|
|
17
|
+
from verifiers.v1.runtimes import ProgramResult, Runtime
|
|
18
|
+
|
|
19
|
+
__all__ = ["AgentUserTaskset", "ScriptedAgentUserHarness"]
|
|
20
|
+
|
|
21
|
+
AGENT_USER = "vf-agent"
|
|
22
|
+
SECRET = "/opt/vf-agent-user-secret"
|
|
23
|
+
REPORT = "agent-user-report.json"
|
|
24
|
+
ROOT_ACTIONS = ("read_secret", "write_etc", "chmod_secret", "signal_init")
|
|
25
|
+
|
|
26
|
+
SETUP = (
|
|
27
|
+
f"useradd -m {AGENT_USER} && echo secret > {SECRET} && chmod 600 {SECRET} "
|
|
28
|
+
f"&& chown -R {AGENT_USER} ."
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
PROBE = f"""
|
|
32
|
+
r() {{ "$@" >/dev/null 2>&1 && echo ok || echo denied; }}
|
|
33
|
+
printf '{{"user":"%s","secret_exists":"%s","read_secret":"%s","write_etc":"%s","chmod_secret":"%s","signal_init":"%s","write_workdir":"%s"}}' \\
|
|
34
|
+
"$(id -un)" "$(r test -e {SECRET})" "$(r cat {SECRET})" "$(r touch /etc/vf-agent-user-probe)" \\
|
|
35
|
+
"$(r chmod 644 {SECRET})" "$(r kill -0 1)" "$(r touch probe)" > {REPORT}
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class ScriptedAgentUserHarness(Harness[HarnessConfig]):
|
|
40
|
+
async def launch(
|
|
41
|
+
self,
|
|
42
|
+
ctx: ModelContext,
|
|
43
|
+
trace: vf.Trace,
|
|
44
|
+
runtime: Runtime,
|
|
45
|
+
endpoint: str,
|
|
46
|
+
secret: str,
|
|
47
|
+
mcp_urls: dict[str, str],
|
|
48
|
+
data: vf.TaskData,
|
|
49
|
+
tool_interception_url: str | None = None,
|
|
50
|
+
) -> ProgramResult:
|
|
51
|
+
return await runtime.run_program(["sh", "-c", PROBE], {})
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class AgentUserTask(vf.Task):
|
|
55
|
+
async def setup(self, trace: vf.Trace, runtime: Runtime) -> None:
|
|
56
|
+
result = await runtime.run(["sh", "-c", SETUP], {})
|
|
57
|
+
if result.exit_code != 0:
|
|
58
|
+
raise RuntimeError(f"root setup failed: {result.stderr}")
|
|
59
|
+
|
|
60
|
+
@vf.reward(weight=1.0)
|
|
61
|
+
async def root_actions_denied(self, trace: vf.Trace, runtime: Runtime) -> float:
|
|
62
|
+
report = json.loads(await runtime.read(REPORT))
|
|
63
|
+
trace.info["agent_user_report"] = report
|
|
64
|
+
return float(
|
|
65
|
+
report["user"] == AGENT_USER
|
|
66
|
+
and report["secret_exists"] == "ok"
|
|
67
|
+
and report["write_workdir"] == "ok"
|
|
68
|
+
and all(report[action] == "denied" for action in ROOT_ACTIONS)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class AgentUserTaskset(vf.Taskset[AgentUserTask, vf.TasksetConfig]):
|
|
73
|
+
def load(self) -> list[AgentUserTask]:
|
|
74
|
+
return [
|
|
75
|
+
AgentUserTask(
|
|
76
|
+
vf.TaskData(
|
|
77
|
+
idx=0,
|
|
78
|
+
prompt="Scripted: try root-only actions as a non-root user.",
|
|
79
|
+
agent_user=AGENT_USER,
|
|
80
|
+
)
|
|
81
|
+
)
|
|
82
|
+
]
|
|
@@ -190,6 +190,12 @@ USER_RUNTIMES = [
|
|
|
190
190
|
pytest.param("e2b", marks=[mark.e2b], id="harness-in-e2b"),
|
|
191
191
|
]
|
|
192
192
|
|
|
193
|
+
# Runtimes that can switch users (`Runtime.with_user`).
|
|
194
|
+
AGENT_USER_RUNTIMES = [
|
|
195
|
+
pytest.param("docker", marks=[mark.docker], id="harness-in-docker"),
|
|
196
|
+
pytest.param("prime", marks=[mark.prime], id="harness-in-prime"),
|
|
197
|
+
]
|
|
198
|
+
|
|
193
199
|
# ACP-backed harnesses: each must preserve an exchange across interaction segments and
|
|
194
200
|
# retain MCP access after resuming. Cover every harness in the local container runtime,
|
|
195
201
|
# plus remote placements for the sandbox/tunnel and native-process boundaries.
|
|
@@ -332,6 +338,29 @@ async def test_browser_use(run_v1, tmp_path):
|
|
|
332
338
|
assert trace.reward == 1.0
|
|
333
339
|
|
|
334
340
|
|
|
341
|
+
@pytest.mark.e2e
|
|
342
|
+
@pytest.mark.parametrize("harness_runtime", AGENT_USER_RUNTIMES, indirect=True)
|
|
343
|
+
async def test_agent_user_cannot_act_as_root(run_v1, harness_runtime, tmp_path):
|
|
344
|
+
"""A scripted, model-free agent runs as the task's non-root `agent_user`: it can see
|
|
345
|
+
the secret the root-run setup planted and write its own workspace, but every
|
|
346
|
+
root-only action (read the secret, write /etc, chmod the secret, signal PID 1) is
|
|
347
|
+
denied."""
|
|
348
|
+
(trace,) = await run_v1(
|
|
349
|
+
"agent-user-v1",
|
|
350
|
+
harness="agent-user-v1",
|
|
351
|
+
runtime={"type": harness_runtime},
|
|
352
|
+
output_dir=tmp_path,
|
|
353
|
+
)
|
|
354
|
+
report = trace.info["agent_user_report"]
|
|
355
|
+
assert report["user"] == "vf-agent"
|
|
356
|
+
assert report["secret_exists"] == "ok" and report["write_workdir"] == "ok"
|
|
357
|
+
root_actions = ("read_secret", "write_etc", "chmod_secret", "signal_init")
|
|
358
|
+
assert {action: report[action] for action in root_actions} == dict.fromkeys(
|
|
359
|
+
root_actions, "denied"
|
|
360
|
+
)
|
|
361
|
+
assert trace.reward == 1.0
|
|
362
|
+
|
|
363
|
+
|
|
335
364
|
@pytest.mark.e2e
|
|
336
365
|
@pytest.mark.parametrize("harness_runtime", USER_RUNTIMES, indirect=True)
|
|
337
366
|
async def test_user(run_v1, harness_runtime, tmp_path):
|
|
@@ -14,6 +14,7 @@ from verifiers.v1.configs.runtime import NetworkPolicyConfig
|
|
|
14
14
|
from verifiers.v1.errors import (
|
|
15
15
|
HarnessError,
|
|
16
16
|
RolloutError,
|
|
17
|
+
SandboxError,
|
|
17
18
|
TaskError,
|
|
18
19
|
ToolsetError,
|
|
19
20
|
boundary,
|
|
@@ -52,6 +53,39 @@ class RolloutTimeouts:
|
|
|
52
53
|
"""Timeout (in seconds) for the task + harness metrics + scoring hooks."""
|
|
53
54
|
|
|
54
55
|
|
|
56
|
+
_HOME_PROBE = (
|
|
57
|
+
"home=$(awk -F: -v u=\"$1\" '$1 == u { print $6 }' /etc/passwd); "
|
|
58
|
+
'echo "$home"; test -n "$home" && test -d "$home"'
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
async def agent_runtime(runtime: Runtime, user: str | None) -> Runtime:
|
|
63
|
+
"""The runtime the harness runs on: `runtime` itself, or a view running as `user`
|
|
64
|
+
with `HOME` set to its home. `user` must exist with a home directory it can write
|
|
65
|
+
(task authors ship it in the image), and the view must really run as it, so a
|
|
66
|
+
runtime ignoring the user never runs the agent as root."""
|
|
67
|
+
if user is None:
|
|
68
|
+
return runtime
|
|
69
|
+
lookup = await runtime.run(["sh", "-c", _HOME_PROBE, "sh", user], {})
|
|
70
|
+
home = lookup.stdout.strip()
|
|
71
|
+
if not home:
|
|
72
|
+
raise TaskError(f"agent_user {user!r} does not exist in the image")
|
|
73
|
+
if lookup.exit_code != 0:
|
|
74
|
+
raise TaskError(f"agent_user {user!r} has no home directory ({home})")
|
|
75
|
+
view = runtime.with_user(user)
|
|
76
|
+
view = view.with_env({**view.env, "HOME": home})
|
|
77
|
+
probe = await view.run(["sh", "-c", 'id -un; test -w "$HOME" && echo writable'], {})
|
|
78
|
+
effective, *rest = probe.stdout.split() or [""]
|
|
79
|
+
if effective != user:
|
|
80
|
+
raise SandboxError(
|
|
81
|
+
f"{type(runtime).__name__} ran as {effective!r} instead of agent_user "
|
|
82
|
+
f"{user!r}; refusing to run the agent"
|
|
83
|
+
)
|
|
84
|
+
if rest != ["writable"]:
|
|
85
|
+
raise TaskError(f"agent_user {user!r} cannot write its home directory ({home})")
|
|
86
|
+
return view
|
|
87
|
+
|
|
88
|
+
|
|
55
89
|
class Rollout:
|
|
56
90
|
"""Manages one rollout's lifecycle (open, step, close)."""
|
|
57
91
|
|
|
@@ -341,7 +375,7 @@ class Rollout:
|
|
|
341
375
|
self._harness_session = await self.harness.session(
|
|
342
376
|
self.ctx,
|
|
343
377
|
self.trace,
|
|
344
|
-
runtime,
|
|
378
|
+
await agent_runtime(runtime, harness_data.agent_user),
|
|
345
379
|
self._endpoint,
|
|
346
380
|
self._secret,
|
|
347
381
|
self._urls,
|
|
@@ -136,13 +136,16 @@ class BaseRuntimeInfo(BaseConfig):
|
|
|
136
136
|
|
|
137
137
|
|
|
138
138
|
class Runtime(ABC):
|
|
139
|
-
__slots__ = ("env",)
|
|
139
|
+
__slots__ = ("env", "user")
|
|
140
140
|
|
|
141
141
|
is_local: bool = True
|
|
142
142
|
"""Whether this runtime exchanges host-local URLs without a public tunnel. True for
|
|
143
143
|
subprocess and the local container runtimes; remote runtimes override to False and
|
|
144
144
|
use a host `Tunnel` inward plus `expose` outward."""
|
|
145
145
|
|
|
146
|
+
supports_user: ClassVar[bool] = False
|
|
147
|
+
"""Whether `with_user` can run this runtime's commands as another existing user."""
|
|
148
|
+
|
|
146
149
|
scripts_dir: ClassVar[str] = "/tmp/vf-scripts"
|
|
147
150
|
"""Digest-keyed PEP 723 scripts inside the runtime. Sandboxes own their `/tmp`;
|
|
148
151
|
the host subprocess runtime overrides this with its per-user cache."""
|
|
@@ -159,6 +162,8 @@ class Runtime(ABC):
|
|
|
159
162
|
# Per-run task values live on the runtime rather than its serializable config/info.
|
|
160
163
|
# Explicit process values (model credentials, proxy settings, etc.) override these.
|
|
161
164
|
self.env: dict[str, str] = {}
|
|
165
|
+
self.user: str | None = None
|
|
166
|
+
"""Existing user this view runs commands as; None uses the runtime's default."""
|
|
162
167
|
self._uv_interpreters: dict[str, str] = {}
|
|
163
168
|
self._uv_script_locks: dict[str, asyncio.Lock] = {}
|
|
164
169
|
self._mcp_sources: set[str] = set()
|
|
@@ -215,6 +220,19 @@ class Runtime(ABC):
|
|
|
215
220
|
runtime.env = dict(env)
|
|
216
221
|
return runtime
|
|
217
222
|
|
|
223
|
+
def with_user(self, user: str | None) -> "Runtime":
|
|
224
|
+
"""Share this physical runtime through a view that runs commands as `user`, an
|
|
225
|
+
existing user in the box (None keeps the default). Only the view runs as `user`:
|
|
226
|
+
setup, collection, and grading keep using the original runtime."""
|
|
227
|
+
if user is not None and not self.supports_user:
|
|
228
|
+
raise ValueError(
|
|
229
|
+
f"{type(self).__name__} cannot run commands as another user"
|
|
230
|
+
)
|
|
231
|
+
runtime = copy.copy(self)
|
|
232
|
+
runtime.__dict__ = self.__dict__
|
|
233
|
+
runtime.user = user
|
|
234
|
+
return runtime
|
|
235
|
+
|
|
218
236
|
async def alive(self) -> bool:
|
|
219
237
|
"""Whether the box still executes anything. Not every runtime raises when
|
|
220
238
|
the box is gone — some surface it as `exec`'s own non-zero result,
|
|
@@ -70,6 +70,7 @@ control.sendmsg([b"listener"], [(socket.SOL_SOCKET, socket.SCM_RIGHTS, array.arr
|
|
|
70
70
|
|
|
71
71
|
|
|
72
72
|
class DockerRuntime(ContainerRuntime):
|
|
73
|
+
supports_user: ClassVar[bool] = True
|
|
73
74
|
engine: ClassVar[str] = "docker"
|
|
74
75
|
"""The CLI binary for the shared OCI container operations."""
|
|
75
76
|
info_cls: ClassVar[type[BaseRuntimeInfo]] = DockerRuntimeInfo
|
|
@@ -529,6 +530,7 @@ class DockerRuntime(ContainerRuntime):
|
|
|
529
530
|
"exec",
|
|
530
531
|
*(("-i",) if stdin else ()),
|
|
531
532
|
*(arg for key, value in env.items() for arg in ("--env", f"{key}={value}")),
|
|
533
|
+
*(("--user", self.user) if self.user is not None else ()),
|
|
532
534
|
"--workdir",
|
|
533
535
|
self.config.workdir,
|
|
534
536
|
self._container,
|
|
@@ -144,6 +144,7 @@ class PrimeProcess(RuntimeProcess):
|
|
|
144
144
|
|
|
145
145
|
|
|
146
146
|
class PrimeRuntime(Runtime):
|
|
147
|
+
supports_user: ClassVar[bool] = True
|
|
147
148
|
is_local: ClassVar[bool] = False
|
|
148
149
|
|
|
149
150
|
def __init__(self, config: PrimeConfig, name: str | None = None) -> None:
|
|
@@ -292,6 +293,7 @@ class PrimeRuntime(Runtime):
|
|
|
292
293
|
shlex.join(argv),
|
|
293
294
|
working_dir=self.config.workdir,
|
|
294
295
|
env=self.process_env(env),
|
|
296
|
+
user=self.user,
|
|
295
297
|
)
|
|
296
298
|
delay = 0.1
|
|
297
299
|
output_retries = 0
|
|
@@ -335,6 +337,7 @@ class PrimeRuntime(Runtime):
|
|
|
335
337
|
shlex.join(argv),
|
|
336
338
|
working_dir=self.config.workdir,
|
|
337
339
|
env=self.process_env(env),
|
|
340
|
+
user=self.user,
|
|
338
341
|
)
|
|
339
342
|
except Exception as e:
|
|
340
343
|
raise SandboxError(f"prime live process failed to start: {e}") from e
|
|
@@ -356,6 +359,7 @@ class PrimeRuntime(Runtime):
|
|
|
356
359
|
command,
|
|
357
360
|
working_dir=self.config.workdir,
|
|
358
361
|
env=self.process_env(env),
|
|
362
|
+
user=self.user,
|
|
359
363
|
)
|
|
360
364
|
except Exception as e:
|
|
361
365
|
raise SandboxError(f"prime background launch failed: {e}") from e
|
|
@@ -370,6 +374,7 @@ class PrimeRuntime(Runtime):
|
|
|
370
374
|
f"head -c {max_bytes} -- {shlex.quote(path)}",
|
|
371
375
|
working_dir=self.config.workdir,
|
|
372
376
|
env=self.process_env({}),
|
|
377
|
+
user=self.user,
|
|
373
378
|
)
|
|
374
379
|
async with contextlib.aclosing(process):
|
|
375
380
|
with io.BytesIO() as data:
|
|
@@ -99,6 +99,10 @@ class TaskData(BaseModel):
|
|
|
99
99
|
"""Optional Docker image to use for the task. Only relevant for tasks that run in a container."""
|
|
100
100
|
workdir: str | None = None
|
|
101
101
|
"""Optional working directory to use for the task. Only relevant for tasks that run in a container."""
|
|
102
|
+
agent_user: str | None = None
|
|
103
|
+
"""Existing user in the task's box that the harness, and so every command the agent
|
|
104
|
+
runs, executes as. None uses the runtime's default user (usually root). Task setup,
|
|
105
|
+
harness setup, artifact collection, and grading keep running as the default user."""
|
|
102
106
|
|
|
103
107
|
skills: list[SkillSource] = Field(default_factory=list)
|
|
104
108
|
"""Skill sources installed before the harness's configured skills for this task."""
|
|
@@ -676,6 +676,7 @@ def parse_task(task_dir: Path, idx: int, harbor_config: HarborConfig) -> HarborD
|
|
|
676
676
|
prompt=harbor_task.instruction.strip(),
|
|
677
677
|
image=image,
|
|
678
678
|
workdir=environment.workdir,
|
|
679
|
+
agent_user=None if parsed.agent.user is None else str(parsed.agent.user),
|
|
679
680
|
network_allow=(
|
|
680
681
|
["*"]
|
|
681
682
|
if network.network_mode == NetworkMode.PUBLIC
|
|
@@ -190,7 +190,17 @@ async def _tar_out(runtime: Runtime, artifact: Artifact, budget: int) -> bytes:
|
|
|
190
190
|
)
|
|
191
191
|
# The runtime enforces the remaining collection budget while transferring the
|
|
192
192
|
# bytes, so replacing or growing the archive cannot race a separate size probe.
|
|
193
|
-
|
|
193
|
+
archive, dropped = _drop_special_files(
|
|
194
|
+
await runtime.read(path, max_bytes=budget)
|
|
195
|
+
)
|
|
196
|
+
if dropped:
|
|
197
|
+
logger.warning(
|
|
198
|
+
"artifact %r: dropped %d FIFO or device node(s), e.g. %s",
|
|
199
|
+
artifact.source,
|
|
200
|
+
len(dropped),
|
|
201
|
+
dropped[:3],
|
|
202
|
+
)
|
|
203
|
+
return archive
|
|
194
204
|
finally:
|
|
195
205
|
# Best-effort: the box is about to be destroyed and the name is unique per call.
|
|
196
206
|
try:
|
|
@@ -199,6 +209,32 @@ async def _tar_out(runtime: Runtime, artifact: Artifact, budget: int) -> bytes:
|
|
|
199
209
|
logger.debug("failed to remove %s", path, exc_info=True)
|
|
200
210
|
|
|
201
211
|
|
|
212
|
+
def _drop_special_files(archive: bytes) -> tuple[bytes, list[str]]:
|
|
213
|
+
"""Remove FIFOs and device nodes, plus hard links to them, from a collected archive.
|
|
214
|
+
|
|
215
|
+
They carry no content, and `restore` refuses them, so one an agent leaves in its
|
|
216
|
+
workspace (e.g. a named pipe it made to test streaming input) would otherwise fail
|
|
217
|
+
the whole restore. Returns the archive and the dropped member names."""
|
|
218
|
+
with tarfile.open(fileobj=io.BytesIO(archive), mode="r:") as source:
|
|
219
|
+
members = source.getmembers()
|
|
220
|
+
special = {m.name for m in members if m.isfifo() or m.ischr() or m.isblk()}
|
|
221
|
+
if not special:
|
|
222
|
+
return archive, []
|
|
223
|
+
dropped = [
|
|
224
|
+
m.name
|
|
225
|
+
for m in members
|
|
226
|
+
if m.name in special or (m.islnk() and m.linkname in special)
|
|
227
|
+
]
|
|
228
|
+
out = io.BytesIO()
|
|
229
|
+
with tarfile.open(fileobj=out, mode="w:", format=source.format) as target:
|
|
230
|
+
for member in members:
|
|
231
|
+
if member.name in dropped:
|
|
232
|
+
continue
|
|
233
|
+
content = source.extractfile(member) if member.isfile() else None
|
|
234
|
+
target.addfile(member, content)
|
|
235
|
+
return out.getvalue(), dropped
|
|
236
|
+
|
|
237
|
+
|
|
202
238
|
def _validate_restore(root: str, archive: bytes | None) -> None:
|
|
203
239
|
"""Reject archive content that could restore outside its declared root."""
|
|
204
240
|
root_path = PurePosixPath(root)
|
|
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
|
{verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/tests/v1/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
|
|
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
|
{verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/agentic_judge/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/isolated_verifier/__init__.py
RENAMED
|
File without changes
|
{verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/isolated_verifier/env.py
RENAMED
|
File without changes
|
{verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/shared_agentic_judge/__init__.py
RENAMED
|
File without changes
|
{verifiers-0.3.2.dev168 → verifiers-0.3.2.dev170}/verifiers/v1/envs/single_agent/__init__.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
|