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,1459 @@
1
+ #!/usr/bin/env python3
2
+ """Pinned, user-mounted ReFormeR inference worker.
3
+
4
+ No upstream source is vendored. The worker verifies a caller-mounted checkout,
5
+ loads ``Reformulator`` from that checkout, and directly calls the official
6
+ ``select_best_pattern`` and ``apply_pattern`` methods. AgentInputLab only
7
+ supplies a bounded OpenAI-compatible model seam and materializes the documented
8
+ paper/repository output-semantics divergence.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import argparse
14
+ import ast
15
+ import hashlib
16
+ import importlib.util
17
+ import json
18
+ import math
19
+ import os
20
+ import re
21
+ import subprocess
22
+ import sys
23
+ import types
24
+ import urllib.error
25
+ import urllib.parse
26
+ import urllib.request
27
+ from collections.abc import Mapping, Sequence
28
+ from contextlib import redirect_stdout
29
+ from dataclasses import dataclass
30
+ from pathlib import Path, PurePosixPath
31
+ from types import SimpleNamespace
32
+ from typing import Any, Protocol, TextIO
33
+
34
+ UPSTREAM_COMMIT = "72e52450a922bc0051b5b39c3a6307186a555137"
35
+ METHOD_ID = "reformer"
36
+ PROTOCOL_VERSION = "agentinputlab.reformer.v2"
37
+ ADAPTER_REVISION = "unique-library-name-reference-and-failure-usage.v2"
38
+ MANIFEST_SCHEMA = "agentinputlab.reformer.compatibility.v1"
39
+ DEFAULT_MANIFEST = Path(__file__).with_name("compatibility_manifest.json")
40
+ DEFAULT_PATTERN_PATH = "reformer/patterns/extracted_patterns.json"
41
+ PROMPT_PATH = "reformer/prompts.json"
42
+ CORE_PATH = "reformer/core/reformer.py"
43
+ PROMPT_MANAGER_PATH = "reformer/prompt_manager.py"
44
+ INDUCTION_PATH = "reformer/patterns/iterative_pattern_extraction.py"
45
+ MAX_REQUEST_BYTES = 4 * 1024 * 1024
46
+ MAX_RESPONSE_BYTES = 4 * 1024 * 1024
47
+ MAX_CONTEXT_BLOCKS = 256
48
+ MAX_TEXT_CHARS = 1_000_000
49
+ _HASH_RE = re.compile(r"[0-9a-f]{64}")
50
+ _COMMIT_RE = re.compile(r"[0-9a-f]{40}")
51
+ _REF_RE = re.compile(r"refs/[A-Za-z0-9._/-]+")
52
+ _ENV_NAME_RE = re.compile(r"[A-Z_][A-Z0-9_]*")
53
+ _ROOT_FIELDS = frozenset(
54
+ {
55
+ "method_id",
56
+ "release_id",
57
+ "upstream_commit",
58
+ "state_hash",
59
+ "payload",
60
+ "dependency_fingerprints",
61
+ "minimum_reservation",
62
+ "protocol_version",
63
+ "request_id",
64
+ }
65
+ )
66
+ _PAYLOAD_FIELDS = frozenset(
67
+ {
68
+ "task_id",
69
+ "query",
70
+ "context",
71
+ "top_document_count",
72
+ "pattern_artifact_hash",
73
+ "prompt_artifact_hash",
74
+ "semantics",
75
+ "pattern_mode",
76
+ "manual_pattern_id",
77
+ "source_license_acknowledged",
78
+ "controls",
79
+ "seed",
80
+ }
81
+ )
82
+ _CONTROL_FIELDS = frozenset({"max_model_calls", "max_tokens", "max_cost_usd"})
83
+
84
+
85
+ class DriverError(RuntimeError):
86
+ """Expected, secret-free worker failure."""
87
+
88
+ def __init__(
89
+ self,
90
+ code: str,
91
+ message: str,
92
+ *,
93
+ consumed: bool = False,
94
+ usage: Mapping[str, int | float] | None = None,
95
+ provider_usage: Mapping[str, int] | None = None,
96
+ diagnostics: Mapping[str, Any] | None = None,
97
+ ) -> None:
98
+ super().__init__(message)
99
+ self.code = code
100
+ self.consumed = consumed
101
+ self.usage = dict(usage) if usage is not None else None
102
+ self.provider_usage = dict(provider_usage) if provider_usage is not None else None
103
+ self.diagnostics = dict(diagnostics or {})
104
+
105
+
106
+ @dataclass(frozen=True, slots=True)
107
+ class CompatibilityPolicy:
108
+ commit: str
109
+ license_status: str
110
+ license_file_present: bool
111
+ license_evidence_path: str
112
+ license_evidence_sha256: str
113
+ require_clean_checkout: bool
114
+ source_hashes: Mapping[str, str]
115
+ profiles: Mapping[str, Mapping[str, str]]
116
+
117
+ @classmethod
118
+ def from_mapping(cls, value: Mapping[str, Any]) -> CompatibilityPolicy:
119
+ if value.get("schema_version") != MANIFEST_SCHEMA:
120
+ raise DriverError("INVALID_MANIFEST", "ReFormeR manifest schema mismatch")
121
+ upstream = _mapping(value.get("upstream"), "manifest upstream")
122
+ source_files = _mapping(value.get("source_files"), "manifest source_files")
123
+ profiles = _mapping(value.get("profiles"), "manifest profiles")
124
+ if upstream.get("commit") != UPSTREAM_COMMIT:
125
+ raise DriverError("INVALID_MANIFEST", "manifest commit is not approved")
126
+ if upstream.get("license_spdx") != "NOASSERTION":
127
+ raise DriverError("INVALID_MANIFEST", "ReFormeR license must remain NOASSERTION")
128
+ if upstream.get("license_file_present") is not False:
129
+ raise DriverError("INVALID_MANIFEST", "manifest must record the absent license file")
130
+ clean = upstream.get("require_clean_checkout")
131
+ if not isinstance(clean, bool):
132
+ raise DriverError("INVALID_MANIFEST", "clean-checkout flag must be boolean")
133
+ hashes: dict[str, str] = {}
134
+ for raw_path, raw_hash in source_files.items():
135
+ path = _safe_relative_path(raw_path, "manifest source path")
136
+ hashes[path] = _hash(raw_hash, f"manifest hash for {path}")
137
+ required = {
138
+ "README.md",
139
+ CORE_PATH,
140
+ PROMPT_MANAGER_PATH,
141
+ PROMPT_PATH,
142
+ DEFAULT_PATTERN_PATH,
143
+ INDUCTION_PATH,
144
+ }
145
+ if not required <= set(hashes):
146
+ raise DriverError("INVALID_MANIFEST", "manifest omits required upstream sources")
147
+ normalized_profiles: dict[str, Mapping[str, str]] = {}
148
+ expected = {
149
+ "rewrite.reformer.repo_native_r_only": ("r_only", "automatic"),
150
+ "rewrite.reformer.paper_spec_q_concat_r": ("q_concat_r", "automatic"),
151
+ "rewrite.reformer.controlled_r_only": ("r_only", "manual"),
152
+ "rewrite.reformer.controlled_q_concat_r": ("q_concat_r", "manual"),
153
+ }
154
+ if set(profiles) != set(expected):
155
+ raise DriverError("INVALID_MANIFEST", "manifest must define exactly four profiles")
156
+ for release_id, identity in expected.items():
157
+ item = _mapping(profiles[release_id], f"manifest profile {release_id}")
158
+ _exact_keys(item, {"semantics", "pattern_mode"}, "manifest profile")
159
+ if (item["semantics"], item["pattern_mode"]) != identity:
160
+ raise DriverError("INVALID_MANIFEST", "manifest profile identity mismatch")
161
+ normalized_profiles[release_id] = dict(item)
162
+ evidence = _safe_relative_path(
163
+ upstream.get("license_evidence_path"), "license evidence path"
164
+ )
165
+ return cls(
166
+ commit=UPSTREAM_COMMIT,
167
+ license_status="NOASSERTION",
168
+ license_file_present=False,
169
+ license_evidence_path=evidence,
170
+ license_evidence_sha256=_hash(
171
+ upstream.get("license_evidence_sha256"), "license evidence hash"
172
+ ),
173
+ require_clean_checkout=clean,
174
+ source_hashes=hashes,
175
+ profiles=normalized_profiles,
176
+ )
177
+
178
+
179
+ def _fingerprint_model(value: Mapping[str, Any]) -> str | None:
180
+ """Resolve model identity from native or AgentInputLab backend fingerprints."""
181
+
182
+ for key in ("model", "model_id"):
183
+ candidate = value.get(key)
184
+ if isinstance(candidate, str) and candidate.strip():
185
+ return candidate
186
+ nested = value.get("backend")
187
+ if isinstance(nested, Mapping):
188
+ return _fingerprint_model(nested)
189
+ return None
190
+
191
+
192
+ @dataclass(frozen=True, slots=True)
193
+ class BackendConfig:
194
+ base_url: str
195
+ api_key_env: str
196
+ model: str
197
+ fingerprint: Mapping[str, Any]
198
+ extra_body: Mapping[str, Any]
199
+ timeout_seconds: float
200
+ max_input_tokens_per_call: int
201
+ max_output_tokens: int
202
+ temperature: float
203
+ input_cost_per_million: float
204
+ output_cost_per_million: float
205
+
206
+ @classmethod
207
+ def from_json(cls, raw: str) -> BackendConfig:
208
+ value = _mapping(_loads_strict_json(raw), "backend configuration")
209
+ _exact_keys(
210
+ value,
211
+ {
212
+ "base_url",
213
+ "api_key_env",
214
+ "model",
215
+ "fingerprint",
216
+ "timeout_seconds",
217
+ "extra_body",
218
+ "max_input_tokens_per_call",
219
+ "max_output_tokens",
220
+ "temperature",
221
+ "input_cost_per_million",
222
+ "output_cost_per_million",
223
+ },
224
+ "backend configuration",
225
+ )
226
+ model = _text(value["model"], "backend model")
227
+ fingerprint = dict(_mapping(value["fingerprint"], "backend fingerprint"))
228
+ if not fingerprint or _fingerprint_model(fingerprint) != model:
229
+ raise DriverError(
230
+ "INVALID_BACKEND_CONFIG", "backend fingerprint must bind the exact model"
231
+ )
232
+ extra_body = dict(_mapping(value["extra_body"], "backend extra_body"))
233
+ reserved = {"model", "messages", "temperature", "seed", "max_tokens"}
234
+ if reserved & set(extra_body):
235
+ raise DriverError(
236
+ "INVALID_BACKEND_CONFIG", "backend extra_body overrides reserved fields"
237
+ )
238
+ _canonical_json(extra_body)
239
+ api_key_env = _text(value["api_key_env"], "backend api_key_env")
240
+ if _ENV_NAME_RE.fullmatch(api_key_env) is None:
241
+ raise DriverError("INVALID_BACKEND_CONFIG", "api_key_env is invalid")
242
+ temperature = _nonnegative_float(value["temperature"], "backend temperature")
243
+ if temperature > 2:
244
+ raise DriverError("INVALID_BACKEND_CONFIG", "backend temperature exceeds 2")
245
+ return cls(
246
+ base_url=_validate_base_url(_text(value["base_url"], "backend base_url")),
247
+ api_key_env=api_key_env,
248
+ model=model,
249
+ fingerprint=fingerprint,
250
+ extra_body=extra_body,
251
+ timeout_seconds=_positive_float(value["timeout_seconds"], "backend timeout"),
252
+ max_input_tokens_per_call=_positive_int(
253
+ value["max_input_tokens_per_call"],
254
+ "backend max_input_tokens_per_call",
255
+ ),
256
+ max_output_tokens=_positive_int(
257
+ value["max_output_tokens"], "backend max_output_tokens"
258
+ ),
259
+ temperature=temperature,
260
+ input_cost_per_million=_nonnegative_float(
261
+ value["input_cost_per_million"], "backend input price"
262
+ ),
263
+ output_cost_per_million=_nonnegative_float(
264
+ value["output_cost_per_million"], "backend output price"
265
+ ),
266
+ )
267
+
268
+
269
+ @dataclass(frozen=True, slots=True)
270
+ class CompletionResult:
271
+ text: str
272
+ input_tokens: int
273
+ output_tokens: int
274
+ finish_reason: str | None = None
275
+
276
+
277
+ class CompletionBackend(Protocol):
278
+ def fingerprint(self) -> Mapping[str, Any]: ...
279
+
280
+ def complete(
281
+ self,
282
+ *,
283
+ messages: Sequence[Mapping[str, str]],
284
+ seed: int,
285
+ temperature: float,
286
+ max_output_tokens: int,
287
+ ) -> CompletionResult: ...
288
+
289
+
290
+ class OpenAICompatibleBackend:
291
+ def __init__(self, config: BackendConfig) -> None:
292
+ self.config = config
293
+
294
+ def fingerprint(self) -> Mapping[str, Any]:
295
+ return self.config.fingerprint
296
+
297
+ def complete(
298
+ self,
299
+ *,
300
+ messages: Sequence[Mapping[str, str]],
301
+ seed: int,
302
+ temperature: float,
303
+ max_output_tokens: int,
304
+ ) -> CompletionResult:
305
+ key = os.environ.get(self.config.api_key_env)
306
+ if not key:
307
+ raise DriverError("BACKEND_CREDENTIAL_UNAVAILABLE", "backend credential unavailable")
308
+ body = {
309
+ "model": self.config.model,
310
+ "messages": list(messages),
311
+ "temperature": temperature,
312
+ "seed": seed,
313
+ "max_tokens": max_output_tokens,
314
+ }
315
+ body.update(self.config.extra_body)
316
+ request = urllib.request.Request(
317
+ f"{self.config.base_url}/chat/completions",
318
+ data=_canonical_json(body).encode("utf-8"),
319
+ headers={"Authorization": f"Bearer {key}", "Content-Type": "application/json"},
320
+ method="POST",
321
+ )
322
+ try:
323
+ with urllib.request.urlopen(request, timeout=self.config.timeout_seconds) as response:
324
+ raw = response.read(MAX_RESPONSE_BYTES + 1)
325
+ except (OSError, urllib.error.HTTPError, urllib.error.URLError) as exc:
326
+ raise DriverError(
327
+ "BACKEND_CALL_FAILED",
328
+ "backend completion request failed",
329
+ consumed=True,
330
+ ) from exc
331
+ if len(raw) > MAX_RESPONSE_BYTES:
332
+ raise DriverError(
333
+ "BACKEND_RESPONSE_TOO_LARGE",
334
+ "backend response exceeded limit",
335
+ consumed=True,
336
+ )
337
+ provider_usage = None
338
+ diagnostics: dict[str, Any] = {"response_sha256": _sha256_bytes(raw)}
339
+ try:
340
+ root = _mapping(_loads_strict_json(raw.decode("utf-8")), "backend response")
341
+ usage = _mapping(root.get("usage"), "backend usage")
342
+ provider_usage = {
343
+ "input_tokens": _nonnegative_int(usage.get("prompt_tokens"), "prompt_tokens"),
344
+ "output_tokens": _nonnegative_int(usage.get("completion_tokens"), "completion_tokens"),
345
+ }
346
+ if root.get("model") not in {None, self.config.model}:
347
+ raise DriverError("BACKEND_IDENTITY_MISMATCH", "provider returned another model")
348
+ choices = root.get("choices")
349
+ if (
350
+ not isinstance(choices, Sequence)
351
+ or isinstance(choices, (str, bytes))
352
+ or len(choices) != 1
353
+ ):
354
+ raise DriverError("BACKEND_OUTPUT_INVALID", "backend must return one choice")
355
+ choice = _mapping(choices[0], "backend choice")
356
+ finish_reason = choice.get("finish_reason")
357
+ if isinstance(finish_reason, str) and finish_reason in {
358
+ "stop", "length", "content_filter", "tool_calls"
359
+ }:
360
+ diagnostics["finish_reason"] = finish_reason
361
+ message = _mapping(choice.get("message"), "message")
362
+ text = message.get("content")
363
+ diagnostics["content_type"] = type(text).__name__
364
+ if text is None or (isinstance(text, str) and not text.strip()):
365
+ diagnostics["failure_kind"] = (
366
+ "empty_final_at_output_limit" if finish_reason == "length" else "empty_final"
367
+ )
368
+ raise DriverError("BACKEND_OUTPUT_INVALID", "backend returned no final text")
369
+ if not isinstance(text, str):
370
+ raise DriverError("BACKEND_OUTPUT_INVALID", "backend content must be text")
371
+ return CompletionResult(
372
+ text=text,
373
+ input_tokens=provider_usage["input_tokens"],
374
+ output_tokens=provider_usage["output_tokens"],
375
+ finish_reason=finish_reason if isinstance(finish_reason, str) else None,
376
+ )
377
+ except (DriverError, UnicodeDecodeError) as exc:
378
+ if isinstance(exc, DriverError):
379
+ exc.consumed = True
380
+ exc.provider_usage = provider_usage
381
+ exc.diagnostics.update(diagnostics)
382
+ raise
383
+ raise DriverError(
384
+ "BACKEND_OUTPUT_INVALID",
385
+ "backend response must be UTF-8 JSON",
386
+ consumed=True,
387
+ ) from exc
388
+
389
+
390
+ @dataclass(frozen=True, slots=True)
391
+ class Controls:
392
+ max_model_calls: int
393
+ max_tokens: int
394
+ max_cost_usd: float
395
+
396
+
397
+ @dataclass(frozen=True, slots=True)
398
+ class ValidatedRequest:
399
+ request_id: str
400
+ release_id: str
401
+ query: str
402
+ documents: tuple[Mapping[str, str], ...]
403
+ pattern_hash: str
404
+ semantics: str
405
+ pattern_mode: str
406
+ manual_pattern_id: str
407
+ controls: Controls
408
+ seed: int
409
+
410
+
411
+ class UsageTracker:
412
+ def __init__(self, controls: Controls, config: BackendConfig) -> None:
413
+ self.controls = controls
414
+ self.config = config
415
+ self.model_calls = 0
416
+ self.input_tokens = 0
417
+ self.output_tokens = 0
418
+ self.cost_usd = 0.0
419
+ self.stages: list[dict[str, Any]] = []
420
+
421
+ def complete(
422
+ self,
423
+ backend: CompletionBackend,
424
+ *,
425
+ stage: str,
426
+ messages: Sequence[Mapping[str, str]],
427
+ seed: int,
428
+ ) -> str:
429
+ if self.model_calls >= self.controls.max_model_calls:
430
+ raise DriverError("MODEL_CALL_BUDGET_EXCEEDED", "ReFormeR max_model_calls exhausted")
431
+ token_ceiling = self.config.max_input_tokens_per_call + self.config.max_output_tokens
432
+ remaining_tokens = self.controls.max_tokens - self.input_tokens - self.output_tokens
433
+ if token_ceiling > remaining_tokens:
434
+ raise DriverError(
435
+ "TOKEN_BUDGET_EXCEEDED",
436
+ "ReFormeR attested input/output ceiling exceeds the remaining token budget",
437
+ )
438
+ call_cost_ceiling = (
439
+ self.config.max_input_tokens_per_call * self.config.input_cost_per_million
440
+ + self.config.max_output_tokens * self.config.output_cost_per_million
441
+ ) / 1_000_000
442
+ if self.cost_usd + call_cost_ceiling > self.controls.max_cost_usd:
443
+ raise DriverError(
444
+ "COST_BUDGET_EXCEEDED",
445
+ "ReFormeR attested provider-price ceiling exceeds the remaining cost budget",
446
+ )
447
+ self.model_calls += 1
448
+ try:
449
+ result = backend.complete(
450
+ messages=messages,
451
+ seed=seed,
452
+ temperature=self.config.temperature,
453
+ max_output_tokens=self.config.max_output_tokens,
454
+ )
455
+ except DriverError as exc:
456
+ if exc.code == "BACKEND_CREDENTIAL_UNAVAILABLE" and not exc.consumed:
457
+ self.model_calls -= 1
458
+ else:
459
+ exc.consumed = True
460
+ if exc.provider_usage is not None:
461
+ self._add_usage(
462
+ exc.provider_usage["input_tokens"], exc.provider_usage["output_tokens"]
463
+ )
464
+ self.stages.append(
465
+ {
466
+ "index": len(self.stages),
467
+ "stage": stage,
468
+ "seed": seed,
469
+ "failure_code": exc.code,
470
+ **exc.diagnostics,
471
+ "provider_usage": exc.provider_usage,
472
+ }
473
+ )
474
+ exc.usage = self.as_dict()
475
+ raise
476
+ if not isinstance(result, CompletionResult):
477
+ raise DriverError(
478
+ "BACKEND_OUTPUT_INVALID",
479
+ "backend returned invalid completion",
480
+ consumed=True,
481
+ usage=self.as_dict(),
482
+ )
483
+ input_tokens = _nonnegative_int(result.input_tokens, "completion input_tokens")
484
+ output_tokens = _nonnegative_int(result.output_tokens, "completion output_tokens")
485
+ self._add_usage(input_tokens, output_tokens)
486
+ if (
487
+ input_tokens > self.config.max_input_tokens_per_call
488
+ or output_tokens > self.config.max_output_tokens
489
+ ):
490
+ raise DriverError(
491
+ "BACKEND_USAGE_ATTESTATION_EXCEEDED",
492
+ "ReFormeR provider usage exceeded the startup token attestation",
493
+ consumed=True,
494
+ usage=self.as_dict(),
495
+ )
496
+ if self.input_tokens + self.output_tokens > self.controls.max_tokens:
497
+ raise DriverError(
498
+ "TOKEN_BUDGET_EXCEEDED",
499
+ "ReFormeR max_tokens exceeded",
500
+ consumed=True,
501
+ usage=self.as_dict(),
502
+ )
503
+ if self.cost_usd > self.controls.max_cost_usd:
504
+ raise DriverError(
505
+ "COST_BUDGET_EXCEEDED",
506
+ "ReFormeR max_cost_usd exceeded",
507
+ consumed=True,
508
+ usage=self.as_dict(),
509
+ )
510
+ if not isinstance(result.text, str):
511
+ raise DriverError(
512
+ "BACKEND_OUTPUT_INVALID",
513
+ "backend content must be text",
514
+ consumed=True,
515
+ usage=self.as_dict(),
516
+ )
517
+ self.stages.append(
518
+ {
519
+ "index": len(self.stages),
520
+ "stage": stage,
521
+ "seed": seed,
522
+ "input_tokens": result.input_tokens,
523
+ "output_tokens": result.output_tokens,
524
+ "response_sha256": _sha256_bytes(result.text.encode("utf-8")),
525
+ "finish_reason": result.finish_reason,
526
+ }
527
+ )
528
+ if not result.text.strip():
529
+ raise DriverError(
530
+ "BACKEND_OUTPUT_INVALID",
531
+ "backend returned no final text",
532
+ consumed=True,
533
+ usage=self.as_dict(),
534
+ )
535
+ return result.text
536
+
537
+ def _add_usage(self, input_tokens: int, output_tokens: int) -> None:
538
+ self.input_tokens += input_tokens
539
+ self.output_tokens += output_tokens
540
+ self.cost_usd += (
541
+ input_tokens * self.config.input_cost_per_million
542
+ + output_tokens * self.config.output_cost_per_million
543
+ ) / 1_000_000
544
+
545
+ def as_dict(self) -> dict[str, int | float]:
546
+ return {
547
+ "model_calls": self.model_calls,
548
+ "retrieval_calls": 0,
549
+ "input_tokens": self.input_tokens,
550
+ "output_tokens": self.output_tokens,
551
+ "cost_usd": self.cost_usd,
552
+ }
553
+
554
+
555
+ class _MessageTokenizer:
556
+ """Preserve official messages while replacing only the vLLM serialization seam."""
557
+
558
+ def apply_chat_template(self, messages, *, tokenize, add_generation_prompt):
559
+ if tokenize is not False or add_generation_prompt is not True:
560
+ raise DriverError("UPSTREAM_API_MISMATCH", "official chat-template call changed")
561
+ if not isinstance(messages, Sequence) or isinstance(messages, (str, bytes)):
562
+ raise DriverError("UPSTREAM_API_MISMATCH", "official messages are invalid")
563
+ normalized: list[dict[str, str]] = []
564
+ for message in messages:
565
+ item = _mapping(message, "official prompt message")
566
+ if set(item) != {"role", "content"}:
567
+ raise DriverError("UPSTREAM_API_MISMATCH", "official message shape changed")
568
+ normalized.append(
569
+ {
570
+ "role": _text(item["role"], "official message role"),
571
+ "content": _text(item["content"], "official message content"),
572
+ }
573
+ )
574
+ return normalized
575
+
576
+
577
+ class _OfficialLLMShim:
578
+ def __init__(self, backend: CompletionBackend, tracker: UsageTracker, seed: int) -> None:
579
+ self.backend = backend
580
+ self.tracker = tracker
581
+ self.seed = seed
582
+ self.stage = ""
583
+ self.fatal_error: DriverError | None = None
584
+ self.raw_text: dict[str, str] = {}
585
+
586
+ def generate(self, *, prompts, sampling_params):
587
+ expected_sampling = {
588
+ "max_tokens": self.tracker.config.max_output_tokens,
589
+ "temperature": self.tracker.config.temperature,
590
+ }
591
+ try:
592
+ observed_sampling = vars(sampling_params)
593
+ except TypeError as exc:
594
+ raise DriverError(
595
+ "UPSTREAM_API_MISMATCH", "official sampling parameters changed"
596
+ ) from exc
597
+ if observed_sampling != expected_sampling:
598
+ raise DriverError("UPSTREAM_API_MISMATCH", "official sampling parameters changed")
599
+ if self.stage not in {"pattern_selection", "pattern_application"}:
600
+ raise DriverError("UPSTREAM_API_MISMATCH", "official call occurred outside a stage")
601
+ if not isinstance(prompts, Sequence) or len(prompts) != 1:
602
+ raise DriverError("UPSTREAM_API_MISMATCH", "official generate call shape changed")
603
+ messages = prompts[0]
604
+ offset = 0 if self.stage == "pattern_selection" else 1
605
+ try:
606
+ text = self.tracker.complete(
607
+ self.backend,
608
+ stage=self.stage,
609
+ messages=messages,
610
+ seed=self.seed + offset,
611
+ )
612
+ except DriverError as exc:
613
+ self.fatal_error = exc
614
+ raise
615
+ self.raw_text[self.stage] = text
616
+ return [SimpleNamespace(outputs=[SimpleNamespace(text=text)])]
617
+
618
+ def raise_fatal(self) -> None:
619
+ if self.fatal_error is not None:
620
+ raise self.fatal_error
621
+
622
+
623
+ class _BlockedNativeVLLMSymbol:
624
+ """Fail closed if pinned source escapes the audited remote-model seam.
625
+
626
+ The pinned ReFormeR module imports ``LLM`` and ``SamplingParams`` at module
627
+ load time, even though AgentInputLab bypasses its constructor and injects
628
+ ``_OfficialLLMShim`` plus an explicit sampling-parameter object. Requiring
629
+ the full vLLM package in every short-lived worker would therefore add an
630
+ unused accelerator runtime and make the worker environment differ from the
631
+ declared OpenAI-compatible dependency. These symbols satisfy only the
632
+ source-locked import. Any future upstream path that tries to instantiate
633
+ either native symbol fails instead of silently loading another model.
634
+ """
635
+
636
+ def __init__(self, *args: Any, **kwargs: Any) -> None:
637
+ del args, kwargs
638
+ raise DriverError(
639
+ "UNDECLARED_NATIVE_MODEL_LOAD",
640
+ "pinned ReFormeR attempted to bypass the audited remote-model seam",
641
+ )
642
+
643
+
644
+ class ReFormeRRuntime:
645
+ def __init__(
646
+ self,
647
+ checkout: Path,
648
+ backend_config: BackendConfig,
649
+ backend: CompletionBackend,
650
+ *,
651
+ pattern_path: Path | None = None,
652
+ source_license_acknowledged: bool = False,
653
+ policy: CompatibilityPolicy | None = None,
654
+ ) -> None:
655
+ if source_license_acknowledged is not True:
656
+ raise DriverError(
657
+ "SOURCE_LICENSE_NOT_ACKNOWLEDGED",
658
+ "ReFormeR source is NOASSERTION and requires operator acknowledgement",
659
+ )
660
+ self.policy = policy or load_compatibility_policy()
661
+ self.checkout = verify_checkout(checkout, self.policy)
662
+ self.backend_config = backend_config
663
+ self.backend = backend
664
+ if _canonical_json(backend.fingerprint()) != _canonical_json(backend_config.fingerprint):
665
+ raise DriverError("BACKEND_IDENTITY_MISMATCH", "backend differs from startup config")
666
+ selected_path = pattern_path or (self.checkout / DEFAULT_PATTERN_PATH)
667
+ self.pattern_path = selected_path.expanduser().resolve(strict=True)
668
+ if not self.pattern_path.is_file() or self.pattern_path.is_symlink():
669
+ raise DriverError("PATTERN_ARTIFACT_UNAVAILABLE", "pattern artifact is unavailable")
670
+ self.pattern_hash = _sha256_file(self.pattern_path)
671
+ self.patterns = _load_patterns(self.pattern_path)
672
+ self.prompt_hash = _sha256_file(self.checkout / PROMPT_PATH)
673
+ self.reformulator_class, self.prompt_manager_class = _load_official_runtime(self.checkout)
674
+
675
+ def run(self, value: Mapping[str, Any]) -> dict[str, Any]:
676
+ request = validate_request(
677
+ value,
678
+ self.policy,
679
+ self.backend_config,
680
+ pattern_hash=self.pattern_hash,
681
+ prompt_hash=self.prompt_hash,
682
+ )
683
+ tracker = UsageTracker(request.controls, self.backend_config)
684
+ try:
685
+ return self._run_validated(request, tracker)
686
+ except DriverError as exc:
687
+ # Parsing or library validation can fail after a paid model call.
688
+ # Preserve that cost just as for transport-level failures.
689
+ if tracker.model_calls:
690
+ exc.consumed = True
691
+ exc.usage = tracker.as_dict()
692
+ exc.diagnostics.update(
693
+ {"adapter_revision": ADAPTER_REVISION, "model_trace": tracker.stages}
694
+ )
695
+ raise
696
+
697
+ def _run_validated(
698
+ self, request: ValidatedRequest, tracker: UsageTracker
699
+ ) -> dict[str, Any]:
700
+ llm = _OfficialLLMShim(self.backend, tracker, request.seed)
701
+ reformulator = self.reformulator_class.__new__(self.reformulator_class)
702
+ reformulator.patterns = self.patterns
703
+ reformulator.prompt_manager = self.prompt_manager_class(str(self.checkout / PROMPT_PATH))
704
+ reformulator.tokenizer = _MessageTokenizer()
705
+ reformulator.llm = llm
706
+ reformulator.sampling_params = SimpleNamespace(
707
+ max_tokens=self.backend_config.max_output_tokens,
708
+ temperature=self.backend_config.temperature,
709
+ )
710
+
711
+ if request.pattern_mode == "manual":
712
+ selected = _pattern_by_id(self.patterns, request.manual_pattern_id)
713
+ parse_status = "manual"
714
+ fallback_id = ""
715
+ elif not request.documents:
716
+ selected = reformulator.select_best_pattern(request.query, [])
717
+ llm.raise_fatal()
718
+ parse_status = "no_documents_first_pattern"
719
+ fallback_id = _pattern_id(selected)
720
+ else:
721
+ llm.stage = "pattern_selection"
722
+ selected = reformulator.select_best_pattern(
723
+ request.query,
724
+ [document["text"] for document in request.documents],
725
+ )
726
+ llm.raise_fatal()
727
+ raw_selection = llm.raw_text.get("pattern_selection", "")
728
+ parsed = _try_json(raw_selection)
729
+ if isinstance(parsed, Mapping):
730
+ parse_status = "valid_json"
731
+ fallback_id = ""
732
+ else:
733
+ parse_status = "first_pattern_fallback"
734
+ fallback_id = _pattern_id(self.patterns[0])
735
+ raw_selected_hash = _canonical_hash(selected)
736
+ name_reference = isinstance(selected, Mapping) and set(selected) == {"pattern_name"}
737
+ selected = _require_library_pattern(selected, self.patterns)
738
+ selection_match = (
739
+ "unique_name_reference" if name_reference else
740
+ "exact" if raw_selected_hash == _canonical_hash(selected) else "application_fields"
741
+ )
742
+ llm.stage = "pattern_application"
743
+ reformulation = reformulator.apply_pattern(request.query, selected)
744
+ llm.raise_fatal()
745
+ if not isinstance(reformulation, str) or not reformulation.strip():
746
+ raise DriverError("UPSTREAM_OUTPUT_INVALID", "official application returned empty text")
747
+ pattern_id = _pattern_id(selected)
748
+ pattern_json = _canonical_json(selected)
749
+ return {
750
+ "status": "ok",
751
+ "request_id": request.request_id,
752
+ "upstream_commit": UPSTREAM_COMMIT,
753
+ "protocol_version": PROTOCOL_VERSION,
754
+ "payload": {
755
+ "adapter_revision": ADAPTER_REVISION,
756
+ "selection_library_match": selection_match,
757
+ "raw_selected_pattern_hash": raw_selected_hash,
758
+ "pattern_library_hash": self.pattern_hash,
759
+ "prompt_artifact_hash": self.prompt_hash,
760
+ "selected_pattern_id": pattern_id,
761
+ "selected_pattern": _text(
762
+ selected.get("transformation_rule"), "selected transformation_rule"
763
+ ),
764
+ "selected_pattern_hash": _sha256_bytes(pattern_json.encode("utf-8")),
765
+ "selected_examples_hash": _canonical_hash(selected.get("examples", [])),
766
+ "reformulation": reformulation.strip(),
767
+ "top_document_ids": [document["document_id"] for document in request.documents],
768
+ "retrieval_state_hash": _canonical_hash(request.documents),
769
+ "selection_parse_status": parse_status,
770
+ "fallback_first_pattern_id": fallback_id,
771
+ "semantics": request.semantics,
772
+ "pattern_mode": request.pattern_mode,
773
+ "manual_pattern_id": request.manual_pattern_id,
774
+ "official_calls": (
775
+ ["Reformulator.apply_pattern"]
776
+ if request.pattern_mode == "manual"
777
+ else [
778
+ "Reformulator.select_best_pattern",
779
+ "Reformulator.apply_pattern",
780
+ ]
781
+ if request.documents
782
+ else [
783
+ "Reformulator.select_best_pattern:no_documents",
784
+ "Reformulator.apply_pattern",
785
+ ]
786
+ ),
787
+ "model_fingerprint": dict(self.backend_config.fingerprint),
788
+ "model_trace": tracker.stages,
789
+ "source_license": "NOASSERTION",
790
+ "source_license_acknowledged": True,
791
+ "vendored_upstream_source": False,
792
+ "paper_result_parity_claimed": False,
793
+ },
794
+ "usage": tracker.as_dict(),
795
+ }
796
+
797
+
798
+ def load_compatibility_policy(path: Path = DEFAULT_MANIFEST) -> CompatibilityPolicy:
799
+ try:
800
+ value = _loads_strict_json(path.read_text(encoding="utf-8"))
801
+ except OSError as exc:
802
+ raise DriverError("MANIFEST_UNAVAILABLE", "compatibility manifest unavailable") from exc
803
+ return CompatibilityPolicy.from_mapping(_mapping(value, "compatibility manifest"))
804
+
805
+
806
+ def verify_checkout(checkout: Path, policy: CompatibilityPolicy) -> Path:
807
+ try:
808
+ root = checkout.expanduser().resolve(strict=True)
809
+ except OSError as exc:
810
+ raise DriverError("CHECKOUT_UNAVAILABLE", "ReFormeR checkout unavailable") from exc
811
+ if not root.is_dir():
812
+ raise DriverError("CHECKOUT_UNAVAILABLE", "checkout must be a directory")
813
+ if read_checkout_head(root) != policy.commit:
814
+ raise DriverError("UPSTREAM_REVISION_MISMATCH", "checkout is not at pinned commit")
815
+ license_candidates = tuple(
816
+ path
817
+ for pattern in ("LICENSE*", "COPYING*", "NOTICE*")
818
+ for path in root.glob(pattern)
819
+ if path.is_file()
820
+ )
821
+ if license_candidates:
822
+ raise DriverError(
823
+ "LICENSE_STATE_MISMATCH",
824
+ "pinned ReFormeR revision is expected to have no license file",
825
+ )
826
+ evidence = _checkout_file(root, policy.license_evidence_path)
827
+ if _sha256_file(evidence) != policy.license_evidence_sha256:
828
+ raise DriverError("LICENSE_EVIDENCE_MISMATCH", "README license evidence hash mismatch")
829
+ if "License-MIT" not in evidence.read_text(encoding="utf-8", errors="strict"):
830
+ raise DriverError("LICENSE_EVIDENCE_MISMATCH", "README MIT badge evidence is absent")
831
+ for relative, expected in policy.source_hashes.items():
832
+ source = _checkout_file(root, relative)
833
+ if _sha256_file(source) != expected:
834
+ raise DriverError("UPSTREAM_SOURCE_MISMATCH", f"source hash mismatch: {relative}")
835
+ audit_source_symbols(root, policy)
836
+ if policy.require_clean_checkout:
837
+ _require_clean_checkout(root)
838
+ return root
839
+
840
+
841
+ def audit_source_symbols(root: Path, policy: CompatibilityPolicy) -> dict[str, tuple[str, ...]]:
842
+ del policy
843
+ expected = {
844
+ CORE_PATH: {
845
+ "Reformulator": (
846
+ "select_best_pattern",
847
+ "apply_pattern",
848
+ "reformulate_query",
849
+ )
850
+ },
851
+ INDUCTION_PATH: {
852
+ "IterativePatternExtractor": (
853
+ "extract_patterns_from_batch",
854
+ "run_iterative_extraction",
855
+ )
856
+ },
857
+ }
858
+ found: dict[str, tuple[str, ...]] = {}
859
+ for relative, classes in expected.items():
860
+ try:
861
+ tree = ast.parse(_checkout_file(root, relative).read_text(encoding="utf-8"))
862
+ except (OSError, SyntaxError, UnicodeError) as exc:
863
+ raise DriverError("UPSTREAM_SOURCE_INVALID", f"cannot parse {relative}") from exc
864
+ definitions = {
865
+ node.name: {
866
+ child.name
867
+ for child in node.body
868
+ if isinstance(child, (ast.FunctionDef, ast.AsyncFunctionDef))
869
+ }
870
+ for node in tree.body
871
+ if isinstance(node, ast.ClassDef)
872
+ }
873
+ for class_name, methods in classes.items():
874
+ if class_name not in definitions or not set(methods) <= definitions[class_name]:
875
+ raise DriverError(
876
+ "UPSTREAM_SYMBOL_MISMATCH", f"official symbols changed: {relative}"
877
+ )
878
+ found[class_name] = methods
879
+ return found
880
+
881
+
882
+ def validate_request(
883
+ value: Mapping[str, Any],
884
+ policy: CompatibilityPolicy,
885
+ config: BackendConfig,
886
+ *,
887
+ pattern_hash: str,
888
+ prompt_hash: str,
889
+ ) -> ValidatedRequest:
890
+ _exact_keys(value, set(_ROOT_FIELDS), "worker request")
891
+ if value["method_id"] != METHOD_ID:
892
+ raise DriverError("PROFILE_IDENTITY_MISMATCH", "request targets another method")
893
+ release_id = _text(value["release_id"], "release_id")
894
+ profile = policy.profiles.get(release_id)
895
+ if profile is None:
896
+ raise DriverError("PROFILE_IDENTITY_MISMATCH", "unknown ReFormeR profile")
897
+ if value["upstream_commit"] != UPSTREAM_COMMIT:
898
+ raise DriverError("UPSTREAM_REVISION_MISMATCH", "request revision mismatch")
899
+ if value["protocol_version"] != PROTOCOL_VERSION:
900
+ raise DriverError("PROTOCOL_MISMATCH", "request protocol mismatch")
901
+ request_id = _hash(value["request_id"], "request_id")
902
+ _hash(value["state_hash"], "state_hash")
903
+ identity = {key: value[key] for key in _ROOT_FIELDS if key != "request_id"}
904
+ if request_id != _canonical_hash(identity):
905
+ raise DriverError("REQUEST_ID_MISMATCH", "request_id is invalid")
906
+ payload = _mapping(value["payload"], "worker payload")
907
+ _exact_keys(payload, set(_PAYLOAD_FIELDS), "worker payload")
908
+ if payload["source_license_acknowledged"] is not True:
909
+ raise DriverError("SOURCE_LICENSE_NOT_ACKNOWLEDGED", "per-request license gate failed")
910
+ semantics = _text(payload["semantics"], "semantics")
911
+ pattern_mode = _text(payload["pattern_mode"], "pattern_mode")
912
+ if semantics != profile["semantics"] or pattern_mode != profile["pattern_mode"]:
913
+ raise DriverError("PROFILE_IDENTITY_MISMATCH", "request profile axes mismatch")
914
+ requested_pattern_hash = _hash(payload["pattern_artifact_hash"], "pattern hash")
915
+ if requested_pattern_hash != pattern_hash:
916
+ raise DriverError("PATTERN_IDENTITY_MISMATCH", "pattern artifact hash mismatch")
917
+ if payload["prompt_artifact_hash"] != prompt_hash:
918
+ raise DriverError("PROMPT_IDENTITY_MISMATCH", "prompt artifact hash mismatch")
919
+ dependencies = _mapping(value["dependency_fingerprints"], "dependencies")
920
+ if set(dependencies) != {"backend", "retriever"}:
921
+ raise DriverError("DEPENDENCY_IDENTITY_MISMATCH", "dependency fields mismatch")
922
+ backend_fp = _mapping(dependencies["backend"], "backend fingerprint")
923
+ if _canonical_json(backend_fp) != _canonical_json(config.fingerprint):
924
+ raise DriverError("BACKEND_IDENTITY_MISMATCH", "request model differs from startup")
925
+ retriever_fp = _mapping(dependencies["retriever"], "retriever fingerprint")
926
+ if pattern_mode == "automatic" and not retriever_fp:
927
+ raise DriverError("DEPENDENCY_IDENTITY_MISMATCH", "automatic profile requires retriever")
928
+ manual_pattern_id = payload["manual_pattern_id"]
929
+ if not isinstance(manual_pattern_id, str):
930
+ raise DriverError("INVALID_SCHEMA", "manual_pattern_id must be text")
931
+ if pattern_mode == "manual" and not manual_pattern_id.strip():
932
+ raise DriverError("INVALID_SCHEMA", "manual profile requires pattern ID")
933
+ if pattern_mode == "automatic" and manual_pattern_id:
934
+ raise DriverError("INVALID_SCHEMA", "automatic profile cannot set manual pattern")
935
+ top_count = _positive_int(payload["top_document_count"], "top_document_count")
936
+ documents = _validate_documents(payload["context"], top_count)
937
+ expected_calls = 2 if pattern_mode == "automatic" and documents else 1
938
+ reservation = _mapping(value["minimum_reservation"], "minimum_reservation")
939
+ if reservation != {"model_calls": expected_calls}:
940
+ raise DriverError("INVALID_RESERVATION", "model-call reservation mismatches trajectory")
941
+ controls = _validate_controls(payload["controls"])
942
+ if controls.max_model_calls < expected_calls:
943
+ raise DriverError("MODEL_CALL_BUDGET_EXCEEDED", "profile cannot fit max_model_calls")
944
+ query = _text(payload["query"], "query")
945
+ if len(query) > MAX_TEXT_CHARS:
946
+ raise DriverError("REQUEST_TOO_LARGE", "query exceeds limit")
947
+ task_id = payload["task_id"]
948
+ if not isinstance(task_id, str):
949
+ raise DriverError("INVALID_SCHEMA", "task_id must be text")
950
+ return ValidatedRequest(
951
+ request_id=request_id,
952
+ release_id=release_id,
953
+ query=query,
954
+ documents=documents,
955
+ pattern_hash=requested_pattern_hash,
956
+ semantics=semantics,
957
+ pattern_mode=pattern_mode,
958
+ manual_pattern_id=manual_pattern_id,
959
+ controls=controls,
960
+ seed=_nonnegative_int(payload["seed"], "seed"),
961
+ )
962
+
963
+
964
+ def _validate_documents(value: Any, count: int) -> tuple[Mapping[str, str], ...]:
965
+ if not isinstance(value, Sequence) or isinstance(value, (str, bytes)):
966
+ raise DriverError("INVALID_SCHEMA", "context must be a sequence")
967
+ if len(value) > MAX_CONTEXT_BLOCKS:
968
+ raise DriverError("REQUEST_TOO_LARGE", "too many context blocks")
969
+ documents: list[Mapping[str, str]] = []
970
+ seen: set[str] = set()
971
+ for index, raw in enumerate(value[:count]):
972
+ item = _mapping(raw, f"context[{index}]")
973
+ _exact_keys(item, {"text", "block_id", "source", "score", "metadata"}, "context block")
974
+ text = _text(item["text"], f"context[{index}] text")
975
+ document_id = _text(item["block_id"], f"context[{index}] block_id")
976
+ if document_id in seen:
977
+ raise DriverError("INVALID_SCHEMA", "context document IDs must be unique")
978
+ seen.add(document_id)
979
+ _canonical_json(item["metadata"])
980
+ score = item["score"]
981
+ if score is not None:
982
+ _finite_float(score, f"context[{index}] score")
983
+ documents.append({"document_id": document_id, "text": text})
984
+ if len(_canonical_json(documents)) > MAX_TEXT_CHARS:
985
+ raise DriverError("REQUEST_TOO_LARGE", "context text exceeds limit")
986
+ return tuple(documents)
987
+
988
+
989
+ def _validate_controls(value: Any) -> Controls:
990
+ item = _mapping(value, "controls")
991
+ _exact_keys(item, set(_CONTROL_FIELDS), "controls")
992
+ return Controls(
993
+ max_model_calls=_positive_int(item["max_model_calls"], "max_model_calls"),
994
+ max_tokens=_positive_int(item["max_tokens"], "max_tokens"),
995
+ max_cost_usd=_nonnegative_float(item["max_cost_usd"], "max_cost_usd"),
996
+ )
997
+
998
+
999
+ def _load_patterns(path: Path) -> tuple[Mapping[str, Any], ...]:
1000
+ try:
1001
+ value = _loads_strict_json(path.read_text(encoding="utf-8"))
1002
+ except OSError as exc:
1003
+ raise DriverError("PATTERN_ARTIFACT_UNAVAILABLE", "cannot read pattern artifact") from exc
1004
+ if not isinstance(value, Sequence) or isinstance(value, (str, bytes)) or not value:
1005
+ raise DriverError("PATTERN_ARTIFACT_INVALID", "pattern artifact must be non-empty list")
1006
+ patterns: list[Mapping[str, Any]] = []
1007
+ ids: set[str] = set()
1008
+ for index, raw in enumerate(value):
1009
+ item = _mapping(raw, f"pattern[{index}]")
1010
+ _exact_keys(
1011
+ item,
1012
+ {"pattern_name", "description", "transformation_rule", "examples"},
1013
+ "pattern",
1014
+ )
1015
+ pattern_id = _text(item["pattern_name"], "pattern_name")
1016
+ if pattern_id in ids:
1017
+ raise DriverError("PATTERN_ARTIFACT_INVALID", "pattern names must be unique")
1018
+ ids.add(pattern_id)
1019
+ _text(item["description"], "pattern description")
1020
+ _text(item["transformation_rule"], "pattern transformation_rule")
1021
+ examples = item["examples"]
1022
+ if not isinstance(examples, Sequence) or isinstance(examples, (str, bytes)):
1023
+ raise DriverError("PATTERN_ARTIFACT_INVALID", "pattern examples must be a sequence")
1024
+ for pair in examples:
1025
+ if (
1026
+ not isinstance(pair, Sequence)
1027
+ or isinstance(pair, (str, bytes))
1028
+ or len(pair) != 2
1029
+ or not all(isinstance(part, str) for part in pair)
1030
+ ):
1031
+ raise DriverError("PATTERN_ARTIFACT_INVALID", "pattern example must be text pair")
1032
+ patterns.append(dict(item))
1033
+ return tuple(patterns)
1034
+
1035
+
1036
+ def _load_official_runtime(root: Path) -> tuple[type[Any], type[Any]]:
1037
+ namespace = f"_agentinputlab_reformer_{hashlib.sha256(str(root).encode()).hexdigest()[:12]}"
1038
+ reformer_package = f"{namespace}.reformer"
1039
+ core_package = f"{reformer_package}.core"
1040
+ for name, path in (
1041
+ (namespace, root),
1042
+ (reformer_package, root / "reformer"),
1043
+ (core_package, root / "reformer" / "core"),
1044
+ ):
1045
+ module = types.ModuleType(name)
1046
+ module.__path__ = [str(path)]
1047
+ module.__package__ = name
1048
+ sys.modules[name] = module
1049
+ previous_dont_write_bytecode = sys.dont_write_bytecode
1050
+ missing = object()
1051
+ previous_vllm = sys.modules.get("vllm", missing)
1052
+ vllm_shim = types.ModuleType("vllm")
1053
+ vllm_shim.LLM = _BlockedNativeVLLMSymbol
1054
+ vllm_shim.SamplingParams = _BlockedNativeVLLMSymbol
1055
+ sys.modules["vllm"] = vllm_shim
1056
+ sys.dont_write_bytecode = True
1057
+ try:
1058
+ prompt_module = _load_module(
1059
+ f"{reformer_package}.prompt_manager", root / PROMPT_MANAGER_PATH
1060
+ )
1061
+ core_module = _load_module(f"{core_package}.reformer", root / CORE_PATH)
1062
+ except ModuleNotFoundError as exc:
1063
+ raise DriverError(
1064
+ "UPSTREAM_DEPENDENCY_UNAVAILABLE",
1065
+ f"pinned ReFormeR dependency unavailable: {exc.name or 'unknown'}",
1066
+ ) from exc
1067
+ except (ImportError, OSError, SyntaxError) as exc:
1068
+ raise DriverError("UPSTREAM_IMPORT_FAILED", "pinned ReFormeR import failed") from exc
1069
+ finally:
1070
+ sys.dont_write_bytecode = previous_dont_write_bytecode
1071
+ if previous_vllm is missing:
1072
+ sys.modules.pop("vllm", None)
1073
+ else:
1074
+ sys.modules["vllm"] = previous_vllm
1075
+ reformulator = getattr(core_module, "Reformulator", None)
1076
+ prompt_manager = getattr(prompt_module, "PromptManager", None)
1077
+ if not isinstance(reformulator, type) or not isinstance(prompt_manager, type):
1078
+ raise DriverError("UPSTREAM_SYMBOL_MISMATCH", "official runtime classes are missing")
1079
+ return reformulator, prompt_manager
1080
+
1081
+
1082
+ def _load_module(name: str, path: Path):
1083
+ spec = importlib.util.spec_from_file_location(name, path)
1084
+ if spec is None or spec.loader is None:
1085
+ raise DriverError("UPSTREAM_IMPORT_FAILED", "cannot create upstream module spec")
1086
+ module = importlib.util.module_from_spec(spec)
1087
+ sys.modules[name] = module
1088
+ spec.loader.exec_module(module)
1089
+ return module
1090
+
1091
+
1092
+ def _pattern_by_id(patterns: Sequence[Mapping[str, Any]], pattern_id: str):
1093
+ for pattern in patterns:
1094
+ if pattern.get("pattern_name") == pattern_id:
1095
+ return pattern
1096
+ raise DriverError("MANUAL_PATTERN_NOT_FOUND", "manual pattern ID is not in pattern set")
1097
+
1098
+
1099
+ def _require_library_pattern(selected: Any, patterns: Sequence[Mapping[str, Any]]):
1100
+ if not isinstance(selected, Mapping):
1101
+ raise DriverError("UPSTREAM_OUTPUT_INVALID", "official selector returned no pattern")
1102
+ same_name = [p for p in patterns if p.get("pattern_name") == selected.get("pattern_name")]
1103
+ # A complete name-only JSON object references the pinned library, not a new
1104
+ # generated rule. Never fuzzy-match, resolve ambiguity or ignore conflicting
1105
+ # operative fields. This adapter revision records the resolution explicitly.
1106
+ if set(selected) == {"pattern_name"} and len(same_name) == 1:
1107
+ return same_name[0]
1108
+ # The pinned apply_pattern reads only transformation_rule and examples.
1109
+ # Description/annotation differences must not reject an otherwise identical
1110
+ # application. Objects supplying rules/examples must match them exactly.
1111
+ matches = [
1112
+ pattern
1113
+ for pattern in patterns
1114
+ if selected.get("pattern_name") == pattern.get("pattern_name")
1115
+ and selected.get("transformation_rule") == pattern.get("transformation_rule")
1116
+ and _canonical_json(selected.get("examples", []))
1117
+ == _canonical_json(pattern.get("examples", []))
1118
+ ]
1119
+ if len(matches) == 1:
1120
+ return matches[0]
1121
+ raise DriverError(
1122
+ "PATTERN_SELECTION_OUTSIDE_LIBRARY",
1123
+ "selector returned unknown pattern",
1124
+ diagnostics={
1125
+ "pattern_selection": {
1126
+ "same_name_candidates": len(same_name),
1127
+ "rule_matches_named_pattern": any(
1128
+ p.get("transformation_rule") == selected.get("transformation_rule")
1129
+ for p in same_name
1130
+ ),
1131
+ "examples_match_named_pattern": any(
1132
+ _canonical_json(p.get("examples", []))
1133
+ == _canonical_json(selected.get("examples", []))
1134
+ for p in same_name
1135
+ ),
1136
+ }
1137
+ },
1138
+ )
1139
+
1140
+
1141
+ def _pattern_id(pattern: Mapping[str, Any]) -> str:
1142
+ return _text(pattern.get("pattern_name"), "selected pattern_name")
1143
+
1144
+
1145
+ def _try_json(value: str) -> Any:
1146
+ try:
1147
+ return _loads_strict_json(value)
1148
+ except DriverError:
1149
+ return None
1150
+
1151
+
1152
+ def read_checkout_head(root: Path) -> str:
1153
+ git_entry = root / ".git"
1154
+ if git_entry.is_dir():
1155
+ git_dir = git_entry.resolve(strict=True)
1156
+ elif git_entry.is_file():
1157
+ raw = git_entry.read_text(encoding="utf-8").strip()
1158
+ if not raw.startswith("gitdir: "):
1159
+ raise DriverError("GIT_METADATA_INVALID", "checkout .git file malformed")
1160
+ candidate = Path(raw.removeprefix("gitdir: "))
1161
+ git_dir = (
1162
+ (root / candidate).resolve(strict=True)
1163
+ if not candidate.is_absolute()
1164
+ else candidate.resolve(strict=True)
1165
+ )
1166
+ else:
1167
+ raise DriverError("GIT_METADATA_INVALID", "checkout lacks Git metadata")
1168
+ head = (git_dir / "HEAD").read_text(encoding="utf-8").strip()
1169
+ if _COMMIT_RE.fullmatch(head):
1170
+ return head
1171
+ if not head.startswith("ref: "):
1172
+ raise DriverError("GIT_METADATA_INVALID", "checkout HEAD malformed")
1173
+ ref = head.removeprefix("ref: ")
1174
+ if _REF_RE.fullmatch(ref) is None or ".." in PurePosixPath(ref).parts:
1175
+ raise DriverError("GIT_METADATA_INVALID", "checkout HEAD reference unsafe")
1176
+ for base in (git_dir, _common_git_dir(git_dir)):
1177
+ loose = _safe_child(base, ref)
1178
+ if loose.is_file():
1179
+ value = loose.read_text(encoding="utf-8").strip()
1180
+ if _COMMIT_RE.fullmatch(value):
1181
+ return value
1182
+ packed = base / "packed-refs"
1183
+ if packed.is_file():
1184
+ for line in packed.read_text(encoding="utf-8").splitlines():
1185
+ commit, separator, name = line.partition(" ")
1186
+ if separator and name == ref and _COMMIT_RE.fullmatch(commit):
1187
+ return commit
1188
+ raise DriverError("GIT_METADATA_INVALID", "checkout HEAD commit unavailable")
1189
+
1190
+
1191
+ def _common_git_dir(git_dir: Path) -> Path:
1192
+ marker = git_dir / "commondir"
1193
+ if not marker.is_file():
1194
+ return git_dir
1195
+ candidate = Path(marker.read_text(encoding="utf-8").strip())
1196
+ return (
1197
+ (git_dir / candidate).resolve(strict=True)
1198
+ if not candidate.is_absolute()
1199
+ else candidate.resolve(strict=True)
1200
+ )
1201
+
1202
+
1203
+ def _require_clean_checkout(root: Path) -> None:
1204
+ environment = {
1205
+ "PATH": os.environ.get("PATH", ""),
1206
+ "LC_ALL": "C",
1207
+ "GIT_CONFIG_NOSYSTEM": "1",
1208
+ "GIT_CONFIG_GLOBAL": os.devnull,
1209
+ "GIT_OPTIONAL_LOCKS": "0",
1210
+ }
1211
+ try:
1212
+ result = subprocess.run(
1213
+ (
1214
+ "git",
1215
+ "-c",
1216
+ "core.fsmonitor=false",
1217
+ "-C",
1218
+ str(root),
1219
+ "status",
1220
+ "--porcelain=v1",
1221
+ "--untracked-files=all",
1222
+ ),
1223
+ capture_output=True,
1224
+ check=False,
1225
+ text=True,
1226
+ encoding="utf-8",
1227
+ errors="replace",
1228
+ env=environment,
1229
+ timeout=15,
1230
+ )
1231
+ except (OSError, subprocess.SubprocessError) as exc:
1232
+ raise DriverError("GIT_STATUS_FAILED", "clean-checkout check failed") from exc
1233
+ if result.returncode != 0:
1234
+ raise DriverError("GIT_STATUS_FAILED", "clean-checkout check failed")
1235
+ if result.stdout:
1236
+ raise DriverError("DIRTY_CHECKOUT", "checkout contains changes")
1237
+
1238
+
1239
+ def serve(runtime: ReFormeRRuntime, input_stream: TextIO, output_stream: TextIO) -> None:
1240
+ for raw_line in input_stream:
1241
+ if not raw_line.strip():
1242
+ continue
1243
+ request_id = ""
1244
+ try:
1245
+ if len(raw_line.encode("utf-8")) > MAX_REQUEST_BYTES:
1246
+ raise DriverError("REQUEST_TOO_LARGE", "request exceeds byte limit")
1247
+ value = _mapping(_loads_strict_json(raw_line), "JSONL request")
1248
+ if isinstance(value.get("request_id"), str):
1249
+ request_id = value["request_id"][:128]
1250
+ with redirect_stdout(sys.stderr):
1251
+ response = runtime.run(value)
1252
+ except DriverError as exc:
1253
+ response = _failure_response(request_id, exc)
1254
+ except Exception as exc: # pragma: no cover
1255
+ response = _failure_response(
1256
+ request_id,
1257
+ DriverError("INTERNAL_WORKER_ERROR", f"worker failed with {type(exc).__name__}"),
1258
+ )
1259
+ output_stream.write(_canonical_json(response) + "\n")
1260
+ output_stream.flush()
1261
+
1262
+
1263
+ def _failure_response(request_id: str, error: DriverError) -> dict[str, Any]:
1264
+ response: dict[str, Any] = {
1265
+ "status": "error",
1266
+ "request_id": request_id,
1267
+ "upstream_commit": UPSTREAM_COMMIT,
1268
+ "protocol_version": PROTOCOL_VERSION,
1269
+ "failure_code": error.code,
1270
+ "message": str(error),
1271
+ "consumed": error.consumed,
1272
+ }
1273
+ if error.usage is not None:
1274
+ response["usage"] = dict(error.usage)
1275
+ if error.diagnostics:
1276
+ response["diagnostics"] = dict(error.diagnostics)
1277
+ return response
1278
+
1279
+
1280
+ def _checkout_file(root: Path, relative: str) -> Path:
1281
+ path = _safe_child(root, relative)
1282
+ if not path.is_file() or path.is_symlink():
1283
+ raise DriverError("UPSTREAM_FILE_UNAVAILABLE", f"pinned file unavailable: {relative}")
1284
+ return path
1285
+
1286
+
1287
+ def _safe_child(root: Path, relative: str) -> Path:
1288
+ root = root.resolve(strict=True)
1289
+ candidate = (root / relative).resolve(strict=False)
1290
+ if candidate != root and root not in candidate.parents:
1291
+ raise DriverError("UNSAFE_PATH", "path escapes fixed root")
1292
+ return candidate
1293
+
1294
+
1295
+ def _safe_relative_path(value: Any, label: str) -> str:
1296
+ if not isinstance(value, str) or not value or "\\" in value:
1297
+ raise DriverError("INVALID_MANIFEST", f"{label} invalid")
1298
+ path = PurePosixPath(value)
1299
+ if path.is_absolute() or any(part in {"", ".", ".."} for part in path.parts):
1300
+ raise DriverError("INVALID_MANIFEST", f"{label} unsafe")
1301
+ return path.as_posix()
1302
+
1303
+
1304
+ def _sha256_file(path: Path) -> str:
1305
+ digest = hashlib.sha256()
1306
+ with path.open("rb") as handle:
1307
+ for chunk in iter(lambda: handle.read(1024 * 1024), b""):
1308
+ digest.update(chunk)
1309
+ return digest.hexdigest()
1310
+
1311
+
1312
+ def _sha256_bytes(value: bytes) -> str:
1313
+ return hashlib.sha256(value).hexdigest()
1314
+
1315
+
1316
+ def _canonical_hash(value: Any) -> str:
1317
+ return _sha256_bytes(_canonical_json(value).encode("utf-8"))
1318
+
1319
+
1320
+ def _canonical_json(value: Any) -> str:
1321
+ try:
1322
+ return json.dumps(
1323
+ value,
1324
+ ensure_ascii=False,
1325
+ sort_keys=True,
1326
+ separators=(",", ":"),
1327
+ allow_nan=False,
1328
+ )
1329
+ except (TypeError, ValueError) as exc:
1330
+ raise DriverError("NON_CANONICAL_JSON", "value is not canonical JSON") from exc
1331
+
1332
+
1333
+ def _loads_strict_json(raw: str) -> Any:
1334
+ def reject_constant(value: str) -> None:
1335
+ raise ValueError(f"non-finite constant: {value}")
1336
+
1337
+ def reject_duplicates(pairs: list[tuple[str, Any]]) -> dict[str, Any]:
1338
+ result: dict[str, Any] = {}
1339
+ for key, value in pairs:
1340
+ if key in result:
1341
+ raise ValueError(f"duplicate key: {key}")
1342
+ result[key] = value
1343
+ return result
1344
+
1345
+ try:
1346
+ return json.loads(raw, parse_constant=reject_constant, object_pairs_hook=reject_duplicates)
1347
+ except (TypeError, ValueError, json.JSONDecodeError) as exc:
1348
+ raise DriverError("INVALID_JSON", "input is not strict JSON") from exc
1349
+
1350
+
1351
+ def _mapping(value: Any, label: str) -> Mapping[str, Any]:
1352
+ if not isinstance(value, Mapping) or any(not isinstance(key, str) for key in value):
1353
+ raise DriverError("INVALID_SCHEMA", f"{label} must be string-keyed mapping")
1354
+ return value
1355
+
1356
+
1357
+ def _exact_keys(value: Mapping[str, Any], expected: set[str], label: str) -> None:
1358
+ if set(value) != expected:
1359
+ raise DriverError("INVALID_SCHEMA", f"{label} fields do not match protocol")
1360
+
1361
+
1362
+ def _text(value: Any, label: str) -> str:
1363
+ if not isinstance(value, str) or not value.strip():
1364
+ raise DriverError("INVALID_SCHEMA", f"{label} must be non-empty text")
1365
+ return value
1366
+
1367
+
1368
+ def _hash(value: Any, label: str) -> str:
1369
+ if not isinstance(value, str) or _HASH_RE.fullmatch(value) is None:
1370
+ raise DriverError("INVALID_SCHEMA", f"{label} must be SHA-256")
1371
+ return value
1372
+
1373
+
1374
+ def _positive_int(value: Any, label: str) -> int:
1375
+ if isinstance(value, bool) or not isinstance(value, int) or value < 1:
1376
+ raise DriverError("INVALID_SCHEMA", f"{label} must be positive integer")
1377
+ return value
1378
+
1379
+
1380
+ def _nonnegative_int(value: Any, label: str) -> int:
1381
+ if isinstance(value, bool) or not isinstance(value, int) or value < 0:
1382
+ raise DriverError("INVALID_SCHEMA", f"{label} must be non-negative integer")
1383
+ return value
1384
+
1385
+
1386
+ def _finite_float(value: Any, label: str) -> float:
1387
+ if isinstance(value, bool) or not isinstance(value, (int, float)):
1388
+ raise DriverError("INVALID_SCHEMA", f"{label} must be numeric")
1389
+ result = float(value)
1390
+ if not math.isfinite(result):
1391
+ raise DriverError("INVALID_SCHEMA", f"{label} must be finite")
1392
+ return result
1393
+
1394
+
1395
+ def _nonnegative_float(value: Any, label: str) -> float:
1396
+ result = _finite_float(value, label)
1397
+ if result < 0:
1398
+ raise DriverError("INVALID_SCHEMA", f"{label} must be non-negative")
1399
+ return result
1400
+
1401
+
1402
+ def _positive_float(value: Any, label: str) -> float:
1403
+ result = _nonnegative_float(value, label)
1404
+ if result <= 0:
1405
+ raise DriverError("INVALID_SCHEMA", f"{label} must be positive")
1406
+ return result
1407
+
1408
+
1409
+ def _validate_base_url(value: str) -> str:
1410
+ parsed = urllib.parse.urlparse(value)
1411
+ if parsed.scheme not in {"http", "https"} or not parsed.netloc:
1412
+ raise DriverError("INVALID_BACKEND_CONFIG", "base_url must be HTTP(S)")
1413
+ if parsed.username or parsed.password or parsed.query or parsed.fragment:
1414
+ raise DriverError("INVALID_BACKEND_CONFIG", "base_url contains forbidden components")
1415
+ return value.rstrip("/")
1416
+
1417
+
1418
+ def main(argv: Sequence[str] | None = None) -> int:
1419
+ parser = argparse.ArgumentParser(description=__doc__)
1420
+ parser.add_argument("--checkout", type=Path, required=True)
1421
+ parser.add_argument("--patterns", type=Path)
1422
+ parser.add_argument("--compatibility-manifest", type=Path, default=DEFAULT_MANIFEST)
1423
+ parser.add_argument("--backend-config-json")
1424
+ parser.add_argument("--acknowledge-noassertion-license", action="store_true")
1425
+ parser.add_argument("--verify-only", action="store_true")
1426
+ args = parser.parse_args(argv)
1427
+ policy = load_compatibility_policy(args.compatibility_manifest)
1428
+ if args.verify_only:
1429
+ root = verify_checkout(args.checkout, policy)
1430
+ print(
1431
+ _canonical_json(
1432
+ {
1433
+ "status": "ok",
1434
+ "upstream_commit": UPSTREAM_COMMIT,
1435
+ "source_license": "NOASSERTION",
1436
+ "symbols": audit_source_symbols(root, policy),
1437
+ }
1438
+ )
1439
+ )
1440
+ return 0
1441
+ if not args.backend_config_json:
1442
+ parser.error("--backend-config-json is required unless --verify-only is used")
1443
+ config = BackendConfig.from_json(args.backend_config_json)
1444
+ sys.dont_write_bytecode = True
1445
+ with redirect_stdout(sys.stderr):
1446
+ runtime = ReFormeRRuntime(
1447
+ args.checkout,
1448
+ config,
1449
+ OpenAICompatibleBackend(config),
1450
+ pattern_path=args.patterns,
1451
+ source_license_acknowledged=args.acknowledge_noassertion_license,
1452
+ policy=policy,
1453
+ )
1454
+ serve(runtime, sys.stdin, sys.stdout)
1455
+ return 0
1456
+
1457
+
1458
+ if __name__ == "__main__":
1459
+ raise SystemExit(main())