agentevolve-optimizer 0.5.0__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 (414) hide show
  1. agent_evolve/__init__.py +722 -0
  2. agent_evolve/agentic.py +2800 -0
  3. agent_evolve/api.py +767 -0
  4. agent_evolve/application/__init__.py +1580 -0
  5. agent_evolve/application/action_allocation.py +744 -0
  6. agent_evolve/application/action_allocation_frame.py +347 -0
  7. agent_evolve/application/action_allocation_frame_commit.py +185 -0
  8. agent_evolve/application/action_allocation_frame_commit_v3.py +184 -0
  9. agent_evolve/application/action_allocation_frame_v3.py +338 -0
  10. agent_evolve/application/action_archive_value.py +497 -0
  11. agent_evolve/application/action_evidence_consistency.py +455 -0
  12. agent_evolve/application/action_forecast_partitioning.py +1471 -0
  13. agent_evolve/application/action_metric_projection.py +211 -0
  14. agent_evolve/application/action_role_value.py +680 -0
  15. agent_evolve/application/action_score_authorities.py +363 -0
  16. agent_evolve/application/action_structural_signature.py +116 -0
  17. agent_evolve/application/action_target_realization.py +402 -0
  18. agent_evolve/application/agentic_evolution.py +7734 -0
  19. agent_evolve/application/agentic_portfolio_residual_expert.py +835 -0
  20. agent_evolve/application/anchor_residual_identification.py +463 -0
  21. agent_evolve/application/archive_conditioned_action_target.py +208 -0
  22. agent_evolve/application/artifact_journal.py +246 -0
  23. agent_evolve/application/artifact_replay.py +347 -0
  24. agent_evolve/application/budgeted_optimizer.py +1828 -0
  25. agent_evolve/application/calibrated_campaign.py +485 -0
  26. agent_evolve/application/calibrated_current_prefix_forecast_opportunity.py +322 -0
  27. agent_evolve/application/calibrated_positive_gain_opportunity.py +1581 -0
  28. agent_evolve/application/campaign_capacity_recourse.py +254 -0
  29. agent_evolve/application/campaign_contextual_outcomes.py +119 -0
  30. agent_evolve/application/campaign_diagnostic_blocks.py +930 -0
  31. agent_evolve/application/campaign_evidence_registry.py +262 -0
  32. agent_evolve/application/campaign_execution.py +2537 -0
  33. agent_evolve/application/campaign_generation_audit.py +942 -0
  34. agent_evolve/application/campaign_learning.py +1812 -0
  35. agent_evolve/application/campaign_learning_runtime.py +1977 -0
  36. agent_evolve/application/campaign_search_phase.py +227 -0
  37. agent_evolve/application/campaign_selector_context_extension.py +220 -0
  38. agent_evolve/application/campaign_variation_envelope.py +649 -0
  39. agent_evolve/application/campaign_variation_trace.py +451 -0
  40. agent_evolve/application/candidate_archive_consequence.py +128 -0
  41. agent_evolve/application/causal_opportunity_portfolio_gate.py +385 -0
  42. agent_evolve/application/composite_outcome_updater.py +145 -0
  43. agent_evolve/application/composition_portfolio_selection.py +363 -0
  44. agent_evolve/application/concurrent_stage.py +144 -0
  45. agent_evolve/application/contextual_action_allocation.py +181 -0
  46. agent_evolve/application/contextual_campaign_outcomes.py +267 -0
  47. agent_evolve/application/contextual_campaign_planning.py +1366 -0
  48. agent_evolve/application/contextual_delayed_credit.py +651 -0
  49. agent_evolve/application/contextual_search_controller.py +2374 -0
  50. agent_evolve/application/current_prefix_forecast_opportunity.py +714 -0
  51. agent_evolve/application/decision_metric_projection.py +112 -0
  52. agent_evolve/application/derived_action_semantics.py +129 -0
  53. agent_evolve/application/detailed_evaluation.py +449 -0
  54. agent_evolve/application/earned_lineage.py +1011 -0
  55. agent_evolve/application/effective_choice_audit.py +484 -0
  56. agent_evolve/application/empirical_consequence_calibration.py +908 -0
  57. agent_evolve/application/evaluation_accounting.py +325 -0
  58. agent_evolve/application/evaluation_cache.py +199 -0
  59. agent_evolve/application/evaluation_escrow.py +547 -0
  60. agent_evolve/application/evaluation_recourse.py +253 -0
  61. agent_evolve/application/event_recorder.py +151 -0
  62. agent_evolve/application/evolution_campaign.py +1840 -0
  63. agent_evolve/application/executable_hypothesis.py +323 -0
  64. agent_evolve/application/factorial_branch_pilot.py +772 -0
  65. agent_evolve/application/finite_acquisition_capacity_recourse.py +672 -0
  66. agent_evolve/application/finite_acquisition_residual_expert.py +373 -0
  67. agent_evolve/application/finite_acquisition_variation_envelope.py +802 -0
  68. agent_evolve/application/finite_action_hypothesis_semantics.py +446 -0
  69. agent_evolve/application/finite_action_selection.py +188 -0
  70. agent_evolve/application/finite_action_set.py +306 -0
  71. agent_evolve/application/finite_action_transition.py +537 -0
  72. agent_evolve/application/finite_variation_eligibility.py +296 -0
  73. agent_evolve/application/forecast_geometry_portfolio.py +799 -0
  74. agent_evolve/application/forecast_opportunity_shadow_calibration.py +316 -0
  75. agent_evolve/application/front_proximity_admission.py +311 -0
  76. agent_evolve/application/front_proximity_parent_basis.py +458 -0
  77. agent_evolve/application/frozen_hurdle_score.py +659 -0
  78. agent_evolve/application/g3_causal_screen.py +2257 -0
  79. agent_evolve/application/g3_causal_validation.py +1046 -0
  80. agent_evolve/application/g3_postseal_curation.py +818 -0
  81. agent_evolve/application/gated_agentic_generator.py +205 -0
  82. agent_evolve/application/generation_feedback.py +293 -0
  83. agent_evolve/application/generative_proposal_journal.py +185 -0
  84. agent_evolve/application/geometry_conditional_elasticity.py +453 -0
  85. agent_evolve/application/global_wave_action_allocation.py +1151 -0
  86. agent_evolve/application/head_mass_conditional_seat.py +268 -0
  87. agent_evolve/application/identifiable_reflection_evidence.py +1147 -0
  88. agent_evolve/application/identifiable_reflection_learning.py +395 -0
  89. agent_evolve/application/identifiable_reflection_request.py +364 -0
  90. agent_evolve/application/in_memory_residual_archive.py +341 -0
  91. agent_evolve/application/insight_memory.py +1804 -0
  92. agent_evolve/application/live_runtime_manifest.py +758 -0
  93. agent_evolve/application/llm_task_queue.py +769 -0
  94. agent_evolve/application/matched_finite_action_block.py +409 -0
  95. agent_evolve/application/materialized_action_broker.py +2328 -0
  96. agent_evolve/application/materialized_action_constraints.py +83 -0
  97. agent_evolve/application/materialized_variation.py +211 -0
  98. agent_evolve/application/multi_option_evolution.py +1536 -0
  99. agent_evolve/application/outcome_adaptive_action_racing.py +2827 -0
  100. agent_evolve/application/outcome_adaptive_residual_campaign_runtime.py +580 -0
  101. agent_evolve/application/outcome_adaptive_residual_portfolio_evolution.py +3671 -0
  102. agent_evolve/application/outcome_conditioned_portfolio_selection.py +1374 -0
  103. agent_evolve/application/outcome_relation.py +193 -0
  104. agent_evolve/application/paired_allocation_comparison.py +241 -0
  105. agent_evolve/application/paired_block_schedule.py +127 -0
  106. agent_evolve/application/parent_measurement.py +226 -0
  107. agent_evolve/application/pareto_archive.py +811 -0
  108. agent_evolve/application/portfolio_campaign_runtime.py +4739 -0
  109. agent_evolve/application/portfolio_evolution.py +2950 -0
  110. agent_evolve/application/portfolio_hypothesis_observations.py +814 -0
  111. agent_evolve/application/portfolio_memory_attribution.py +581 -0
  112. agent_evolve/application/portfolio_memory_dose.py +788 -0
  113. agent_evolve/application/portfolio_memory_matched_control.py +938 -0
  114. agent_evolve/application/portfolio_memory_transfer.py +297 -0
  115. agent_evolve/application/portfolio_optimization_memory.py +363 -0
  116. agent_evolve/application/portfolio_outcome_feedback.py +1613 -0
  117. agent_evolve/application/portfolio_projection.py +335 -0
  118. agent_evolve/application/portfolio_recombination.py +2032 -0
  119. agent_evolve/application/post_evolution_reflection.py +834 -0
  120. agent_evolve/application/postcommit_rank_authority.py +245 -0
  121. agent_evolve/application/precommitted_portfolio_racing.py +2762 -0
  122. agent_evolve/application/prequential_archive_opportunity_calibration.py +1154 -0
  123. agent_evolve/application/prequential_residual_exploration.py +343 -0
  124. agent_evolve/application/prequential_score_portfolio.py +954 -0
  125. agent_evolve/application/projections.py +292 -0
  126. agent_evolve/application/protected_action_committee.py +1027 -0
  127. agent_evolve/application/protected_branch_pilot.py +376 -0
  128. agent_evolve/application/protected_current_prefix_forecast_opportunity.py +552 -0
  129. agent_evolve/application/provider_replay.py +910 -0
  130. agent_evolve/application/rank_balanced_causal_pilot.py +1372 -0
  131. agent_evolve/application/recombination_residual_expert.py +403 -0
  132. agent_evolve/application/reflection_workflow.py +571 -0
  133. agent_evolve/application/region_conditional_credit.py +911 -0
  134. agent_evolve/application/residual_campaign_runtime.py +531 -0
  135. agent_evolve/application/residual_headroom_campaign_runtime.py +459 -0
  136. agent_evolve/application/residual_headroom_ledger.py +1544 -0
  137. agent_evolve/application/residual_learning_transaction.py +396 -0
  138. agent_evolve/application/residual_portfolio_evolution.py +1228 -0
  139. agent_evolve/application/residual_reachability.py +749 -0
  140. agent_evolve/application/residual_stage_credit.py +499 -0
  141. agent_evolve/application/same_prefix_paired_audit.py +1580 -0
  142. agent_evolve/application/semantic_coverage_score_portfolio.py +838 -0
  143. agent_evolve/application/sequential_lineage_allocation.py +1017 -0
  144. agent_evolve/application/sequential_market_replay.py +1395 -0
  145. agent_evolve/application/sequential_residual_campaign_runtime.py +305 -0
  146. agent_evolve/application/sequential_residual_portfolio_evolution.py +940 -0
  147. agent_evolve/application/single_score_action_allocation.py +299 -0
  148. agent_evolve/application/source_exposure_allocation.py +906 -0
  149. agent_evolve/application/staged_memory.py +210 -0
  150. agent_evolve/application/stratified_cold_start_allocation.py +732 -0
  151. agent_evolve/application/support_guarded_hurdle_score.py +549 -0
  152. agent_evolve/application/target_conditioned_action_forecast.py +595 -0
  153. agent_evolve/application/target_conditioned_campaign.py +566 -0
  154. agent_evolve/application/treatment_assignment.py +201 -0
  155. agent_evolve/application/trusted_objective_evidence.py +217 -0
  156. agent_evolve/application/two_stage_action_evolution.py +1131 -0
  157. agent_evolve/application/v8lite_allocation_policy.py +1083 -0
  158. agent_evolve/application/v9_candidate_policy.py +1303 -0
  159. agent_evolve/bootstrap.py +108 -0
  160. agent_evolve/campaign_presets.py +517 -0
  161. agent_evolve/campaign_profiles.py +452 -0
  162. agent_evolve/campaign_variation_topology.py +288 -0
  163. agent_evolve/campaign_workload.py +950 -0
  164. agent_evolve/cli.py +797 -0
  165. agent_evolve/contract.py +241 -0
  166. agent_evolve/core/__init__.py +91 -0
  167. agent_evolve/core/action_semantics.py +411 -0
  168. agent_evolve/core/authored.py +105 -0
  169. agent_evolve/core/formatting.py +286 -0
  170. agent_evolve/core/optimization_semantics.py +324 -0
  171. agent_evolve/core/problem.py +167 -0
  172. agent_evolve/core/results.py +323 -0
  173. agent_evolve/core/stats.py +70 -0
  174. agent_evolve/core/telemetry.py +100 -0
  175. agent_evolve/domain/__init__.py +89 -0
  176. agent_evolve/domain/artifact.py +162 -0
  177. agent_evolve/domain/durable_text.py +68 -0
  178. agent_evolve/domain/event.py +1454 -0
  179. agent_evolve/domain/finite_action_set.py +426 -0
  180. agent_evolve/domain/finite_variation.py +526 -0
  181. agent_evolve/domain/generative_emission.py +559 -0
  182. agent_evolve/domain/ids.py +163 -0
  183. agent_evolve/domain/inline_text.py +106 -0
  184. agent_evolve/domain/insight.py +27 -0
  185. agent_evolve/domain/lineage.py +737 -0
  186. agent_evolve/domain/llm_task_queue.py +960 -0
  187. agent_evolve/domain/outcome.py +96 -0
  188. agent_evolve/domain/patch.py +854 -0
  189. agent_evolve/domain/typed_json.py +542 -0
  190. agent_evolve/domain/variation_space.py +158 -0
  191. agent_evolve/driver.py +1014 -0
  192. agent_evolve/harness/__init__.py +29 -0
  193. agent_evolve/harness/base.py +242 -0
  194. agent_evolve/harness/directives.py +163 -0
  195. agent_evolve/harness/generative_seal.py +479 -0
  196. agent_evolve/harness/registry.py +41 -0
  197. agent_evolve/infrastructure/__init__.py +39 -0
  198. agent_evolve/infrastructure/artifacts/__init__.py +6 -0
  199. agent_evolve/infrastructure/artifacts/_verification.py +67 -0
  200. agent_evolve/infrastructure/artifacts/filesystem.py +343 -0
  201. agent_evolve/infrastructure/artifacts/in_memory.py +73 -0
  202. agent_evolve/infrastructure/asyncio_runtime.py +109 -0
  203. agent_evolve/infrastructure/authored_runtime.py +188 -0
  204. agent_evolve/infrastructure/authored_worker.py +171 -0
  205. agent_evolve/infrastructure/clock.py +53 -0
  206. agent_evolve/infrastructure/events/__init__.py +6 -0
  207. agent_evolve/infrastructure/events/_validation.py +89 -0
  208. agent_evolve/infrastructure/events/in_memory.py +56 -0
  209. agent_evolve/infrastructure/events/jsonl.py +193 -0
  210. agent_evolve/infrastructure/exception_provenance.py +215 -0
  211. agent_evolve/infrastructure/ids.py +118 -0
  212. agent_evolve/infrastructure/lineage_codec.py +1836 -0
  213. agent_evolve/infrastructure/outcome_adaptive_phase_journal.py +170 -0
  214. agent_evolve/infrastructure/residual_headroom_journal.py +221 -0
  215. agent_evolve/infrastructure/resource_lease.py +370 -0
  216. agent_evolve/infrastructure/sanitization/__init__.py +8 -0
  217. agent_evolve/infrastructure/sanitization/strict_json.py +484 -0
  218. agent_evolve/infrastructure/sequential_phase_journal.py +170 -0
  219. agent_evolve/infrastructure/stream_liveness.py +383 -0
  220. agent_evolve/infrastructure/subprocess_boundary.py +136 -0
  221. agent_evolve/integrations/__init__.py +1 -0
  222. agent_evolve/integrations/botorch/__init__.py +28 -0
  223. agent_evolve/integrations/botorch/finite_qlognehvi.py +190 -0
  224. agent_evolve/integrations/botorch/finite_qlognehvi_batch.py +155 -0
  225. agent_evolve/integrations/botorch/finite_qlognehvi_batch_identity.py +20 -0
  226. agent_evolve/integrations/botorch/finite_qlognehvi_batch_worker.py +55 -0
  227. agent_evolve/integrations/botorch/finite_qlognehvi_identity.py +22 -0
  228. agent_evolve/integrations/botorch/finite_qlognehvi_worker.py +55 -0
  229. agent_evolve/integrations/botorch/subprocess_qlognehvi.py +261 -0
  230. agent_evolve/integrations/botorch/subprocess_qlognehvi_batch.py +273 -0
  231. agent_evolve/integrations/completion.py +242 -0
  232. agent_evolve/integrations/pydantic_ai/__init__.py +441 -0
  233. agent_evolve/integrations/pydantic_ai/action_forecast.py +1068 -0
  234. agent_evolve/integrations/pydantic_ai/agentic_generator.py +2308 -0
  235. agent_evolve/integrations/pydantic_ai/async_generator.py +1604 -0
  236. agent_evolve/integrations/pydantic_ai/boundary_codec.py +1526 -0
  237. agent_evolve/integrations/pydantic_ai/calibrated_portfolio_campaign.py +756 -0
  238. agent_evolve/integrations/pydantic_ai/calibrated_portfolio_selection.py +7537 -0
  239. agent_evolve/integrations/pydantic_ai/campaign_acquisition.py +609 -0
  240. agent_evolve/integrations/pydantic_ai/execution_binding.py +138 -0
  241. agent_evolve/integrations/pydantic_ai/forecast_geometry_action_committee.py +217 -0
  242. agent_evolve/integrations/pydantic_ai/harness.py +159 -0
  243. agent_evolve/integrations/pydantic_ai/heterogeneous_model_execution.py +306 -0
  244. agent_evolve/integrations/pydantic_ai/hierarchical_residual_adaptive_semantic_view.py +179 -0
  245. agent_evolve/integrations/pydantic_ai/json_schema_dialect.py +108 -0
  246. agent_evolve/integrations/pydantic_ai/materialized_hierarchical_residual_expert.py +952 -0
  247. agent_evolve/integrations/pydantic_ai/materialized_portfolio_judge.py +520 -0
  248. agent_evolve/integrations/pydantic_ai/model_execution_profile.py +659 -0
  249. agent_evolve/integrations/pydantic_ai/outbound_request_manifest.py +1170 -0
  250. agent_evolve/integrations/pydantic_ai/portable_residual_consequence_features.py +575 -0
  251. agent_evolve/integrations/pydantic_ai/portfolio_selection.py +422 -0
  252. agent_evolve/integrations/pydantic_ai/progress_aware_openrouter.py +416 -0
  253. agent_evolve/integrations/pydantic_ai/provider_attempt_join.py +1523 -0
  254. agent_evolve/integrations/pydantic_ai/provider_free_calibrated_runner.py +607 -0
  255. agent_evolve/integrations/pydantic_ai/queued_runner.py +2634 -0
  256. agent_evolve/integrations/pydantic_ai/reconciled_residual_reachability.py +1417 -0
  257. agent_evolve/integrations/pydantic_ai/residual_forecast_geometry.py +445 -0
  258. agent_evolve/integrations/pydantic_ai/residual_reachability.py +674 -0
  259. agent_evolve/integrations/pydantic_ai/residual_semantic_cells.py +239 -0
  260. agent_evolve/integrations/pydantic_ai/sealed_output_replay.py +1068 -0
  261. agent_evolve/integrations/pydantic_ai/semantic_coverage_residual_portfolio.py +770 -0
  262. agent_evolve/integrations/pydantic_ai/semantic_decision_replay.py +383 -0
  263. agent_evolve/integrations/pydantic_ai/support_adaptive_residual_portfolio.py +135 -0
  264. agent_evolve/integrations/pydantic_ai/trusted_residual_prompt_context.py +143 -0
  265. agent_evolve/integrations/pydantic_ai/validated_openrouter_model.py +107 -0
  266. agent_evolve/integrations/pymoo_adapter.py +242 -0
  267. agent_evolve/policies/__init__.py +17 -0
  268. agent_evolve/policies/check.py +469 -0
  269. agent_evolve/policies/emit_scaffold.py +451 -0
  270. agent_evolve/policies/feedback/__init__.py +37 -0
  271. agent_evolve/policies/feedback/held_out_asn.py +1325 -0
  272. agent_evolve/policies/genetic.py +607 -0
  273. agent_evolve/policies/llm_backoff.py +183 -0
  274. agent_evolve/policies/llm_chooser.py +226 -0
  275. agent_evolve/policies/llm_generator.py +1760 -0
  276. agent_evolve/policies/llm_init.py +267 -0
  277. agent_evolve/policies/llm_operator.py +109 -0
  278. agent_evolve/policies/llm_prior.py +194 -0
  279. agent_evolve/policies/llm_surrogate.py +334 -0
  280. agent_evolve/policies/measurement_evidence.py +704 -0
  281. agent_evolve/policies/memory/__init__.py +223 -0
  282. agent_evolve/policies/memory/balanced_subset_blocks.py +707 -0
  283. agent_evolve/policies/memory/compatibility_matching.py +593 -0
  284. agent_evolve/policies/memory/global_falsification.py +1841 -0
  285. agent_evolve/policies/memory/prompt_shape.py +503 -0
  286. agent_evolve/policies/memory/randomized_subset.py +714 -0
  287. agent_evolve/policies/memory/staged_causal.py +1270 -0
  288. agent_evolve/policies/memory/treatment_compliance.py +759 -0
  289. agent_evolve/policies/objective_resolution/__init__.py +17 -0
  290. agent_evolve/policies/objective_resolution/fixed_grid.py +364 -0
  291. agent_evolve/policies/operator_portfolio.py +407 -0
  292. agent_evolve/policies/reguidance.py +1133 -0
  293. agent_evolve/policies/reward/__init__.py +83 -0
  294. agent_evolve/policies/reward/affine_candidate_consequence.py +156 -0
  295. agent_evolve/policies/reward/affine_candidate_consequence_3d.py +159 -0
  296. agent_evolve/policies/reward/affine_hypervolume.py +490 -0
  297. agent_evolve/policies/reward/affine_hypervolume_3d.py +567 -0
  298. agent_evolve/policies/reward/contextual_marginal_utility.py +318 -0
  299. agent_evolve/policies/reward/frozen_archive.py +360 -0
  300. agent_evolve/policies/reward/frozen_wave_archive.py +368 -0
  301. agent_evolve/policies/search_state.py +208 -0
  302. agent_evolve/policies/selection/__init__.py +345 -0
  303. agent_evolve/policies/selection/acquisition_certified_slate.py +684 -0
  304. agent_evolve/policies/selection/affine_frontier_context.py +330 -0
  305. agent_evolve/policies/selection/affine_frontier_target.py +473 -0
  306. agent_evolve/policies/selection/archive_elite.py +1346 -0
  307. agent_evolve/policies/selection/calibrated_portfolio_binding.py +640 -0
  308. agent_evolve/policies/selection/calibrated_slate.py +1394 -0
  309. agent_evolve/policies/selection/calibrated_slate_codec.py +579 -0
  310. agent_evolve/policies/selection/common_candidate_pool.py +685 -0
  311. agent_evolve/policies/selection/diagnostic_sampling.py +319 -0
  312. agent_evolve/policies/selection/disjoint_pairs.py +479 -0
  313. agent_evolve/policies/selection/elite_explorer.py +719 -0
  314. agent_evolve/policies/selection/finite_action.py +187 -0
  315. agent_evolve/policies/selection/finite_option_prompt_projection.py +377 -0
  316. agent_evolve/policies/selection/finite_palette_evidence.py +247 -0
  317. agent_evolve/policies/selection/forecast_calibration.py +922 -0
  318. agent_evolve/policies/selection/frontier_probe_slate.py +814 -0
  319. agent_evolve/policies/selection/frozen_archive_pairs.py +762 -0
  320. agent_evolve/policies/selection/full_support_slate.py +91 -0
  321. agent_evolve/policies/selection/meaningful_direction.py +240 -0
  322. agent_evolve/policies/selection/memory_dose_feasibility.py +259 -0
  323. agent_evolve/policies/selection/model_anchored_slate.py +826 -0
  324. agent_evolve/policies/selection/phenotype_recourse.py +979 -0
  325. agent_evolve/policies/selection/proposal_support.py +368 -0
  326. agent_evolve/policies/selection/random_portfolio.py +254 -0
  327. agent_evolve/policies/selection/regret_bounded_slate.py +1084 -0
  328. agent_evolve/policies/selection/residual_frontier.py +463 -0
  329. agent_evolve/policies/selection/residual_frontier_target.py +605 -0
  330. agent_evolve/policies/selection/structural_posterior_slate.py +1571 -0
  331. agent_evolve/policies/selection/target_conditioned_allocator.py +648 -0
  332. agent_evolve/policies/selection/target_conditioned_features.py +812 -0
  333. agent_evolve/policies/selection/target_conditioned_prequential.py +1527 -0
  334. agent_evolve/policies/selection/task_keyed_palette.py +906 -0
  335. agent_evolve/policies/semantics.py +147 -0
  336. agent_evolve/policies/structure.py +362 -0
  337. agent_evolve/policies/structured_output_budget.py +62 -0
  338. agent_evolve/policies/surrogate.py +696 -0
  339. agent_evolve/policies/variation/__init__.py +1 -0
  340. agent_evolve/policies/variation/compositional_finite_catalog.py +426 -0
  341. agent_evolve/policies/variation/crossover_inheritance.py +575 -0
  342. agent_evolve/policies/variation/disjoint_recombination.py +611 -0
  343. agent_evolve/policies/variation/exact_composition_capacity.py +214 -0
  344. agent_evolve/policies/variation/exact_parent_crossover.py +950 -0
  345. agent_evolve/policies/variation/multiscale_restart_catalog.py +372 -0
  346. agent_evolve/policies/variation/source_union_finite_catalog.py +403 -0
  347. agent_evolve/policies/variation/typed_patch.py +1981 -0
  348. agent_evolve/policies/weighted_prior.py +394 -0
  349. agent_evolve/ports/__init__.py +383 -0
  350. agent_evolve/ports/action_allocation.py +733 -0
  351. agent_evolve/ports/action_allocation_frame.py +1153 -0
  352. agent_evolve/ports/action_allocation_frame_commit.py +294 -0
  353. agent_evolve/ports/action_allocation_frame_commit_v3.py +432 -0
  354. agent_evolve/ports/action_allocation_frame_v3.py +995 -0
  355. agent_evolve/ports/action_forecast.py +1568 -0
  356. agent_evolve/ports/action_metric_projection.py +165 -0
  357. agent_evolve/ports/agentic_generator.py +1561 -0
  358. agent_evolve/ports/archive_context.py +136 -0
  359. agent_evolve/ports/artifact_sanitizer.py +44 -0
  360. agent_evolve/ports/artifact_store.py +225 -0
  361. agent_evolve/ports/clock.py +13 -0
  362. agent_evolve/ports/contextual_search_allocation.py +827 -0
  363. agent_evolve/ports/decision_metric_projection.py +258 -0
  364. agent_evolve/ports/event_store.py +55 -0
  365. agent_evolve/ports/executable_hypothesis.py +557 -0
  366. agent_evolve/ports/finite_acquisition.py +377 -0
  367. agent_evolve/ports/finite_acquisition_batch.py +296 -0
  368. agent_evolve/ports/finite_acquisition_batch_json.py +164 -0
  369. agent_evolve/ports/finite_acquisition_json.py +247 -0
  370. agent_evolve/ports/finite_acquisition_space.py +168 -0
  371. agent_evolve/ports/finite_action_selection.py +348 -0
  372. agent_evolve/ports/finite_action_set.py +256 -0
  373. agent_evolve/ports/frontier_target.py +396 -0
  374. agent_evolve/ports/generation_failure.py +43 -0
  375. agent_evolve/ports/hard_feasibility.py +233 -0
  376. agent_evolve/ports/id_factory.py +34 -0
  377. agent_evolve/ports/llm_task_queue.py +93 -0
  378. agent_evolve/ports/objective_resolution.py +419 -0
  379. agent_evolve/ports/paired_allocation_comparison.py +401 -0
  380. agent_evolve/ports/paired_block_schedule.py +475 -0
  381. agent_evolve/ports/parent_measurement.py +336 -0
  382. agent_evolve/ports/portfolio_memory_dose.py +643 -0
  383. agent_evolve/ports/portfolio_selection.py +3169 -0
  384. agent_evolve/ports/postcommit_rank_authority.py +467 -0
  385. agent_evolve/ports/presented_action_evidence.py +794 -0
  386. agent_evolve/ports/resource_lease.py +162 -0
  387. agent_evolve/ports/structured_generator.py +734 -0
  388. agent_evolve/ports/structured_output_budget.py +120 -0
  389. agent_evolve/ports/subprocess_boundary.py +138 -0
  390. agent_evolve/ports/treatment_assignment.py +466 -0
  391. agent_evolve/ports/variation_catalog.py +76 -0
  392. agent_evolve/ports/variation_source.py +226 -0
  393. agent_evolve/proposal_mode.py +157 -0
  394. agent_evolve/proposers/__init__.py +10 -0
  395. agent_evolve/proposers/random_proposer.py +188 -0
  396. agent_evolve/provider_accounting.py +163 -0
  397. agent_evolve/py.typed +0 -0
  398. agent_evolve/reference_method.py +1570 -0
  399. agent_evolve/session/__init__.py +11 -0
  400. agent_evolve/session/authorship.py +864 -0
  401. agent_evolve/session/evaluate.py +236 -0
  402. agent_evolve/session/fidelity.py +237 -0
  403. agent_evolve/session/genetic_loop.py +742 -0
  404. agent_evolve/session/loop.py +803 -0
  405. agent_evolve/session/screening.py +671 -0
  406. agent_evolve/settings.py +376 -0
  407. agent_evolve/workload_kit.py +368 -0
  408. agent_evolve/workload_prompt.py +398 -0
  409. agentevolve_optimizer-0.5.0.dist-info/METADATA +599 -0
  410. agentevolve_optimizer-0.5.0.dist-info/RECORD +414 -0
  411. agentevolve_optimizer-0.5.0.dist-info/WHEEL +5 -0
  412. agentevolve_optimizer-0.5.0.dist-info/entry_points.txt +2 -0
  413. agentevolve_optimizer-0.5.0.dist-info/licenses/LICENSE +21 -0
  414. agentevolve_optimizer-0.5.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,734 @@
1
+ """Provider-neutral port for one typed LLM generation attempt.
2
+
3
+ Retrying, queueing, and experiment policy deliberately live outside this port. An
4
+ adapter executes exactly one provider attempt and either returns typed telemetry or
5
+ raises :class:`StructuredGenerationError` with a closed, non-secret classification.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import hashlib
11
+ import json
12
+ import math
13
+ import re
14
+ from dataclasses import dataclass, field
15
+ from decimal import Decimal
16
+ from enum import Enum
17
+ from typing import Callable, Generic, Protocol, TypeVar, runtime_checkable
18
+
19
+ from agent_evolve.domain.ids import LLMCallId, ProviderAttemptId
20
+ from agent_evolve.domain.llm_task_queue import (
21
+ CanonicalProviderErrorCode,
22
+ MAX_VALIDATION_ISSUES,
23
+ SanitizedExceptionProvenance,
24
+ SanitizedValidationIssue,
25
+ StreamTimeoutPhase,
26
+ StructuredOutputFailureMode,
27
+ )
28
+ from agent_evolve.ports.generation_failure import GenerationFailureDisposition
29
+
30
+
31
+ OutputT = TypeVar("OutputT")
32
+ _OPERATION_TOKEN = re.compile(r"^[a-z][a-z0-9_.-]{0,95}$")
33
+ _TOOL_TOKEN = re.compile(r"^[A-Za-z][A-Za-z0-9_-]{0,63}$")
34
+ _LOWER_SHA256 = re.compile(r"^[0-9a-f]{64}$")
35
+ _REPAIR_PATH_TOKEN = re.compile(r"^(?:\*|[A-Za-z_][A-Za-z0-9_-]{0,63})$")
36
+ MAX_PROMPT_UTF8_BYTES = 512_000
37
+ # Provider capabilities are injected by composition policies; this is only a
38
+ # language/runtime safety envelope for the integer carried across the generic
39
+ # port. In particular, it must not encode one model route's completion cap.
40
+ MAX_OUTPUT_TOKENS = 2_147_483_647
41
+ MAX_STRUCTURED_REPAIR_LITERAL_SETS = 8
42
+ MAX_STRUCTURED_REPAIR_LITERALS = 1_024
43
+ MAX_STRUCTURED_REPAIR_LITERAL_UTF8_BYTES = 256
44
+ MAX_STRUCTURED_REPAIR_CONTEXT_UTF8_BYTES = 16_384
45
+ DEFAULT_STREAM_CANCEL_DRAIN_TIMEOUT_NS = 5_000_000_000
46
+ DEFAULT_STREAM_TRANSPORT_RETIRE_TIMEOUT_NS = 5_000_000_000
47
+ STREAM_CLEANUP_POLICY_ID = "bounded_cancel_drain"
48
+ STREAM_CLEANUP_POLICY_VERSION = 1
49
+ STREAM_CLEANUP_POLICY_DEFINITION_SHA256 = hashlib.sha256(
50
+ b"agent-evolve:bounded-stream-cleanup:v1:"
51
+ b"cancel-on-liveness-expiry;wait-bounded-cancel-drain;"
52
+ b"if-unsettled-retire-supervisor-and-owned-transport-bounded;"
53
+ b"publish-terminal-nonretryable-cleanup-timeout;never-overlap-retry"
54
+ ).hexdigest()
55
+ _STREAM_CLEANUP_CONFIGURATION_DOMAIN = (
56
+ b"agent-evolve:bounded-stream-cleanup-configuration:v1\x00"
57
+ )
58
+ IDENTITY_PROMPT_RENDERER_ID = "agent_evolve.identity_prompt"
59
+ IDENTITY_PROMPT_RENDERER_REVISION = "identity_v1"
60
+ IDENTITY_PROMPT_RENDERER_DEFINITION_SHA256 = hashlib.sha256(
61
+ b"agent-evolve:prompt-renderer:identity:v1\x00"
62
+ b"wire-prompt-utf8-bytes-equal-semantic-prompt-utf8-bytes"
63
+ ).hexdigest()
64
+
65
+
66
+ class GenerationFailureKind(str, Enum):
67
+ """Closed failure classes used by scheduler and trace projections."""
68
+
69
+ RATE_LIMITED = "rate_limited"
70
+ TIMEOUT = "timeout"
71
+ PROVIDER_UNAVAILABLE = "provider_unavailable"
72
+ CAPABILITY_MISMATCH = "capability_mismatch"
73
+ INVALID_REQUEST = "invalid_request"
74
+ AUTHENTICATION = "authentication"
75
+ PAYMENT_REQUIRED = "payment_required"
76
+ CONTENT_REJECTED = "content_rejected"
77
+ OUTPUT_INVALID = "output_invalid"
78
+ CANCELLED = "cancelled"
79
+ UNKNOWN = "unknown"
80
+
81
+
82
+ class StructuredStreamProgressKind(str, Enum):
83
+ """Closed, content-free model-stream lifecycle events.
84
+
85
+ The part and output-selection values project provider-framework events.
86
+ ``STREAM_COMPLETED`` is different: the adapter emits it locally only after
87
+ the supervised agent call has returned a typed result. No text,
88
+ reasoning, tool arguments, or candidate data may cross this boundary.
89
+ """
90
+
91
+ PART_STARTED = "part_started"
92
+ PART_DELTA = "part_delta"
93
+ PART_ENDED = "part_ended"
94
+ OUTPUT_SELECTED = "output_selected"
95
+ STREAM_COMPLETED = "stream_completed"
96
+
97
+
98
+ class StructuredStreamChannel(str, Enum):
99
+ """Closed stream channel classification safe for experiment journals."""
100
+
101
+ TEXT = "text"
102
+ THINKING = "thinking"
103
+ TOOL_CALL = "tool_call"
104
+ OTHER = "other"
105
+
106
+
107
+ StructuredStreamTimeoutPhase = StreamTimeoutPhase
108
+
109
+
110
+ @dataclass(frozen=True, slots=True)
111
+ class StructuredStreamCleanupPolicy:
112
+ """Bounded cleanup/retirement policy after a liveness deadline expires.
113
+
114
+ This is not a healthy-generation deadline. It begins only after first-event,
115
+ idle, absolute, or caller cancellation has already terminated the attempt.
116
+ """
117
+
118
+ cancel_drain_timeout_ns: int = DEFAULT_STREAM_CANCEL_DRAIN_TIMEOUT_NS
119
+ transport_retire_timeout_ns: int = (
120
+ DEFAULT_STREAM_TRANSPORT_RETIRE_TIMEOUT_NS
121
+ )
122
+ policy_id: str = STREAM_CLEANUP_POLICY_ID
123
+ policy_version: int = STREAM_CLEANUP_POLICY_VERSION
124
+ definition_sha256: str = STREAM_CLEANUP_POLICY_DEFINITION_SHA256
125
+
126
+ def __post_init__(self) -> None:
127
+ for name in ("cancel_drain_timeout_ns", "transport_retire_timeout_ns"):
128
+ value = getattr(self, name)
129
+ if type(value) is not int or value <= 0:
130
+ raise ValueError(f"{name} must be a positive exact integer")
131
+ if type(self.policy_id) is not str or _OPERATION_TOKEN.fullmatch(
132
+ self.policy_id
133
+ ) is None:
134
+ raise ValueError("policy_id must use the closed token grammar")
135
+ if type(self.policy_version) is not int or self.policy_version <= 0:
136
+ raise ValueError("policy_version must be a positive exact integer")
137
+ if (
138
+ type(self.definition_sha256) is not str
139
+ or _LOWER_SHA256.fullmatch(self.definition_sha256) is None
140
+ ):
141
+ raise ValueError("definition_sha256 must be lowercase SHA-256")
142
+
143
+ @property
144
+ def configuration_sha256(self) -> str:
145
+ self.__post_init__()
146
+ payload = json.dumps(
147
+ {
148
+ "cancel_drain_timeout_ns": self.cancel_drain_timeout_ns,
149
+ "definition_sha256": self.definition_sha256,
150
+ "policy_id": self.policy_id,
151
+ "policy_version": self.policy_version,
152
+ "transport_retire_timeout_ns": self.transport_retire_timeout_ns,
153
+ },
154
+ allow_nan=False,
155
+ ensure_ascii=True,
156
+ separators=(",", ":"),
157
+ sort_keys=True,
158
+ ).encode("ascii")
159
+ return hashlib.sha256(
160
+ _STREAM_CLEANUP_CONFIGURATION_DOMAIN + payload
161
+ ).hexdigest()
162
+
163
+ def to_manifest_record(self) -> dict[str, object]:
164
+ self.__post_init__()
165
+ return {
166
+ "policy_id": self.policy_id,
167
+ "policy_version": self.policy_version,
168
+ "definition_sha256": self.definition_sha256,
169
+ "configuration_sha256": self.configuration_sha256,
170
+ "cancel_drain_timeout_ns": self.cancel_drain_timeout_ns,
171
+ "transport_retire_timeout_ns": self.transport_retire_timeout_ns,
172
+ }
173
+
174
+
175
+ @dataclass(frozen=True, slots=True)
176
+ class StructuredStreamLivenessPolicy:
177
+ """Content-blind liveness policy for one streamed provider attempt.
178
+
179
+ ``first_event_timeout_ns`` bounds an attempt that never starts producing
180
+ model-stream events. ``idle_timeout_ns`` is reset by every meaningful
181
+ event. ``absolute_timeout_ns`` is an optional operational fail-safe; it is
182
+ intentionally ``None`` by default so a healthy, progressing generation is
183
+ not truncated merely because it is long. ``cleanup_policy`` starts only
184
+ after one of those liveness boundaries (or caller cancellation) has fired.
185
+ """
186
+
187
+ first_event_timeout_ns: int
188
+ idle_timeout_ns: int
189
+ absolute_timeout_ns: int | None = None
190
+ cleanup_policy: StructuredStreamCleanupPolicy = field(
191
+ default_factory=StructuredStreamCleanupPolicy
192
+ )
193
+
194
+ def __post_init__(self) -> None:
195
+ for name in ("first_event_timeout_ns", "idle_timeout_ns"):
196
+ value = getattr(self, name)
197
+ if type(value) is not int or value <= 0:
198
+ raise ValueError(f"{name} must be a positive exact integer")
199
+ if self.absolute_timeout_ns is not None and (
200
+ type(self.absolute_timeout_ns) is not int
201
+ or self.absolute_timeout_ns <= 0
202
+ ):
203
+ raise ValueError(
204
+ "absolute_timeout_ns must be a positive exact integer or None"
205
+ )
206
+ if type(self.cleanup_policy) is not StructuredStreamCleanupPolicy:
207
+ raise TypeError(
208
+ "cleanup_policy must be an exact StructuredStreamCleanupPolicy"
209
+ )
210
+ self.cleanup_policy.__post_init__()
211
+
212
+
213
+ @dataclass(frozen=True, slots=True)
214
+ class StructuredStreamProgress:
215
+ """One content-free, monotonically sequenced stream observation.
216
+
217
+ The byte counters and rolling digest authenticate the adapter's exact
218
+ semantic UTF-8 fragments without retaining those fragments. They are not
219
+ transport/SSE byte counts. Lifecycle events legitimately carry a zero
220
+ delta and repeat the preceding rolling digest.
221
+ """
222
+
223
+ call_id: str
224
+ sequence: int
225
+ kind: StructuredStreamProgressKind
226
+ channel: StructuredStreamChannel
227
+ elapsed_ns: int
228
+ event_content_utf8_bytes: int
229
+ cumulative_content_utf8_bytes: int
230
+ rolling_content_sha256: str
231
+ provider_attempt_id: str | None = None
232
+
233
+ def __post_init__(self) -> None:
234
+ LLMCallId(self.call_id)
235
+ if type(self.sequence) is not int or self.sequence <= 0:
236
+ raise ValueError("sequence must be a positive exact integer")
237
+ if type(self.kind) is not StructuredStreamProgressKind:
238
+ raise TypeError("kind must be a StructuredStreamProgressKind")
239
+ if type(self.channel) is not StructuredStreamChannel:
240
+ raise TypeError("channel must be a StructuredStreamChannel")
241
+ if type(self.elapsed_ns) is not int or self.elapsed_ns < 0:
242
+ raise ValueError("elapsed_ns must be a non-negative exact integer")
243
+ if (
244
+ type(self.event_content_utf8_bytes) is not int
245
+ or self.event_content_utf8_bytes < 0
246
+ ):
247
+ raise ValueError(
248
+ "event_content_utf8_bytes must be a non-negative exact integer"
249
+ )
250
+ if self.kind in {
251
+ StructuredStreamProgressKind.OUTPUT_SELECTED,
252
+ StructuredStreamProgressKind.STREAM_COMPLETED,
253
+ } and (
254
+ self.channel is not StructuredStreamChannel.OTHER
255
+ or self.event_content_utf8_bytes != 0
256
+ ):
257
+ raise ValueError(
258
+ "output selection and stream completion are content-free other events"
259
+ )
260
+ if (
261
+ type(self.cumulative_content_utf8_bytes) is not int
262
+ or self.cumulative_content_utf8_bytes < self.event_content_utf8_bytes
263
+ ):
264
+ raise ValueError(
265
+ "cumulative_content_utf8_bytes must include the event byte count"
266
+ )
267
+ if (
268
+ type(self.rolling_content_sha256) is not str
269
+ or _LOWER_SHA256.fullmatch(self.rolling_content_sha256) is None
270
+ ):
271
+ raise ValueError(
272
+ "rolling_content_sha256 must be a lowercase SHA-256 digest"
273
+ )
274
+ if self.provider_attempt_id is not None:
275
+ ProviderAttemptId(self.provider_attempt_id)
276
+
277
+
278
+ StructuredStreamProgressSink = Callable[[StructuredStreamProgress], None]
279
+
280
+
281
+ class StructuredGenerationError(RuntimeError):
282
+ """A sanitized one-attempt failure safe to retain in experiment traces."""
283
+
284
+ def __init__(
285
+ self,
286
+ *,
287
+ kind: GenerationFailureKind,
288
+ retryable: bool,
289
+ safe_message: str,
290
+ status_code: int | None = None,
291
+ retry_after_seconds: float | None = None,
292
+ output_failure_mode: StructuredOutputFailureMode | None = None,
293
+ validation_issues: tuple[SanitizedValidationIssue, ...] = (),
294
+ provider_error_code: CanonicalProviderErrorCode | None = None,
295
+ provider_error_envelope_sha256: str | None = None,
296
+ exception_provenance: SanitizedExceptionProvenance | None = None,
297
+ ) -> None:
298
+ if type(kind) is not GenerationFailureKind:
299
+ raise TypeError("kind must be a GenerationFailureKind")
300
+ if type(retryable) is not bool:
301
+ raise TypeError("retryable must be bool")
302
+ if type(safe_message) is not str or not safe_message.strip():
303
+ raise ValueError("safe_message must be non-empty")
304
+ if len(safe_message.encode("utf-8", errors="strict")) > 512:
305
+ raise ValueError("safe_message is too large for inline telemetry")
306
+ if status_code is not None and (
307
+ type(status_code) is not int or not 100 <= status_code <= 599
308
+ ):
309
+ raise ValueError("status_code must be an HTTP status or None")
310
+ if retry_after_seconds is not None and (
311
+ isinstance(retry_after_seconds, bool)
312
+ or not isinstance(retry_after_seconds, (int, float))
313
+ or not math.isfinite(float(retry_after_seconds))
314
+ or float(retry_after_seconds) < 0
315
+ ):
316
+ raise ValueError("retry_after_seconds must be finite and non-negative")
317
+ if (
318
+ output_failure_mode is not None
319
+ and type(output_failure_mode) is not StructuredOutputFailureMode
320
+ ):
321
+ raise TypeError(
322
+ "output_failure_mode must be a StructuredOutputFailureMode or None"
323
+ )
324
+ if (
325
+ output_failure_mode is not None
326
+ and kind is not GenerationFailureKind.OUTPUT_INVALID
327
+ ):
328
+ raise ValueError(
329
+ "only output_invalid failures may carry output diagnostics"
330
+ )
331
+ if type(validation_issues) is not tuple:
332
+ raise TypeError("validation_issues must be an exact tuple")
333
+ if len(validation_issues) > MAX_VALIDATION_ISSUES:
334
+ raise ValueError(
335
+ f"validation_issues cannot exceed {MAX_VALIDATION_ISSUES} entries"
336
+ )
337
+ if any(
338
+ type(issue) is not SanitizedValidationIssue for issue in validation_issues
339
+ ):
340
+ raise TypeError(
341
+ "validation_issues must contain exact SanitizedValidationIssue values"
342
+ )
343
+ if output_failure_mode is None and validation_issues:
344
+ raise ValueError("validation issues require an output failure mode")
345
+ if (
346
+ validation_issues
347
+ and output_failure_mode is not StructuredOutputFailureMode.SCHEMA_VALIDATION
348
+ ):
349
+ raise ValueError("validation issues require schema_validation mode")
350
+ if provider_error_code is not None and (
351
+ type(provider_error_code) is not CanonicalProviderErrorCode
352
+ ):
353
+ raise TypeError(
354
+ "provider_error_code must be a CanonicalProviderErrorCode or None"
355
+ )
356
+ if provider_error_envelope_sha256 is not None and (
357
+ type(provider_error_envelope_sha256) is not str
358
+ or _LOWER_SHA256.fullmatch(provider_error_envelope_sha256) is None
359
+ ):
360
+ raise ValueError(
361
+ "provider_error_envelope_sha256 must be lowercase SHA-256 or None"
362
+ )
363
+ if (
364
+ provider_error_code is not None
365
+ or provider_error_envelope_sha256 is not None
366
+ ) and status_code is None:
367
+ raise ValueError("provider HTTP diagnostics require status_code")
368
+ if exception_provenance is not None and (
369
+ type(exception_provenance) is not SanitizedExceptionProvenance
370
+ ):
371
+ raise TypeError(
372
+ "exception_provenance must be SanitizedExceptionProvenance or None"
373
+ )
374
+ if exception_provenance is not None:
375
+ SanitizedExceptionProvenance.__post_init__(exception_provenance)
376
+ if kind is not GenerationFailureKind.UNKNOWN:
377
+ raise ValueError(
378
+ "exception provenance is retained only for unknown failures"
379
+ )
380
+ super().__init__(safe_message)
381
+ self.kind = kind
382
+ self.retryable = retryable
383
+ self.safe_message = safe_message
384
+ self.status_code = status_code
385
+ self.retry_after_seconds = (
386
+ None if retry_after_seconds is None else float(retry_after_seconds)
387
+ )
388
+ self.output_failure_mode = output_failure_mode
389
+ self.validation_issues = validation_issues
390
+ self.provider_error_code = provider_error_code
391
+ self.provider_error_envelope_sha256 = provider_error_envelope_sha256
392
+ self.exception_provenance = exception_provenance
393
+
394
+ @property
395
+ def generation_failure_disposition(self) -> GenerationFailureDisposition:
396
+ if self.kind in {
397
+ GenerationFailureKind.OUTPUT_INVALID,
398
+ GenerationFailureKind.CONTENT_REJECTED,
399
+ }:
400
+ return GenerationFailureDisposition.MODEL_OR_SCHEMA_FAILURE
401
+ return GenerationFailureDisposition.INFRASTRUCTURE_FAILURE
402
+
403
+
404
+ class StructuredStreamTimeoutError(StructuredGenerationError, TimeoutError):
405
+ """A content-blind stream liveness boundary expired before completion."""
406
+
407
+ def __init__(self, phase: StructuredStreamTimeoutPhase) -> None:
408
+ if type(phase) is not StructuredStreamTimeoutPhase:
409
+ raise TypeError("phase must be a StructuredStreamTimeoutPhase")
410
+ messages = {
411
+ StructuredStreamTimeoutPhase.FIRST_EVENT: (
412
+ "provider stream produced no first event before its liveness deadline"
413
+ ),
414
+ StructuredStreamTimeoutPhase.IDLE: (
415
+ "provider stream stopped producing progress before completion"
416
+ ),
417
+ StructuredStreamTimeoutPhase.ABSOLUTE: (
418
+ "provider stream exceeded its absolute operational fail-safe"
419
+ ),
420
+ }
421
+ super().__init__(
422
+ kind=GenerationFailureKind.TIMEOUT,
423
+ retryable=True,
424
+ safe_message=messages[phase],
425
+ )
426
+ self.phase = phase
427
+
428
+
429
+ class StructuredStreamCleanupTimeoutError(StructuredGenerationError, TimeoutError):
430
+ """Cancellation did not settle; the attempt and transport are retired.
431
+
432
+ Unlike an ordinary liveness timeout this failure is terminal. Retrying could
433
+ overlap the still-running provider attempt whose cancellation was resisted.
434
+ """
435
+
436
+ def __init__(self, phase: StructuredStreamTimeoutPhase) -> None:
437
+ if type(phase) is not StructuredStreamTimeoutPhase:
438
+ raise TypeError("phase must be a StructuredStreamTimeoutPhase")
439
+ super().__init__(
440
+ kind=GenerationFailureKind.TIMEOUT,
441
+ retryable=False,
442
+ safe_message=(
443
+ "provider stream resisted bounded cancellation; its transport "
444
+ "was retired and retry is forbidden"
445
+ ),
446
+ )
447
+ self.phase = phase
448
+
449
+
450
+ class StructuredStreamRetiredError(StructuredGenerationError):
451
+ """A supervisor/transport retired after an abandoned provider attempt."""
452
+
453
+ def __init__(self) -> None:
454
+ super().__init__(
455
+ kind=GenerationFailureKind.CANCELLED,
456
+ retryable=False,
457
+ safe_message=(
458
+ "provider stream supervisor is retired after incomplete cleanup"
459
+ ),
460
+ )
461
+
462
+
463
+ @dataclass(frozen=True, slots=True)
464
+ class StructuredPromptLineage:
465
+ """Content-free commitment joining a semantic prompt to its wire renderer."""
466
+
467
+ semantic_prompt_sha256: str
468
+ renderer_id: str
469
+ renderer_revision: str
470
+ renderer_definition_sha256: str
471
+
472
+ def __post_init__(self) -> None:
473
+ for name in ("semantic_prompt_sha256", "renderer_definition_sha256"):
474
+ value = getattr(self, name)
475
+ if type(value) is not str or _LOWER_SHA256.fullmatch(value) is None:
476
+ raise ValueError(f"{name} must be a lowercase SHA-256 digest")
477
+ for name in ("renderer_id", "renderer_revision"):
478
+ value = getattr(self, name)
479
+ if type(value) is not str or _OPERATION_TOKEN.fullmatch(value) is None:
480
+ raise ValueError(
481
+ f"{name} must use the closed lowercase token grammar"
482
+ )
483
+
484
+
485
+ def identity_prompt_lineage(prompt: str) -> StructuredPromptLineage:
486
+ """Commit an exact prompt to the generic byte-identity renderer."""
487
+
488
+ if type(prompt) is not str or not prompt.strip():
489
+ raise ValueError("prompt must be a non-empty exact string")
490
+ prompt_bytes = prompt.encode("utf-8", errors="strict")
491
+ if len(prompt_bytes) > MAX_PROMPT_UTF8_BYTES:
492
+ raise ValueError("prompt exceeds MAX_PROMPT_UTF8_BYTES")
493
+ return StructuredPromptLineage(
494
+ semantic_prompt_sha256=hashlib.sha256(prompt_bytes).hexdigest(),
495
+ renderer_id=IDENTITY_PROMPT_RENDERER_ID,
496
+ renderer_revision=IDENTITY_PROMPT_RENDERER_REVISION,
497
+ renderer_definition_sha256=IDENTITY_PROMPT_RENDERER_DEFINITION_SHA256,
498
+ )
499
+
500
+
501
+ @dataclass(frozen=True, slots=True)
502
+ class StructuredOutputRepairLiteralSet:
503
+ """Provider-visible closed literals for a bounded structured-output repair.
504
+
505
+ This is a generic output-contract hint, not workload advice. A caller may
506
+ expose values that were already visible in the original provider request so
507
+ a retry can restate a large local closed set without weakening exact local
508
+ validation. No free-form text is accepted at this boundary.
509
+ """
510
+
511
+ field_path: tuple[str, ...]
512
+ allowed_literals: tuple[str, ...]
513
+
514
+ def __post_init__(self) -> None:
515
+ if type(self.field_path) is not tuple or not 1 <= len(self.field_path) <= 8:
516
+ raise ValueError("field_path must contain between one and eight segments")
517
+ if any(
518
+ type(segment) is not str
519
+ or _REPAIR_PATH_TOKEN.fullmatch(segment) is None
520
+ for segment in self.field_path
521
+ ):
522
+ raise ValueError("field_path segments violate the closed repair grammar")
523
+ if type(self.allowed_literals) is not tuple or not (
524
+ 1 <= len(self.allowed_literals) <= MAX_STRUCTURED_REPAIR_LITERALS
525
+ ):
526
+ raise ValueError(
527
+ "allowed_literals must be a non-empty bounded exact tuple"
528
+ )
529
+ if len(set(self.allowed_literals)) != len(self.allowed_literals):
530
+ raise ValueError("allowed_literals must be distinct")
531
+ for literal in self.allowed_literals:
532
+ if type(literal) is not str or not literal:
533
+ raise ValueError("allowed_literals must contain non-empty strings")
534
+ if (
535
+ len(literal.encode("utf-8", errors="strict"))
536
+ > MAX_STRUCTURED_REPAIR_LITERAL_UTF8_BYTES
537
+ ):
538
+ raise ValueError("one repair literal exceeds its UTF-8 byte bound")
539
+
540
+ def to_record(self) -> dict[str, object]:
541
+ self.__post_init__()
542
+ return {
543
+ "field_path": list(self.field_path),
544
+ "allowed_literals": list(self.allowed_literals),
545
+ }
546
+
547
+
548
+ @dataclass(frozen=True, slots=True)
549
+ class StructuredGenerationRequest(Generic[OutputT]):
550
+ """Complete application request for one typed logical LLM call."""
551
+
552
+ call_id: LLMCallId
553
+ operation: str
554
+ prompt: str
555
+ output_type: type[OutputT]
556
+ output_tool_name: str
557
+ max_output_tokens: int = 2_048
558
+ temperature: float | None = None
559
+ provider_attempt_id: ProviderAttemptId | None = None
560
+ prompt_lineage: StructuredPromptLineage | None = None
561
+ repair_literal_sets: tuple[StructuredOutputRepairLiteralSet, ...] = ()
562
+
563
+ def __post_init__(self) -> None:
564
+ if type(self.call_id) is not LLMCallId:
565
+ raise TypeError("call_id must be an exact LLMCallId")
566
+ LLMCallId.__post_init__(self.call_id)
567
+ if (
568
+ type(self.operation) is not str
569
+ or _OPERATION_TOKEN.fullmatch(self.operation) is None
570
+ ):
571
+ raise ValueError("operation must use the closed lowercase token grammar")
572
+ if type(self.prompt) is not str or not self.prompt.strip():
573
+ raise ValueError("prompt must be a non-empty exact string")
574
+ if len(self.prompt.encode("utf-8", errors="strict")) > MAX_PROMPT_UTF8_BYTES:
575
+ raise ValueError("prompt exceeds MAX_PROMPT_UTF8_BYTES")
576
+ if not isinstance(self.output_type, type):
577
+ raise TypeError("output_type must be a runtime type")
578
+ if (
579
+ type(self.output_tool_name) is not str
580
+ or _TOOL_TOKEN.fullmatch(self.output_tool_name) is None
581
+ ):
582
+ raise ValueError("output_tool_name must use the closed tool token grammar")
583
+ if (
584
+ type(self.max_output_tokens) is not int
585
+ or not 1 <= self.max_output_tokens <= MAX_OUTPUT_TOKENS
586
+ ):
587
+ raise ValueError(f"max_output_tokens must lie in [1, {MAX_OUTPUT_TOKENS}]")
588
+ if self.temperature is not None and (
589
+ isinstance(self.temperature, bool)
590
+ or not isinstance(self.temperature, (int, float))
591
+ or not math.isfinite(float(self.temperature))
592
+ or not 0 <= float(self.temperature) <= 2
593
+ ):
594
+ raise ValueError("temperature must be finite in [0,2] or None")
595
+ if self.provider_attempt_id is not None and (
596
+ type(self.provider_attempt_id) is not ProviderAttemptId
597
+ ):
598
+ raise TypeError(
599
+ "provider_attempt_id must be a ProviderAttemptId or None"
600
+ )
601
+ if self.prompt_lineage is not None:
602
+ if type(self.prompt_lineage) is not StructuredPromptLineage:
603
+ raise TypeError(
604
+ "prompt_lineage must be an exact StructuredPromptLineage or None"
605
+ )
606
+ StructuredPromptLineage.__post_init__(self.prompt_lineage)
607
+ if self.prompt_lineage.renderer_id == IDENTITY_PROMPT_RENDERER_ID:
608
+ expected_semantic_sha256 = hashlib.sha256(
609
+ self.prompt.encode("utf-8", errors="strict")
610
+ ).hexdigest()
611
+ if (
612
+ self.prompt_lineage.renderer_revision
613
+ != IDENTITY_PROMPT_RENDERER_REVISION
614
+ or self.prompt_lineage.renderer_definition_sha256
615
+ != IDENTITY_PROMPT_RENDERER_DEFINITION_SHA256
616
+ or self.prompt_lineage.semantic_prompt_sha256
617
+ != expected_semantic_sha256
618
+ ):
619
+ raise ValueError(
620
+ "identity prompt lineage does not authenticate the exact "
621
+ "wire prompt"
622
+ )
623
+ if type(self.repair_literal_sets) is not tuple or len(
624
+ self.repair_literal_sets
625
+ ) > MAX_STRUCTURED_REPAIR_LITERAL_SETS:
626
+ raise ValueError("repair_literal_sets must be a bounded exact tuple")
627
+ if any(
628
+ type(item) is not StructuredOutputRepairLiteralSet
629
+ for item in self.repair_literal_sets
630
+ ):
631
+ raise TypeError(
632
+ "repair_literal_sets must contain exact "
633
+ "StructuredOutputRepairLiteralSet values"
634
+ )
635
+ for item in self.repair_literal_sets:
636
+ item.__post_init__()
637
+ paths = tuple(item.field_path for item in self.repair_literal_sets)
638
+ if len(set(paths)) != len(paths):
639
+ raise ValueError("repair_literal_sets cannot repeat a field path")
640
+ repair_context_bytes = json.dumps(
641
+ [item.to_record() for item in self.repair_literal_sets],
642
+ allow_nan=False,
643
+ ensure_ascii=True,
644
+ separators=(",", ":"),
645
+ sort_keys=True,
646
+ ).encode("ascii")
647
+ if len(repair_context_bytes) > MAX_STRUCTURED_REPAIR_CONTEXT_UTF8_BYTES:
648
+ raise ValueError("repair_literal_sets exceed the aggregate byte bound")
649
+
650
+
651
+ @dataclass(frozen=True, slots=True)
652
+ class StructuredGenerationResponse(Generic[OutputT]):
653
+ """Typed output plus the telemetry available from exactly one attempt."""
654
+
655
+ value: OutputT
656
+ requested_model: str
657
+ resolved_model: str
658
+ resolved_provider: str
659
+ provider_response_id: str | None
660
+ finish_reason: str | None
661
+ input_tokens: int
662
+ output_tokens: int
663
+ reasoning_tokens: int
664
+ cache_read_tokens: int
665
+ cache_write_tokens: int
666
+ cost_usd: Decimal | None
667
+ latency_ns: int
668
+
669
+ def __post_init__(self) -> None:
670
+ for name in ("requested_model", "resolved_model", "resolved_provider"):
671
+ value = getattr(self, name)
672
+ if type(value) is not str or not value.strip():
673
+ raise ValueError(f"{name} must be a non-empty exact string")
674
+ for name in ("provider_response_id", "finish_reason"):
675
+ value = getattr(self, name)
676
+ if value is not None and (type(value) is not str or not value.strip()):
677
+ raise ValueError(f"{name} must be a non-empty exact string or None")
678
+ for name in (
679
+ "input_tokens",
680
+ "output_tokens",
681
+ "reasoning_tokens",
682
+ "cache_read_tokens",
683
+ "cache_write_tokens",
684
+ "latency_ns",
685
+ ):
686
+ value = getattr(self, name)
687
+ if type(value) is not int or value < 0:
688
+ raise ValueError(f"{name} must be a non-negative exact integer")
689
+ if self.cost_usd is not None and (
690
+ type(self.cost_usd) is not Decimal
691
+ or not self.cost_usd.is_finite()
692
+ or self.cost_usd < 0
693
+ ):
694
+ raise ValueError("cost_usd must be a finite non-negative Decimal or None")
695
+
696
+
697
+ @runtime_checkable
698
+ class StructuredGenerator(Protocol):
699
+ """Execute one provider attempt; an outer scheduler owns all retries."""
700
+
701
+ async def generate_once(
702
+ self, request: StructuredGenerationRequest[OutputT]
703
+ ) -> StructuredGenerationResponse[OutputT]: ...
704
+
705
+
706
+ __all__ = [
707
+ "DEFAULT_STREAM_CANCEL_DRAIN_TIMEOUT_NS",
708
+ "DEFAULT_STREAM_TRANSPORT_RETIRE_TIMEOUT_NS",
709
+ "GenerationFailureKind",
710
+ "IDENTITY_PROMPT_RENDERER_DEFINITION_SHA256",
711
+ "IDENTITY_PROMPT_RENDERER_ID",
712
+ "IDENTITY_PROMPT_RENDERER_REVISION",
713
+ "MAX_OUTPUT_TOKENS",
714
+ "MAX_PROMPT_UTF8_BYTES",
715
+ "STREAM_CLEANUP_POLICY_DEFINITION_SHA256",
716
+ "STREAM_CLEANUP_POLICY_ID",
717
+ "STREAM_CLEANUP_POLICY_VERSION",
718
+ "StructuredGenerationError",
719
+ "StructuredGenerationRequest",
720
+ "StructuredGenerationResponse",
721
+ "StructuredGenerator",
722
+ "StructuredPromptLineage",
723
+ "StructuredStreamChannel",
724
+ "StructuredStreamCleanupPolicy",
725
+ "StructuredStreamCleanupTimeoutError",
726
+ "StructuredStreamLivenessPolicy",
727
+ "StructuredStreamProgress",
728
+ "StructuredStreamProgressKind",
729
+ "StructuredStreamProgressSink",
730
+ "StructuredStreamRetiredError",
731
+ "StructuredStreamTimeoutError",
732
+ "StructuredStreamTimeoutPhase",
733
+ "identity_prompt_lineage",
734
+ ]