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,165 @@
1
+ """Deterministic native, controlled, and factorial experiment planning."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import itertools
6
+ from collections.abc import Mapping, Sequence
7
+ from dataclasses import dataclass, field
8
+ from typing import Any
9
+
10
+ from agentinputlab.contracts.dependency import DependencyBinding, DependencyRole
11
+ from agentinputlab.contracts.enums import ProfileKind
12
+ from agentinputlab.contracts.serialization import content_hash, freeze_mapping
13
+ from agentinputlab.runner.balance import BalanceAuditor, ComparisonArm, ComparisonProfile
14
+
15
+
16
+ @dataclass(frozen=True, slots=True)
17
+ class StudyArmSpec:
18
+ arm_id: str
19
+ release_id: str
20
+ bindings: tuple[DependencyBinding, ...]
21
+ parameters: Mapping[str, Any] = field(default_factory=dict)
22
+
23
+ def __post_init__(self) -> None:
24
+ object.__setattr__(self, "bindings", tuple(self.bindings))
25
+ object.__setattr__(self, "parameters", freeze_mapping(self.parameters))
26
+ ComparisonArm(self.arm_id, self.release_id, self.bindings).binding_map()
27
+
28
+
29
+ @dataclass(frozen=True, slots=True)
30
+ class StudyCell:
31
+ benchmark_id: str
32
+ example_id: str
33
+ seed: int
34
+ profile_id: str
35
+ arms: tuple[StudyArmSpec, ...]
36
+
37
+ def __post_init__(self) -> None:
38
+ object.__setattr__(self, "arms", tuple(self.arms))
39
+ if not self.benchmark_id or not self.example_id:
40
+ raise ValueError("study cell requires benchmark and example IDs")
41
+ if isinstance(self.seed, bool) or not isinstance(self.seed, int):
42
+ raise ValueError("study cell seed must be an integer")
43
+ if len(self.arms) < 2:
44
+ raise ValueError("study cell requires at least two comparison arms")
45
+ if len({arm.arm_id for arm in self.arms}) != len(self.arms):
46
+ raise ValueError("study cell arm IDs must be unique")
47
+
48
+ @property
49
+ def cell_id(self) -> str:
50
+ return content_hash(self)[:20]
51
+
52
+
53
+ @dataclass(frozen=True, slots=True)
54
+ class StudyPlan:
55
+ study_id: str
56
+ profile: ComparisonProfile
57
+ cells: tuple[StudyCell, ...]
58
+ metadata: Mapping[str, Any] = field(default_factory=dict)
59
+
60
+ def __post_init__(self) -> None:
61
+ object.__setattr__(self, "cells", tuple(self.cells))
62
+ object.__setattr__(self, "metadata", freeze_mapping(self.metadata))
63
+ if not self.study_id or not self.cells:
64
+ raise ValueError("study plan requires an ID and at least one cell")
65
+ if any(cell.profile_id != self.profile.profile_id for cell in self.cells):
66
+ raise ValueError("study cells must reference the plan comparison profile")
67
+ if len({cell.cell_id for cell in self.cells}) != len(self.cells):
68
+ raise ValueError("study plan contains duplicate cells")
69
+
70
+ @property
71
+ def plan_hash(self) -> str:
72
+ return content_hash(self)
73
+
74
+
75
+ def build_study_plan(
76
+ *,
77
+ study_id: str,
78
+ profile: ComparisonProfile,
79
+ benchmark_id: str,
80
+ example_ids: Sequence[str],
81
+ seeds: Sequence[int],
82
+ arms: Sequence[StudyArmSpec],
83
+ factorial_levels: Mapping[str, Sequence[DependencyBinding]] | None = None,
84
+ metadata: Mapping[str, Any] | None = None,
85
+ ) -> StudyPlan:
86
+ """Expand a frozen manifest without executing or silently dropping cells."""
87
+
88
+ examples = tuple(example_ids)
89
+ seed_values = tuple(seeds)
90
+ base_arms = tuple(arms)
91
+ if not examples or not seed_values or not base_arms:
92
+ raise ValueError("study expansion requires examples, seeds, and arms")
93
+ if len(set(examples)) != len(examples):
94
+ raise ValueError("example IDs must be unique")
95
+ if len(set(seed_values)) != len(seed_values):
96
+ raise ValueError("seeds must be unique")
97
+ levels = factorial_levels or {}
98
+ if levels and profile.kind is not ProfileKind.FACTORIAL_ADAPTER:
99
+ raise ValueError("factorial levels require a factorial comparison profile")
100
+ if profile.kind is ProfileKind.FACTORIAL_ADAPTER and set(levels) != set(profile.varied_slots):
101
+ raise ValueError("factorial level slots must exactly match profile.varied_slots")
102
+ expanded_arms = _expand_arms(base_arms, levels)
103
+ if profile.kind is not ProfileKind.OFFICIAL_NATIVE:
104
+ BalanceAuditor().audit(
105
+ profile,
106
+ tuple(ComparisonArm(arm.arm_id, arm.release_id, arm.bindings) for arm in expanded_arms),
107
+ ).require_eligible()
108
+ cells = tuple(
109
+ StudyCell(
110
+ benchmark_id=benchmark_id,
111
+ example_id=example_id,
112
+ seed=seed,
113
+ profile_id=profile.profile_id,
114
+ arms=expanded_arms,
115
+ )
116
+ for example_id in examples
117
+ for seed in seed_values
118
+ )
119
+ return StudyPlan(
120
+ study_id=study_id,
121
+ profile=profile,
122
+ cells=cells,
123
+ metadata=metadata or {},
124
+ )
125
+
126
+
127
+ def _expand_arms(
128
+ arms: tuple[StudyArmSpec, ...],
129
+ levels: Mapping[str, Sequence[DependencyBinding]],
130
+ ) -> tuple[StudyArmSpec, ...]:
131
+ if not levels:
132
+ return arms
133
+ slot_names = tuple(sorted(levels))
134
+ choices = tuple(tuple(levels[slot]) for slot in slot_names)
135
+ if any(not values for values in choices):
136
+ raise ValueError("each factorial slot requires at least one dependency level")
137
+ for slot, values in zip(slot_names, choices, strict=True):
138
+ if any(binding.slot != slot for binding in values):
139
+ raise ValueError(f"factorial bindings for {slot} must use that slot name")
140
+ if any(binding.role is not DependencyRole.CROSSED for binding in values):
141
+ raise ValueError(f"factorial bindings for {slot} must have role='crossed'")
142
+ expanded: list[StudyArmSpec] = []
143
+ for arm in arms:
144
+ base = {binding.slot: binding for binding in arm.bindings}
145
+ overlap = set(base) & set(slot_names)
146
+ if overlap:
147
+ joined = ", ".join(sorted(overlap))
148
+ raise ValueError(
149
+ f"factorial slots cannot silently replace base-arm dependencies: {joined}"
150
+ )
151
+ for combination in itertools.product(*choices):
152
+ bindings = dict(base)
153
+ bindings.update({binding.slot: binding for binding in combination})
154
+ suffix = ".".join(
155
+ f"{binding.slot}={binding.resolved_hash[:8]}" for binding in combination
156
+ )
157
+ expanded.append(
158
+ StudyArmSpec(
159
+ arm_id=f"{arm.arm_id}::{suffix}",
160
+ release_id=arm.release_id,
161
+ bindings=tuple(bindings[key] for key in sorted(bindings)),
162
+ parameters=arm.parameters,
163
+ )
164
+ )
165
+ return tuple(expanded)
@@ -0,0 +1,322 @@
1
+ """Paired study runner with mandatory pre-run balance audit."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from collections.abc import Mapping
7
+ from dataclasses import dataclass
8
+ from types import TracebackType
9
+
10
+ from agentinputlab.contracts.errors import (
11
+ AlgorithmUnavailableError,
12
+ ArmExecutionError,
13
+ ArtifactError,
14
+ BalanceError,
15
+ CapabilityError,
16
+ RegistryError,
17
+ ValidationError,
18
+ )
19
+ from agentinputlab.contracts.lifecycle import Intervention, InterventionContext
20
+ from agentinputlab.contracts.serialization import freeze_mapping
21
+ from agentinputlab.contracts.state import FrozenAgentState
22
+ from agentinputlab.observability import (
23
+ BudgetLedger,
24
+ RunMonitor,
25
+ )
26
+ from agentinputlab.runner.balance import (
27
+ BalanceAuditor,
28
+ BalanceReport,
29
+ ComparisonArm,
30
+ ComparisonProfile,
31
+ context_dependency_fingerprints,
32
+ )
33
+ from agentinputlab.runner.engine import InterventionRunner, RunRecord
34
+ from agentinputlab.runner.runtime_guard import (
35
+ inspect_object_graph,
36
+ is_runtime_dependency,
37
+ )
38
+
39
+ _PAIRED_RUNTIME_SLOTS = (
40
+ "backend",
41
+ "dense_embedder",
42
+ "retriever",
43
+ "vector_searcher",
44
+ "tools",
45
+ "external_runtime",
46
+ "artifact_manager",
47
+ )
48
+ _CELL_INVALID_ERRORS = (
49
+ AlgorithmUnavailableError,
50
+ ArtifactError,
51
+ BalanceError,
52
+ CapabilityError,
53
+ RegistryError,
54
+ ValidationError,
55
+ )
56
+ _SECRET_TEXT_PATTERNS = (
57
+ re.compile(r"(?i)\bbearer\s+[A-Za-z0-9._~+/=-]{8,}"),
58
+ re.compile(r"\bsk-[A-Za-z0-9_-]{8,}"),
59
+ re.compile(r"\beyJ[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\.[A-Za-z0-9_-]{6,}\b"),
60
+ re.compile(
61
+ r"(?i)(\b(?:[a-z0-9]+[_-])*(?:api[_-]?key|x[_-]?api[_-]?key|authorization)"
62
+ r"\b\s*[:=]\s*)['\"]?(?:bearer\s+)?[^\s,;'\"]{4,}"
63
+ ),
64
+ )
65
+
66
+
67
+ @dataclass(frozen=True, slots=True)
68
+ class PairedArm:
69
+ comparison_arm: ComparisonArm
70
+ intervention: Intervention
71
+ context: InterventionContext
72
+
73
+ def __post_init__(self) -> None:
74
+ if self.comparison_arm.release_id != self.intervention.release_id:
75
+ raise ValueError("comparison arm and intervention release IDs differ")
76
+
77
+
78
+ @dataclass(frozen=True, slots=True)
79
+ class PairedRun:
80
+ state_hash: str
81
+ balance: BalanceReport
82
+ outcomes: tuple[ArmOutcome, ...]
83
+ observed_dependency_hashes: Mapping[str, Mapping[str, str]]
84
+
85
+ def __post_init__(self) -> None:
86
+ object.__setattr__(self, "outcomes", tuple(self.outcomes))
87
+ object.__setattr__(
88
+ self,
89
+ "observed_dependency_hashes",
90
+ freeze_mapping(self.observed_dependency_hashes),
91
+ )
92
+
93
+ @property
94
+ def records(self) -> tuple[RunRecord, ...]:
95
+ """Successful records retained for backward-compatible aggregation."""
96
+
97
+ return tuple(outcome.record for outcome in self.outcomes if outcome.record is not None)
98
+
99
+
100
+ @dataclass(frozen=True, slots=True)
101
+ class ArmFailure:
102
+ category: str
103
+ message: str
104
+ monitor_run_id: str = ""
105
+
106
+ def __post_init__(self) -> None:
107
+ if not self.category:
108
+ raise ValueError("arm failure category must be non-empty")
109
+ object.__setattr__(self, "message", _safe_failure_message(self.message))
110
+ if not isinstance(self.monitor_run_id, str):
111
+ raise TypeError("monitor_run_id must be a string")
112
+
113
+
114
+ @dataclass(frozen=True, slots=True)
115
+ class ArmOutcome:
116
+ arm_id: str
117
+ status: str
118
+ record: RunRecord | None = None
119
+ failure: ArmFailure | None = None
120
+
121
+ def __post_init__(self) -> None:
122
+ if self.status not in {"succeeded", "failed"}:
123
+ raise ValueError("arm outcome status must be succeeded or failed")
124
+ if (self.record is None) == (self.failure is None):
125
+ raise ValueError("arm outcome requires exactly one record or failure")
126
+
127
+
128
+ class PairedStudyRunner:
129
+ def __init__(self) -> None:
130
+ self._balance = BalanceAuditor()
131
+ self._runner = InterventionRunner()
132
+
133
+ def run(
134
+ self,
135
+ state: FrozenAgentState,
136
+ profile: ComparisonProfile,
137
+ arms: tuple[PairedArm, ...],
138
+ ) -> PairedRun:
139
+ _reject_shared_runtime_instances(arms)
140
+ before = {
141
+ arm.comparison_arm.arm_id: context_dependency_fingerprints(arm.context) for arm in arms
142
+ }
143
+ report = self._balance.audit(
144
+ profile,
145
+ tuple(arm.comparison_arm for arm in arms),
146
+ runtime_fingerprints=before,
147
+ )
148
+ report.require_eligible()
149
+ outcomes: list[ArmOutcome] = []
150
+ for arm in arms:
151
+ monitor = arm.context.monitor or self._runner.monitor
152
+ if monitor is not None and not isinstance(monitor, RunMonitor):
153
+ raise TypeError("context.monitor must be a RunMonitor")
154
+ prior_run_ids = (
155
+ frozenset(snapshot.run_id for snapshot in monitor.list_snapshots())
156
+ if monitor is not None
157
+ else frozenset()
158
+ )
159
+ try:
160
+ record = self._runner.run(arm.intervention, state, arm.context)
161
+ except Exception as exc:
162
+ monitor_run_id = _find_new_monitor_run_id(
163
+ monitor,
164
+ prior_run_ids,
165
+ release_id=arm.intervention.release_id,
166
+ state_hash=state.state_hash,
167
+ )
168
+ if _invalidates_cell(exc):
169
+ raise
170
+ outcomes.append(
171
+ ArmOutcome(
172
+ arm_id=arm.comparison_arm.arm_id,
173
+ status="failed",
174
+ failure=ArmFailure(
175
+ type(exc).__name__,
176
+ str(exc),
177
+ monitor_run_id=monitor_run_id,
178
+ ),
179
+ )
180
+ )
181
+ else:
182
+ outcomes.append(
183
+ ArmOutcome(
184
+ arm_id=arm.comparison_arm.arm_id,
185
+ status="succeeded",
186
+ record=record,
187
+ )
188
+ )
189
+ records = tuple(outcome.record for outcome in outcomes if outcome.record is not None)
190
+ if any(record.input_state_hash != state.state_hash for record in records):
191
+ raise RuntimeError("paired runner produced a non-paired input identity")
192
+ after = {
193
+ arm.comparison_arm.arm_id: context_dependency_fingerprints(arm.context) for arm in arms
194
+ }
195
+ if before != after:
196
+ raise BalanceError("runtime dependency identity changed while executing paired arms")
197
+ post_report = self._balance.audit(
198
+ profile,
199
+ tuple(arm.comparison_arm for arm in arms),
200
+ runtime_fingerprints=after,
201
+ )
202
+ post_report.require_eligible()
203
+ return PairedRun(
204
+ state_hash=state.state_hash,
205
+ balance=post_report,
206
+ outcomes=tuple(outcomes),
207
+ observed_dependency_hashes=after,
208
+ )
209
+
210
+
211
+ def _reject_shared_runtime_instances(arms: tuple[PairedArm, ...]) -> None:
212
+ """Require equal-but-independent runtime dependencies across comparison arms."""
213
+
214
+ runtime_owners: dict[int, set[str]] = {}
215
+ ledger_owners: dict[int, set[str]] = {}
216
+ for arm in arms:
217
+ arm_id = arm.comparison_arm.arm_id
218
+ if isinstance(arm.context.budget_ledger, BudgetLedger):
219
+ ledger_owners.setdefault(id(arm.context.budget_ledger), set()).add(arm_id)
220
+ for slot in _PAIRED_RUNTIME_SLOTS:
221
+ dependency = getattr(arm.context, slot)
222
+ if dependency is None:
223
+ continue
224
+ graph = inspect_object_graph(
225
+ dependency,
226
+ root_path=f"context.{slot}",
227
+ terminal_types=(RunMonitor, BudgetLedger),
228
+ traverse_runtime_delegates=True,
229
+ )
230
+ for node in graph:
231
+ if is_runtime_dependency(node.value):
232
+ runtime_owners.setdefault(id(node.value), set()).add(arm_id)
233
+ if isinstance(node.value, BudgetLedger):
234
+ ledger_owners.setdefault(id(node.value), set()).add(arm_id)
235
+
236
+ shared_runtimes = [sorted(arm_ids) for arm_ids in runtime_owners.values() if len(arm_ids) > 1]
237
+ if shared_runtimes:
238
+ details = ", ".join("/".join(arm_ids) for arm_ids in shared_runtimes)
239
+ raise BalanceError(
240
+ "runtime dependency objects, including proxy inners, must be independently "
241
+ f"constructed across arms: {details}"
242
+ )
243
+ shared_ledgers = [sorted(arm_ids) for arm_ids in ledger_owners.values() if len(arm_ids) > 1]
244
+ if shared_ledgers:
245
+ details = ", ".join("/".join(arm_ids) for arm_ids in shared_ledgers)
246
+ raise BalanceError(
247
+ "runtime BudgetLedger instances must be independently constructed across arms: "
248
+ f"{details}"
249
+ )
250
+
251
+
252
+ def _find_new_monitor_run_id(
253
+ monitor: RunMonitor | None,
254
+ prior_run_ids: frozenset[str],
255
+ *,
256
+ release_id: str,
257
+ state_hash: str,
258
+ ) -> str:
259
+ if monitor is None:
260
+ return ""
261
+ matches = [
262
+ snapshot.run_id
263
+ for snapshot in monitor.list_snapshots()
264
+ if snapshot.run_id not in prior_run_ids
265
+ and snapshot.release_id == release_id
266
+ and snapshot.state_hash == state_hash
267
+ ]
268
+ return matches[-1] if matches else ""
269
+
270
+
271
+ def _invalidates_cell(error: Exception) -> bool:
272
+ """Return whether an exception invalidates the experiment rather than one arm."""
273
+
274
+ # Arm-local subclasses take precedence because they intentionally remain
275
+ # ValidationError subclasses for public API compatibility.
276
+ if isinstance(error, ArmExecutionError):
277
+ return False
278
+ if isinstance(error, (*_CELL_INVALID_ERRORS, MemoryError)):
279
+ return True
280
+ frames = _traceback_frames(error.__traceback__)
281
+ if any(
282
+ module == "agentinputlab.observability.monitor" and function != "run_scope"
283
+ for module, function in frames
284
+ ):
285
+ return True
286
+ origin = frames[-1][0] if frames else ""
287
+ if origin.startswith(("agentinputlab.artifacts", "agentinputlab.data")):
288
+ return True
289
+ if origin == "agentinputlab.observability.instrumentation" and isinstance(
290
+ error, (TypeError, ValueError)
291
+ ):
292
+ return True
293
+ if origin == "agentinputlab.runner.runtime_guard" and isinstance(
294
+ error, (AttributeError, TypeError)
295
+ ):
296
+ return True
297
+ return origin == "agentinputlab.runner.engine" and isinstance(
298
+ error, (AttributeError, TypeError)
299
+ )
300
+
301
+
302
+ def _traceback_frames(traceback: TracebackType | None) -> tuple[tuple[str, str], ...]:
303
+ frames: list[tuple[str, str]] = []
304
+ while traceback is not None:
305
+ frames.append(
306
+ (
307
+ str(traceback.tb_frame.f_globals.get("__name__", "")),
308
+ traceback.tb_frame.f_code.co_name,
309
+ )
310
+ )
311
+ traceback = traceback.tb_next
312
+ return tuple(frames)
313
+
314
+
315
+ def _safe_failure_message(message: object) -> str:
316
+ safe = str(message)[:2048]
317
+ for pattern in _SECRET_TEXT_PATTERNS:
318
+ if pattern.groups:
319
+ safe = pattern.sub(lambda match: f"{match.group(1)}<redacted>", safe)
320
+ else:
321
+ safe = pattern.sub("<redacted>", safe)
322
+ return safe
@@ -0,0 +1,6 @@
1
+ """Packaged, dependency-free experiment Studio for AgentInputLab."""
2
+
3
+ from .campaigns import CampaignManager
4
+ from .engine import RunManager, build_catalog, validate_config
5
+
6
+ __all__ = ["CampaignManager", "RunManager", "build_catalog", "validate_config"]