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,379 @@
1
+ """Future-turn outcome modeling for clarification selection.
2
+
3
+ This is a controlled inference-time adapter of Zhang, Knox, and Choi (ICLR
4
+ 2025). The official method learns from double-turn preference labels. The
5
+ adapter retains the paper's defining comparison—rank a direct answer and
6
+ clarifying questions by their simulated future outcomes—but performs that
7
+ comparison at inference time because the authors did not publish checkpoints.
8
+ It must therefore not be described as official checkpoint or result parity.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import re
14
+ from dataclasses import dataclass
15
+ from typing import Any
16
+
17
+ from agentinputlab.backends.llm import GenerationRequest, LLMBackend, ModelCapability
18
+ from agentinputlab.backends.llm.base import require_capabilities
19
+ from agentinputlab.contracts import (
20
+ AlgorithmOutputError,
21
+ ExecutionTrace,
22
+ ExternalDependencyError,
23
+ FrozenAgentState,
24
+ InputPatch,
25
+ InterventionContext,
26
+ PatchOp,
27
+ PatchOperation,
28
+ SemanticFamily,
29
+ TraceEvent,
30
+ TracePhase,
31
+ ValidationError,
32
+ )
33
+
34
+ from ._structured import parse_json_object, string_list, visible_problem
35
+
36
+ FUTURE_TURNS_UPSTREAM_COMMIT = "cfda2bdf3946de19a7ab4e7a8bc764ee8526ef95"
37
+ FUTURE_TURNS_RELEASE = "clarify.future_turns.future_outcome_match"
38
+ FUTURE_TURNS_PROMPT_PROTOCOL = "agentinputlab.future-turn-clarification.v1"
39
+
40
+
41
+ @dataclass(frozen=True, slots=True)
42
+ class FutureTurnControls:
43
+ max_interpretations: int = 5
44
+ max_candidates: int = 3
45
+ max_tokens: int = 768
46
+ temperature: float = 0.0
47
+
48
+ def __post_init__(self) -> None:
49
+ if not 2 <= self.max_interpretations <= 10:
50
+ raise ValidationError("future-turn max_interpretations must be in [2, 10]")
51
+ if not 1 <= self.max_candidates <= 8:
52
+ raise ValidationError("future-turn max_candidates must be in [1, 8]")
53
+ if self.max_tokens < 128:
54
+ raise ValidationError("future-turn max_tokens must be at least 128")
55
+ if self.temperature < 0:
56
+ raise ValidationError("future-turn temperature must be non-negative")
57
+
58
+
59
+ @dataclass(frozen=True, slots=True)
60
+ class FutureTurnOutcome:
61
+ clarification_answer: str
62
+ tailored_response: str
63
+ abstain: bool
64
+
65
+
66
+ @dataclass(frozen=True, slots=True)
67
+ class FutureTurnCandidate:
68
+ question: str
69
+ outcomes: tuple[FutureTurnOutcome, ...]
70
+ utility: float
71
+
72
+
73
+ @dataclass(slots=True)
74
+ class FutureTurnClarifier:
75
+ """Select clarification only when simulated future utility beats direct answer."""
76
+
77
+ backend: LLMBackend | None = None
78
+ controls: FutureTurnControls = FutureTurnControls()
79
+ method_id: str = "future_turns"
80
+ release_id: str = FUTURE_TURNS_RELEASE
81
+ family: SemanticFamily = SemanticFamily.CLARIFY
82
+
83
+ def __post_init__(self) -> None:
84
+ if not isinstance(self.controls, FutureTurnControls):
85
+ raise ValidationError("future-turn controls must be FutureTurnControls")
86
+
87
+ def propose(self, state: FrozenAgentState, context: InterventionContext) -> InputPatch:
88
+ backend = self.backend or context.backend
89
+ if backend is None:
90
+ raise ExternalDependencyError("future-turn clarification requires an LLM backend")
91
+ require_capabilities(
92
+ backend,
93
+ {ModelCapability.CHAT, ModelCapability.JSON_OBJECT, ModelCapability.SEED},
94
+ )
95
+ calls: list[dict[str, Any]] = []
96
+ analysis = self._call(
97
+ backend,
98
+ system=(
99
+ "Identify plausible user interpretations without using hidden benchmark labels. "
100
+ "Return JSON only."
101
+ ),
102
+ prompt=(
103
+ f"{visible_problem(state)}\n\n"
104
+ 'Return {"interpretations":[...],"direct_answer":"...",'
105
+ '"direct_supported_ids":[0,...]}. List distinct plausible intended tasks. '
106
+ "direct_supported_ids are interpretations safely satisfied by the direct answer."
107
+ ),
108
+ seed=context.seed,
109
+ phase="interpretations_and_direct_answer",
110
+ calls=calls,
111
+ )
112
+ interpretations = string_list(
113
+ analysis.get("interpretations"),
114
+ label="future-turn interpretations",
115
+ minimum=1,
116
+ maximum=self.controls.max_interpretations,
117
+ )
118
+ direct_answer = analysis.get("direct_answer")
119
+ if not isinstance(direct_answer, str) or not direct_answer.strip():
120
+ raise AlgorithmOutputError("future-turn direct_answer must be non-empty text")
121
+ direct_ids = _integer_ids(
122
+ analysis.get("direct_supported_ids"),
123
+ upper=len(interpretations),
124
+ label="direct_supported_ids",
125
+ )
126
+ direct_utility = len(direct_ids) / len(interpretations)
127
+
128
+ candidates: tuple[FutureTurnCandidate, ...] = ()
129
+ if len(interpretations) > 1:
130
+ generated = self._call(
131
+ backend,
132
+ system=(
133
+ "Generate concise clarifying questions that distinguish the supplied user "
134
+ "interpretations. Return JSON only."
135
+ ),
136
+ prompt=(
137
+ f"{visible_problem(state)}\n\n"
138
+ f"Interpretations:\n{_numbered(interpretations)}\n\n"
139
+ f'Return {{"questions":[...]}} with at most '
140
+ f"{self.controls.max_candidates} targeted questions."
141
+ ),
142
+ seed=context.seed + 1,
143
+ phase="candidate_questions",
144
+ calls=calls,
145
+ )
146
+ questions = string_list(
147
+ generated.get("questions"),
148
+ label="future-turn candidate questions",
149
+ minimum=1,
150
+ maximum=self.controls.max_candidates,
151
+ )
152
+ candidates = tuple(
153
+ self._simulate_candidate(
154
+ backend,
155
+ state=state,
156
+ interpretations=interpretations,
157
+ question=question,
158
+ seed=context.seed + 2 + index,
159
+ calls=calls,
160
+ )
161
+ for index, question in enumerate(questions)
162
+ )
163
+
164
+ best = max(candidates, key=lambda item: item.utility, default=None)
165
+ should_clarify = best is not None and best.utility > direct_utility
166
+ operation = (
167
+ PatchOperation(
168
+ PatchOp.REQUEST_CLARIFICATION,
169
+ best.question,
170
+ target="user",
171
+ rationale="Simulated double-turn utility exceeded direct-answer utility.",
172
+ )
173
+ if should_clarify
174
+ else PatchOperation(
175
+ PatchOp.NO_OP,
176
+ rationale=(
177
+ "The direct response covered at least as many modeled interpretations as "
178
+ "the best simulated clarification."
179
+ ),
180
+ )
181
+ )
182
+ counters = _usage_counters(calls)
183
+ trace = ExecutionTrace(
184
+ method_id=self.method_id,
185
+ release_id=self.release_id,
186
+ events=(
187
+ TraceEvent(
188
+ TracePhase.PREPARE,
189
+ "future_turn_interpretations",
190
+ {
191
+ "count": len(interpretations),
192
+ "direct_supported": len(direct_ids),
193
+ "direct_utility": direct_utility,
194
+ },
195
+ ),
196
+ TraceEvent(
197
+ TracePhase.PROPOSE,
198
+ "future_outcome_preference",
199
+ {
200
+ "candidate_count": len(candidates),
201
+ "candidate_utilities": [item.utility for item in candidates],
202
+ "selected_question": best.question if should_clarify else "",
203
+ "clarification_selected": should_clarify,
204
+ },
205
+ ),
206
+ ),
207
+ counters=counters,
208
+ warnings=(
209
+ "controlled_inference_time_adapter_not_released_trained_checkpoint",
210
+ "future_outcomes_are_model_simulations_not_hidden_user_labels",
211
+ ),
212
+ )
213
+ return InputPatch(
214
+ method_id=self.method_id,
215
+ release_id=self.release_id,
216
+ source_state_hash=state.state_hash,
217
+ operations=(operation,),
218
+ trace=trace,
219
+ implementation_identity=(f"future_turn_outcome_match@{FUTURE_TURNS_UPSTREAM_COMMIT}"),
220
+ profile_kind="controlled_adapter",
221
+ metadata={
222
+ "protocol": FUTURE_TURNS_PROMPT_PROTOCOL,
223
+ "upstream_commit": FUTURE_TURNS_UPSTREAM_COMMIT,
224
+ "interpretation_count": len(interpretations),
225
+ "direct_utility": direct_utility,
226
+ "candidate_utilities": [item.utility for item in candidates],
227
+ "clarification_selected": should_clarify,
228
+ "official_checkpoint_used": False,
229
+ "paper_result_parity_claimed": False,
230
+ "backend_fingerprint": dict(backend.fingerprint()),
231
+ },
232
+ )
233
+
234
+ def _simulate_candidate(
235
+ self,
236
+ backend: LLMBackend,
237
+ *,
238
+ state: FrozenAgentState,
239
+ interpretations: tuple[str, ...],
240
+ question: str,
241
+ seed: int,
242
+ calls: list[dict[str, Any]],
243
+ ) -> FutureTurnCandidate:
244
+ response = self._call(
245
+ backend,
246
+ system=(
247
+ "Simulate the next user turn and the tailored assistant response for each "
248
+ "possible interpretation. A clarification answer must not reveal the final "
249
+ "answer verbatim. Return JSON only."
250
+ ),
251
+ prompt=(
252
+ f"{visible_problem(state)}\n\n"
253
+ f"Interpretations:\n{_numbered(interpretations)}\n\n"
254
+ f"Clarifying question: {question}\n\n"
255
+ 'Return {"outcomes":[{"interpretation_id":0,'
256
+ '"clarification_answer":"...","tailored_response":"..."},...]}. '
257
+ "Include every interpretation exactly once. Use empty strings when a "
258
+ "future answer or tailored response cannot be produced. "
259
+ "Keep each clarification_answer under 12 words and each tailored_response "
260
+ "under 24 words so the JSON object is complete within the output budget."
261
+ ),
262
+ seed=seed,
263
+ phase="simulate_future_turn",
264
+ calls=calls,
265
+ )
266
+ raw = response.get("outcomes")
267
+ if not isinstance(raw, list):
268
+ raise AlgorithmOutputError("future-turn outcomes must be a JSON array")
269
+ indexed: dict[int, FutureTurnOutcome] = {}
270
+ for item in raw:
271
+ if not isinstance(item, dict):
272
+ raise AlgorithmOutputError("future-turn outcome entries must be objects")
273
+ identifier = item.get("interpretation_id")
274
+ if isinstance(identifier, bool) or not isinstance(identifier, int):
275
+ raise AlgorithmOutputError("future-turn interpretation_id must be an integer")
276
+ if identifier in indexed or not 0 <= identifier < len(interpretations):
277
+ raise AlgorithmOutputError("future-turn interpretation_id is invalid or duplicated")
278
+ answer = item.get("clarification_answer")
279
+ tailored = item.get("tailored_response")
280
+ if not isinstance(answer, str) or not isinstance(tailored, str):
281
+ raise AlgorithmOutputError("future-turn simulated answers must be strings")
282
+ clean_answer = answer.strip()
283
+ clean_tailored = tailored.strip()
284
+ # The host derives whether the future turn is usable from required
285
+ # text fields; it never trusts an unconstrained model-authored flag.
286
+ indexed[identifier] = FutureTurnOutcome(
287
+ clean_answer,
288
+ clean_tailored,
289
+ not clean_answer or not clean_tailored,
290
+ )
291
+ if set(indexed) != set(range(len(interpretations))):
292
+ raise AlgorithmOutputError("future-turn outcomes must cover every interpretation")
293
+ outcomes = tuple(indexed[index] for index in range(len(interpretations)))
294
+ useful = [
295
+ item
296
+ for item in outcomes
297
+ if not item.abstain
298
+ and item.clarification_answer
299
+ and item.tailored_response
300
+ and not _leaks_response(item.clarification_answer, item.tailored_response)
301
+ ]
302
+ coverage = len(useful) / len(outcomes)
303
+ diversity = len({_normalize(item.tailored_response) for item in useful}) / len(outcomes)
304
+ return FutureTurnCandidate(
305
+ question=question,
306
+ outcomes=outcomes,
307
+ utility=(coverage + diversity) / 2.0,
308
+ )
309
+
310
+ def _call(
311
+ self,
312
+ backend: LLMBackend,
313
+ *,
314
+ system: str,
315
+ prompt: str,
316
+ seed: int,
317
+ phase: str,
318
+ calls: list[dict[str, Any]],
319
+ ) -> Any:
320
+ request = GenerationRequest(
321
+ prompt=prompt,
322
+ system=system,
323
+ temperature=self.controls.temperature,
324
+ max_tokens=self.controls.max_tokens,
325
+ seed=seed,
326
+ response_format={"type": "json_object"},
327
+ metadata={
328
+ "method_id": self.method_id,
329
+ "release_id": self.release_id,
330
+ "phase": phase,
331
+ },
332
+ )
333
+ response = backend.generate(request)
334
+ calls.append(
335
+ {
336
+ "request_hash": request.request_hash,
337
+ "input_tokens": response.usage.input_tokens,
338
+ "output_tokens": response.usage.output_tokens,
339
+ "cost_usd": response.usage.cost_usd,
340
+ }
341
+ )
342
+ return parse_json_object(response.text, label=f"future-turn {phase}")
343
+
344
+
345
+ def _integer_ids(value: Any, *, upper: int, label: str) -> tuple[int, ...]:
346
+ if not isinstance(value, list):
347
+ raise AlgorithmOutputError(f"future-turn {label} must be a JSON array")
348
+ result: list[int] = []
349
+ for item in value:
350
+ if isinstance(item, bool) or not isinstance(item, int) or not 0 <= item < upper:
351
+ raise AlgorithmOutputError(f"future-turn {label} contains an invalid index")
352
+ if item not in result:
353
+ result.append(item)
354
+ return tuple(result)
355
+
356
+
357
+ def _normalize(text: str) -> str:
358
+ return re.sub(r"\W+", "", text.casefold())
359
+
360
+
361
+ def _leaks_response(answer: str, response: str) -> bool:
362
+ normalized_answer = _normalize(answer)
363
+ normalized_response = _normalize(response)
364
+ return bool(normalized_response) and normalized_response in normalized_answer
365
+
366
+
367
+ def _numbered(items: tuple[str, ...]) -> str:
368
+ return "\n".join(f"{index}. {item}" for index, item in enumerate(items))
369
+
370
+
371
+ def _usage_counters(calls: list[dict[str, Any]]) -> dict[str, int | float]:
372
+ priced = [item["cost_usd"] for item in calls if item["cost_usd"] is not None]
373
+ return {
374
+ "model_calls": len(calls),
375
+ "input_tokens": sum(int(item["input_tokens"]) for item in calls),
376
+ "output_tokens": sum(int(item["output_tokens"]) for item in calls),
377
+ "cost_usd": sum(float(item) for item in priced),
378
+ "unpriced_model_calls": sum(item["cost_usd"] is None for item in calls),
379
+ }
@@ -0,0 +1,255 @@
1
+ """Prompt-native UDCS component preserving the repository routing semantics."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import re
6
+ from dataclasses import dataclass
7
+
8
+ from agentinputlab.backends.llm import GenerationRequest, LLMBackend, ModelCapability
9
+ from agentinputlab.backends.llm.base import require_capabilities
10
+ from agentinputlab.contracts import (
11
+ AlgorithmOutputError,
12
+ ExecutionTrace,
13
+ ExternalDependencyError,
14
+ FrozenAgentState,
15
+ InputPatch,
16
+ InterventionContext,
17
+ PatchOp,
18
+ PatchOperation,
19
+ SemanticFamily,
20
+ TraceEvent,
21
+ TracePhase,
22
+ ValidationError,
23
+ )
24
+
25
+ _PROBABILITY = r"[\d.]+"
26
+
27
+
28
+ @dataclass(frozen=True, slots=True)
29
+ class UDCSDecision:
30
+ think: str
31
+ u_request: float
32
+ u_request_explanation: str
33
+ action: str
34
+ confidence: float
35
+ explanation: str
36
+ raw_text: str
37
+ clamped_fields: tuple[str, ...] = ()
38
+
39
+ @property
40
+ def requests_clarification(self) -> bool:
41
+ return self.action.strip().lower().startswith("request_clarification")
42
+
43
+
44
+ def parse_udcs_response(text: str) -> UDCSDecision:
45
+ """Parse the six repository tags.
46
+
47
+ This intentionally preserves the upstream behavior: ``think`` and both
48
+ explanations may be empty, action falls back to a fenced block/full output,
49
+ and numeric uncertainty/confidence values are clamped to ``[0, 1]``.
50
+ """
51
+
52
+ if not isinstance(text, str) or not text.strip():
53
+ raise AlgorithmOutputError("UDCS response must be non-empty text")
54
+ think = _optional_tag(text, "think")
55
+ action = _parse_action(text)
56
+ u_raw = _required_probability(text, "u_request")
57
+ confidence_raw = _required_probability(text, "confidence")
58
+ clamped: list[str] = []
59
+ u_request = _clamp(u_raw)
60
+ confidence = _clamp(confidence_raw)
61
+ if u_request != u_raw:
62
+ clamped.append("u_request")
63
+ if confidence != confidence_raw:
64
+ clamped.append("confidence")
65
+ return UDCSDecision(
66
+ think=think,
67
+ u_request=u_request,
68
+ u_request_explanation=_optional_tag(text, "u_request_explanation"),
69
+ action=action,
70
+ confidence=confidence,
71
+ explanation=_optional_tag(text, "explanation"),
72
+ raw_text=text,
73
+ clamped_fields=tuple(clamped),
74
+ )
75
+
76
+
77
+ def _optional_tag(text: str, tag: str) -> str:
78
+ match = re.search(rf"<{tag}>(.*?)</{tag}>", text, re.DOTALL)
79
+ return match.group(1).strip() if match else ""
80
+
81
+
82
+ def _required_probability(text: str, tag: str) -> float:
83
+ match = re.search(rf"<{tag}>\s*({_PROBABILITY})\s*</{tag}>", text)
84
+ if not match:
85
+ raise AlgorithmOutputError(f"UDCS response is missing a valid <{tag}> value")
86
+ try:
87
+ return float(match.group(1))
88
+ except ValueError as exc:
89
+ raise AlgorithmOutputError(f"UDCS <{tag}> value is not numeric") from exc
90
+
91
+
92
+ def _parse_action(text: str) -> str:
93
+ match = re.search(r"<action>(.*?)</action>", text, re.DOTALL)
94
+ if match:
95
+ return match.group(1).strip()
96
+ fenced = re.search(r"```(?:\w+)?\s*(.*?)\s*```", text, re.DOTALL)
97
+ if fenced:
98
+ return fenced.group(1).strip()
99
+ return text.strip()
100
+
101
+
102
+ def _clamp(value: float) -> float:
103
+ return max(0.0, min(1.0, value))
104
+
105
+
106
+ @dataclass(slots=True)
107
+ class UDCSPromptNativePolicy:
108
+ """One-step prompt-native component from the UDCS Proposed-v4 runner.
109
+
110
+ The threshold is stated in the prompt but is deliberately *not* enforced
111
+ in Python. This reproduces the pinned repository semantics. A
112
+ deterministic threshold router must use a different release ID.
113
+ """
114
+
115
+ backend: LLMBackend | None = None
116
+ clarification_threshold: float = 0.5
117
+ temperature: float = 0.0
118
+ max_tokens: int = 800
119
+ method_id: str = "udcs"
120
+ release_id: str = "clarify.udcs.repo_native_prompt_route"
121
+ family: SemanticFamily = SemanticFamily.CLARIFY
122
+
123
+ def __post_init__(self) -> None:
124
+ if not 0.0 <= self.clarification_threshold <= 1.0:
125
+ raise ValidationError("UDCS clarification_threshold must be in [0, 1]")
126
+ if self.temperature < 0:
127
+ raise ValidationError("UDCS temperature must be non-negative")
128
+ if self.max_tokens < 1:
129
+ raise ValidationError("UDCS max_tokens must be positive")
130
+
131
+ def propose(self, state: FrozenAgentState, context: InterventionContext) -> InputPatch:
132
+ backend = self.backend or context.backend
133
+ if backend is None:
134
+ raise ExternalDependencyError("UDCS requires an injected chat backend")
135
+ require_capabilities(backend, {ModelCapability.CHAT})
136
+ response = backend.generate(
137
+ GenerationRequest(
138
+ prompt=_build_user_prompt(state, self.clarification_threshold),
139
+ system=_system_prompt(),
140
+ temperature=self.temperature,
141
+ max_tokens=self.max_tokens,
142
+ seed=context.seed,
143
+ stop=(),
144
+ metadata={
145
+ "method_id": self.method_id,
146
+ "release_id": self.release_id,
147
+ "routing_semantics": "prompt_native",
148
+ },
149
+ )
150
+ )
151
+ decision = parse_udcs_response(response.text)
152
+ warns = tuple(f"clamped_{name}" for name in decision.clamped_fields)
153
+ trace = ExecutionTrace(
154
+ method_id=self.method_id,
155
+ release_id=self.release_id,
156
+ events=(
157
+ TraceEvent(
158
+ TracePhase.PREPARE,
159
+ "prompt_native_threshold",
160
+ {
161
+ "threshold": self.clarification_threshold,
162
+ "python_enforced": False,
163
+ },
164
+ ),
165
+ TraceEvent(
166
+ TracePhase.PROPOSE,
167
+ "parsed_udcs_decision",
168
+ {
169
+ "think": decision.think,
170
+ "u_request": decision.u_request,
171
+ "u_request_explanation": decision.u_request_explanation,
172
+ "action": decision.action,
173
+ "confidence": decision.confidence,
174
+ "explanation": decision.explanation,
175
+ "threshold_disagreement": (
176
+ decision.u_request >= self.clarification_threshold
177
+ and not decision.requests_clarification
178
+ ),
179
+ },
180
+ ),
181
+ ),
182
+ counters={"model_calls": 1},
183
+ warnings=warns,
184
+ )
185
+ if decision.requests_clarification:
186
+ operation = PatchOperation(
187
+ PatchOp.REQUEST_CLARIFICATION,
188
+ _clarification_request(decision),
189
+ target="user",
190
+ rationale=decision.u_request_explanation,
191
+ )
192
+ else:
193
+ operation = PatchOperation(
194
+ PatchOp.NO_OP,
195
+ rationale=(
196
+ "UDCS prompt-native model selected a non-clarification action; "
197
+ "the repository does not enforce the numerical threshold"
198
+ ),
199
+ )
200
+ return InputPatch(
201
+ method_id=self.method_id,
202
+ release_id=self.release_id,
203
+ source_state_hash=state.state_hash,
204
+ operations=(operation,),
205
+ trace=trace,
206
+ implementation_identity="thin_prompt_native_component",
207
+ profile_kind="official_native",
208
+ metadata={
209
+ "u_request": decision.u_request,
210
+ "confidence": decision.confidence,
211
+ "raw_action": decision.action,
212
+ "threshold": self.clarification_threshold,
213
+ "threshold_enforced": False,
214
+ "backend_fingerprint": dict(backend.fingerprint()),
215
+ },
216
+ )
217
+
218
+
219
+ def _system_prompt() -> str:
220
+ return (
221
+ "You are an interactive agent. Follow the available-action contract. "
222
+ "Return all six XML-like fields requested by the user message."
223
+ )
224
+
225
+
226
+ def _build_user_prompt(state: FrozenAgentState, threshold: float) -> str:
227
+ context = "\n\n".join(block.text for block in state.context) or "(none)"
228
+ actions = "\n".join(f"- {name}" for name in state.tool_names) or "(none)"
229
+ history = "\n".join(f"{message.role}: {message.content}" for message in state.messages)
230
+ return (
231
+ f"# Goal\n\n{state.query}\n\n"
232
+ f"# Instruction\n\n{state.instruction or '(none)'}\n\n"
233
+ f"# Current Observation\n\n{context}\n\n"
234
+ f"# Available Actions\n\n{actions}\n"
235
+ "- request_clarification\n\n"
236
+ f"# History\n\n{history or '(none)'}\n\n"
237
+ "# Next action\n\n"
238
+ "Reason inside <think>...</think>. Assess request uncertainty from 0.0 to 1.0 "
239
+ "inside <u_request>...</u_request>, then explain it inside "
240
+ "<u_request_explanation>...</u_request_explanation>. "
241
+ f"If u_request >= {threshold}, your action MUST be request_clarification. "
242
+ "Put the selected action inside <action>...</action>. Finally provide "
243
+ "<confidence>...</confidence> and <explanation>...</explanation>."
244
+ )
245
+
246
+
247
+ def _clarification_request(decision: UDCSDecision) -> str:
248
+ action = decision.action.strip()
249
+ if ":" in action:
250
+ requested = action.split(":", 1)[1].strip()
251
+ if requested:
252
+ return requested
253
+ if decision.u_request_explanation:
254
+ return decision.u_request_explanation
255
+ return "Please clarify the missing or ambiguous details in your request."