benchflow 0.5.3.dev908__tar.gz → 0.5.3.dev956__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/PKG-INFO +1 -1
  2. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/pyproject.toml +1 -1
  3. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/providers/litellm_bedrock_patch.py +5 -0
  4. benchflow-0.5.3.dev956/src/benchflow/providers/litellm_bedrock_preflight.py +181 -0
  5. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/providers/litellm_runtime.py +33 -1
  6. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_litellm_hardening.py +187 -1
  7. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_litellm_runtime.py +28 -1
  8. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/.gitignore +0 -0
  9. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/CHANGELOG.md +0 -0
  10. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/LICENSE +0 -0
  11. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/README.md +0 -0
  12. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/__init__.py +0 -0
  13. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_dotenv.py +0 -0
  14. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_paths.py +0 -0
  15. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_run.py +0 -0
  16. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_types.py +0 -0
  17. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/__init__.py +0 -0
  18. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/benchmark_repos.py +0 -0
  19. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/config.py +0 -0
  20. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/evaluation_results.py +0 -0
  21. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/json_safe.py +0 -0
  22. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/learner_memory.py +0 -0
  23. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/result_metadata.py +0 -0
  24. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/reward_events.py +0 -0
  25. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/scoring.py +0 -0
  26. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/source_provenance.py +0 -0
  27. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/task_authoring.py +0 -0
  28. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/_utils/yaml_loader.py +0 -0
  29. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/acp/__init__.py +0 -0
  30. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/acp/client.py +0 -0
  31. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/acp/container_transport.py +0 -0
  32. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/acp/runtime.py +0 -0
  33. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/acp/session.py +0 -0
  34. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/acp/transport.py +0 -0
  35. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/acp/types.py +0 -0
  36. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/adapters/__init__.py +0 -0
  37. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/adapters/harbor.py +0 -0
  38. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/adapters/inbound.py +0 -0
  39. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/adapters/inspect_ai.py +0 -0
  40. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/adapters/ors.py +0 -0
  41. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/adapters/terminal_bench.py +0 -0
  42. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/__init__.py +0 -0
  43. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/codex_config.py +0 -0
  44. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/credentials.py +0 -0
  45. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/env.py +0 -0
  46. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/errors.py +0 -0
  47. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/harvey_lab_acp_shim.py +0 -0
  48. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/install.py +0 -0
  49. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/openclaw_acp_shim.py +0 -0
  50. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/pi_acp_launcher.py +0 -0
  51. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/protocol.py +0 -0
  52. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/providers.py +0 -0
  53. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/agents/registry.py +0 -0
  54. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/branch.py +0 -0
  55. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/cli/__init__.py +0 -0
  56. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/cli/continue_cmd.py +0 -0
  57. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/cli/main.py +0 -0
  58. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/cli/trace_import.py +0 -0
  59. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/compat/__init__.py +0 -0
  60. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/compat/harbor_registry.py +0 -0
  61. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/continue_run/__init__.py +0 -0
  62. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/continue_run/batch.py +0 -0
  63. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/continue_run/orchestrator.py +0 -0
  64. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/continue_run/replay_proxy.py +0 -0
  65. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/continue_run/run_folder.py +0 -0
  66. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/continue_run/sandbox_proxy.py +0 -0
  67. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/contracts/__init__.py +0 -0
  68. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/contracts/planes.py +0 -0
  69. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/contracts/user.py +0 -0
  70. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/demo_task/environment/Dockerfile +0 -0
  71. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/demo_task/instruction.md +0 -0
  72. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/demo_task/task.toml +0 -0
  73. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/demo_task/tests/test.sh +0 -0
  74. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/diagnostics.py +0 -0
  75. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/environment/__init__.py +0 -0
  76. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/environment/manifest.py +0 -0
  77. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/environment/manifest_env.py +0 -0
  78. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/environment/protocol.py +0 -0
  79. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/environment/readiness.py +0 -0
  80. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/eval_sharding.py +0 -0
  81. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/eval_worker.py +0 -0
  82. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/evaluation.py +0 -0
  83. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/experimental/__init__.py +0 -0
  84. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/experimental/mcp/__init__.py +0 -0
  85. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/experimental/mcp/hooks.py +0 -0
  86. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/experimental/mcp/reviewer_server.py +0 -0
  87. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/hosted_env.py +0 -0
  88. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/learner_skills.py +0 -0
  89. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/learner_store.py +0 -0
  90. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/metrics.py +0 -0
  91. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/models.py +0 -0
  92. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/monitor.py +0 -0
  93. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/providers/__init__.py +0 -0
  94. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/providers/litellm_config.py +0 -0
  95. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/providers/litellm_logging.py +0 -0
  96. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/providers/runtime.py +0 -0
  97. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/py.typed +0 -0
  98. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/README.md +0 -0
  99. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/__init__.py +0 -0
  100. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/builtins.py +0 -0
  101. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/events.py +0 -0
  102. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/file_readers.py +0 -0
  103. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/llm.py +0 -0
  104. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/memory_scorer.py +0 -0
  105. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/node.py +0 -0
  106. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/protocol.py +0 -0
  107. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/rubric.py +0 -0
  108. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/rubric_config.py +0 -0
  109. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rewards/validation.py +0 -0
  110. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rollout.py +0 -0
  111. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rollout_branch.py +0 -0
  112. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/rollout_planes.py +0 -0
  113. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/runtime.py +0 -0
  114. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/__init__.py +0 -0
  115. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/_base.py +0 -0
  116. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/_compose.py +0 -0
  117. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/_compose_files/docker-compose-base.yaml +0 -0
  118. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/_compose_files/docker-compose-build.yaml +0 -0
  119. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/_compose_files/docker-compose-no-network.yaml +0 -0
  120. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/_compose_files/docker-compose-prebuilt.yaml +0 -0
  121. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/_sdk_ops.py +0 -0
  122. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/daytona.py +0 -0
  123. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/docker.py +0 -0
  124. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/lockdown.py +0 -0
  125. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/metadata.py +0 -0
  126. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/modal_impl.py +0 -0
  127. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/process.py +0 -0
  128. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/protocol.py +0 -0
  129. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/services.py +0 -0
  130. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/setup.py +0 -0
  131. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/snapshot.py +0 -0
  132. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sandbox/user.py +0 -0
  133. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/scenes.py +0 -0
  134. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/sdk.py +0 -0
  135. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/self_gen.py +0 -0
  136. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/skill_eval/__init__.py +0 -0
  137. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/skill_eval/_core.py +0 -0
  138. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/skill_eval/gepa_export.py +0 -0
  139. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/skill_eval/schema.py +0 -0
  140. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/skill_policy.py +0 -0
  141. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/skills.py +0 -0
  142. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/task/__init__.py +0 -0
  143. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/task/config.py +0 -0
  144. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/task/env.py +0 -0
  145. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/task/paths.py +0 -0
  146. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/task/task.py +0 -0
  147. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/task/verifier.py +0 -0
  148. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/templates/__init__.py +0 -0
  149. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/templates/judge.py.tmpl +0 -0
  150. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/templates/test.sh.tmpl +0 -0
  151. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/traces/__init__.py +0 -0
  152. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/traces/huggingface.py +0 -0
  153. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/traces/local.py +0 -0
  154. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/traces/models.py +0 -0
  155. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/traces/parsers.py +0 -0
  156. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/traces/task_gen.py +0 -0
  157. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/trajectories/__init__.py +0 -0
  158. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/trajectories/_capture.py +0 -0
  159. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/trajectories/export.py +0 -0
  160. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/trajectories/metrics.py +0 -0
  161. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/trajectories/otel.py +0 -0
  162. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/trajectories/tree.py +0 -0
  163. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/trajectories/types.py +0 -0
  164. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/trajectories/viewer.py +0 -0
  165. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/src/benchflow/usage_tracking.py +0 -0
  166. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/__init__.py +0 -0
  167. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/agents/__init__.py +0 -0
  168. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/agents/test_protocol.py +0 -0
  169. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/README.md +0 -0
  170. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/acp_smoke/environment/Dockerfile +0 -0
  171. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/acp_smoke/environment/docker-compose.yaml +0 -0
  172. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/acp_smoke/environment/skills/conformance-writer/SKILL.md +0 -0
  173. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/acp_smoke/instruction.md +0 -0
  174. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/acp_smoke/solution/solve.sh +0 -0
  175. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/acp_smoke/task.toml +0 -0
  176. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/acp_smoke/tests/test.sh +0 -0
  177. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/conformance-results.json +0 -0
  178. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/proof_multi_agent.py +0 -0
  179. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/proof_snapshot.py +0 -0
  180. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/run_conformance.py +0 -0
  181. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conformance/self_gen_smoke_skills/skill-creator/SKILL.md +0 -0
  182. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/conftest.py +0 -0
  183. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/continue_run/__init__.py +0 -0
  184. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/continue_run/_helpers.py +0 -0
  185. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/continue_run/test_batch.py +0 -0
  186. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/continue_run/test_orchestrator.py +0 -0
  187. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/continue_run/test_replay_proxy.py +0 -0
  188. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/continue_run/test_run_folder.py +0 -0
  189. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/environment/__init__.py +0 -0
  190. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/environment/test_chibench_manifest.py +0 -0
  191. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/environment/test_clawsbench_manifest.py +0 -0
  192. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/environment/test_manifest.py +0 -0
  193. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/environment/test_manifest_env.py +0 -0
  194. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/environment/test_protocol.py +0 -0
  195. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/environment/test_readiness.py +0 -0
  196. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/hello-world-task/environment/Dockerfile +0 -0
  197. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/hello-world-task/instruction.md +0 -0
  198. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/hello-world-task/solution/solve.sh +0 -0
  199. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/hello-world-task/task.toml +0 -0
  200. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/hello-world-task/tests/test.sh +0 -0
  201. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/terminal-bench-smoke-task/environment/Dockerfile +0 -0
  202. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/terminal-bench-smoke-task/instruction.md +0 -0
  203. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/terminal-bench-smoke-task/solution/solve.sh +0 -0
  204. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/terminal-bench-smoke-task/task.toml +0 -0
  205. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/terminal-bench-smoke-task/tests/test.sh +0 -0
  206. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/terminal-bench-smoke-task/tests/test_state.py +0 -0
  207. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/test_claude.sh +0 -0
  208. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/test_codex.sh +0 -0
  209. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/test_codex_custom_provider.sh +0 -0
  210. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/test_gemini.sh +0 -0
  211. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/test_openclaw.sh +0 -0
  212. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/traces/minimal-claude.jsonl +0 -0
  213. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/examples/traces/minimal-opentraces.jsonl +0 -0
  214. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/fixtures/mock_acp_agent.py +0 -0
  215. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/fixtures/mock_acp_agent_interleaved.py +0 -0
  216. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/fixtures/mock_acp_agent_multi_turn.py +0 -0
  217. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/fixtures/mock_openai_responses_server.py +0 -0
  218. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/check_adapter_evidence.py +0 -0
  219. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/check_hosted_env_evidence.py +0 -0
  220. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/check_results.py +0 -0
  221. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/check_skillsbench_harbor_parity.py +0 -0
  222. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/check_trace_to_task_evidence.py +0 -0
  223. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/configs/claude-agent-acp.yaml +0 -0
  224. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/configs/codex-acp.yaml +0 -0
  225. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/configs/gemini.yaml +0 -0
  226. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/configs/harvey-lab-harness.yaml +0 -0
  227. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/configs/openclaw.yaml +0 -0
  228. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/configs/opencode.yaml +0 -0
  229. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/configs/openhands.yaml +0 -0
  230. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/configs/pi-acp.yaml +0 -0
  231. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/run.sh +0 -0
  232. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/run_suite.py +0 -0
  233. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/integration/suites/release.yaml +0 -0
  234. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_acp.py +0 -0
  235. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_acp_capability_advertising.py +0 -0
  236. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_acp_model_config_dispatch.py +0 -0
  237. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_acp_pinned_protocol_guard.py +0 -0
  238. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_acp_setup_failure_propagation.py +0 -0
  239. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_adapter_scripts.py +0 -0
  240. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_adapters.py +0 -0
  241. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_agent_cli.py +0 -0
  242. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_agent_env_resolution.py +0 -0
  243. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_agent_gemini_defaults.py +0 -0
  244. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_agent_idle_timeout_cli.py +0 -0
  245. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_agent_model_decouple.py +0 -0
  246. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_agent_registry.py +0 -0
  247. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_agent_setup.py +0 -0
  248. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_agent_spec.py +0 -0
  249. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_base_install_imports.py +0 -0
  250. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_bedrock_thinking.py +0 -0
  251. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_branch.py +0 -0
  252. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_capture_trajectory.py +0 -0
  253. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_clawsbench_slice.py +0 -0
  254. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_cli_daytona.py +0 -0
  255. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_cli_docs_drift.py +0 -0
  256. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_cli_misc.py +0 -0
  257. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_compat_harbor_registry.py +0 -0
  258. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_config_redaction.py +0 -0
  259. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_connect_as_env.py +0 -0
  260. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_continuallearningbench_adapter.py +0 -0
  261. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_dashboard_credential_env_scrub.py +0 -0
  262. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_dashboard_daytona_key.py +0 -0
  263. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_dashboard_no_host_paths.py +0 -0
  264. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_dashboard_release_evidence.py +0 -0
  265. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_dashboard_roadmap.py +0 -0
  266. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_dashboard_symlink_ingestion.py +0 -0
  267. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_dashboard_sync.py +0 -0
  268. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_daytona_command_polling.py +0 -0
  269. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_daytona_litellm_runtime.py +0 -0
  270. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_daytona_status.py +0 -0
  271. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_docker_prune_scoping.py +0 -0
  272. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_docker_uploads.py +0 -0
  273. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_docs_examples.py +0 -0
  274. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_eng50_capabilities.py +0 -0
  275. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_env_setup.py +0 -0
  276. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_environment_manifest_controls.py +0 -0
  277. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_eval_filters_applied.py +0 -0
  278. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_eval_sharding.py +0 -0
  279. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_eval_single_task_summary.py +0 -0
  280. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_eval_source_provenance.py +0 -0
  281. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_eval_worker_retry.py +0 -0
  282. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_eval_zero_task_guard.py +0 -0
  283. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_evaluation_environment_manifest.py +0 -0
  284. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_exclude_tasks.py +0 -0
  285. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_experiments_status.py +0 -0
  286. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_harvey_lab_shim.py +0 -0
  287. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_hf_scores.py +0 -0
  288. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_hilbench_adapter.py +0 -0
  289. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_hosted_env.py +0 -0
  290. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_hosted_env_rollout_contract.py +0 -0
  291. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_inbound_adapter_manifest.py +0 -0
  292. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_inbound_adapters.py +0 -0
  293. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_integration_check_results.py +0 -0
  294. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_integration_run_suite.py +0 -0
  295. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_internet_policy.py +0 -0
  296. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_job.py +0 -0
  297. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_job_sequential_shared.py +0 -0
  298. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_job_sequential_shared_resume.py +0 -0
  299. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_judge_symlink_ingestion.py +0 -0
  300. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_learner_skills.py +0 -0
  301. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_learner_skills_traversal.py +0 -0
  302. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_learner_store.py +0 -0
  303. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_learner_store_persistence.py +0 -0
  304. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_litellm_config.py +0 -0
  305. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_litellm_logging.py +0 -0
  306. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_litellm_smoke.py +0 -0
  307. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_llm_judge.py +0 -0
  308. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_llm_judge_event_tags.py +0 -0
  309. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_llm_judge_verifier.py +0 -0
  310. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_memory_scorer.py +0 -0
  311. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_metrics.py +0 -0
  312. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_mock_openai_responses_server.py +0 -0
  313. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_monitor_scaffold.py +0 -0
  314. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_native_acp_usage.py +0 -0
  315. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_no_cross_provider_fallback.py +0 -0
  316. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_notification_order_real.py +0 -0
  317. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_oracle.py +0 -0
  318. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_oracle_chokepoint.py +0 -0
  319. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_paths_safe.py +0 -0
  320. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_paths_symlink_helpers.py +0 -0
  321. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_pi_acp_launcher.py +0 -0
  322. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_process.py +0 -0
  323. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_provider_auth_detection.py +0 -0
  324. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_providers.py +0 -0
  325. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_reexport.py +0 -0
  326. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_registry_invariants.py +0 -0
  327. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_release_version.py +0 -0
  328. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_resolve_env_helpers.py +0 -0
  329. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_reward_node.py +0 -0
  330. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_reward_unified_contract.py +0 -0
  331. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_rewards.py +0 -0
  332. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_rewards_jsonl.py +0 -0
  333. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_rollout_architecture.py +0 -0
  334. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_rollout_branch.py +0 -0
  335. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_rollout_config_path_coercion.py +0 -0
  336. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_rollout_environment.py +0 -0
  337. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_rollout_import_no_side_effects.py +0 -0
  338. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_rollout_on_ask_user_wiring.py +0 -0
  339. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_rollout_probe_sandbox_health.py +0 -0
  340. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_rollout_upload.py +0 -0
  341. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_rubric_config.py +0 -0
  342. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_runtime.py +0 -0
  343. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_runtime_config_wired.py +0 -0
  344. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_runtime_live_sandbox.py +0 -0
  345. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sandbox.py +0 -0
  346. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sandbox_exec_secret_handling.py +0 -0
  347. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sandbox_hardening.py +0 -0
  348. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sandbox_isolation_copy_traversal.py +0 -0
  349. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sandbox_multi_service.py +0 -0
  350. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sandbox_protocol.py +0 -0
  351. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sandbox_setup.py +0 -0
  352. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sandbox_snapshot_contract.py +0 -0
  353. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sandbox_upload_symlink.py +0 -0
  354. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sandbox_verifier_workspace.py +0 -0
  355. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_scene.py +0 -0
  356. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_scene_outbox_trial.py +0 -0
  357. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_scene_parallel_group.py +0 -0
  358. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_scene_result_aggregation.py +0 -0
  359. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_scoring.py +0 -0
  360. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sdk_internals.py +0 -0
  361. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_sdk_lockdown.py +0 -0
  362. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_self_gen_cli.py +0 -0
  363. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_self_gen_export_error_channel.py +0 -0
  364. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_self_gen_export_failures.py +0 -0
  365. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_self_gen_orchestration.py +0 -0
  366. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_session_request_permission_dispatch.py +0 -0
  367. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skill_eval.py +0 -0
  368. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skill_eval_dryrun.py +0 -0
  369. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skill_eval_integration.py +0 -0
  370. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skill_eval_sweep.py +0 -0
  371. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skill_eval_traversal.py +0 -0
  372. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skill_invocation_artifacts.py +0 -0
  373. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skill_policy.py +0 -0
  374. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skills.py +0 -0
  375. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skills_dir_agent_home_link.py +0 -0
  376. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skillsbench_harbor_parity.py +0 -0
  377. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skillsbench_harbor_run_suite.py +0 -0
  378. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_skillsbench_publish_scrub.py +0 -0
  379. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_smoke.py +0 -0
  380. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_subscription_auth.py +0 -0
  381. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_task_check_eval_consistency.py +0 -0
  382. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_task_config.py +0 -0
  383. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_task_download.py +0 -0
  384. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_tasks.py +0 -0
  385. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_token_usage_normalization.py +0 -0
  386. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_trace_import_cli.py +0 -0
  387. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_trace_task_gen_traversal.py +0 -0
  388. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_trace_to_task_evidence.py +0 -0
  389. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_traces_huggingface.py +0 -0
  390. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_traces_parsers.py +0 -0
  391. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_traces_task_gen.py +0 -0
  392. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_train_mode_artifact_emission.py +0 -0
  393. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_trajectory_integration.py +0 -0
  394. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_trajectory_streaming.py +0 -0
  395. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_trial_agent_timeout_verify.py +0 -0
  396. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_trial_install_agent_timeout.py +0 -0
  397. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_trial_litellm_runtime.py +0 -0
  398. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_usage_litellm.py +0 -0
  399. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_usage_required.py +0 -0
  400. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_usage_tracking.py +0 -0
  401. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_user.py +0 -0
  402. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_verifier_multi_container.py +0 -0
  403. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_verifier_output.py +0 -0
  404. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_verifier_output_freshness.py +0 -0
  405. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_verify.py +0 -0
  406. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_workflow_action_pinning.py +0 -0
  407. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/test_yaml_config.py +0 -0
  408. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/trajectories/__init__.py +0 -0
  409. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/trajectories/test_export.py +0 -0
  410. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/trajectories/test_export_nan_handling.py +0 -0
  411. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/trajectories/test_redaction.py +0 -0
  412. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/tests/trajectories/test_step_granularity.py +0 -0
  413. {benchflow-0.5.3.dev908 → benchflow-0.5.3.dev956}/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.dev908
3
+ Version: 0.5.3.dev956
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "benchflow"
3
- version = "0.5.3.dev908"
3
+ version = "0.5.3.dev956"
4
4
  description = "Multi-turn agent benchmarking with ACP — run any agent, any model, any provider."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12"
@@ -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)
@@ -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
- _host_litellm_executable(),
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,
@@ -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__(self, *, fail_launch: bool = False, log_content: str = _SUCCESS_LOG):
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
  # --------------------------------------------------------------------------- #
@@ -5,6 +5,7 @@ from types import SimpleNamespace
5
5
  import pytest
6
6
 
7
7
  from benchflow.providers import litellm_runtime as runtime_mod
8
+ from benchflow.providers.litellm_bedrock_preflight import BedrockPatchPreflightError
8
9
  from benchflow.providers.litellm_config import LITELLM_MODEL_ALIAS_ENV
9
10
  from benchflow.providers.runtime import (
10
11
  ProviderRuntime,
@@ -153,7 +154,9 @@ async def test_runtime_reuse_and_stop(monkeypatch):
153
154
 
154
155
 
155
156
  @pytest.mark.asyncio
156
- async def test_required_usage_fails_when_litellm_lacks_provider_key():
157
+ async def test_required_usage_fails_when_litellm_lacks_provider_key(monkeypatch):
158
+ monkeypatch.setattr(runtime_mod, "uses_native_subscription_auth", lambda *_: False)
159
+
157
160
  with pytest.raises(RuntimeError, match="requires OPENAI_API_KEY"):
158
161
  await ensure_litellm_runtime(
159
162
  agent="codex-acp",
@@ -332,6 +335,30 @@ async def test_auto_usage_falls_back_when_litellm_start_fails(monkeypatch):
332
335
  assert provider_runtime is None
333
336
 
334
337
 
338
+ @pytest.mark.asyncio
339
+ async def test_auto_usage_does_not_fallback_on_bedrock_patch_preflight(monkeypatch):
340
+ """Guards PR #668's fail-closed fix for issue #602: an inactive Bedrock patch
341
+ must abort even when usage_tracking=auto would normally skip LiteLLM."""
342
+
343
+ async def fail_start(**_kwargs):
344
+ raise BedrockPatchPreflightError("patch inactive")
345
+
346
+ monkeypatch.setattr(runtime_mod, "_start_host_litellm", fail_start)
347
+
348
+ with pytest.raises(BedrockPatchPreflightError, match="patch inactive"):
349
+ await ensure_litellm_runtime(
350
+ agent="openhands",
351
+ agent_env={
352
+ "AWS_BEARER_TOKEN_BEDROCK": "tok",
353
+ "AWS_REGION": "us-west-2",
354
+ },
355
+ model="aws-bedrock/us.anthropic.claude-opus-4-8-20251101-v1:0",
356
+ runtime=None,
357
+ environment="docker",
358
+ usage_tracking="auto",
359
+ )
360
+
361
+
335
362
  @pytest.mark.asyncio
336
363
  async def test_auto_usage_requires_sandbox_handle_for_sandbox_local_litellm():
337
364
  """Guards the follow-up to PR #620: auto must not hide wiring bugs."""