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,462 @@
1
+ """Pinned upstream bridge for SkillOpt offline text-space optimization.
2
+
3
+ AgentInputLab does not reimplement SkillOpt's six-stage optimizer. This module
4
+ verifies the audited source files, launches the upstream ``scripts/train.py``
5
+ entry point without a shell, freezes the fairness-relevant overrides, and
6
+ returns a content-addressed ``best_skill.md`` artifact. Provider credentials
7
+ remain environment-only and are never written to the artifact manifest.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import hashlib
13
+ import json
14
+ import math
15
+ import os
16
+ import subprocess
17
+ import sys
18
+ from collections.abc import Mapping
19
+ from dataclasses import asdict, dataclass, field, fields
20
+ from pathlib import Path
21
+ from types import MappingProxyType
22
+ from typing import Any
23
+
24
+ from agentinputlab.artifacts import load_pinned_json_mapping
25
+ from agentinputlab.contracts import ExternalDependencyError, InterventionContext, ValidationError
26
+ from agentinputlab.contracts.serialization import content_hash, freeze_mapping, to_jsonable
27
+
28
+ from .skillopt_environment import ENVIRONMENT_RECEIPT, SkillOptEnvironmentBinding
29
+
30
+ SKILLOPT_UPSTREAM_COMMIT = "9639719632daecacd1baaa47fe781f3c0253600a"
31
+ SKILLOPT_RELEASE_ID = "recipe.skillopt.offline"
32
+ SKILLOPT_PROTOCOL = "agentinputlab.skillopt.upstream-cli.v1"
33
+ SKILLOPT_SOURCE_HASHES = MappingProxyType(
34
+ {
35
+ "LICENSE": "9515a04280cf50ce154eb3ab8fa375c7cc5e6b45ea5cb23b7ff3830737020c15",
36
+ "scripts/train.py": ("e4423a5da59db78c9dd58c0c8c7736863131c5f5d87c4d0a23a61a714fd62703"),
37
+ "skillopt/engine/trainer.py": (
38
+ "ff71a1480ee7c7c21a2574bb429eeb7dc0c88da0ea018feb22da4fa00b663a7f"
39
+ ),
40
+ "skillopt/evaluation/gate.py": (
41
+ "3c2405f13288e97f53afa0bdfc0752ba6917c51edd1904a810deb4b5a1a81bef"
42
+ ),
43
+ "skillopt/config.py": ("cf28e722ac31b6a60ffc168202e0cc07d4f78581506b8df6acd44fc38e03b629"),
44
+ "configs/_base_/default.yaml": (
45
+ "385c1d79af97796f28051589e60551b36668e526b5a9788af53a5196997f42c1"
46
+ ),
47
+ }
48
+ )
49
+ _REQUIRED_OUTPUTS = (
50
+ "best_skill.md",
51
+ "config.json",
52
+ "history.json",
53
+ "runtime_state.json",
54
+ )
55
+
56
+
57
+ @dataclass(frozen=True, slots=True)
58
+ class SkillOptControls:
59
+ """Fairness-relevant overrides passed to the upstream trainer unchanged."""
60
+
61
+ num_epochs: int = 4
62
+ batch_size: int = 40
63
+ learning_rate: int = 4
64
+ seed: int = 0
65
+ max_steps: int | None = None
66
+ timeout_seconds: float = 7200.0
67
+
68
+ def __post_init__(self) -> None:
69
+ integer_values = (self.num_epochs, self.batch_size, self.learning_rate, self.seed)
70
+ if any(isinstance(value, bool) or not isinstance(value, int) for value in integer_values):
71
+ raise ValidationError(
72
+ "SkillOpt epochs, batch size, learning rate, and seed must be integers"
73
+ )
74
+ if min(self.num_epochs, self.batch_size, self.learning_rate) < 1:
75
+ raise ValidationError("SkillOpt epochs, batch size, and learning rate must be positive")
76
+ if self.seed < 0:
77
+ raise ValidationError("SkillOpt seed must be non-negative")
78
+ if self.max_steps is not None and (
79
+ isinstance(self.max_steps, bool)
80
+ or not isinstance(self.max_steps, int)
81
+ or self.max_steps < 1
82
+ ):
83
+ raise ValidationError("SkillOpt max_steps must be null or a positive integer")
84
+ try:
85
+ valid_timeout = (
86
+ not isinstance(self.timeout_seconds, bool)
87
+ and isinstance(self.timeout_seconds, (int, float))
88
+ and math.isfinite(self.timeout_seconds)
89
+ and self.timeout_seconds > 0
90
+ )
91
+ except OverflowError:
92
+ valid_timeout = False
93
+ if not valid_timeout:
94
+ raise ValidationError("SkillOpt timeout_seconds must be finite and positive")
95
+
96
+ @property
97
+ def cfg_options(self) -> tuple[str, ...]:
98
+ options = (
99
+ f"train.num_epochs={self.num_epochs}",
100
+ f"train.batch_size={self.batch_size}",
101
+ f"train.seed={self.seed}",
102
+ f"optimizer.learning_rate={self.learning_rate}",
103
+ "evaluation.use_gate=true",
104
+ )
105
+ if self.max_steps is not None:
106
+ return (*options, f"env.max_steps={self.max_steps}")
107
+ return options
108
+
109
+
110
+ @dataclass(frozen=True, slots=True)
111
+ class SkillOptArtifact:
112
+ """Frozen deployment artifact produced by one audited upstream run."""
113
+
114
+ artifact_id: str
115
+ release_id: str
116
+ best_skill: str
117
+ best_skill_sha256: str
118
+ upstream_commit: str
119
+ protocol: str
120
+ config_sha256: str
121
+ source_hashes: Mapping[str, str]
122
+ output_hashes: Mapping[str, str]
123
+ controls: Mapping[str, Any]
124
+ model_fingerprints: Mapping[str, Mapping[str, Any]]
125
+ environment_keys: tuple[str, ...]
126
+ command_sha256: str
127
+
128
+ def __post_init__(self) -> None:
129
+ if self.release_id != SKILLOPT_RELEASE_ID:
130
+ raise ValidationError("SkillOpt artifact release identity mismatch")
131
+ if self.upstream_commit != SKILLOPT_UPSTREAM_COMMIT:
132
+ raise ValidationError("SkillOpt artifact upstream revision mismatch")
133
+ if self.protocol != SKILLOPT_PROTOCOL:
134
+ raise ValidationError("SkillOpt artifact protocol mismatch")
135
+ if not isinstance(self.best_skill, str) or not self.best_skill.strip():
136
+ raise ValidationError("SkillOpt best_skill.md must be non-empty")
137
+ if _sha256_bytes(self.best_skill.encode("utf-8")) != self.best_skill_sha256:
138
+ raise ValidationError("SkillOpt best_skill text differs from its digest")
139
+ if any(
140
+ not isinstance(getattr(self, name), Mapping)
141
+ for name in ("source_hashes", "output_hashes", "controls", "model_fingerprints")
142
+ ) or any(not isinstance(value, Mapping) for value in self.model_fingerprints.values()):
143
+ raise ValidationError(
144
+ "SkillOpt artifact hashes, controls, and fingerprints must be mappings"
145
+ )
146
+ if not isinstance(self.environment_keys, (list, tuple)):
147
+ raise ValidationError("SkillOpt environment_keys must be an array of names")
148
+ if self.output_hashes.get("best_skill.md") != self.best_skill_sha256:
149
+ raise ValidationError("SkillOpt best_skill digest differs from its output manifest")
150
+ object.__setattr__(self, "source_hashes", freeze_mapping(self.source_hashes))
151
+ object.__setattr__(self, "output_hashes", freeze_mapping(self.output_hashes))
152
+ object.__setattr__(self, "controls", freeze_mapping(self.controls))
153
+ object.__setattr__(
154
+ self,
155
+ "model_fingerprints",
156
+ MappingProxyType(
157
+ {
158
+ str(role): freeze_mapping(fingerprint)
159
+ for role, fingerprint in self.model_fingerprints.items()
160
+ }
161
+ ),
162
+ )
163
+ keys = tuple(self.environment_keys)
164
+ if len(keys) != len(set(keys)) or any(
165
+ not isinstance(key, str) or not key.strip() or key != key.strip() for key in keys
166
+ ):
167
+ raise ValidationError("SkillOpt environment key names must be unique and non-empty")
168
+ object.__setattr__(self, "environment_keys", keys)
169
+ if self.artifact_id != content_hash(self.identity_payload()):
170
+ raise ValidationError("SkillOpt artifact content identity mismatch")
171
+
172
+ def identity_payload(self) -> dict[str, Any]:
173
+ return {
174
+ f.name: getattr(self, f.name)
175
+ for f in fields(self)
176
+ if f.name not in {"artifact_id", "best_skill"}
177
+ }
178
+
179
+ @classmethod
180
+ def from_mapping(cls, value: Mapping[str, Any]) -> SkillOptArtifact:
181
+ if not isinstance(value, Mapping) or set(value) != {f.name for f in fields(cls)}:
182
+ raise ValidationError("SkillOpt artifact fields are invalid")
183
+ malformed = False
184
+ try:
185
+ return cls(**dict(value))
186
+ except ValidationError:
187
+ raise
188
+ except (AttributeError, TypeError, ValueError, RecursionError):
189
+ malformed = True
190
+ if malformed:
191
+ raise ValidationError("SkillOpt artifact values are malformed")
192
+
193
+ @classmethod
194
+ def from_json(
195
+ cls, path: str | Path, *, expected_sha256: str, max_bytes: int = 4 * 1024 * 1024
196
+ ) -> SkillOptArtifact:
197
+ return cls.from_mapping(
198
+ load_pinned_json_mapping(path, expected_sha256=expected_sha256, max_bytes=max_bytes)
199
+ )
200
+
201
+ def as_dict(self) -> dict[str, Any]:
202
+ return to_jsonable(self)
203
+
204
+
205
+ @dataclass(slots=True)
206
+ class SkillOptOfflineRecipe:
207
+ """Execute the pinned upstream trainer and validate its deployable artifact."""
208
+
209
+ controls: SkillOptControls = field(default_factory=SkillOptControls)
210
+ python_executable: str = sys.executable
211
+ method_id: str = "recipe.skillopt"
212
+ release_id: str = SKILLOPT_RELEASE_ID
213
+ environment_binding: SkillOptEnvironmentBinding | None = None
214
+
215
+ def build_command(
216
+ self,
217
+ *,
218
+ checkout: str | Path,
219
+ config_path: str | Path,
220
+ output_root: str | Path,
221
+ ) -> tuple[str, ...]:
222
+ source = Path(checkout).expanduser().resolve()
223
+ config = Path(config_path).expanduser().resolve()
224
+ output = Path(output_root).expanduser().resolve()
225
+ if self.environment_binding is None:
226
+ prefix = (self.python_executable, str(source / "scripts" / "train.py"))
227
+ else:
228
+ if not isinstance(self.environment_binding, SkillOptEnvironmentBinding):
229
+ raise ValidationError("SkillOpt environment_binding must be explicit and checksum-bound")
230
+ prefix = (self.python_executable, "-m", "agentinputlab.recipes.skillopt_environment_cli",
231
+ "--checkout", str(source), *self.environment_binding.command_options(),
232
+ "--receipt", str(output / ENVIRONMENT_RECEIPT), "--")
233
+ return (
234
+ *prefix,
235
+ "--config",
236
+ str(config),
237
+ "--out_root",
238
+ str(output),
239
+ "--cfg-options",
240
+ *self.controls.cfg_options,
241
+ )
242
+
243
+ def fit(
244
+ self,
245
+ *,
246
+ checkout: str | Path,
247
+ config_path: str | Path,
248
+ output_root: str | Path,
249
+ context: InterventionContext,
250
+ environment: Mapping[str, str] | None = None,
251
+ ) -> SkillOptArtifact:
252
+ if self.controls.seed != context.seed:
253
+ raise ValidationError("SkillOpt controls.seed must equal InterventionContext.seed")
254
+ if self.environment_binding is not None and not isinstance(self.environment_binding, SkillOptEnvironmentBinding):
255
+ raise ValidationError("SkillOpt environment_binding must be explicit and checksum-bound")
256
+ source = validate_skillopt_checkout(checkout)
257
+ binding_identity = self.environment_binding.verify() if self.environment_binding is not None else None
258
+ config = Path(config_path).expanduser().resolve()
259
+ if not config.is_file() or config.is_symlink():
260
+ raise ExternalDependencyError("SkillOpt config must be a regular, non-symlink file")
261
+ output = Path(output_root).expanduser().resolve()
262
+ if output == source or source in output.parents:
263
+ raise ValidationError("SkillOpt output_root must be outside the pinned checkout")
264
+ if output.exists() and any(output.iterdir()):
265
+ raise ValidationError("SkillOpt output_root must be absent or empty")
266
+ output.mkdir(parents=True, exist_ok=True)
267
+
268
+ model_fingerprints = _model_fingerprints(context)
269
+ command = self.build_command(
270
+ checkout=source,
271
+ config_path=config,
272
+ output_root=output,
273
+ )
274
+ extra_environment = _validated_environment(environment or {})
275
+ process_environment = dict(os.environ)
276
+ process_environment.update(extra_environment)
277
+ completed = subprocess.run(
278
+ command,
279
+ cwd=source,
280
+ env=process_environment,
281
+ capture_output=True,
282
+ text=True,
283
+ timeout=float(self.controls.timeout_seconds),
284
+ check=False,
285
+ )
286
+ if completed.returncode != 0:
287
+ diagnostic = (completed.stderr or completed.stdout or "").strip()[-4000:]
288
+ raise ExternalDependencyError(
289
+ f"SkillOpt upstream trainer exited with code {completed.returncode}: {diagnostic}"
290
+ )
291
+ artifact = load_skillopt_artifact(
292
+ output,
293
+ config_sha256=_sha256_file(config),
294
+ controls=asdict(self.controls),
295
+ model_fingerprints=model_fingerprints,
296
+ environment_keys=tuple(sorted(extra_environment)),
297
+ command_sha256=content_hash(command),
298
+ environment_binding=binding_identity,
299
+ )
300
+ manifest = output / "agentinputlab_skillopt_manifest.json"
301
+ manifest.write_text(
302
+ json.dumps(artifact.as_dict(), ensure_ascii=False, indent=2, sort_keys=True) + "\n",
303
+ encoding="utf-8",
304
+ )
305
+ return artifact
306
+
307
+
308
+ def load_skillopt_artifact(
309
+ output_root: str | Path,
310
+ *,
311
+ config_sha256: str,
312
+ controls: Mapping[str, Any],
313
+ model_fingerprints: Mapping[str, Mapping[str, Any]],
314
+ environment_keys: tuple[str, ...] = (),
315
+ command_sha256: str,
316
+ environment_binding: Mapping[str, Any] | None = None,
317
+ ) -> SkillOptArtifact:
318
+ """Validate a completed upstream output directory without rerunning training."""
319
+
320
+ output = Path(output_root).expanduser().resolve()
321
+ output_hashes: dict[str, str] = {}
322
+ for relative in _REQUIRED_OUTPUTS:
323
+ path = output / relative
324
+ if not path.is_file() or path.is_symlink():
325
+ raise ExternalDependencyError(f"SkillOpt output is missing regular file {relative}")
326
+ output_hashes[relative] = _sha256_file(path)
327
+ source_hashes = dict(SKILLOPT_SOURCE_HASHES)
328
+ if environment_binding is None and (output / ENVIRONMENT_RECEIPT).exists():
329
+ raise ExternalDependencyError("SkillOpt custom environment output requires its explicit environment binding")
330
+ if environment_binding is not None:
331
+ path = output / ENVIRONMENT_RECEIPT
332
+ if not path.is_file() or path.is_symlink():
333
+ raise ExternalDependencyError("SkillOpt completed environment binding receipt is missing")
334
+ receipt = load_pinned_json_mapping(path, expected_sha256=_sha256_file(path), max_bytes=1024 * 1024)
335
+ if (receipt.get("schema") != "agentinputlab.skillopt.environment_binding.v1"
336
+ or dict(receipt.get("binding", {})) != dict(environment_binding)
337
+ or not receipt.get("environment_fingerprint")
338
+ or receipt.get("native_training_algorithm_unchanged") is not True
339
+ or receipt.get("profile_kind") != "caller_environment_adapter"):
340
+ raise ExternalDependencyError("SkillOpt completed environment binding differs from the configured factory")
341
+ output_hashes[ENVIRONMENT_RECEIPT] = _sha256_file(path)
342
+ source_hashes.update(operator_environment_factory=environment_binding["factory_sha256"],
343
+ operator_environment_configuration=environment_binding["configuration_sha256"])
344
+ best_skill = (output / "best_skill.md").read_text(encoding="utf-8")
345
+ artifact_base = {
346
+ "release_id": SKILLOPT_RELEASE_ID,
347
+ "best_skill_sha256": output_hashes["best_skill.md"],
348
+ "upstream_commit": SKILLOPT_UPSTREAM_COMMIT,
349
+ "protocol": SKILLOPT_PROTOCOL,
350
+ "config_sha256": config_sha256,
351
+ "source_hashes": source_hashes,
352
+ "output_hashes": output_hashes,
353
+ "controls": dict(controls),
354
+ "model_fingerprints": {
355
+ role: dict(fingerprint) for role, fingerprint in model_fingerprints.items()
356
+ },
357
+ "environment_keys": tuple(environment_keys),
358
+ "command_sha256": command_sha256,
359
+ }
360
+ return SkillOptArtifact(
361
+ artifact_id=content_hash(artifact_base),
362
+ best_skill=best_skill,
363
+ **artifact_base,
364
+ )
365
+
366
+
367
+ def validate_skillopt_checkout(checkout: str | Path) -> Path:
368
+ """Verify the audited SkillOpt commit and critical optimization files."""
369
+
370
+ checkout = Path(checkout).expanduser().resolve()
371
+ if not checkout.is_dir() or checkout.is_symlink():
372
+ raise ExternalDependencyError("SkillOpt checkout must be a regular directory")
373
+ for relative, expected_hash in SKILLOPT_SOURCE_HASHES.items():
374
+ path = checkout / relative
375
+ if not path.is_file() or path.is_symlink():
376
+ raise ExternalDependencyError(f"SkillOpt checkout is missing {relative}")
377
+ if _sha256_file(path) != expected_hash:
378
+ raise ExternalDependencyError(f"SkillOpt pinned source hash changed: {relative}")
379
+ try:
380
+ head = subprocess.run(
381
+ ("git", "-C", str(checkout), "rev-parse", "HEAD"),
382
+ capture_output=True,
383
+ text=True,
384
+ timeout=30,
385
+ check=True,
386
+ ).stdout.strip()
387
+ status = subprocess.run(
388
+ ("git", "-C", str(checkout), "status", "--porcelain"),
389
+ capture_output=True,
390
+ text=True,
391
+ timeout=30,
392
+ check=True,
393
+ ).stdout.strip()
394
+ except (OSError, subprocess.CalledProcessError, subprocess.TimeoutExpired) as exc:
395
+ raise ExternalDependencyError("SkillOpt Git checkout verification failed") from exc
396
+ if head != SKILLOPT_UPSTREAM_COMMIT:
397
+ raise ExternalDependencyError("SkillOpt checkout is not at the pinned commit")
398
+ if status:
399
+ raise ExternalDependencyError("SkillOpt pinned checkout must be clean")
400
+ return checkout
401
+
402
+
403
+ def _model_fingerprints(
404
+ context: InterventionContext,
405
+ ) -> Mapping[str, Mapping[str, Any]]:
406
+ configured = context.run_config.get("skillopt_model_fingerprints")
407
+ if configured is not None:
408
+ if not isinstance(configured, Mapping):
409
+ raise ValidationError("skillopt_model_fingerprints must be a mapping")
410
+ result: dict[str, Mapping[str, Any]] = {}
411
+ for role in ("target", "optimizer"):
412
+ value = configured.get(role)
413
+ if not isinstance(value, Mapping) or not value:
414
+ raise ValidationError(f"SkillOpt is missing the {role} model fingerprint")
415
+ result[role] = dict(value)
416
+ return MappingProxyType(result)
417
+ if context.backend is None:
418
+ raise ExternalDependencyError(
419
+ "SkillOpt requires explicit target/optimizer fingerprints or a backend"
420
+ )
421
+ try:
422
+ shared = dict(context.backend.fingerprint())
423
+ except AttributeError as exc:
424
+ raise ExternalDependencyError("SkillOpt backend does not expose a fingerprint") from exc
425
+ return MappingProxyType({"target": dict(shared), "optimizer": dict(shared)})
426
+
427
+
428
+ def _validated_environment(value: Mapping[str, str]) -> dict[str, str]:
429
+ result: dict[str, str] = {}
430
+ for key, item in value.items():
431
+ if not isinstance(key, str) or not key.strip() or key != key.strip():
432
+ raise ValidationError("SkillOpt environment keys must be trimmed non-empty strings")
433
+ if not isinstance(item, str):
434
+ raise ValidationError("SkillOpt environment values must be strings")
435
+ result[key] = item
436
+ return result
437
+
438
+
439
+ def _sha256_file(path: Path) -> str:
440
+ digest = hashlib.sha256()
441
+ with path.open("rb") as handle:
442
+ for chunk in iter(lambda: handle.read(1024 * 1024), b""):
443
+ digest.update(chunk)
444
+ return digest.hexdigest()
445
+
446
+
447
+ def _sha256_bytes(value: bytes) -> str:
448
+ return hashlib.sha256(value).hexdigest()
449
+
450
+
451
+ __all__ = [
452
+ "SKILLOPT_PROTOCOL",
453
+ "SKILLOPT_RELEASE_ID",
454
+ "SKILLOPT_SOURCE_HASHES",
455
+ "SKILLOPT_UPSTREAM_COMMIT",
456
+ "SkillOptArtifact",
457
+ "SkillOptControls",
458
+ "SkillOptEnvironmentBinding",
459
+ "SkillOptOfflineRecipe",
460
+ "load_skillopt_artifact",
461
+ "validate_skillopt_checkout",
462
+ ]
@@ -0,0 +1,154 @@
1
+ """Frozen SkillOpt skill replay for the common-support paper arenas.
2
+
3
+ The skill is produced offline by the pinned upstream ``scripts/train.py``
4
+ pipeline. This adapter does not re-run or approximate that optimizer. It
5
+ only appends the validated, content-addressed ``best_skill.md`` to the visible
6
+ context used by the unchanged downstream agent.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ from dataclasses import dataclass
12
+
13
+ from agentinputlab.contracts import (
14
+ ContextBlock,
15
+ ExecutionTrace,
16
+ FrozenAgentState,
17
+ InputPatch,
18
+ InterventionContext,
19
+ PatchOp,
20
+ PatchOperation,
21
+ SemanticFamily,
22
+ TraceEvent,
23
+ TracePhase,
24
+ ValidationError,
25
+ )
26
+ from agentinputlab.contracts.serialization import content_hash
27
+
28
+ from .skillopt import SkillOptArtifact
29
+
30
+ SKILLOPT_COMMON_SUPPORT_RELEASE = "recipe.skillopt.eval_only"
31
+ SKILLOPT_COMMON_SUPPORT_PLACEMENT_RULE = "append_frozen_skill_context.v1"
32
+
33
+
34
+ @dataclass(slots=True)
35
+ class SkillOptSkillCommonSupport:
36
+ """Replay one audited SkillOpt artifact through the shared patch seam."""
37
+
38
+ artifact: SkillOptArtifact
39
+ method_id: str = "skillopt"
40
+ release_id: str = SKILLOPT_COMMON_SUPPORT_RELEASE
41
+ family: SemanticFamily = SemanticFamily.CURATE
42
+
43
+ def __post_init__(self) -> None:
44
+ if not isinstance(self.artifact, SkillOptArtifact):
45
+ raise ValidationError("SkillOpt common support requires a SkillOptArtifact")
46
+ if not self.artifact.best_skill.strip():
47
+ raise ValidationError("SkillOpt common-support skill must not be empty")
48
+
49
+ def propose(self, state: FrozenAgentState, context: InterventionContext) -> InputPatch:
50
+ del context
51
+ skill_text = _render_skill(self.artifact)
52
+ model_fingerprints_hash = content_hash(self.artifact.model_fingerprints)
53
+ block = ContextBlock(
54
+ text=skill_text,
55
+ block_id=f"skillopt-skill:{self.artifact.artifact_id[:20]}",
56
+ source="SkillOpt frozen best_skill.md",
57
+ metadata={
58
+ "artifact_id": self.artifact.artifact_id,
59
+ "best_skill_sha256": self.artifact.best_skill_sha256,
60
+ "upstream_commit": self.artifact.upstream_commit,
61
+ "placement_rule": SKILLOPT_COMMON_SUPPORT_PLACEMENT_RULE,
62
+ },
63
+ )
64
+ trace = ExecutionTrace(
65
+ method_id=self.method_id,
66
+ release_id=self.release_id,
67
+ events=(
68
+ TraceEvent(
69
+ TracePhase.PREPARE,
70
+ "skillopt_frozen_artifact_verified",
71
+ {
72
+ "artifact_id": self.artifact.artifact_id,
73
+ "best_skill_sha256": self.artifact.best_skill_sha256,
74
+ "upstream_commit": self.artifact.upstream_commit,
75
+ "model_fingerprints_hash": model_fingerprints_hash,
76
+ "command_sha256": self.artifact.command_sha256,
77
+ },
78
+ ),
79
+ TraceEvent(
80
+ TracePhase.FINALIZE,
81
+ "skillopt_skill_appended_to_visible_context",
82
+ {
83
+ "placement_rule": SKILLOPT_COMMON_SUPPORT_PLACEMENT_RULE,
84
+ "source_context_blocks": len(state.context),
85
+ "output_context_blocks": len(state.context) + 1,
86
+ "skill_characters": len(skill_text),
87
+ },
88
+ ),
89
+ ),
90
+ counters={
91
+ "model_calls": 0,
92
+ "retrieval_calls": 0,
93
+ "tool_calls": 0,
94
+ "input_tokens": 0,
95
+ "output_tokens": 0,
96
+ "source_context_blocks": len(state.context),
97
+ "output_context_blocks": len(state.context) + 1,
98
+ "skill_characters": len(skill_text),
99
+ },
100
+ warnings=(
101
+ "offline_training_cost_is_reported_once_not_charged_per_eval_unit",
102
+ "controlled_common_support_skill_mapping_not_paper_result_parity",
103
+ ),
104
+ )
105
+ return InputPatch(
106
+ method_id=self.method_id,
107
+ release_id=self.release_id,
108
+ source_state_hash=state.state_hash,
109
+ operations=(
110
+ PatchOperation(
111
+ PatchOp.ADD_CONTEXT,
112
+ block,
113
+ target="context",
114
+ rationale=(
115
+ "Expose the frozen upstream SkillOpt best_skill.md without changing "
116
+ "the captured request or evidence."
117
+ ),
118
+ ),
119
+ ),
120
+ trace=trace,
121
+ implementation_identity=(
122
+ "pinned_upstream_skillopt_offline+" + SKILLOPT_COMMON_SUPPORT_PLACEMENT_RULE
123
+ ),
124
+ profile_kind="controlled_adapter",
125
+ metadata={
126
+ "artifact_id": self.artifact.artifact_id,
127
+ "best_skill_sha256": self.artifact.best_skill_sha256,
128
+ "upstream_commit": self.artifact.upstream_commit,
129
+ "config_sha256": self.artifact.config_sha256,
130
+ "command_sha256": self.artifact.command_sha256,
131
+ "model_fingerprints_hash": model_fingerprints_hash,
132
+ "common_support_placement_rule": SKILLOPT_COMMON_SUPPORT_PLACEMENT_RULE,
133
+ "source_state_hash": state.state_hash,
134
+ "paper_result_parity_claimed": False,
135
+ },
136
+ )
137
+
138
+
139
+ def _render_skill(artifact: SkillOptArtifact) -> str:
140
+ return "\n".join(
141
+ (
142
+ "SKILLOPT LEARNED SKILL (frozen offline artifact)",
143
+ "Use these learned strategies when relevant; the user request and visible "
144
+ "evidence remain authoritative.",
145
+ artifact.best_skill.strip(),
146
+ )
147
+ )
148
+
149
+
150
+ __all__ = [
151
+ "SKILLOPT_COMMON_SUPPORT_PLACEMENT_RULE",
152
+ "SKILLOPT_COMMON_SUPPORT_RELEASE",
153
+ "SkillOptSkillCommonSupport",
154
+ ]