benchflow 0.5.3.dev908__tar.gz → 0.5.3.dev957__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.
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/PKG-INFO +1 -1
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/pyproject.toml +1 -1
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/providers/litellm_bedrock_patch.py +5 -0
- benchflow-0.5.3.dev957/src/benchflow/providers/litellm_bedrock_preflight.py +181 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/providers/litellm_runtime.py +33 -1
- benchflow-0.5.3.dev957/src/benchflow/sandbox/_cache_reclaim.py +97 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/lockdown.py +8 -14
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_litellm_hardening.py +187 -1
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_litellm_runtime.py +28 -1
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sandbox_hardening.py +106 -50
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/.gitignore +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/CHANGELOG.md +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/LICENSE +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/README.md +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_dotenv.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_paths.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_run.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_types.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/benchmark_repos.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/config.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/evaluation_results.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/json_safe.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/learner_memory.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/result_metadata.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/reward_events.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/scoring.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/source_provenance.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/task_authoring.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/_utils/yaml_loader.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/acp/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/acp/client.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/acp/container_transport.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/acp/runtime.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/acp/session.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/acp/transport.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/acp/types.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/adapters/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/adapters/harbor.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/adapters/inbound.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/adapters/inspect_ai.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/adapters/ors.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/adapters/terminal_bench.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/codex_config.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/credentials.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/env.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/errors.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/harvey_lab_acp_shim.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/install.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/openclaw_acp_shim.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/pi_acp_launcher.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/protocol.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/providers.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/agents/registry.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/branch.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/cli/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/cli/continue_cmd.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/cli/main.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/cli/trace_import.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/compat/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/compat/harbor_registry.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/continue_run/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/continue_run/batch.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/continue_run/orchestrator.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/continue_run/replay_proxy.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/continue_run/run_folder.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/continue_run/sandbox_proxy.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/contracts/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/contracts/planes.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/contracts/user.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/demo_task/environment/Dockerfile +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/demo_task/instruction.md +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/demo_task/task.toml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/demo_task/tests/test.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/diagnostics.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/environment/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/environment/manifest.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/environment/manifest_env.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/environment/protocol.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/environment/readiness.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/eval_sharding.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/eval_worker.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/evaluation.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/experimental/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/experimental/mcp/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/experimental/mcp/hooks.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/experimental/mcp/reviewer_server.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/hosted_env.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/learner_skills.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/learner_store.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/metrics.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/models.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/monitor.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/providers/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/providers/litellm_config.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/providers/litellm_logging.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/providers/runtime.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/py.typed +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/README.md +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/builtins.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/events.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/file_readers.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/llm.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/memory_scorer.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/node.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/protocol.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/rubric.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/rubric_config.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rewards/validation.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rollout.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rollout_branch.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/rollout_planes.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/runtime.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/_base.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/_compose.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/_compose_files/docker-compose-base.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/_compose_files/docker-compose-build.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/_compose_files/docker-compose-no-network.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/_compose_files/docker-compose-prebuilt.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/_sdk_ops.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/daytona.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/docker.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/metadata.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/modal_impl.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/process.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/protocol.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/services.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/setup.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/snapshot.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sandbox/user.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/scenes.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/sdk.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/self_gen.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/skill_eval/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/skill_eval/_core.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/skill_eval/gepa_export.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/skill_eval/schema.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/skill_policy.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/skills.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/task/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/task/config.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/task/env.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/task/paths.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/task/task.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/task/verifier.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/templates/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/templates/judge.py.tmpl +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/templates/test.sh.tmpl +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/traces/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/traces/huggingface.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/traces/local.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/traces/models.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/traces/parsers.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/traces/task_gen.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/trajectories/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/trajectories/_capture.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/trajectories/export.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/trajectories/metrics.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/trajectories/otel.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/trajectories/tree.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/trajectories/types.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/trajectories/viewer.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/usage_tracking.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/agents/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/agents/test_protocol.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/README.md +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/acp_smoke/environment/Dockerfile +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/acp_smoke/environment/docker-compose.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/acp_smoke/environment/skills/conformance-writer/SKILL.md +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/acp_smoke/instruction.md +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/acp_smoke/solution/solve.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/acp_smoke/task.toml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/acp_smoke/tests/test.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/conformance-results.json +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/proof_multi_agent.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/proof_snapshot.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/run_conformance.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conformance/self_gen_smoke_skills/skill-creator/SKILL.md +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/conftest.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/continue_run/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/continue_run/_helpers.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/continue_run/test_batch.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/continue_run/test_orchestrator.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/continue_run/test_replay_proxy.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/continue_run/test_run_folder.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/environment/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/environment/test_chibench_manifest.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/environment/test_clawsbench_manifest.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/environment/test_manifest.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/environment/test_manifest_env.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/environment/test_protocol.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/environment/test_readiness.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/hello-world-task/environment/Dockerfile +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/hello-world-task/instruction.md +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/hello-world-task/solution/solve.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/hello-world-task/task.toml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/hello-world-task/tests/test.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/terminal-bench-smoke-task/environment/Dockerfile +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/terminal-bench-smoke-task/instruction.md +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/terminal-bench-smoke-task/solution/solve.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/terminal-bench-smoke-task/task.toml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/terminal-bench-smoke-task/tests/test.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/terminal-bench-smoke-task/tests/test_state.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/test_claude.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/test_codex.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/test_codex_custom_provider.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/test_gemini.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/test_openclaw.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/traces/minimal-claude.jsonl +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/examples/traces/minimal-opentraces.jsonl +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/fixtures/mock_acp_agent.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/fixtures/mock_acp_agent_interleaved.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/fixtures/mock_acp_agent_multi_turn.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/fixtures/mock_openai_responses_server.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/check_adapter_evidence.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/check_hosted_env_evidence.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/check_results.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/check_skillsbench_harbor_parity.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/check_trace_to_task_evidence.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/configs/claude-agent-acp.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/configs/codex-acp.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/configs/gemini.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/configs/harvey-lab-harness.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/configs/openclaw.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/configs/opencode.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/configs/openhands.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/configs/pi-acp.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/run.sh +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/run_suite.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/integration/suites/release.yaml +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_acp.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_acp_capability_advertising.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_acp_model_config_dispatch.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_acp_pinned_protocol_guard.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_acp_setup_failure_propagation.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_adapter_scripts.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_adapters.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_agent_cli.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_agent_env_resolution.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_agent_gemini_defaults.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_agent_idle_timeout_cli.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_agent_model_decouple.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_agent_registry.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_agent_setup.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_agent_spec.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_base_install_imports.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_bedrock_thinking.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_branch.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_capture_trajectory.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_clawsbench_slice.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_cli_daytona.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_cli_docs_drift.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_cli_misc.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_compat_harbor_registry.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_config_redaction.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_connect_as_env.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_continuallearningbench_adapter.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_dashboard_credential_env_scrub.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_dashboard_daytona_key.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_dashboard_no_host_paths.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_dashboard_release_evidence.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_dashboard_roadmap.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_dashboard_symlink_ingestion.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_dashboard_sync.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_daytona_command_polling.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_daytona_litellm_runtime.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_daytona_status.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_docker_prune_scoping.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_docker_uploads.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_docs_examples.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_eng50_capabilities.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_env_setup.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_environment_manifest_controls.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_eval_filters_applied.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_eval_sharding.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_eval_single_task_summary.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_eval_source_provenance.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_eval_worker_retry.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_eval_zero_task_guard.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_evaluation_environment_manifest.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_exclude_tasks.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_experiments_status.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_harvey_lab_shim.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_hf_scores.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_hilbench_adapter.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_hosted_env.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_hosted_env_rollout_contract.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_inbound_adapter_manifest.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_inbound_adapters.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_integration_check_results.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_integration_run_suite.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_internet_policy.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_job.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_job_sequential_shared.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_job_sequential_shared_resume.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_judge_symlink_ingestion.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_learner_skills.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_learner_skills_traversal.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_learner_store.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_learner_store_persistence.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_litellm_config.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_litellm_logging.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_litellm_smoke.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_llm_judge.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_llm_judge_event_tags.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_llm_judge_verifier.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_memory_scorer.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_metrics.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_mock_openai_responses_server.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_monitor_scaffold.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_native_acp_usage.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_no_cross_provider_fallback.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_notification_order_real.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_oracle.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_oracle_chokepoint.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_paths_safe.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_paths_symlink_helpers.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_pi_acp_launcher.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_process.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_provider_auth_detection.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_providers.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_reexport.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_registry_invariants.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_release_version.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_resolve_env_helpers.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_reward_node.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_reward_unified_contract.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_rewards.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_rewards_jsonl.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_rollout_architecture.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_rollout_branch.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_rollout_config_path_coercion.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_rollout_environment.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_rollout_import_no_side_effects.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_rollout_on_ask_user_wiring.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_rollout_probe_sandbox_health.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_rollout_upload.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_rubric_config.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_runtime.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_runtime_config_wired.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_runtime_live_sandbox.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sandbox.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sandbox_exec_secret_handling.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sandbox_isolation_copy_traversal.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sandbox_multi_service.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sandbox_protocol.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sandbox_setup.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sandbox_snapshot_contract.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sandbox_upload_symlink.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sandbox_verifier_workspace.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_scene.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_scene_outbox_trial.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_scene_parallel_group.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_scene_result_aggregation.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_scoring.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sdk_internals.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_sdk_lockdown.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_self_gen_cli.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_self_gen_export_error_channel.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_self_gen_export_failures.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_self_gen_orchestration.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_session_request_permission_dispatch.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skill_eval.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skill_eval_dryrun.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skill_eval_integration.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skill_eval_sweep.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skill_eval_traversal.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skill_invocation_artifacts.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skill_policy.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skills.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skills_dir_agent_home_link.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skillsbench_harbor_parity.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skillsbench_harbor_run_suite.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_skillsbench_publish_scrub.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_smoke.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_subscription_auth.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_task_check_eval_consistency.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_task_config.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_task_download.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_tasks.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_token_usage_normalization.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_trace_import_cli.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_trace_task_gen_traversal.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_trace_to_task_evidence.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_traces_huggingface.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_traces_parsers.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_traces_task_gen.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_train_mode_artifact_emission.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_trajectory_integration.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_trajectory_streaming.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_trial_agent_timeout_verify.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_trial_install_agent_timeout.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_trial_litellm_runtime.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_usage_litellm.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_usage_required.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_usage_tracking.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_user.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_verifier_multi_container.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_verifier_output.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_verifier_output_freshness.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_verify.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_workflow_action_pinning.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/test_yaml_config.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/trajectories/__init__.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/trajectories/test_export.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/trajectories/test_export_nan_handling.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/trajectories/test_redaction.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/trajectories/test_step_granularity.py +0 -0
- {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/tests/trajectories/test_tree.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: benchflow
|
|
3
|
-
Version: 0.5.3.
|
|
3
|
+
Version: 0.5.3.dev957
|
|
4
4
|
Summary: Multi-turn agent benchmarking with ACP — run any agent, any model, any provider.
|
|
5
5
|
Project-URL: Homepage, https://github.com/benchflow-ai/benchflow
|
|
6
6
|
Project-URL: Repository, https://github.com/benchflow-ai/benchflow
|
{benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/providers/litellm_bedrock_patch.py
RENAMED
|
@@ -70,6 +70,11 @@ def _patch_bedrock_effort() -> None:
|
|
|
70
70
|
reasoning_effort = override
|
|
71
71
|
return original(self, model, reasoning_effort, optional_params)
|
|
72
72
|
|
|
73
|
+
# Marker for the fail-closed startup preflight (#602): lets the runtime
|
|
74
|
+
# verify this override is installed without importing this module (which
|
|
75
|
+
# would itself apply the patches and mask a sitecustomize load failure).
|
|
76
|
+
setattr(handle, "__benchflow_bedrock_patch__", True) # noqa: B010
|
|
77
|
+
|
|
73
78
|
setattr( # noqa: B010 - avoids static type narrowing on monkey-patched vendor API
|
|
74
79
|
AmazonConverseConfig,
|
|
75
80
|
"_handle_reasoning_effort_parameter",
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
"""Fail-closed checks for BenchFlow's Bedrock Claude 4.8+ LiteLLM patch."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import shlex
|
|
6
|
+
import shutil
|
|
7
|
+
import subprocess
|
|
8
|
+
import sys
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from benchflow.providers.litellm_config import LiteLLMRoute
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class BedrockPatchPreflightError(RuntimeError):
|
|
16
|
+
"""Raised when the Bedrock patch cannot be proven active."""
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# Behavioral preflight for the Bedrock Claude 4.8+ adaptive-thinking patch
|
|
20
|
+
# (#602). Runs in a fresh interpreter with the same env/PYTHONPATH as the proxy,
|
|
21
|
+
# so site loads the runtime dir's sitecustomize exactly like the proxy process
|
|
22
|
+
# does. It deliberately imports only litellm internals, never the patch module
|
|
23
|
+
# itself, which would apply the patches in-process and mask a load failure.
|
|
24
|
+
BEDROCK_PATCH_PREFLIGHT_SOURCE = """\
|
|
25
|
+
import sys
|
|
26
|
+
|
|
27
|
+
# Probe with a versioned Bedrock inference-profile ID: stock litellm 1.88.0rc1
|
|
28
|
+
# resolves the bare alias through its cost map, so only the versioned form
|
|
29
|
+
# discriminates patched from stock (#602).
|
|
30
|
+
PROBE = "us.anthropic.claude-opus-4-8-20251101-v1:0"
|
|
31
|
+
|
|
32
|
+
failures = []
|
|
33
|
+
try:
|
|
34
|
+
from litellm.llms.anthropic.chat.transformation import AnthropicConfig
|
|
35
|
+
|
|
36
|
+
if not AnthropicConfig._is_adaptive_thinking_model(PROBE):
|
|
37
|
+
failures.append(
|
|
38
|
+
"adaptive-thinking gate inactive: "
|
|
39
|
+
f"_is_adaptive_thinking_model({PROBE!r}) is False"
|
|
40
|
+
)
|
|
41
|
+
except Exception as exc: # noqa: BLE001 - report any import/shape drift
|
|
42
|
+
failures.append(f"anthropic transform unavailable: {exc}")
|
|
43
|
+
try:
|
|
44
|
+
from litellm.llms.bedrock.chat.converse_transformation import AmazonConverseConfig
|
|
45
|
+
|
|
46
|
+
handler = AmazonConverseConfig._handle_reasoning_effort_parameter
|
|
47
|
+
if not getattr(handler, "__benchflow_bedrock_patch__", False):
|
|
48
|
+
failures.append("reasoning-effort override inactive")
|
|
49
|
+
except Exception as exc: # noqa: BLE001 - report any import/shape drift
|
|
50
|
+
failures.append(f"bedrock converse transform unavailable: {exc}")
|
|
51
|
+
if failures:
|
|
52
|
+
print("; ".join(failures))
|
|
53
|
+
sys.exit(1)
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def route_requires_bedrock_patch(route: LiteLLMRoute) -> bool:
|
|
58
|
+
"""True when this resolved route depends on the Bedrock 4.8+ patch (#602)."""
|
|
59
|
+
return (
|
|
60
|
+
route.provider_name == "aws-bedrock"
|
|
61
|
+
and "reasoning_effort" in route.litellm_params
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _python_from_shebang(executable: Path, *, path_env: str | None) -> str | None:
|
|
66
|
+
try:
|
|
67
|
+
line = executable.open("rb").readline(4096).decode(errors="ignore").strip()
|
|
68
|
+
except OSError:
|
|
69
|
+
return None
|
|
70
|
+
if not line.startswith("#!"):
|
|
71
|
+
return None
|
|
72
|
+
try:
|
|
73
|
+
parts = shlex.split(line[2:].strip())
|
|
74
|
+
except ValueError:
|
|
75
|
+
return None
|
|
76
|
+
if not parts:
|
|
77
|
+
return None
|
|
78
|
+
|
|
79
|
+
command = parts[0]
|
|
80
|
+
if Path(command).name == "env":
|
|
81
|
+
args = parts[1:]
|
|
82
|
+
while args and args[0].startswith("-"):
|
|
83
|
+
args = args[1:]
|
|
84
|
+
if not args:
|
|
85
|
+
return None
|
|
86
|
+
command = args[0]
|
|
87
|
+
|
|
88
|
+
if not Path(command).name.startswith("python"):
|
|
89
|
+
return None
|
|
90
|
+
if "/" in command:
|
|
91
|
+
return command
|
|
92
|
+
return shutil.which(command, path=path_env) or command
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _host_python_for_litellm(
|
|
96
|
+
litellm_executable: str, *, env: dict[str, str] | None = None
|
|
97
|
+
) -> str:
|
|
98
|
+
executable = Path(litellm_executable)
|
|
99
|
+
shebang_python = _python_from_shebang(
|
|
100
|
+
executable, path_env=env.get("PATH") if env else None
|
|
101
|
+
)
|
|
102
|
+
if shebang_python:
|
|
103
|
+
return shebang_python
|
|
104
|
+
sibling = executable.with_name("python")
|
|
105
|
+
if sibling.exists():
|
|
106
|
+
return str(sibling)
|
|
107
|
+
return sys.executable
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def _failure_message(runtime: str, detail: str) -> str:
|
|
111
|
+
return (
|
|
112
|
+
"Bedrock Claude 4.8+ adaptive-thinking patch is NOT active in the "
|
|
113
|
+
f"{runtime} LiteLLM runtime: {detail[:2000]}. Failing closed before "
|
|
114
|
+
"agent launch (#602) - a silent fallback would send the legacy thinking "
|
|
115
|
+
"shape Bedrock rejects."
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def preflight_host_bedrock_patch(
|
|
120
|
+
*,
|
|
121
|
+
env: dict[str, str],
|
|
122
|
+
litellm_executable: str,
|
|
123
|
+
) -> None:
|
|
124
|
+
"""Fail closed if the Bedrock 4.8+ patch is not active for the host proxy."""
|
|
125
|
+
try:
|
|
126
|
+
result = subprocess.run(
|
|
127
|
+
[
|
|
128
|
+
_host_python_for_litellm(litellm_executable, env=env),
|
|
129
|
+
"-c",
|
|
130
|
+
BEDROCK_PATCH_PREFLIGHT_SOURCE,
|
|
131
|
+
],
|
|
132
|
+
env=env,
|
|
133
|
+
capture_output=True,
|
|
134
|
+
text=True,
|
|
135
|
+
timeout=120,
|
|
136
|
+
)
|
|
137
|
+
except Exception as exc:
|
|
138
|
+
raise BedrockPatchPreflightError(
|
|
139
|
+
_failure_message("host", f"preflight execution failed: {exc}")
|
|
140
|
+
) from exc
|
|
141
|
+
if result.returncode != 0:
|
|
142
|
+
detail = (result.stdout or "").strip() or (result.stderr or "").strip()
|
|
143
|
+
raise BedrockPatchPreflightError(_failure_message("host", detail))
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
async def preflight_sandbox_bedrock_patch(
|
|
147
|
+
sandbox: Any,
|
|
148
|
+
*,
|
|
149
|
+
python: str,
|
|
150
|
+
runtime_dir: str,
|
|
151
|
+
preflight_path: str,
|
|
152
|
+
) -> None:
|
|
153
|
+
"""Fail closed if the Bedrock 4.8+ patch is not active in a sandbox proxy."""
|
|
154
|
+
command = (
|
|
155
|
+
f"PYTHONPATH={shlex.quote(runtime_dir)} "
|
|
156
|
+
f"{shlex.quote(python)} {shlex.quote(preflight_path)}"
|
|
157
|
+
)
|
|
158
|
+
try:
|
|
159
|
+
result = await sandbox.exec(command, timeout_sec=120)
|
|
160
|
+
except Exception as exc:
|
|
161
|
+
raise BedrockPatchPreflightError(
|
|
162
|
+
_failure_message("sandbox", f"preflight execution failed: {exc}")
|
|
163
|
+
) from exc
|
|
164
|
+
if result.return_code != 0:
|
|
165
|
+
raise BedrockPatchPreflightError(
|
|
166
|
+
_failure_message(
|
|
167
|
+
"sandbox",
|
|
168
|
+
_exec_details("bedrock patch preflight", result),
|
|
169
|
+
)
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def _exec_details(label: str, result: Any) -> str:
|
|
174
|
+
stdout = (getattr(result, "stdout", "") or "").strip()
|
|
175
|
+
stderr = (getattr(result, "stderr", "") or "").strip()
|
|
176
|
+
details = [f"{label} failed with exit code {getattr(result, 'return_code', '?')}"]
|
|
177
|
+
if stdout:
|
|
178
|
+
details.append(f"stdout: {stdout[:2000]}")
|
|
179
|
+
if stderr:
|
|
180
|
+
details.append(f"stderr: {stderr[:2000]}")
|
|
181
|
+
return "; ".join(details)
|
{benchflow-0.5.3.dev908 → benchflow-0.5.3.dev957}/src/benchflow/providers/litellm_runtime.py
RENAMED
|
@@ -27,6 +27,13 @@ import yaml
|
|
|
27
27
|
from benchflow.agents.codex_config import apply_codex_provider_config
|
|
28
28
|
from benchflow.agents.env import uses_native_subscription_auth
|
|
29
29
|
from benchflow.agents.registry import AGENTS
|
|
30
|
+
from benchflow.providers.litellm_bedrock_preflight import (
|
|
31
|
+
BEDROCK_PATCH_PREFLIGHT_SOURCE,
|
|
32
|
+
BedrockPatchPreflightError,
|
|
33
|
+
preflight_host_bedrock_patch,
|
|
34
|
+
preflight_sandbox_bedrock_patch,
|
|
35
|
+
route_requires_bedrock_patch,
|
|
36
|
+
)
|
|
30
37
|
from benchflow.providers.litellm_config import (
|
|
31
38
|
LITELLM_MASTER_KEY_ENV,
|
|
32
39
|
LITELLM_MODEL_ALIAS_ENV,
|
|
@@ -447,12 +454,13 @@ async def _start_host_litellm(
|
|
|
447
454
|
"BENCHFLOW_LITELLM_LOG_PATH": str(log_path),
|
|
448
455
|
}
|
|
449
456
|
)
|
|
457
|
+
litellm_executable = _host_litellm_executable()
|
|
450
458
|
stdout = stdout_path.open("ab")
|
|
451
459
|
stderr = stderr_path.open("ab")
|
|
452
460
|
try:
|
|
453
461
|
process = subprocess.Popen(
|
|
454
462
|
[
|
|
455
|
-
|
|
463
|
+
litellm_executable,
|
|
456
464
|
"--config",
|
|
457
465
|
str(config_path),
|
|
458
466
|
"--host",
|
|
@@ -481,6 +489,14 @@ async def _start_host_litellm(
|
|
|
481
489
|
)
|
|
482
490
|
try:
|
|
483
491
|
await _poll_host_health(runner)
|
|
492
|
+
if route_requires_bedrock_patch(route):
|
|
493
|
+
# Fail closed before the agent launches when the Bedrock 4.8+
|
|
494
|
+
# thinking patch did not activate (#602).
|
|
495
|
+
await asyncio.to_thread(
|
|
496
|
+
preflight_host_bedrock_patch,
|
|
497
|
+
env=env,
|
|
498
|
+
litellm_executable=litellm_executable,
|
|
499
|
+
)
|
|
484
500
|
except BaseException:
|
|
485
501
|
# A proxy that never became healthy still holds provider credentials and
|
|
486
502
|
# an on-disk config with the master key — tear it down, don't leak it.
|
|
@@ -573,6 +589,7 @@ async def _upload_runtime_files_to_sandbox(
|
|
|
573
589
|
"state": f"{runtime_dir}/state.json",
|
|
574
590
|
"venv": f"{runtime_dir}/venv",
|
|
575
591
|
"launch_config": f"{runtime_dir}/launch_config.json",
|
|
592
|
+
"preflight": f"{runtime_dir}/bedrock_patch_preflight.py",
|
|
576
593
|
}
|
|
577
594
|
result = await sandbox.exec(f"mkdir -p {shlex.quote(runtime_dir)}", timeout_sec=20)
|
|
578
595
|
if result.return_code != 0:
|
|
@@ -591,6 +608,9 @@ async def _upload_runtime_files_to_sandbox(
|
|
|
591
608
|
sandbox, f"import {_PATCH_MODULE}\n", paths["sitecustomize"], ".py"
|
|
592
609
|
)
|
|
593
610
|
await _upload_text(sandbox, _sandbox_launcher_source(), paths["launcher"], ".py")
|
|
611
|
+
await _upload_text(
|
|
612
|
+
sandbox, BEDROCK_PATCH_PREFLIGHT_SOURCE, paths["preflight"], ".py"
|
|
613
|
+
)
|
|
594
614
|
return paths
|
|
595
615
|
|
|
596
616
|
|
|
@@ -765,6 +785,16 @@ async def _start_sandbox_litellm(
|
|
|
765
785
|
port=port,
|
|
766
786
|
stderr_path=paths["stderr"],
|
|
767
787
|
)
|
|
788
|
+
if route_requires_bedrock_patch(route):
|
|
789
|
+
# Fail closed before the agent launches when the Bedrock 4.8+
|
|
790
|
+
# thinking patch did not activate (#602). On Daytona this proxy is
|
|
791
|
+
# the only protection — there is no host proxy to fall back to.
|
|
792
|
+
await preflight_sandbox_bedrock_patch(
|
|
793
|
+
sandbox,
|
|
794
|
+
python=python,
|
|
795
|
+
runtime_dir=runtime_dir,
|
|
796
|
+
preflight_path=paths["preflight"],
|
|
797
|
+
)
|
|
768
798
|
except BaseException:
|
|
769
799
|
# Never leak a half-started proxy (provider keys + master_key on disk).
|
|
770
800
|
await _terminate_sandbox_litellm(
|
|
@@ -1054,6 +1084,8 @@ async def ensure_litellm_runtime(
|
|
|
1054
1084
|
session_id=session_id,
|
|
1055
1085
|
agent_name=agent,
|
|
1056
1086
|
)
|
|
1087
|
+
except BedrockPatchPreflightError:
|
|
1088
|
+
raise
|
|
1057
1089
|
except Exception as exc:
|
|
1058
1090
|
return await _fallback_or_raise_for_unavailable_litellm(
|
|
1059
1091
|
usage_cfg=usage_cfg,
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Pre-verifier cache reclaim command construction.
|
|
2
|
+
|
|
3
|
+
The sandbox cannot import benchflow internals, so the reclaim implementation is
|
|
4
|
+
an embedded Python snippet passed to ``python3 -c``. Keep it here instead of in
|
|
5
|
+
``lockdown.py`` so the hardening orchestrator stays readable.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import shlex
|
|
9
|
+
from textwrap import dedent
|
|
10
|
+
|
|
11
|
+
# Symlink- and workspace-safe cache reclaim for #601.
|
|
12
|
+
#
|
|
13
|
+
# The previous shell form (`rm -rf "$u/.cache/uv" ...; rm -rf /tmp/uv-*`) could
|
|
14
|
+
# delete agent-visible state before scoring: `rm -rf` traverses intermediate
|
|
15
|
+
# symlinks (an agent-planted `~/.cache -> /app` turned the cache delete into
|
|
16
|
+
# `rm -rf /app/uv`), and the `/tmp/uv-*` glob matched a legitimate
|
|
17
|
+
# `/tmp/uv-workspace`. The textual `$WS`/`$u` guard saw none of that. Since
|
|
18
|
+
# ``restore_workspace`` defaults to False, nothing undid the damage.
|
|
19
|
+
#
|
|
20
|
+
# This snippet hardens every deletion candidate:
|
|
21
|
+
# - rejects any candidate with a symlink path component, including the final
|
|
22
|
+
# one, so agent-controlled parents can no longer redirect the delete;
|
|
23
|
+
# - resolves protected roots (workspace + /logs, covering /logs/artifacts and
|
|
24
|
+
# /logs/verifier) via realpath and skips candidates overlapping in either
|
|
25
|
+
# direction, applied uniformly to per-user caches, /tmp globs, and apt;
|
|
26
|
+
# - deletes with shutil.rmtree, which removes child symlinks without following
|
|
27
|
+
# them.
|
|
28
|
+
#
|
|
29
|
+
# argv[1] = active workspace (or /nonexistent). argv[2] = optional filesystem
|
|
30
|
+
# prefix, "" in production; tests pass a temp root so the exact production code
|
|
31
|
+
# runs hermetically against a fake filesystem.
|
|
32
|
+
#
|
|
33
|
+
# Fail-safe by construction: if python3 is unavailable the reclaim simply does
|
|
34
|
+
# not run (the trailing `true` swallows it). Losing best-effort ENOSPC mitigation
|
|
35
|
+
# is strictly better than deleting the wrong state.
|
|
36
|
+
RECLAIM_CACHES_PY = dedent(
|
|
37
|
+
"""
|
|
38
|
+
import glob, os, shutil, sys
|
|
39
|
+
|
|
40
|
+
ws = sys.argv[1]
|
|
41
|
+
px = sys.argv[2] if len(sys.argv) > 2 else ''
|
|
42
|
+
|
|
43
|
+
def linked(path):
|
|
44
|
+
p = px or ''
|
|
45
|
+
for part in path[len(px):].strip('/').split('/'):
|
|
46
|
+
p = p + '/' + part
|
|
47
|
+
if os.path.islink(p):
|
|
48
|
+
return True
|
|
49
|
+
return False
|
|
50
|
+
|
|
51
|
+
protected = []
|
|
52
|
+
for root in (ws, px + '/logs'):
|
|
53
|
+
try:
|
|
54
|
+
if root and os.path.exists(root):
|
|
55
|
+
protected.append(os.path.realpath(root))
|
|
56
|
+
except OSError:
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
def overlaps(path):
|
|
60
|
+
return any(
|
|
61
|
+
path == r or path.startswith(r + '/') or r.startswith(path + '/')
|
|
62
|
+
for r in protected
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
cands = [
|
|
66
|
+
u + '/.cache/' + name
|
|
67
|
+
for u in [px + '/root'] + sorted(glob.glob(px + '/home/*'))
|
|
68
|
+
for name in ('uv', 'pip', 'uv_build')
|
|
69
|
+
]
|
|
70
|
+
cands += sorted(glob.glob(px + '/tmp/uv-*'))
|
|
71
|
+
cands += sorted(glob.glob(px + '/tmp/.uv-*'))
|
|
72
|
+
cands += sorted(glob.glob(px + '/var/cache/apt/archives/*.deb'))
|
|
73
|
+
for c in cands:
|
|
74
|
+
try:
|
|
75
|
+
if not os.path.lexists(c) or linked(c):
|
|
76
|
+
continue
|
|
77
|
+
# linked() proved no symlink components below the prefix, so
|
|
78
|
+
# realpath only normalizes the prefix itself - consistent with
|
|
79
|
+
# the realpath'd protected roots.
|
|
80
|
+
if overlaps(os.path.realpath(c)):
|
|
81
|
+
continue
|
|
82
|
+
if os.path.isdir(c):
|
|
83
|
+
shutil.rmtree(c, ignore_errors=True)
|
|
84
|
+
else:
|
|
85
|
+
os.remove(c)
|
|
86
|
+
except OSError:
|
|
87
|
+
pass
|
|
88
|
+
"""
|
|
89
|
+
).strip()
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def build_reclaim_caches_cmd(workspace: str | None) -> str:
|
|
93
|
+
"""Build the best-effort cache reclaim shell command."""
|
|
94
|
+
workspace_arg = shlex.quote(workspace) if workspace else "/nonexistent"
|
|
95
|
+
return (
|
|
96
|
+
f"python3 -c {shlex.quote(RECLAIM_CACHES_PY)} {workspace_arg} 2>/dev/null; true"
|
|
97
|
+
)
|
|
@@ -20,6 +20,7 @@ from pathlib import Path
|
|
|
20
20
|
from typing import TYPE_CHECKING, Any
|
|
21
21
|
|
|
22
22
|
from benchflow.agents.registry import get_sandbox_home_dirs
|
|
23
|
+
from benchflow.sandbox._cache_reclaim import build_reclaim_caches_cmd
|
|
23
24
|
|
|
24
25
|
if TYPE_CHECKING:
|
|
25
26
|
from benchflow.task import Task
|
|
@@ -877,22 +878,15 @@ async def harden_before_verify(
|
|
|
877
878
|
# installed tools, or task assets — and a failure here never blocks the
|
|
878
879
|
# verifier. Runs on `main` only, consistent with the hardening policy above.
|
|
879
880
|
#
|
|
880
|
-
# Workspace-aware: a task can legitimately use
|
|
881
|
-
#
|
|
882
|
-
#
|
|
883
|
-
#
|
|
884
|
-
#
|
|
885
|
-
|
|
881
|
+
# Workspace-aware AND symlink-safe (#601): a task can legitimately use
|
|
882
|
+
# /root, /home/<user>, or /tmp/uv-* as its workspace, and an agent can
|
|
883
|
+
# plant `~/.cache -> /app` so a naive `rm -rf "$u/.cache/uv"` traverses
|
|
884
|
+
# into workspace/output state. The reclaim command rejects symlinked
|
|
885
|
+
# candidates and realpath-guards every deletion against the workspace and
|
|
886
|
+
# /logs — this matters because restore_workspace defaults to False.
|
|
886
887
|
try:
|
|
887
888
|
await env.exec(
|
|
888
|
-
|
|
889
|
-
"for u in /root /home/*; do "
|
|
890
|
-
' case "$WS" in "$u" | "$u"/*) continue ;; esac; '
|
|
891
|
-
' case "$u" in "$WS"/*) continue ;; esac; '
|
|
892
|
-
' rm -rf "$u/.cache/uv" "$u/.cache/pip" "$u/.cache/uv_build" 2>/dev/null; '
|
|
893
|
-
"done; "
|
|
894
|
-
"rm -rf /tmp/uv-* /tmp/.uv-* /var/cache/apt/archives/*.deb 2>/dev/null; "
|
|
895
|
-
"true",
|
|
889
|
+
build_reclaim_caches_cmd(workspace),
|
|
896
890
|
user="root",
|
|
897
891
|
timeout_sec=30,
|
|
898
892
|
)
|
|
@@ -13,6 +13,7 @@ from pathlib import Path
|
|
|
13
13
|
|
|
14
14
|
import pytest
|
|
15
15
|
|
|
16
|
+
from benchflow.providers import litellm_bedrock_preflight as preflight_mod
|
|
16
17
|
from benchflow.providers import litellm_runtime as runtime_mod
|
|
17
18
|
from benchflow.providers.litellm_config import resolve_litellm_route
|
|
18
19
|
from benchflow.providers.litellm_logging import (
|
|
@@ -242,10 +243,17 @@ _SUCCESS_LOG = json.dumps(
|
|
|
242
243
|
class _FakeSandbox:
|
|
243
244
|
"""Drives the real sandbox-local LiteLLM launch/teardown code paths."""
|
|
244
245
|
|
|
245
|
-
def __init__(
|
|
246
|
+
def __init__(
|
|
247
|
+
self,
|
|
248
|
+
*,
|
|
249
|
+
fail_launch: bool = False,
|
|
250
|
+
fail_preflight: bool = False,
|
|
251
|
+
log_content: str = _SUCCESS_LOG,
|
|
252
|
+
):
|
|
246
253
|
self.uploaded: dict[str, str] = {}
|
|
247
254
|
self.exec_calls: list[str] = []
|
|
248
255
|
self.fail_launch = fail_launch
|
|
256
|
+
self.fail_preflight = fail_preflight
|
|
249
257
|
self.log_content = log_content
|
|
250
258
|
self._started = False
|
|
251
259
|
|
|
@@ -258,6 +266,10 @@ class _FakeSandbox:
|
|
|
258
266
|
return _ExecResult(0, stdout=str(len(self.log_content)))
|
|
259
267
|
if "urllib.request" in command:
|
|
260
268
|
return _ExecResult(0)
|
|
269
|
+
if "bedrock_patch_preflight.py" in command:
|
|
270
|
+
if self.fail_preflight:
|
|
271
|
+
return _ExecResult(1, stdout="adaptive-thinking gate inactive")
|
|
272
|
+
return _ExecResult(0)
|
|
261
273
|
if "launcher.py" in command:
|
|
262
274
|
if self.fail_launch:
|
|
263
275
|
return _ExecResult(1, stderr="boom")
|
|
@@ -410,6 +422,180 @@ def test_bedrock_patch_flags_cost_map_when_entry_present():
|
|
|
410
422
|
assert flagged, "bedrock 4.8+ cost entries should be flagged adaptive-thinking"
|
|
411
423
|
|
|
412
424
|
|
|
425
|
+
# --------------------------------------------------------------------------- #
|
|
426
|
+
# Bedrock 4.8+ patch preflight fails closed (issue #602) #
|
|
427
|
+
# --------------------------------------------------------------------------- #
|
|
428
|
+
|
|
429
|
+
_BEDROCK_ENV = {"AWS_BEARER_TOKEN_BEDROCK": "tok", "AWS_REGION": "us-east-1"}
|
|
430
|
+
|
|
431
|
+
|
|
432
|
+
@pytest.mark.parametrize(
|
|
433
|
+
"model,required",
|
|
434
|
+
[
|
|
435
|
+
("aws-bedrock/us.anthropic.claude-opus-4-8-20251101-v1:0", True),
|
|
436
|
+
("aws-bedrock/eu.anthropic.claude-sonnet-4-9-20260301-v1:0", True),
|
|
437
|
+
("aws-bedrock/us.anthropic.claude-opus-4-7-20251101-v1:0", False),
|
|
438
|
+
],
|
|
439
|
+
)
|
|
440
|
+
def test_route_requires_bedrock_patch_gating(model, required):
|
|
441
|
+
"""Guards PR #668's fail-closed gating for issue #602: only Bedrock Claude 4.8+
|
|
442
|
+
routes require the thinking patch; 4.7 and below stay best-effort."""
|
|
443
|
+
route = resolve_litellm_route(model, dict(_BEDROCK_ENV))
|
|
444
|
+
assert preflight_mod.route_requires_bedrock_patch(route) is required
|
|
445
|
+
|
|
446
|
+
|
|
447
|
+
def test_route_requires_bedrock_patch_ignores_non_bedrock_providers():
|
|
448
|
+
"""Guards PR #668 / issue #602 scope: a 4.8 model on a non-Bedrock provider does not
|
|
449
|
+
trigger the fail-closed preflight (direct Anthropic handles 4.8 natively)."""
|
|
450
|
+
route = resolve_litellm_route(
|
|
451
|
+
"minimax/MiniMax-M3",
|
|
452
|
+
{"MINIMAX_API_KEY": "k", "MINIMAX_BASE_URL": "https://api.minimax.io/v1"},
|
|
453
|
+
)
|
|
454
|
+
assert preflight_mod.route_requires_bedrock_patch(route) is False
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def test_host_bedrock_preflight_uses_litellm_shebang_python(tmp_path):
|
|
458
|
+
"""Guards PR #668 against checking a different Python than the LiteLLM CLI
|
|
459
|
+
will actually run under when the executable is a script with a shebang."""
|
|
460
|
+
litellm = tmp_path / "litellm"
|
|
461
|
+
python = tmp_path / "tools" / "python"
|
|
462
|
+
python.parent.mkdir()
|
|
463
|
+
litellm.write_text(f"#!{python}\n")
|
|
464
|
+
|
|
465
|
+
assert preflight_mod._host_python_for_litellm(str(litellm)) == str(python)
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def test_host_bedrock_preflight_resolves_env_shebang_with_proxy_path(tmp_path):
|
|
469
|
+
"""Guards PR #668 against resolving `/usr/bin/env python*` with a different
|
|
470
|
+
PATH than the LiteLLM proxy receives."""
|
|
471
|
+
bindir = tmp_path / "bin"
|
|
472
|
+
bindir.mkdir()
|
|
473
|
+
python = bindir / "python3"
|
|
474
|
+
python.write_text("")
|
|
475
|
+
python.chmod(0o755)
|
|
476
|
+
litellm = tmp_path / "litellm"
|
|
477
|
+
litellm.write_text("#!/usr/bin/env python3\n")
|
|
478
|
+
|
|
479
|
+
assert preflight_mod._host_python_for_litellm(
|
|
480
|
+
str(litellm), env={"PATH": str(bindir)}
|
|
481
|
+
) == str(python)
|
|
482
|
+
|
|
483
|
+
|
|
484
|
+
def test_bedrock_patch_preflight_passes_when_runtime_files_on_pythonpath(tmp_path):
|
|
485
|
+
"""End-to-end happy path for the PR #668 preflight (issue #602): a fresh interpreter
|
|
486
|
+
with the runtime dir on PYTHONPATH loads sitecustomize -> patch module, so
|
|
487
|
+
the behavioral probe sees the patched litellm and exits 0."""
|
|
488
|
+
import os
|
|
489
|
+
import subprocess
|
|
490
|
+
import sys
|
|
491
|
+
|
|
492
|
+
runtime_mod._write_runtime_files(tmp_path, config={"model_list": []})
|
|
493
|
+
env = dict(os.environ)
|
|
494
|
+
env["PYTHONPATH"] = str(tmp_path)
|
|
495
|
+
result = subprocess.run(
|
|
496
|
+
[sys.executable, "-c", preflight_mod.BEDROCK_PATCH_PREFLIGHT_SOURCE],
|
|
497
|
+
env=env,
|
|
498
|
+
capture_output=True,
|
|
499
|
+
text=True,
|
|
500
|
+
timeout=120,
|
|
501
|
+
)
|
|
502
|
+
assert result.returncode == 0, result.stdout + result.stderr
|
|
503
|
+
|
|
504
|
+
|
|
505
|
+
def test_bedrock_patch_preflight_fails_closed_when_patch_not_loaded(tmp_path):
|
|
506
|
+
"""THE regression test for issue #602's fail-open (fixed in PR #668): when the patch never
|
|
507
|
+
loads (sitecustomize missing from PYTHONPATH — the exact silent-failure
|
|
508
|
+
mode), the behavioral probe against stock litellm must exit non-zero so
|
|
509
|
+
setup fails before the agent launches, instead of regressing mid-task."""
|
|
510
|
+
import os
|
|
511
|
+
import subprocess
|
|
512
|
+
import sys
|
|
513
|
+
|
|
514
|
+
env = dict(os.environ)
|
|
515
|
+
env.pop("PYTHONPATH", None)
|
|
516
|
+
result = subprocess.run(
|
|
517
|
+
[sys.executable, "-c", preflight_mod.BEDROCK_PATCH_PREFLIGHT_SOURCE],
|
|
518
|
+
env=env,
|
|
519
|
+
capture_output=True,
|
|
520
|
+
text=True,
|
|
521
|
+
timeout=120,
|
|
522
|
+
)
|
|
523
|
+
assert result.returncode != 0
|
|
524
|
+
assert "inactive" in result.stdout
|
|
525
|
+
|
|
526
|
+
|
|
527
|
+
@pytest.mark.asyncio
|
|
528
|
+
async def test_sandbox_litellm_bedrock_route_runs_preflight():
|
|
529
|
+
"""Guards PR #668 / issue #602 wiring: a Bedrock 4.8+ sandbox route must run the
|
|
530
|
+
patch preflight after health and succeed when the patch is active."""
|
|
531
|
+
route = resolve_litellm_route(
|
|
532
|
+
"aws-bedrock/us.anthropic.claude-opus-4-8-20251101-v1:0", dict(_BEDROCK_ENV)
|
|
533
|
+
)
|
|
534
|
+
sandbox = _FakeSandbox()
|
|
535
|
+
|
|
536
|
+
proc = await runtime_mod._start_sandbox_litellm(
|
|
537
|
+
sandbox=sandbox,
|
|
538
|
+
route=route,
|
|
539
|
+
master_key="sk-master",
|
|
540
|
+
agent_env=dict(_BEDROCK_ENV),
|
|
541
|
+
session_id="s",
|
|
542
|
+
agent_name="openhands",
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
preflights = [c for c in sandbox.exec_calls if "bedrock_patch_preflight.py" in c]
|
|
546
|
+
assert preflights, "Bedrock 4.8+ route must run the patch preflight"
|
|
547
|
+
assert proc.base_url == "http://127.0.0.1:45999"
|
|
548
|
+
|
|
549
|
+
|
|
550
|
+
@pytest.mark.asyncio
|
|
551
|
+
async def test_sandbox_litellm_bedrock_preflight_failure_fails_closed():
|
|
552
|
+
"""THE sandbox fail-closed regression for issue #602 (PR #668): an inactive patch on
|
|
553
|
+
a Daytona Bedrock 4.8+ route must abort startup (RuntimeError) and tear the
|
|
554
|
+
half-started proxy down — never continue into the task fail-open."""
|
|
555
|
+
route = resolve_litellm_route(
|
|
556
|
+
"aws-bedrock/us.anthropic.claude-opus-4-8-20251101-v1:0", dict(_BEDROCK_ENV)
|
|
557
|
+
)
|
|
558
|
+
sandbox = _FakeSandbox(fail_preflight=True)
|
|
559
|
+
|
|
560
|
+
with pytest.raises(RuntimeError, match="NOT active"):
|
|
561
|
+
await runtime_mod._start_sandbox_litellm(
|
|
562
|
+
sandbox=sandbox,
|
|
563
|
+
route=route,
|
|
564
|
+
master_key="sk-master",
|
|
565
|
+
agent_env=dict(_BEDROCK_ENV),
|
|
566
|
+
session_id="s",
|
|
567
|
+
agent_name="openhands",
|
|
568
|
+
)
|
|
569
|
+
|
|
570
|
+
assert any(call.strip().startswith("rm -rf") for call in sandbox.exec_calls)
|
|
571
|
+
|
|
572
|
+
|
|
573
|
+
@pytest.mark.asyncio
|
|
574
|
+
async def test_sandbox_litellm_non_bedrock_route_skips_preflight():
|
|
575
|
+
"""Guards PR #668 / issue #602 scope: non-Bedrock routes never run the preflight, so
|
|
576
|
+
a broken patch can not fail runs that do not depend on it."""
|
|
577
|
+
route = resolve_litellm_route(
|
|
578
|
+
"minimax/MiniMax-M3",
|
|
579
|
+
{"MINIMAX_API_KEY": "k", "MINIMAX_BASE_URL": "https://api.minimax.io/v1"},
|
|
580
|
+
)
|
|
581
|
+
sandbox = _FakeSandbox(fail_preflight=True) # would fail IF it ran
|
|
582
|
+
|
|
583
|
+
proc = await runtime_mod._start_sandbox_litellm(
|
|
584
|
+
sandbox=sandbox,
|
|
585
|
+
route=route,
|
|
586
|
+
master_key="sk-master",
|
|
587
|
+
agent_env={
|
|
588
|
+
"MINIMAX_API_KEY": "k",
|
|
589
|
+
"MINIMAX_BASE_URL": "https://api.minimax.io/v1",
|
|
590
|
+
},
|
|
591
|
+
session_id="s",
|
|
592
|
+
agent_name="openhands",
|
|
593
|
+
)
|
|
594
|
+
|
|
595
|
+
assert not [c for c in sandbox.exec_calls if "bedrock_patch_preflight.py" in c]
|
|
596
|
+
assert proc.base_url == "http://127.0.0.1:45999"
|
|
597
|
+
|
|
598
|
+
|
|
413
599
|
# --------------------------------------------------------------------------- #
|
|
414
600
|
# Embedded callback logger actually produces importable JSONL (no drift) #
|
|
415
601
|
# --------------------------------------------------------------------------- #
|