agentinputlab 0.1.0a1__py3-none-any.whl

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 (469) hide show
  1. agentinputlab/__init__.py +28 -0
  2. agentinputlab/algorithms/__init__.py +6 -0
  3. agentinputlab/algorithms/acquire/__init__.py +145 -0
  4. agentinputlab/algorithms/acquire/adaptive_rag/__init__.py +43 -0
  5. agentinputlab/algorithms/acquire/adaptive_rag/replay.py +367 -0
  6. agentinputlab/algorithms/acquire/adaptive_rag/runtime.py +1202 -0
  7. agentinputlab/algorithms/acquire/adaptive_rag_common_support.py +542 -0
  8. agentinputlab/algorithms/acquire/hyde.py +296 -0
  9. agentinputlab/algorithms/acquire/hyde_controlled.py +200 -0
  10. agentinputlab/algorithms/acquire/hyde_external.py +148 -0
  11. agentinputlab/algorithms/acquire/ircot.py +28 -0
  12. agentinputlab/algorithms/acquire/ircot_common_support.py +478 -0
  13. agentinputlab/algorithms/acquire/ircot_native.py +355 -0
  14. agentinputlab/algorithms/acquire/ircot_replay.py +327 -0
  15. agentinputlab/algorithms/acquire/qrag/__init__.py +79 -0
  16. agentinputlab/algorithms/acquire/qrag/bridge.py +828 -0
  17. agentinputlab/algorithms/acquire/qrag/common_support.py +891 -0
  18. agentinputlab/algorithms/acquire/qrag/native_axis.py +71 -0
  19. agentinputlab/algorithms/acquire/qrag/reader_adapter.py +139 -0
  20. agentinputlab/algorithms/acquire/r2ag/__init__.py +57 -0
  21. agentinputlab/algorithms/acquire/r2ag/bridge.py +1312 -0
  22. agentinputlab/algorithms/acquire/r2ag/common_support.py +1029 -0
  23. agentinputlab/algorithms/acquire/r2ag/socket_runtime.py +255 -0
  24. agentinputlab/algorithms/clarify/__init__.py +61 -0
  25. agentinputlab/algorithms/clarify/_structured.py +64 -0
  26. agentinputlab/algorithms/clarify/active_task_disambiguation.py +371 -0
  27. agentinputlab/algorithms/clarify/ask_or_assume/__init__.py +17 -0
  28. agentinputlab/algorithms/clarify/ask_or_assume/monitor.py +410 -0
  29. agentinputlab/algorithms/clarify/future_turns.py +379 -0
  30. agentinputlab/algorithms/clarify/udcs.py +255 -0
  31. agentinputlab/algorithms/clarify/udcs_deterministic.py +196 -0
  32. agentinputlab/algorithms/curate/__init__.py +65 -0
  33. agentinputlab/algorithms/curate/acon/__init__.py +27 -0
  34. agentinputlab/algorithms/curate/acon/common.py +284 -0
  35. agentinputlab/algorithms/curate/acon/common_support.py +136 -0
  36. agentinputlab/algorithms/curate/acon/history_bridge.py +309 -0
  37. agentinputlab/algorithms/curate/acon/observation_bridge.py +290 -0
  38. agentinputlab/algorithms/curate/llmlingua/__init__.py +30 -0
  39. agentinputlab/algorithms/curate/llmlingua/adapters.py +537 -0
  40. agentinputlab/algorithms/curate/llmlingua/budget.py +48 -0
  41. agentinputlab/algorithms/curate/llmlingua/controlled.py +175 -0
  42. agentinputlab/algorithms/curate/llmlingua/multilingual.py +105 -0
  43. agentinputlab/algorithms/curate/llmlingua/span_map.py +167 -0
  44. agentinputlab/algorithms/curate/recomp/__init__.py +47 -0
  45. agentinputlab/algorithms/curate/recomp/external.py +1129 -0
  46. agentinputlab/algorithms/curate/recomp/selective.py +304 -0
  47. agentinputlab/algorithms/decompose/__init__.py +107 -0
  48. agentinputlab/algorithms/decompose/decomp/__init__.py +53 -0
  49. agentinputlab/algorithms/decompose/decomp/common_support.py +478 -0
  50. agentinputlab/algorithms/decompose/decomp/planner_component.py +199 -0
  51. agentinputlab/algorithms/decompose/decomp/worker_bridge.py +416 -0
  52. agentinputlab/algorithms/decompose/llm_compiler/__init__.py +35 -0
  53. agentinputlab/algorithms/decompose/llm_compiler/bridge.py +520 -0
  54. agentinputlab/algorithms/decompose/llm_compiler/common_support.py +504 -0
  55. agentinputlab/algorithms/decompose/plan_and_budget/__init__.py +43 -0
  56. agentinputlab/algorithms/decompose/plan_and_budget/cached_soft_budget.py +362 -0
  57. agentinputlab/algorithms/decompose/plan_and_budget/decomposer_component.py +107 -0
  58. agentinputlab/algorithms/decompose/plan_and_budget/full.py +205 -0
  59. agentinputlab/algorithms/decompose/plan_and_budget/hard_cap.py +246 -0
  60. agentinputlab/algorithms/decompose/plan_and_budget/regenerated_soft_budget.py +448 -0
  61. agentinputlab/algorithms/decompose/plan_and_solve/__init__.py +33 -0
  62. agentinputlab/algorithms/decompose/plan_and_solve/plan_component.py +192 -0
  63. agentinputlab/algorithms/decompose/plan_and_solve/ps_prompt.py +127 -0
  64. agentinputlab/algorithms/decompose/self_ask/__init__.py +27 -0
  65. agentinputlab/algorithms/decompose/self_ask/loop.py +362 -0
  66. agentinputlab/algorithms/decompose/self_ask/planner_component.py +117 -0
  67. agentinputlab/algorithms/reformulate/__init__.py +85 -0
  68. agentinputlab/algorithms/reformulate/infocqr/__init__.py +40 -0
  69. agentinputlab/algorithms/reformulate/infocqr/cache_replay.py +362 -0
  70. agentinputlab/algorithms/reformulate/infocqr/external.py +675 -0
  71. agentinputlab/algorithms/reformulate/infocqr/student.py +189 -0
  72. agentinputlab/algorithms/reformulate/query2doc/__init__.py +42 -0
  73. agentinputlab/algorithms/reformulate/query2doc/controlled_live.py +190 -0
  74. agentinputlab/algorithms/reformulate/query2doc/models.py +95 -0
  75. agentinputlab/algorithms/reformulate/query2doc/official_cached.py +335 -0
  76. agentinputlab/algorithms/reformulate/query2doc/querygym_bridge.py +223 -0
  77. agentinputlab/algorithms/reformulate/query2doc/querygym_runtime.py +326 -0
  78. agentinputlab/algorithms/reformulate/reformer/__init__.py +23 -0
  79. agentinputlab/algorithms/reformulate/reformer/external.py +417 -0
  80. agentinputlab/algorithms/reformulate/rrr.py +696 -0
  81. agentinputlab/annotation/__init__.py +5 -0
  82. agentinputlab/annotation/independent.py +428 -0
  83. agentinputlab/annotation/server.py +233 -0
  84. agentinputlab/annotation/static/app.js +121 -0
  85. agentinputlab/annotation/static/index.html +60 -0
  86. agentinputlab/annotation/static/review.css +2 -0
  87. agentinputlab/annotation/static/review.html +10 -0
  88. agentinputlab/annotation/static/review.js +11 -0
  89. agentinputlab/annotation/static/styles.css +55 -0
  90. agentinputlab/annotation/store.py +444 -0
  91. agentinputlab/api.py +368 -0
  92. agentinputlab/artifacts/__init__.py +15 -0
  93. agentinputlab/artifacts/json_file.py +104 -0
  94. agentinputlab/artifacts/manifest.py +98 -0
  95. agentinputlab/artifacts/store.py +157 -0
  96. agentinputlab/backends/__init__.py +98 -0
  97. agentinputlab/backends/embedding/__init__.py +25 -0
  98. agentinputlab/backends/embedding/base.py +145 -0
  99. agentinputlab/backends/embedding/callable.py +75 -0
  100. agentinputlab/backends/embedding/replay.py +129 -0
  101. agentinputlab/backends/llm/__init__.py +31 -0
  102. agentinputlab/backends/llm/base.py +149 -0
  103. agentinputlab/backends/llm/callable.py +108 -0
  104. agentinputlab/backends/llm/decomp_completion.py +88 -0
  105. agentinputlab/backends/llm/final_content_stop.py +72 -0
  106. agentinputlab/backends/llm/gpt_oss_final_channel.py +84 -0
  107. agentinputlab/backends/llm/openai_compatible.py +332 -0
  108. agentinputlab/backends/llm/transformers.py +171 -0
  109. agentinputlab/backends/retrieval/__init__.py +35 -0
  110. agentinputlab/backends/retrieval/base.py +50 -0
  111. agentinputlab/backends/retrieval/dense.py +777 -0
  112. agentinputlab/backends/retrieval/memory.py +119 -0
  113. agentinputlab/backends/retrieval/sqlite_fts.py +155 -0
  114. agentinputlab/backends/user/__init__.py +15 -0
  115. agentinputlab/backends/user/base.py +66 -0
  116. agentinputlab/backends/user/callable.py +54 -0
  117. agentinputlab/backends/user/replay.py +89 -0
  118. agentinputlab/backends/vector.py +38 -0
  119. agentinputlab/benchmarks/__init__.py +246 -0
  120. agentinputlab/benchmarks/acquisition.py +106 -0
  121. agentinputlab/benchmarks/ale.py +540 -0
  122. agentinputlab/benchmarks/appworld_ul.py +669 -0
  123. agentinputlab/benchmarks/assets.py +226 -0
  124. agentinputlab/benchmarks/base.py +68 -0
  125. agentinputlab/benchmarks/beir_archive.py +235 -0
  126. agentinputlab/benchmarks/beir_sample.py +269 -0
  127. agentinputlab/benchmarks/bfcl_native.py +245 -0
  128. agentinputlab/benchmarks/bfcl_v3.py +607 -0
  129. agentinputlab/benchmarks/cache.py +218 -0
  130. agentinputlab/benchmarks/clariq.py +203 -0
  131. agentinputlab/benchmarks/data/registry.json +321 -0
  132. agentinputlab/benchmarks/data/smoke_assets.json +511 -0
  133. agentinputlab/benchmarks/data/statebench_v0_8_1_task_ids.json +475 -0
  134. agentinputlab/benchmarks/data/toolsandbox_165848b_scenario_names.json +1 -0
  135. agentinputlab/benchmarks/execution.py +1111 -0
  136. agentinputlab/benchmarks/interactive.py +257 -0
  137. agentinputlab/benchmarks/ir_query.py +204 -0
  138. agentinputlab/benchmarks/longbench.py +203 -0
  139. agentinputlab/benchmarks/paired_replay.py +479 -0
  140. agentinputlab/benchmarks/preprocess.py +2313 -0
  141. agentinputlab/benchmarks/production.py +236 -0
  142. agentinputlab/benchmarks/qa.py +963 -0
  143. agentinputlab/benchmarks/registry.py +110 -0
  144. agentinputlab/benchmarks/retrieval.py +459 -0
  145. agentinputlab/benchmarks/runtime.py +509 -0
  146. agentinputlab/benchmarks/statebench.py +938 -0
  147. agentinputlab/benchmarks/tau3.py +725 -0
  148. agentinputlab/benchmarks/toolsandbox.py +626 -0
  149. agentinputlab/benchmarks/trec_dl_sample.py +263 -0
  150. agentinputlab/campaign.py +654 -0
  151. agentinputlab/campaign_runner.py +953 -0
  152. agentinputlab/cli/__init__.py +6 -0
  153. agentinputlab/cli/main.py +933 -0
  154. agentinputlab/connectors/__init__.py +46 -0
  155. agentinputlab/connectors/knowledge/__init__.py +4 -0
  156. agentinputlab/connectors/tools/__init__.py +30 -0
  157. agentinputlab/connectors/tools/base.py +57 -0
  158. agentinputlab/connectors/tools/mcp.py +222 -0
  159. agentinputlab/connectors/tools/memory.py +41 -0
  160. agentinputlab/connectors/tools/openapi.py +695 -0
  161. agentinputlab/connectors/tools/schema.py +102 -0
  162. agentinputlab/contracts/__init__.py +91 -0
  163. agentinputlab/contracts/availability.py +24 -0
  164. agentinputlab/contracts/dependency.py +58 -0
  165. agentinputlab/contracts/enums.py +82 -0
  166. agentinputlab/contracts/errors.py +63 -0
  167. agentinputlab/contracts/evidence.py +43 -0
  168. agentinputlab/contracts/intent.py +110 -0
  169. agentinputlab/contracts/lifecycle.py +164 -0
  170. agentinputlab/contracts/patch.py +167 -0
  171. agentinputlab/contracts/serialization.py +93 -0
  172. agentinputlab/contracts/state.py +127 -0
  173. agentinputlab/contracts/trace.py +59 -0
  174. agentinputlab/contracts/worker.py +42 -0
  175. agentinputlab/core/__init__.py +7 -0
  176. agentinputlab/data/__init__.py +32 -0
  177. agentinputlab/data/checksums.py +9 -0
  178. agentinputlab/data/downloader.py +235 -0
  179. agentinputlab/data/http.py +171 -0
  180. agentinputlab/data/index.py +21 -0
  181. agentinputlab/data/overlap.py +28 -0
  182. agentinputlab/data/preprocess.py +32 -0
  183. agentinputlab/data/storage.py +57 -0
  184. agentinputlab/data/trec_sample.py +427 -0
  185. agentinputlab/evaluation/__init__.py +5 -0
  186. agentinputlab/evaluation/outcomes.py +32 -0
  187. agentinputlab/experiments/__init__.py +278 -0
  188. agentinputlab/experiments/analysis.py +981 -0
  189. agentinputlab/experiments/artifacts.py +687 -0
  190. agentinputlab/experiments/automatic_measurement.py +678 -0
  191. agentinputlab/experiments/auxiliary_matrix.py +203 -0
  192. agentinputlab/experiments/bindings.py +430 -0
  193. agentinputlab/experiments/blueprints.py +147 -0
  194. agentinputlab/experiments/builders/__init__.py +45 -0
  195. agentinputlab/experiments/builders/executable_external_payload.py +423 -0
  196. agentinputlab/experiments/builders/external_process_arena.py +1018 -0
  197. agentinputlab/experiments/builders/registry_intervention.py +463 -0
  198. agentinputlab/experiments/cli.py +158 -0
  199. agentinputlab/experiments/controls.py +340 -0
  200. agentinputlab/experiments/driver_guard.py +205 -0
  201. agentinputlab/experiments/drivers/__init__.py +89 -0
  202. agentinputlab/experiments/drivers/external_arena.py +2908 -0
  203. agentinputlab/experiments/drivers/method_process.py +662 -0
  204. agentinputlab/experiments/drivers/parity_process.py +1484 -0
  205. agentinputlab/experiments/drivers/static_production.py +1574 -0
  206. agentinputlab/experiments/executor.py +448 -0
  207. agentinputlab/experiments/loader.py +605 -0
  208. agentinputlab/experiments/measurement.py +675 -0
  209. agentinputlab/experiments/paper_analysis.py +1818 -0
  210. agentinputlab/experiments/parity_identity.py +605 -0
  211. agentinputlab/experiments/plan.py +277 -0
  212. agentinputlab/experiments/production_builders.py +3739 -0
  213. agentinputlab/experiments/readiness.py +432 -0
  214. agentinputlab/experiments/schema.py +514 -0
  215. agentinputlab/experiments/secrets.py +177 -0
  216. agentinputlab/experiments/stateful_analysis.py +1738 -0
  217. agentinputlab/experiments/transfer_analysis.py +1316 -0
  218. agentinputlab/experiments/unseen_analysis.py +1025 -0
  219. agentinputlab/integrations/__init__.py +1 -0
  220. agentinputlab/integrations/action_space/__init__.py +1 -0
  221. agentinputlab/integrations/external_workers/__init__.py +76 -0
  222. agentinputlab/integrations/external_workers/ace.py +431 -0
  223. agentinputlab/integrations/external_workers/base.py +181 -0
  224. agentinputlab/integrations/external_workers/decomp_live.py +249 -0
  225. agentinputlab/integrations/external_workers/decomp_planner.py +30 -0
  226. agentinputlab/integrations/external_workers/infocqr_student.py +280 -0
  227. agentinputlab/integrations/external_workers/ircot.py +576 -0
  228. agentinputlab/integrations/external_workers/llmcompiler_live.py +360 -0
  229. agentinputlab/integrations/external_workers/longllmlingua.py +162 -0
  230. agentinputlab/integrations/external_workers/method.py +314 -0
  231. agentinputlab/integrations/external_workers/process.py +678 -0
  232. agentinputlab/integrations/external_workers/supervisor.py +1071 -0
  233. agentinputlab/integrations/full_architecture/__init__.py +1 -0
  234. agentinputlab/integrations/full_architecture/hyde.py +212 -0
  235. agentinputlab/integrations/full_architecture/plan_and_budget.py +188 -0
  236. agentinputlab/integrations/live_history.py +222 -0
  237. agentinputlab/integrations/prompt_optimization/__init__.py +1 -0
  238. agentinputlab/integrations/training/__init__.py +1 -0
  239. agentinputlab/metrics/__init__.py +50 -0
  240. agentinputlab/metrics/catalog.py +313 -0
  241. agentinputlab/metrics/harm.py +95 -0
  242. agentinputlab/metrics/paired.py +40 -0
  243. agentinputlab/metrics/qa.py +76 -0
  244. agentinputlab/metrics/text.py +33 -0
  245. agentinputlab/metrics/third_party.py +161 -0
  246. agentinputlab/models/__init__.py +4 -0
  247. agentinputlab/observability/__init__.py +56 -0
  248. agentinputlab/observability/budget.py +316 -0
  249. agentinputlab/observability/instrumentation.py +754 -0
  250. agentinputlab/observability/models.py +403 -0
  251. agentinputlab/observability/monitor.py +380 -0
  252. agentinputlab/optimizers/__init__.py +1 -0
  253. agentinputlab/optimizers/clarify/__init__.py +12 -0
  254. agentinputlab/optimizers/context/__init__.py +22 -0
  255. agentinputlab/optimizers/decompose/__init__.py +64 -0
  256. agentinputlab/optimizers/evidence/__init__.py +22 -0
  257. agentinputlab/optimizers/rewrite/__init__.py +30 -0
  258. agentinputlab/parity/__init__.py +5 -0
  259. agentinputlab/parity/base.py +206 -0
  260. agentinputlab/production_campaign.py +763 -0
  261. agentinputlab/py.typed +1 -0
  262. agentinputlab/recipes/__init__.py +333 -0
  263. agentinputlab/recipes/ace.py +418 -0
  264. agentinputlab/recipes/ace_bfcl.py +273 -0
  265. agentinputlab/recipes/ace_common_support.py +169 -0
  266. agentinputlab/recipes/ace_native_plan.py +322 -0
  267. agentinputlab/recipes/ace_online.py +711 -0
  268. agentinputlab/recipes/ace_retrieval.py +330 -0
  269. agentinputlab/recipes/ace_statebench.py +382 -0
  270. agentinputlab/recipes/ace_tau.py +463 -0
  271. agentinputlab/recipes/ace_toolsandbox.py +432 -0
  272. agentinputlab/recipes/acon_guideline.py +22 -0
  273. agentinputlab/recipes/adaptive_rag.py +822 -0
  274. agentinputlab/recipes/llmlingua2_inference.py +146 -0
  275. agentinputlab/recipes/llmlingua2_training.py +796 -0
  276. agentinputlab/recipes/mce.py +1486 -0
  277. agentinputlab/recipes/mce_final.py +335 -0
  278. agentinputlab/recipes/mce_text_fit.py +499 -0
  279. agentinputlab/recipes/mce_text_only.py +298 -0
  280. agentinputlab/recipes/qrag.py +729 -0
  281. agentinputlab/recipes/qrag_inference.py +364 -0
  282. agentinputlab/recipes/r2ag_features.py +236 -0
  283. agentinputlab/recipes/r2ag_inference.py +503 -0
  284. agentinputlab/recipes/r2ag_training.py +948 -0
  285. agentinputlab/recipes/recomp_abstractive.py +592 -0
  286. agentinputlab/recipes/recomp_extractive.py +525 -0
  287. agentinputlab/recipes/reformer.py +17 -0
  288. agentinputlab/recipes/rqrag.py +1516 -0
  289. agentinputlab/recipes/rqrag_common_support.py +193 -0
  290. agentinputlab/recipes/rqrag_completion.py +147 -0
  291. agentinputlab/recipes/skillopt.py +462 -0
  292. agentinputlab/recipes/skillopt_common_support.py +154 -0
  293. agentinputlab/recipes/skillopt_environment.py +165 -0
  294. agentinputlab/recipes/skillopt_environment_cli.py +5 -0
  295. agentinputlab/recipes/skillopt_retrieval.py +188 -0
  296. agentinputlab/recipes/smartsearch.py +897 -0
  297. agentinputlab/recipes/smartsearch_curriculum.py +283 -0
  298. agentinputlab/recipes/smartsearch_grpo_contracts.py +58 -0
  299. agentinputlab/recipes/smartsearch_grpo_data.py +314 -0
  300. agentinputlab/recipes/smartsearch_grpo_meter.py +324 -0
  301. agentinputlab/recipes/smartsearch_grpo_prefix.py +144 -0
  302. agentinputlab/recipes/smartsearch_grpo_rollout.py +119 -0
  303. agentinputlab/recipes/smartsearch_grpo_tools.py +364 -0
  304. agentinputlab/recipes/smartsearch_grpo_training.py +305 -0
  305. agentinputlab/recipes/smartsearch_grpo_transport.py +248 -0
  306. agentinputlab/recipes/smartsearch_grpo_worker.py +364 -0
  307. agentinputlab/recipes/smartsearch_inference.py +524 -0
  308. agentinputlab/recipes/smartsearch_native_data.py +172 -0
  309. agentinputlab/recipes/smartsearch_policy.py +616 -0
  310. agentinputlab/recipes/smartsearch_policy_worker.py +9 -0
  311. agentinputlab/recipes/smartsearch_sampling.py +232 -0
  312. agentinputlab/recipes/smartsearch_teacher.py +203 -0
  313. agentinputlab/recipes/smartsearch_training.py +265 -0
  314. agentinputlab/registry/__init__.py +46 -0
  315. agentinputlab/registry/beta.py +727 -0
  316. agentinputlab/registry/data/algorithms.json +1959 -0
  317. agentinputlab/registry/data/auxiliary_method_profiles.json +34 -0
  318. agentinputlab/registry/loader.py +100 -0
  319. agentinputlab/registry/result_manifest.py +184 -0
  320. agentinputlab/registry/runtime.py +195 -0
  321. agentinputlab/registry/schema.py +449 -0
  322. agentinputlab/runner/__init__.py +30 -0
  323. agentinputlab/runner/balance.py +248 -0
  324. agentinputlab/runner/cache.py +135 -0
  325. agentinputlab/runner/composite.py +130 -0
  326. agentinputlab/runner/engine.py +285 -0
  327. agentinputlab/runner/runtime_guard.py +268 -0
  328. agentinputlab/runner/worker.py +80 -0
  329. agentinputlab/runtime_bootstrap.py +288 -0
  330. agentinputlab/selectors/__init__.py +196 -0
  331. agentinputlab/selectors/advanced.py +1514 -0
  332. agentinputlab/selectors/artifacts.py +1087 -0
  333. agentinputlab/selectors/base.py +112 -0
  334. agentinputlab/selectors/campaigns.py +1893 -0
  335. agentinputlab/selectors/catalog.py +86 -0
  336. agentinputlab/selectors/discovery.py +1860 -0
  337. agentinputlab/selectors/evaluation.py +1348 -0
  338. agentinputlab/selectors/features.py +383 -0
  339. agentinputlab/selectors/learned.py +502 -0
  340. agentinputlab/selectors/no_op.py +28 -0
  341. agentinputlab/selectors/outcome_table.py +475 -0
  342. agentinputlab/selectors/producer.py +853 -0
  343. agentinputlab/selectors/rules.py +109 -0
  344. agentinputlab/selectors/runtime.py +420 -0
  345. agentinputlab/studies/__init__.py +16 -0
  346. agentinputlab/studies/design.py +165 -0
  347. agentinputlab/studies/paired.py +322 -0
  348. agentinputlab/studio/__init__.py +6 -0
  349. agentinputlab/studio/campaigns.py +819 -0
  350. agentinputlab/studio/engine.py +1408 -0
  351. agentinputlab/studio/model_backends.py +425 -0
  352. agentinputlab/studio/prepared.py +410 -0
  353. agentinputlab/studio/server.py +613 -0
  354. agentinputlab/studio/static/app.js +397 -0
  355. agentinputlab/studio/static/campaigns.html +175 -0
  356. agentinputlab/studio/static/campaigns.js +426 -0
  357. agentinputlab/studio/static/index.html +192 -0
  358. agentinputlab/studio/static/result.html +103 -0
  359. agentinputlab/studio/static/result.js +273 -0
  360. agentinputlab/studio/static/styles.css +467 -0
  361. agentinputlab-0.1.0a1.data/data/share/agentinputlab/CITATION.cff +22 -0
  362. agentinputlab-0.1.0a1.dist-info/METADATA +392 -0
  363. agentinputlab-0.1.0a1.dist-info/RECORD +469 -0
  364. agentinputlab-0.1.0a1.dist-info/WHEEL +5 -0
  365. agentinputlab-0.1.0a1.dist-info/entry_points.txt +6 -0
  366. agentinputlab-0.1.0a1.dist-info/licenses/LICENSE +21 -0
  367. agentinputlab-0.1.0a1.dist-info/licenses/NOTICE +31 -0
  368. agentinputlab-0.1.0a1.dist-info/licenses/THIRD_PARTY_NOTICES.md +94 -0
  369. agentinputlab-0.1.0a1.dist-info/top_level.txt +2 -0
  370. workers/README.md +94 -0
  371. workers/ace/README.md +261 -0
  372. workers/ace/__init__.py +1 -0
  373. workers/ace/compatibility_manifest.json +39 -0
  374. workers/ace/driver.py +1682 -0
  375. workers/acon/README.md +215 -0
  376. workers/acon/__init__.py +5 -0
  377. workers/acon/compatibility_manifest.json +93 -0
  378. workers/acon/driver.py +1859 -0
  379. workers/acon/fitted.py +395 -0
  380. workers/acon/guideline.py +470 -0
  381. workers/acon/guideline_source_manifest.json +20 -0
  382. workers/adaptive_rag/README.md +96 -0
  383. workers/adaptive_rag/__init__.py +15 -0
  384. workers/adaptive_rag/compatibility_manifest.json +61 -0
  385. workers/adaptive_rag/driver.py +1470 -0
  386. workers/adaptive_rag/fixture_runtime.py +163 -0
  387. workers/adaptive_rag/runtime.py +252 -0
  388. workers/ask_or_assume/README.md +124 -0
  389. workers/ask_or_assume/__init__.py +1 -0
  390. workers/ask_or_assume/compatibility_manifest.json +36 -0
  391. workers/ask_or_assume/driver.py +1227 -0
  392. workers/decomp/README.md +133 -0
  393. workers/decomp/UPSTREAM_LICENSE.Apache-2.0.txt +201 -0
  394. workers/decomp/__init__.py +5 -0
  395. workers/decomp/compatibility_manifest.json +205 -0
  396. workers/decomp/driver.py +1015 -0
  397. workers/decomp/live.py +137 -0
  398. workers/decomp/runtime.py +231 -0
  399. workers/infocqr/README.md +106 -0
  400. workers/infocqr/__init__.py +1 -0
  401. workers/infocqr/compatibility_manifest.json +84 -0
  402. workers/infocqr/driver.py +1766 -0
  403. workers/ircot/README.md +167 -0
  404. workers/ircot/__init__.py +7 -0
  405. workers/ircot/compatibility_manifest.json +121 -0
  406. workers/ircot/controlled.py +457 -0
  407. workers/ircot/driver.py +1373 -0
  408. workers/ircot/fixture_bindings.json +39 -0
  409. workers/ircot/fixture_config.json +48 -0
  410. workers/ircot/fixture_prompt.txt +2 -0
  411. workers/ircot/native_qa.py +398 -0
  412. workers/ircot/qa_compatibility_manifest.json +57 -0
  413. workers/ircot/runtime.py +97 -0
  414. workers/llmcompiler/README.md +160 -0
  415. workers/llmcompiler/__init__.py +1 -0
  416. workers/llmcompiler/compatibility_manifest.json +45 -0
  417. workers/llmcompiler/driver.py +1514 -0
  418. workers/llmcompiler/export_prompts.py +74 -0
  419. workers/llmcompiler/live.py +174 -0
  420. workers/llmcompiler/patch_manifest.json +147 -0
  421. workers/mce/README.md +198 -0
  422. workers/mce/__init__.py +29 -0
  423. workers/mce/compatibility_manifest.json +115 -0
  424. workers/mce/driver.py +2585 -0
  425. workers/mce/final_eval.py +173 -0
  426. workers/official_arenas/README.md +25 -0
  427. workers/official_arenas/__init__.py +1 -0
  428. workers/official_arenas/capture_records.py +110 -0
  429. workers/official_arenas/driver.py +619 -0
  430. workers/official_arenas/protocol.py +334 -0
  431. workers/official_arenas/providers/__init__.py +1 -0
  432. workers/official_arenas/providers/_live_history.py +228 -0
  433. workers/official_arenas/providers/_message_compat.py +77 -0
  434. workers/official_arenas/providers/appworld_ul.py +196 -0
  435. workers/official_arenas/providers/fixture.py +112 -0
  436. workers/official_arenas/providers/statebench.py +960 -0
  437. workers/official_arenas/providers/tau3.py +1672 -0
  438. workers/official_arenas/providers/tau_retail.py +586 -0
  439. workers/official_arenas/providers/toolsandbox.py +1321 -0
  440. workers/official_arenas/providers/tooltalk.py +699 -0
  441. workers/official_arenas/retail_capture.py +188 -0
  442. workers/official_arenas/retail_driver.py +275 -0
  443. workers/qrag/README.md +172 -0
  444. workers/qrag/__init__.py +1 -0
  445. workers/qrag/compatibility_manifest.json +64 -0
  446. workers/qrag/driver.py +673 -0
  447. workers/r2ag/README.md +154 -0
  448. workers/r2ag/__init__.py +5 -0
  449. workers/r2ag/compatibility_manifest.json +55 -0
  450. workers/r2ag/driver.py +1287 -0
  451. workers/r2ag/feature_schema.json +8 -0
  452. workers/r2ag/runtime.py +589 -0
  453. workers/recomp/README.md +120 -0
  454. workers/recomp/__init__.py +1 -0
  455. workers/recomp/compatibility_manifest.json +43 -0
  456. workers/recomp/driver.py +1653 -0
  457. workers/reformer/README.md +125 -0
  458. workers/reformer/__init__.py +1 -0
  459. workers/reformer/compatibility_manifest.json +68 -0
  460. workers/reformer/driver.py +1459 -0
  461. workers/reformer/induction.py +457 -0
  462. workers/rrr/README.md +126 -0
  463. workers/rrr/__init__.py +1 -0
  464. workers/rrr/compatibility_manifest.json +57 -0
  465. workers/rrr/driver.py +1133 -0
  466. workers/smartsearch/README.md +331 -0
  467. workers/smartsearch/__init__.py +1 -0
  468. workers/smartsearch/compatibility_manifest.json +41 -0
  469. workers/smartsearch/driver.py +1643 -0
@@ -0,0 +1,586 @@
1
+ """Isolated Retail continuation; no banking retrieval or retry-to-success.
2
+
3
+ This module intentionally leaves the source-pinned Banking provider unchanged.
4
+ It shares only the measured agent/budget helpers. A campaign must bind the
5
+ user simulator and judge to the evaluated backbone and approve its task/method
6
+ matrix before invoking this provider. This is backbone-conditioned evaluation,
7
+ not a shared independent judge or an official cross-model leaderboard score.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import copy
13
+ import hashlib
14
+ import json
15
+ import math
16
+ import os
17
+ import subprocess
18
+ from collections import Counter
19
+ from collections.abc import Mapping
20
+ from contextlib import contextmanager
21
+ from pathlib import Path
22
+ from typing import Any
23
+ from urllib.parse import urlparse
24
+
25
+ from ..protocol import (
26
+ OfficialArenaError, ProviderArmResult, content_hash, intervention_usage,
27
+ materialized_state, require_materialized_budget, resolve_shared_budget_config,
28
+ validate_dependency_hashes, validate_shared_budget, visible_shared_budget,
29
+ )
30
+ from .tau3 import (
31
+ Tau3Provider, _downstream_agent_usage, _install_local_tau_cost_accounting,
32
+ _intervened_tau_agent_class, _is_generated_tool_argument_validation,
33
+ _is_generated_user_message_validation, _orchestrator_step_cap,
34
+ _remaining_agent_budget,
35
+ )
36
+ from ._live_history import validate_history_transform
37
+
38
+ SOURCE_REVISION = "cf71a8070269883e38a365ffa85f78f46844c1f4"
39
+ ENVIRONMENT_MODEL_POLICY = "evaluated-backbone-user-and-judge-v1"
40
+ RETAIL_SOURCE_SHA256 = {
41
+ "data/tau2/domains/retail/db.json": "413a65160adbdb5fde0ffc0015c49b6d70250b10c18128de169b597af7766765",
42
+ "data/tau2/domains/retail/policy.md": "2c9652afbce57d6e087768d37cda64d31c53d50b3e3225cfdb791bac66466467",
43
+ "data/tau2/domains/retail/split_tasks.json": "ed0580ec52575b63fbf76568af42490da6ee7783ecb4aa81af46961291358f20",
44
+ "data/tau2/domains/retail/tasks.json": "8e03ebce7901bd6218e7a7dc3105faa9324091a68058f7fe61c65262868812e8",
45
+ "src/tau2/domains/retail/environment.py": "5b819fb895a4ef49df71404c3d9678ab09e8578eec841b8ec9229c8f51e32405",
46
+ "src/tau2/domains/retail/tools.py": "34f4fe9702d36f0dd4697700fbcd63d0cf5386e6eb8e7499aaa336243bad8750",
47
+ "src/tau2/domains/retail/data_model.py": "f5ad09590953855cc49d2ab2ad5c0594be408cae74d1500fb278e5a6bf2c50d6",
48
+ "src/tau2/runner/build.py": "2c4b61b83d4108bb9a2b46724a7b9cc0823548cfd866ca0f415bc536269d964b",
49
+ "src/tau2/evaluator/evaluator.py": "204d95a82812402f2fee989250392d3c66de702a8bcc20258c7e2a8153a1ea8d",
50
+ "src/tau2/evaluator/evaluator_nl_assertions.py": "cb6b3758cdceb02a726732b4ee1af618affcc08f8ab84b44f060146b8f3ad90a",
51
+ "src/tau2/data_model/simulation.py": "518a4eda9af783f25243e1bd2c714f4617cf86188878a0bb584fe73c9528a35a",
52
+ }
53
+
54
+
55
+ class RetailJudgeError(OfficialArenaError):
56
+ """Judge generation/coverage is unresolved, not an agent success or zero."""
57
+
58
+
59
+ def audit_retail_source(checkout: Path) -> dict[str, Any]:
60
+ """Read source and aggregate inventory only; return no hidden DB/gold text."""
61
+ if checkout.is_symlink() or not checkout.is_dir():
62
+ raise OfficialArenaError("Retail checkout is absent or symlinked")
63
+ head = subprocess.check_output(
64
+ ["git", "-C", str(checkout), "rev-parse", "HEAD"], text=True,
65
+ ).strip()
66
+ if head != SOURCE_REVISION:
67
+ raise OfficialArenaError("Retail upstream revision differs")
68
+ for relative, expected in RETAIL_SOURCE_SHA256.items():
69
+ path = checkout / relative
70
+ if path.is_symlink() or not path.is_file():
71
+ raise OfficialArenaError(f"Retail pinned file is absent: {relative}")
72
+ if hashlib.sha256(path.read_bytes()).hexdigest() != expected:
73
+ raise OfficialArenaError(f"Retail pinned file differs: {relative}")
74
+ root = checkout / "data/tau2/domains/retail"
75
+ tasks = json.loads((root / "tasks.json").read_bytes())
76
+ splits = json.loads((root / "split_tasks.json").read_bytes())
77
+ ids = [str(task["id"]) for task in tasks]
78
+ if len(ids) != 114 or len(set(ids)) != 114:
79
+ raise OfficialArenaError("Retail task inventory differs")
80
+ if (len(splits["train"]) != 74 or len(splits["test"]) != 40
81
+ or set(splits["train"]) & set(splits["test"])
82
+ or set(splits["train"]) | set(splits["test"]) != set(ids)
83
+ or set(splits["base"]) != set(ids)):
84
+ raise OfficialArenaError("Retail official split differs")
85
+ rewards = Counter(tuple(task["evaluation_criteria"]["reward_basis"]) for task in tasks)
86
+ if rewards != {("DB", "NL_ASSERTION"): 112, ("DB",): 2}:
87
+ raise OfficialArenaError("Retail reward basis differs")
88
+ return {"source_revision": head, "source_sha256": dict(RETAIL_SOURCE_SHA256),
89
+ "task_counts": {"base": 114, "train": 74, "test": 40},
90
+ "task_ids_by_split": splits, "reward_basis_counts": {"DB+NL_ASSERTION": 112, "DB": 2}}
91
+
92
+
93
+ def capture_first_user_once(*, build_orchestrator: Any, run_config: Any,
94
+ task: Any, seed: int, user_message_type: type) -> tuple[Any, Any]:
95
+ """Exactly one fixed-seed user generation, never an evaluated-agent turn."""
96
+ orchestrator = build_orchestrator(
97
+ run_config, task, seed=seed, simulation_id=f"ailab-retail-capture-{task.id}-{seed}",
98
+ )
99
+ try:
100
+ orchestrator.initialize()
101
+ # Pinned Retail has no user tools. A single native USER step is enough;
102
+ # never step a second time to manufacture a successful checkpoint.
103
+ if str(getattr(orchestrator.to_role, "value", orchestrator.to_role)) != "user":
104
+ raise OfficialArenaError("Retail capture would execute the evaluated agent")
105
+ # Native get_user_tools() raises when the domain has no user toolkit.
106
+ # Inspect its absence without treating that expected condition as failure.
107
+ if getattr(orchestrator.environment, "user_tools", None) is not None:
108
+ raise OfficialArenaError("Retail capture unexpectedly exposes user tools")
109
+ orchestrator.step()
110
+ message = orchestrator.message
111
+ if (not isinstance(message, user_message_type) or not message.content
112
+ or not message.content.strip() or message.is_tool_call()):
113
+ raise OfficialArenaError("Retail first user generation is not a visible request")
114
+ return orchestrator, message
115
+ except BaseException:
116
+ orchestrator._cleanup()
117
+ raise
118
+
119
+
120
+ def _check_judge_response(response: Any, assertions: list[str]) -> None:
121
+ try:
122
+ parsed = json.loads(response.content)
123
+ rows = parsed["results"]
124
+ valid = (isinstance(rows, list) and len(rows) == len(assertions)
125
+ and all(isinstance(row, Mapping)
126
+ and type(row.get("metExpectation")) is bool
127
+ and isinstance(row.get("reasoning"), str) for row in rows)
128
+ and Counter(row.get("expectedOutcome") for row in rows) == Counter(assertions))
129
+ except (AttributeError, KeyError, TypeError, ValueError):
130
+ valid = False
131
+ if not valid:
132
+ # Upstream all([]) otherwise rewards an empty judge result as success.
133
+ raise RetailJudgeError("Retail judge did not cover the exact official assertions")
134
+
135
+
136
+ @contextmanager
137
+ def bound_retail_judge(config: Mapping[str, Any], assertions: list[str]):
138
+ """Scoped judge, explicitly locked to the current evaluated backbone."""
139
+ from tau2.evaluator import evaluator_nl_assertions as module
140
+
141
+ original = (module.DEFAULT_LLM_NL_ASSERTIONS, module.DEFAULT_LLM_NL_ASSERTIONS_ARGS, module.generate)
142
+ counters = {"model_calls": 0, "input_tokens": 0, "output_tokens": 0}
143
+
144
+ def measured_generate(*args: Any, **kwargs: Any) -> Any:
145
+ counters["model_calls"] += 1
146
+ try:
147
+ result = original[2](*args, **kwargs)
148
+ except Exception as error:
149
+ raise RetailJudgeError("Retail backbone-bound judge generation failed") from error
150
+ usage = getattr(result, "usage", None)
151
+ if isinstance(usage, Mapping):
152
+ counters["input_tokens"] += int(usage.get("prompt_tokens", usage.get("input_tokens", 0)) or 0)
153
+ counters["output_tokens"] += int(usage.get("completion_tokens", usage.get("output_tokens", 0)) or 0)
154
+ _check_judge_response(result, assertions)
155
+ return result
156
+
157
+ module.DEFAULT_LLM_NL_ASSERTIONS = config["llm_judge"]
158
+ module.DEFAULT_LLM_NL_ASSERTIONS_ARGS = dict(config["llm_args_judge"])
159
+ module.generate = measured_generate
160
+ try:
161
+ yield counters
162
+ finally:
163
+ module.DEFAULT_LLM_NL_ASSERTIONS, module.DEFAULT_LLM_NL_ASSERTIONS_ARGS, module.generate = original
164
+
165
+
166
+ def _create_only(path: Path, value: Mapping[str, Any]) -> None:
167
+ # Reserve before invoking a model and fsync before continuing. Interrupted
168
+ # or partial records remain evidence; they are never an excuse to retry.
169
+ fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_EXCL | os.O_NOFOLLOW, 0o600)
170
+ with os.fdopen(fd, "w", encoding="utf-8") as handle:
171
+ json.dump(value, handle, ensure_ascii=False, sort_keys=True, indent=2, allow_nan=False)
172
+ handle.write("\n")
173
+ handle.flush()
174
+ os.fsync(handle.fileno())
175
+
176
+
177
+ def _saved_capture(path: Path, *, binding: str, task_id: str) -> Mapping[str, Any]:
178
+ if path.is_symlink() or not path.is_file():
179
+ raise OfficialArenaError("Retail capture receipt is absent or symlinked")
180
+ try:
181
+ saved = json.loads(path.read_bytes())
182
+ valid = (isinstance(saved, Mapping)
183
+ and saved.get("protocol") == "retail-first-capture.v1"
184
+ and saved.get("config_binding") == binding
185
+ and saved.get("task_id") == task_id
186
+ and type(saved.get("seed")) is int and saved["seed"] == 17
187
+ and type(saved.get("attempt")) is int and saved["attempt"] == 1
188
+ and saved.get("terminal") in {"captured", "capture_failed"}
189
+ and saved.get("receipt_sha256") == content_hash(
190
+ {key: value for key, value in saved.items() if key != "receipt_sha256"}))
191
+ if saved.get("terminal") == "captured":
192
+ record = saved.get("record", {})
193
+ valid = valid and (isinstance(record, Mapping) and record.get("checkpoint_id") == task_id
194
+ and record.get("protected", {}).get("task_id") == task_id)
195
+ except (AttributeError, KeyError, TypeError, ValueError):
196
+ valid = False
197
+ if not valid:
198
+ raise OfficialArenaError("Retail existing capture receipt differs")
199
+ return saved
200
+
201
+
202
+ def _retail_agent_class(generation_failures: list[dict[str, Any]]) -> type:
203
+ """Retain errors that the shared measured agent turns into hard stops."""
204
+ from tau2.utils import llm_utils
205
+ original = llm_utils.generate
206
+
207
+ def observed_generate(*args: Any, **kwargs: Any):
208
+ try:
209
+ return original(*args, **kwargs)
210
+ except Exception as error:
211
+ generation_failures.append({"exception_type": type(error).__name__,
212
+ "exception_sha256": hashlib.sha256(str(error).encode()).hexdigest(),
213
+ "call_name": kwargs.get("call_name"), "retry_permitted": False})
214
+ raise
215
+
216
+ # The shared class closes over generate when built. Restore the module
217
+ # immediately; this observer applies only to the evaluated agent, not to
218
+ # the user simulator or judge, and no previous provider is modified.
219
+ llm_utils.generate = observed_generate
220
+ try:
221
+ return _intervened_tau_agent_class()
222
+ finally:
223
+ llm_utils.generate = original
224
+
225
+
226
+ def _paper_terminal_success(raw_reward: float, termination: str, hard_stops: int) -> float:
227
+ """Separate budget/timeout failure accounting from native raw reward."""
228
+ if hard_stops or termination in {"timeout", "max_steps", "too_many_errors", "agent_error", "user_error",
229
+ "infrastructure_error", "context_window_exceeded", "unexpected_error"}:
230
+ return 0.0
231
+ return raw_reward
232
+
233
+
234
+ def _environment_user_usage(messages: list[Any], initial_length: int, user_type: type) -> dict[str, Any]:
235
+ rows = [message for message in messages[initial_length:] if isinstance(message, user_type)]
236
+ known = [message.usage for message in rows if isinstance(getattr(message, "usage", None), Mapping)]
237
+ return {"model_calls": len(rows), "input_tokens": sum(int(row.get("prompt_tokens", row.get("input_tokens", 0)) or 0) for row in known),
238
+ "output_tokens": sum(int(row.get("completion_tokens", row.get("output_tokens", 0)) or 0) for row in known),
239
+ "token_usage_incomplete": len(known) != len(rows)}
240
+
241
+
242
+ class TauRetailProvider:
243
+ benchmark_id = "tau3.retail"
244
+ source_revision = SOURCE_REVISION
245
+ scorer_id = "tau3.retail.official_v1.0.1.backbone_conditioned_judge"
246
+ scorer_revision = content_hash({"native": RETAIL_SOURCE_SHA256["src/tau2/evaluator/evaluator.py"],
247
+ "nl": RETAIL_SOURCE_SHA256["src/tau2/evaluator/evaluator_nl_assertions.py"],
248
+ "judge_coverage_guard": "exact-assertion-multiset-bool-v1",
249
+ "environment_model_policy": ENVIRONMENT_MODEL_POLICY})
250
+ _FIELDS = frozenset({"task_set_name", "task_split_name", "limit", "capture_seed", "llm_agent",
251
+ "llm_user", "llm_judge", "llm_args_agent", "llm_args_user", "llm_args_judge",
252
+ "max_steps", "max_errors", "timeout", "locked_dependency_hashes", "budget_override"})
253
+
254
+ def __init__(self, *, history_transform: Any = None) -> None:
255
+ validate_history_transform(history_transform)
256
+ self.history_transform = history_transform
257
+
258
+ def _validate_config(self, config: Mapping[str, Any]) -> Mapping[str, Any]:
259
+ if not isinstance(config, Mapping):
260
+ raise OfficialArenaError("Retail provider config must be an object")
261
+ parsed = resolve_shared_budget_config(config)
262
+ if set(parsed) != self._FIELDS:
263
+ raise OfficialArenaError("Retail config fields differ; banking retrieval is not applicable")
264
+ if parsed["task_set_name"] != "retail" or parsed["task_split_name"] not in {"train", "test"}:
265
+ raise OfficialArenaError("Retail requires an explicit official train or test split")
266
+ limit = 40 if parsed["task_split_name"] == "test" else 74
267
+ for name, cap in (("limit", limit), ("max_steps", 10000), ("max_errors", 10000)):
268
+ raw = parsed[name]
269
+ if isinstance(raw, bool) or not isinstance(raw, int) or not 1 <= raw <= cap:
270
+ raise OfficialArenaError(f"Retail {name} is invalid")
271
+ if parsed["capture_seed"] != 17 or type(parsed["capture_seed"]) is not int:
272
+ raise OfficialArenaError("Retail capture seed must be frozen at 17")
273
+ timeout = parsed["timeout"]
274
+ if (isinstance(timeout, bool) or not isinstance(timeout, (float, int))
275
+ or not math.isfinite(timeout) or timeout <= 0):
276
+ raise OfficialArenaError("Retail episode timeout must be explicit and finite")
277
+ budget = validate_shared_budget(parsed["budget_override"])
278
+ locks = validate_dependency_hashes(parsed["locked_dependency_hashes"], label="Retail")
279
+ if not {"agent_model", "user_simulator", "nl_assertion_judge", "official_runtime", "scorer"} <= set(locks):
280
+ raise OfficialArenaError("Retail model/user/judge/runtime/scorer locks are incomplete")
281
+ for role in ("agent", "user", "judge"):
282
+ model, args = parsed[f"llm_{role}"], parsed[f"llm_args_{role}"]
283
+ if not isinstance(model, str) or not model.strip() or not isinstance(args, Mapping):
284
+ raise OfficialArenaError(f"Retail {role} model binding is invalid")
285
+ if (urlparse(args.get("api_base", "")).hostname not in {"127.0.0.1", "localhost", "::1"}
286
+ or type(args.get("temperature")) not in {int, float} or args.get("temperature") != 0
287
+ or type(args.get("seed")) is not int or args.get("seed") != 17
288
+ or type(args.get("num_retries")) is not int or args.get("num_retries") != 0):
289
+ raise OfficialArenaError(f"Retail {role} requires local, fixed decoding and no retries")
290
+ cap = args.get("max_tokens")
291
+ if isinstance(cap, bool) or not isinstance(cap, int) or cap < 1:
292
+ raise OfficialArenaError(f"Retail {role} output cap is absent")
293
+ request_timeout = args.get("timeout")
294
+ if (type(request_timeout) not in {int, float} or not math.isfinite(request_timeout)
295
+ or request_timeout <= 0):
296
+ raise OfficialArenaError(f"Retail {role} request timeout must be explicit and finite")
297
+ if parsed["llm_args_agent"]["max_tokens"] > budget["max_output_tokens_per_call"]:
298
+ raise OfficialArenaError("Retail per-call agent cap exceeds its declared shared budget")
299
+ if parsed["llm_args_judge"].get("response_format") != {"type": "json_object"}:
300
+ raise OfficialArenaError("Retail judge requires an explicit JSON response format")
301
+ for role in ("user", "judge"):
302
+ if parsed[f"llm_{role}"] != parsed["llm_agent"]:
303
+ raise OfficialArenaError("Retail user and judge must follow the evaluated backbone")
304
+ if parsed[f"llm_args_{role}"]["api_base"].rstrip("/") != parsed["llm_args_agent"]["api_base"].rstrip("/"):
305
+ raise OfficialArenaError("Retail user and judge must use the evaluated model endpoint")
306
+ return parsed
307
+
308
+ def doctor(self, config: Mapping[str, Any]) -> tuple[str, ...]:
309
+ try:
310
+ self._validate_config(config)
311
+ from tau2.domains.retail import environment
312
+ from tau2.domains.retail.utils import RETAIL_DB_PATH
313
+ from tau2.utils import llm_utils
314
+ checkout = Path(environment.__file__).resolve().parents[4]
315
+ audit_retail_source(checkout)
316
+ if Path(RETAIL_DB_PATH).resolve() != checkout / "data/tau2/domains/retail/db.json":
317
+ raise OfficialArenaError("Retail effective DB is not its pinned data source")
318
+ if getattr(llm_utils.completion, "_agentinputlab_tool_argument_normalizer", False):
319
+ raise OfficialArenaError("Retail requires a fresh process without banking decoder repairs")
320
+ except Exception as error:
321
+ return (f"{type(error).__name__}: {error}",)
322
+ return ()
323
+
324
+ def _run_config(self, config: Mapping[str, Any], *, budget: Mapping[str, Any] | None = None):
325
+ from tau2.data_model.simulation import TextRunConfig
326
+ args = dict(config["llm_args_agent"])
327
+ steps = config["max_steps"]
328
+ if budget is not None:
329
+ steps = min(steps, budget["max_model_calls"])
330
+ args["max_tokens"] = min(args["max_tokens"], budget["max_output_tokens"])
331
+ return TextRunConfig(domain="retail", agent="llm_agent", user="user_simulator",
332
+ llm_agent=config["llm_agent"], llm_user=config["llm_user"],
333
+ llm_args_agent=args, llm_args_user=dict(config["llm_args_user"]),
334
+ max_steps=steps, max_errors=config["max_errors"], timeout=config["timeout"],
335
+ retrieval_config=None, retrieval_config_kwargs={})
336
+
337
+ def capture(self, config: Mapping[str, Any], *, output_root: Path) -> tuple[Mapping[str, Any], ...]:
338
+ batch = self.capture_batch(config, output_root=output_root)
339
+ unresolved = [row["task_id"] for row in batch["dispositions"] if row["status"] != "captured"]
340
+ if unresolved:
341
+ raise OfficialArenaError(f"Retail first-capture failures retained; no automatic retry: {unresolved}")
342
+ return tuple(batch["records"])
343
+
344
+ def capture_batch(self, config: Mapping[str, Any], *, output_root: Path) -> Mapping[str, Any]:
345
+ """Keep the complete expected inventory even when some captures fail.
346
+
347
+ An existing start without a receipt is unresolved, not proof of a dead
348
+ process. The scoped Retail controller can export a partial inventory
349
+ after every task has a terminal disposition, without retrying failures.
350
+ """
351
+ parsed = self._validate_config(config)
352
+ blockers = self.doctor(parsed)
353
+ if blockers:
354
+ raise OfficialArenaError("; ".join(blockers))
355
+ _install_local_tau_cost_accounting(parsed)
356
+ from tau2.data_model.message import UserMessage
357
+ from tau2.runner.build import build_orchestrator
358
+ from tau2.runner.helpers import get_tasks
359
+ tasks = get_tasks("retail", task_split_name=parsed["task_split_name"], num_tasks=parsed["limit"])
360
+ output_root.mkdir(parents=True, exist_ok=True)
361
+ rows, dispositions = [], []
362
+ binding = content_hash(parsed)
363
+ for task in tasks:
364
+ # Official IDs are numerical; reject unexpected path components.
365
+ if not str(task.id).isdigit():
366
+ raise OfficialArenaError("Retail task ID is not a safe official identity")
367
+ target = output_root / f"first-capture-{task.id}.json"
368
+ if target.exists() or target.is_symlink():
369
+ saved = _saved_capture(target, binding=binding, task_id=str(task.id))
370
+ else:
371
+ saved = {"protocol": "retail-first-capture.v1", "config_binding": binding,
372
+ "task_id": str(task.id), "seed": 17, "attempt": 1}
373
+ try:
374
+ _create_only(output_root / f"first-capture-{task.id}-start.json", saved)
375
+ except FileExistsError:
376
+ # This can be live or interrupted. Neither elapsed time nor
377
+ # an absent final file proves termination; never retry it.
378
+ dispositions.append({"task_id": str(task.id), "status": "reserved_unresolved",
379
+ "retry_permitted": False})
380
+ continue
381
+ orchestrator = None
382
+ try:
383
+ orchestrator, message = capture_first_user_once(
384
+ build_orchestrator=build_orchestrator, run_config=self._run_config(parsed),
385
+ task=task, seed=17, user_message_type=UserMessage)
386
+ tools = orchestrator.environment.get_tools()
387
+ schemas = [tool.openai_schema for tool in tools]
388
+ policy = orchestrator.environment.get_policy()
389
+ history = [item.model_copy(update={"timestamp": None, "turn_idx": None}).model_dump(mode="json")
390
+ for item in orchestrator.get_messages()]
391
+ state = {"query": message.content, "task_id": str(task.id), "instruction": policy,
392
+ "context": [{"text": policy, "block_id": "official_policy", "source": "tau3.retail.public_policy",
393
+ "score": None, "metadata": {"domain": "retail"}},
394
+ {"text": json.dumps(schemas, sort_keys=True, ensure_ascii=False),
395
+ "block_id": "official_tool_catalog", "source": "tau3.retail.tool_schemas",
396
+ "score": None, "metadata": {"domain": "retail", "tool_defs_hash": content_hash(schemas)}}],
397
+ "messages": [{"role": "user", "content": message.content, "name": None}],
398
+ "tool_names": [tool.name for tool in tools],
399
+ "metadata": {"benchmark_id": self.benchmark_id, "checkpoint_phase": "after_initial_user_message",
400
+ "clarification_roundtrip_available": True, "state_restore_available": True,
401
+ "capture_attempt": 1, "capture_seed": 17,
402
+ "acquire_structural_na": "no_native_KB_or_approved_public_retriever"},
403
+ "budget": visible_shared_budget(parsed, {})}
404
+ record = {"checkpoint_id": str(task.id), "group_key": str(task.id), "visible_state": state,
405
+ "eligible_families": ["reformulate", "decompose", "clarify", "curate"],
406
+ "protected": {"task_id": str(task.id), "initial_message_history": history,
407
+ "capture_attempt": 1, "capture_seed": 17,
408
+ "locked_dependency_hashes": dict(parsed["locked_dependency_hashes"])}}
409
+ saved.update({"terminal": "captured", "record": record})
410
+ captured_usage = getattr(message, "usage", None)
411
+ saved["environment_capture_usage"] = {"model_calls": 1,
412
+ "tokens": dict(captured_usage) if isinstance(captured_usage, Mapping) else None,
413
+ "token_usage_incomplete": not isinstance(captured_usage, Mapping), "outside_agent_budget": True}
414
+ except Exception as error:
415
+ saved.update({"terminal": "capture_failed", "exception_type": type(error).__name__,
416
+ "exception_sha256": hashlib.sha256(str(error).encode()).hexdigest(),
417
+ "retry_permitted": False})
418
+ finally:
419
+ if orchestrator is not None:
420
+ orchestrator._cleanup()
421
+ saved["receipt_sha256"] = content_hash(saved)
422
+ _create_only(target, saved)
423
+ if saved["terminal"] == "captured":
424
+ rows.append(saved["record"])
425
+ dispositions.append({"task_id": str(task.id), "status": saved["terminal"],
426
+ "receipt_sha256": saved["receipt_sha256"], "retry_permitted": False})
427
+ if not tasks:
428
+ raise OfficialArenaError("Retail capture resolved no official tasks")
429
+ return {"protocol": "retail-capture-batch.v1", "config_binding": binding,
430
+ "expected_task_ids": [str(task.id) for task in tasks], "records": rows,
431
+ "dispositions": dispositions,
432
+ "all_tasks_terminal": all(row["status"] != "reserved_unresolved" for row in dispositions)}
433
+
434
+ def run_arm(self, config: Mapping[str, Any], *, replay_record: Mapping[str, Any],
435
+ arm_payload: Mapping[str, Any], seed: int, role: str, work_dir: Path) -> ProviderArmResult:
436
+ if self.history_transform is not None and (work_dir / "live-history.json").exists():
437
+ raise OfficialArenaError("native history output must be a fresh episode")
438
+ parsed = self._validate_config(config)
439
+ if type(seed) is not int or seed != 17 or role not in {"baseline", "treatment"}:
440
+ raise OfficialArenaError("Retail arm seed or role differs")
441
+ blockers = self.doctor(parsed)
442
+ if blockers:
443
+ raise OfficialArenaError("; ".join(blockers))
444
+ local_models = _install_local_tau_cost_accounting(parsed)
445
+ _install_local_tau_cost_accounting({"llm_agent": parsed["llm_judge"],
446
+ "llm_args_agent": parsed["llm_args_judge"]})
447
+ state = materialized_state(arm_payload)
448
+ budget = _remaining_agent_budget(require_materialized_budget(state, parsed), intervention_usage(arm_payload))
449
+ protected = replay_record["protected"]
450
+ if (not isinstance(protected, Mapping)
451
+ or type(protected.get("capture_attempt")) is not int or protected["capture_attempt"] != 1
452
+ or type(protected.get("capture_seed")) is not int or protected["capture_seed"] != 17
453
+ or protected.get("task_id") != replay_record["checkpoint_id"]
454
+ or not str(protected.get("task_id", "")).isdigit()
455
+ or protected.get("locked_dependency_hashes") != parsed["locked_dependency_hashes"]):
456
+ raise OfficialArenaError("Retail replay is not the fixed first capture")
457
+ # Lock this physical arm before spending model budget. Resuming a saved
458
+ # failure may inspect it but must not perform inference in this directory.
459
+ _create_only(work_dir / "attempt-start.json", {"benchmark_id": self.benchmark_id,
460
+ "checkpoint_id": replay_record["checkpoint_id"], "role": role, "seed": seed,
461
+ "config_sha256": content_hash(parsed), "arm_payload_sha256": content_hash(arm_payload)})
462
+ if (budget["max_model_calls"] < 1 or budget["max_output_tokens"] < 1
463
+ or (budget.get("max_context_tokens") is not None and budget["max_context_tokens"] < 1)):
464
+ return self._terminal_zero(replay_record, role, seed, work_dir, "shared_budget_exhausted_before_agent", [], {}, budget)
465
+ from tau2.data_model.message import AssistantMessage, ToolMessage, UserMessage
466
+ from tau2.data_model.tasks import InitialState
467
+ from tau2.orchestrator.orchestrator import Orchestrator
468
+ from tau2.runner.build import _build_env_kwargs, build_environment, build_user
469
+ from tau2.runner.helpers import get_tasks
470
+ from tau2.runner.simulation import run_simulation
471
+ tasks = get_tasks("retail", task_split_name=parsed["task_split_name"], task_ids=[protected["task_id"]])
472
+ if len(tasks) != 1:
473
+ raise OfficialArenaError("Retail protected task identity is unavailable")
474
+ task = tasks[0]
475
+ message_types = {"assistant": AssistantMessage, "user": UserMessage, "tool": ToolMessage}
476
+ history = [message_types[row["role"]].model_validate(row) for row in protected["initial_message_history"]]
477
+ if not history or not isinstance(history[-1], UserMessage) or history[-1].is_tool_call():
478
+ raise OfficialArenaError("Retail protected capture history is invalid")
479
+ initial = task.initial_state
480
+ task = task.model_copy(update={"initial_state": InitialState(
481
+ initialization_data=initial.initialization_data if initial else None,
482
+ initialization_actions=initial.initialization_actions if initial else None,
483
+ message_history=copy.deepcopy(history))}, deep=True)
484
+ run_config = self._run_config(parsed, budget=budget)
485
+ kwargs = _build_env_kwargs(run_config, task)
486
+ if kwargs:
487
+ raise OfficialArenaError("Retail received non-native environment kwargs")
488
+ environment = build_environment("retail", env_kwargs={})
489
+ generation_failures: list[dict[str, Any]] = []
490
+ agent = _retail_agent_class(generation_failures)(
491
+ tools=environment.get_tools(), domain_policy=environment.get_policy(),
492
+ llm=parsed["llm_agent"], llm_args=dict(run_config.llm_args_agent), materialized=state, budget=budget,
493
+ history_transform=self.history_transform)
494
+ user = build_user("user_simulator", environment, task, llm=parsed["llm_user"], llm_args=dict(parsed["llm_args_user"]))
495
+ orchestrator = Orchestrator(domain="retail", agent=agent, user=user, environment=environment,
496
+ task=task, seed=17, max_steps=_orchestrator_step_cap(remaining_budget=budget, materialized=state),
497
+ max_errors=parsed["max_errors"], timeout=parsed["timeout"],
498
+ simulation_id=f"ailab-retail-{role}-{task.id}-17")
499
+ assertions = list(task.evaluation_criteria.nl_assertions or [])
500
+ try:
501
+ with bound_retail_judge(parsed, assertions) as judge_usage:
502
+ simulation = run_simulation(orchestrator, env_kwargs={})
503
+ except (json.JSONDecodeError, TimeoutError, ValueError) as error:
504
+ recognized = (isinstance(error, (json.JSONDecodeError, TimeoutError))
505
+ or _is_generated_tool_argument_validation(error)
506
+ or _is_generated_user_message_validation(error))
507
+ if not recognized:
508
+ raise
509
+ usage = self._agent_usage(orchestrator.get_messages(), len(history), AssistantMessage, agent)
510
+ reason = "episode_timeout" if isinstance(error, TimeoutError) else "malformed_generated_trajectory"
511
+ result = self._terminal_zero(replay_record, role, seed, work_dir, reason,
512
+ orchestrator.get_messages(), usage, budget, error=error)
513
+ return Tau3Provider._history_result(result, agent, work_dir)
514
+ finally:
515
+ try:
516
+ if getattr(agent, "_history_session", None) is not None:
517
+ agent._history_session.write_receipt(work_dir / "live-history.json",
518
+ target_usage=agent._history_target_usage())
519
+ finally:
520
+ orchestrator._cleanup()
521
+ if simulation.reward_info is None:
522
+ raise RetailJudgeError("Retail official evaluator returned no reward")
523
+ messages = simulation.get_messages()
524
+ usage = self._agent_usage(messages, len(history), AssistantMessage, agent)
525
+ if usage["tool_calls"] != agent._budget_tool_calls:
526
+ raise OfficialArenaError("Retail tool-call trace differs from the enforced counter")
527
+ agent_cost, user_cost = float(simulation.agent_cost or 0), float(simulation.user_cost or 0)
528
+ trace = {"provider": "tau_retail", "benchmark_id": self.benchmark_id, "source_revision": self.source_revision,
529
+ "task_id": str(task.id), "role": role, "seed": 17,
530
+ "termination_reason": simulation.termination_reason.value,
531
+ "messages": [message.model_dump(mode="json") for message in messages],
532
+ "reward_info": simulation.reward_info.model_dump(mode="json"),
533
+ "environment_model_policy": ENVIRONMENT_MODEL_POLICY,
534
+ "backbone_conditioned_environment_models": {"agent": parsed["llm_agent"],
535
+ "user": parsed["llm_user"], "judge": parsed["llm_judge"],
536
+ "user_lock": parsed["locked_dependency_hashes"]["user_simulator"],
537
+ "judge_lock": parsed["locked_dependency_hashes"]["nl_assertion_judge"]},
538
+ "environment_usage": {"judge": judge_usage, "user": _environment_user_usage(messages, len(history), UserMessage),
539
+ "user_cost_usd": user_cost,
540
+ "outside_agent_budget": True},
541
+ "cost_accounting": "local_unpriced_not_free" if local_models else "upstream_litellm",
542
+ "generation_controls": {"hard_stops": agent._budget_hard_stops,
543
+ "executed_tool_calls": agent._budget_tool_calls,
544
+ "discarded_tool_calls": agent._budget_discarded_tool_calls,
545
+ "automatic_retries": 0, "decoder_repair": False,
546
+ "retained_generation_failures": generation_failures},
547
+ "paper_terminal_success": _paper_terminal_success(float(simulation.reward_info.reward),
548
+ simulation.termination_reason.value, agent._budget_hard_stops),
549
+ "failure_accounting": "native_raw_reward_preserved; timeout_and_budget_failure_zero_in_paper_metric"}
550
+ _create_only(work_dir / "simulation.json", trace)
551
+ result = ProviderArmResult(metrics={"official_reward": float(simulation.reward_info.reward),
552
+ "terminal_success": trace["paper_terminal_success"],
553
+ "cost": agent_cost + user_cost, "adapter_hard_stops": float(agent._budget_hard_stops)},
554
+ trace=trace, usage={**usage, "cost_usd": agent_cost + user_cost,
555
+ "unpriced_model_calls": usage["model_calls"] if local_models else 0},
556
+ runtime_instance_id=content_hash({"provider": self.benchmark_id, "task_id": str(task.id),
557
+ "role": role, "seed": seed, "work_dir": str(work_dir)}))
558
+ return Tau3Provider._history_result(result, agent, work_dir)
559
+
560
+ @staticmethod
561
+ def _agent_usage(messages, initial_length, assistant_type, agent):
562
+ return _downstream_agent_usage(messages, initial_history_length=initial_length,
563
+ assistant_message_type=assistant_type,
564
+ measured_model_calls=agent._budget_model_calls,
565
+ measured_input_tokens=agent._budget_input_tokens,
566
+ measured_output_tokens=agent._budget_output_tokens)
567
+
568
+ def _terminal_zero(self, replay, role, seed, work_dir, reason, messages, usage, budget, *, error=None):
569
+ trace = {"provider": "tau_retail", "benchmark_id": self.benchmark_id, "source_revision": self.source_revision,
570
+ "task_id": replay["protected"]["task_id"], "role": role, "seed": seed,
571
+ "termination_reason": reason, "reward_info": None,
572
+ "score_provenance": "predeclared_terminal_zero_not_fabricated_official_reward",
573
+ "messages": [message.model_dump(mode="json") for message in messages],
574
+ "generation_controls": {"hard_stops": 1, "remaining_agent_budget": dict(budget), "automatic_retries": 0},
575
+ "exception_type": type(error).__name__ if error else None,
576
+ "exception_sha256": hashlib.sha256(str(error).encode()).hexdigest() if error else None}
577
+ _create_only(work_dir / "terminal-zero.json", trace)
578
+ measured = {"model_calls": 0, "tool_calls": 0, "input_tokens": 0, "output_tokens": 0, **usage}
579
+ return ProviderArmResult(metrics={"official_reward": 0.0, "terminal_success": 0.0, "cost": 0.0, "adapter_hard_stops": 1.0},
580
+ trace=trace, usage={**measured, "cost_usd": 0.0, "unpriced_model_calls": measured["model_calls"]},
581
+ runtime_instance_id=content_hash({"provider": self.benchmark_id, "checkpoint_id": replay["checkpoint_id"],
582
+ "role": role, "seed": seed, "work_dir": str(work_dir)}))
583
+
584
+
585
+ def factory() -> TauRetailProvider:
586
+ return TauRetailProvider()