agentbyte 0.44.0__tar.gz → 0.45.0__tar.gz

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 (376) hide show
  1. {agentbyte-0.44.0 → agentbyte-0.45.0}/.gitignore +3 -0
  2. {agentbyte-0.44.0 → agentbyte-0.45.0}/CHANGELOG.md +42 -0
  3. {agentbyte-0.44.0 → agentbyte-0.45.0}/PKG-INFO +2 -2
  4. {agentbyte-0.44.0 → agentbyte-0.45.0}/README.md +1 -1
  5. agentbyte-0.45.0/src/agentbyte/__about__.py +2 -0
  6. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/agents/agent.py +2 -2
  7. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/cli/main.py +6 -0
  8. agentbyte-0.45.0/src/agentbyte/cli/optim_commands.py +160 -0
  9. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/history/__init__.py +4 -0
  10. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/history/conformance.py +39 -4
  11. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/history/models.py +71 -0
  12. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/history/sql.py +52 -7
  13. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/history/sqlite.py +47 -7
  14. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/history/store.py +52 -1
  15. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/smoke.py +2 -2
  16. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/execution_trace/__init__.py +2 -1
  17. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/execution_trace/collector.py +17 -17
  18. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/execution_trace/models.py +23 -0
  19. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/optim/__init__.py +18 -0
  20. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/optim/base.py +20 -1
  21. agentbyte-0.45.0/src/agentbyte/optim/report.py +462 -0
  22. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/orchestration/base.py +2 -2
  23. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/agent.py +2 -2
  24. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/core/runner.py +2 -2
  25. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/agent.py +2 -1
  26. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/step.py +2 -2
  27. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_eval_history_backends.py +62 -0
  28. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_eval_workbench.py +24 -1
  29. agentbyte-0.45.0/tests/optim/test_report.py +263 -0
  30. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/test_option_enums.py +19 -1
  31. agentbyte-0.44.0/src/agentbyte/__about__.py +0 -2
  32. {agentbyte-0.44.0 → agentbyte-0.45.0}/LICENSE +0 -0
  33. {agentbyte-0.44.0 → agentbyte-0.45.0}/pyproject.toml +0 -0
  34. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/__init__.py +0 -0
  35. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/_optional.py +0 -0
  36. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/agents/__init__.py +0 -0
  37. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/agents/agent_as_tool.py +0 -0
  38. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/agents/base.py +0 -0
  39. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/agents/embedding_agent.py +0 -0
  40. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/agents/types.py +0 -0
  41. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/cancellation_token.py +0 -0
  42. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/catalog.py +0 -0
  43. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/cli/__init__.py +0 -0
  44. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/cli/__main__.py +0 -0
  45. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/cli/eval_commands.py +0 -0
  46. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/cli/loading.py +0 -0
  47. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/compaction/__init__.py +0 -0
  48. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/compaction/counters.py +0 -0
  49. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/compaction/errors.py +0 -0
  50. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/compaction/grouping.py +0 -0
  51. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/compaction/strategies.py +0 -0
  52. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/component.py +0 -0
  53. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/context.py +0 -0
  54. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/context_providers/__init__.py +0 -0
  55. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/context_providers/base.py +0 -0
  56. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/context_providers/skill_tools.py +0 -0
  57. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/context_providers/skills.py +0 -0
  58. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/__init__.py +0 -0
  59. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/_aiosqlite.py +0 -0
  60. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/base.py +0 -0
  61. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/config.py +0 -0
  62. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/importer.py +0 -0
  63. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/json.py +0 -0
  64. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/loader.py +0 -0
  65. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/publish.py +0 -0
  66. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/publish_config.py +0 -0
  67. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/publishers.py +0 -0
  68. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/s3.py +0 -0
  69. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/sources.py +0 -0
  70. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/sqlite.py +0 -0
  71. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/sqlite_db.py +0 -0
  72. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/write_config.py +0 -0
  73. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/dataset/writers.py +0 -0
  74. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/entity.py +0 -0
  75. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/__init__.py +0 -0
  76. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/base.py +0 -0
  77. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/checks/__init__.py +0 -0
  78. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/checks/decorator.py +0 -0
  79. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/checks/keyword.py +0 -0
  80. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/checks/local.py +0 -0
  81. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/checks/process.py +0 -0
  82. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/checks/tool.py +0 -0
  83. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/checks/types.py +0 -0
  84. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/comparison.py +0 -0
  85. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/eval_dataset.py +0 -0
  86. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/history/errors.py +0 -0
  87. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/history/recorder.py +0 -0
  88. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/history/transitions.py +0 -0
  89. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/judges/__init__.py +0 -0
  90. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/judges/base.py +0 -0
  91. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/judges/composite.py +0 -0
  92. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/judges/llm.py +0 -0
  93. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/judges/pairwise.py +0 -0
  94. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/judges/reference.py +0 -0
  95. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/judges/trajectory.py +0 -0
  96. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/judges/validation.py +0 -0
  97. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/pairwise.py +0 -0
  98. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/report.py +0 -0
  99. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/runner.py +0 -0
  100. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/splitting.py +0 -0
  101. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/targets/__init__.py +0 -0
  102. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/targets/agent.py +0 -0
  103. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/targets/model.py +0 -0
  104. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/targets/multi_turn.py +0 -0
  105. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/targets/orchestrator.py +0 -0
  106. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/targets/runtime.py +0 -0
  107. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/targets/workflow.py +0 -0
  108. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/types.py +0 -0
  109. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/__init__.py +0 -0
  110. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/coordinator.py +0 -0
  111. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/jobs.py +0 -0
  112. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/smoke_tasks.json +0 -0
  113. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/suite.py +0 -0
  114. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/verdict.py +0 -0
  115. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/__init__.py +0 -0
  116. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/_retry_observability.py +0 -0
  117. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/auth.py +0 -0
  118. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/azure/__init__.py +0 -0
  119. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/azure/auth.py +0 -0
  120. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/azure/chat.py +0 -0
  121. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/azure/embedding.py +0 -0
  122. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/azure/settings.py +0 -0
  123. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/azure_openai.py +0 -0
  124. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/azure_openai_embedding.py +0 -0
  125. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/base.py +0 -0
  126. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/embeddings_base.py +0 -0
  127. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/openai/__init__.py +0 -0
  128. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/openai/chat.py +0 -0
  129. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/openai/embedding.py +0 -0
  130. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/openai/settings.py +0 -0
  131. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/openai_embedding.py +0 -0
  132. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/pricing.py +0 -0
  133. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/retry_policy.py +0 -0
  134. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/settings.py +0 -0
  135. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/llm/types.py +0 -0
  136. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/logger.py +0 -0
  137. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/memory/__init__.py +0 -0
  138. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/memory/base.py +0 -0
  139. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/messages.py +0 -0
  140. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/middleware/__init__.py +0 -0
  141. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/middleware/base.py +0 -0
  142. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/middleware/otel.py +0 -0
  143. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/middleware/retry.py +0 -0
  144. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/middleware/sql_usage.py +0 -0
  145. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/middleware/usage_logger.py +0 -0
  146. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/notebook.py +0 -0
  147. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/optim/config.py +0 -0
  148. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/optim/gepa.py +0 -0
  149. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/optim/mipro.py +0 -0
  150. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/optim/pareto.py +0 -0
  151. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/optim/reflective.py +0 -0
  152. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/optim/spec.py +0 -0
  153. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/optim/trace.py +0 -0
  154. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/orchestration/__init__.py +0 -0
  155. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/orchestration/ai.py +0 -0
  156. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/orchestration/handoff.py +0 -0
  157. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/orchestration/plan.py +0 -0
  158. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/orchestration/policies.py +0 -0
  159. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/orchestration/round_robin.py +0 -0
  160. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/__init__.py +0 -0
  161. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/agents.py +0 -0
  162. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/clients.py +0 -0
  163. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/instruction_registry.py +0 -0
  164. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/instructions/orchestrator.yaml +0 -0
  165. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/instructions/query_rewriter.yaml +0 -0
  166. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/instructions/researcher.yaml +0 -0
  167. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/instructions/reviewer.yaml +0 -0
  168. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/instructions/writer.yaml +0 -0
  169. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/orchestration.py +0 -0
  170. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/skills/contracts-analyst/SKILL.md +0 -0
  171. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/skills/hr-analyst/SKILL.md +0 -0
  172. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/skills/hr-analyst/resources/departments.md +0 -0
  173. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/skills/hr-analyst/resources/employees.md +0 -0
  174. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/skills/hr-analyst/resources/payroll.md +0 -0
  175. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/streaming.py +0 -0
  176. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/presets/workflow.py +0 -0
  177. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/session_store.py +0 -0
  178. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/skills/__init__.py +0 -0
  179. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/skills/base.py +0 -0
  180. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/skills/resources.py +0 -0
  181. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/skills/scripts.py +0 -0
  182. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/skills/sources.py +0 -0
  183. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/skills/validation.py +0 -0
  184. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/__init__.py +0 -0
  185. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/base.py +0 -0
  186. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/cancellation.py +0 -0
  187. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/composite.py +0 -0
  188. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/consecutive_agent.py +0 -0
  189. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/external.py +0 -0
  190. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/function_call.py +0 -0
  191. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/handoff.py +0 -0
  192. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/max_message.py +0 -0
  193. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/predicate.py +0 -0
  194. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/source.py +0 -0
  195. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/text_mention.py +0 -0
  196. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/timeout.py +0 -0
  197. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/termination/token_usage.py +0 -0
  198. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/tools/__init__.py +0 -0
  199. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/tools/base.py +0 -0
  200. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/tools/coding_tools.py +0 -0
  201. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/tools/core_tools.py +0 -0
  202. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/tools/decorator.py +0 -0
  203. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/tools/memory_tool.py +0 -0
  204. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/tools/research_tools.py +0 -0
  205. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/types.py +0 -0
  206. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/__init__.py +0 -0
  207. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/discovery.py +0 -0
  208. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/eval_routes.py +0 -0
  209. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/execution.py +0 -0
  210. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/models.py +0 -0
  211. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/registry.py +0 -0
  212. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/server.py +0 -0
  213. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/session_store.py +0 -0
  214. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/sessions.py +0 -0
  215. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/ui/assets/index-BsS4WYZu.css +0 -0
  216. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/ui/assets/index-tGvO1yue.js +0 -0
  217. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/ui/index.html +0 -0
  218. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/webui/ui/vite.svg +0 -0
  219. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/__init__.py +0 -0
  220. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/core/__init__.py +0 -0
  221. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/core/_structure_hash.py +0 -0
  222. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/core/checkpoint.py +0 -0
  223. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/core/models.py +0 -0
  224. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/core/workflow.py +0 -0
  225. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/defaults.py +0 -0
  226. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/errors.py +0 -0
  227. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/loader.py +0 -0
  228. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/schema.py +0 -0
  229. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/schema_utils.py +0 -0
  230. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/sqlite_checkpoint.py +0 -0
  231. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/__init__.py +0 -0
  232. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/echo.py +0 -0
  233. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/function.py +0 -0
  234. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/http.py +0 -0
  235. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/subworkflow.py +0 -0
  236. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/transform.py +0 -0
  237. {agentbyte-0.44.0 → agentbyte-0.45.0}/src/agentbyte/workflow/visualizer.py +0 -0
  238. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_agent_as_tool.py +0 -0
  239. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_agent_basic.py +0 -0
  240. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_agent_context_providers.py +0 -0
  241. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_agent_error_response.py +0 -0
  242. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_agent_event_types.py +0 -0
  243. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_agent_memory_integration.py +0 -0
  244. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_agent_middleware_integration.py +0 -0
  245. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_agent_response_accessors.py +0 -0
  246. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_agent_retry_middleware.py +0 -0
  247. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_agent_stop_at_tools.py +0 -0
  248. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_agent_stream_events.py +0 -0
  249. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_embedding_agent.py +0 -0
  250. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_tool_approval.py +0 -0
  251. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_tool_batch_resolution.py +0 -0
  252. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/agents/test_tool_metadata.py +0 -0
  253. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/cli/test_loading.py +0 -0
  254. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/cli/test_registry_check.py +0 -0
  255. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/compaction/test_compaction.py +0 -0
  256. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/context_providers/__init__.py +0 -0
  257. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/context_providers/test_skill_tools.py +0 -0
  258. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/context_providers/test_skills_provider.py +0 -0
  259. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/dataset/fake_s3.py +0 -0
  260. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/dataset/test_dataset_exit.py +0 -0
  261. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/dataset/test_loader.py +0 -0
  262. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/dataset/test_multi_table.py +0 -0
  263. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/dataset/test_publish.py +0 -0
  264. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/dataset/test_sqlite_db.py +0 -0
  265. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_eval_dataset.py +0 -0
  266. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_eval_history.py +0 -0
  267. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_eval_jobs.py +0 -0
  268. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_execution_trajectories.py +0 -0
  269. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_multi_turn.py +0 -0
  270. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_pairwise.py +0 -0
  271. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_phase1_runner_and_targets.py +0 -0
  272. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_phase2_checks_and_reports.py +0 -0
  273. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_score_integrity.py +0 -0
  274. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_splitting.py +0 -0
  275. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/eval/test_types_and_judges.py +0 -0
  276. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/examples/test_compaction_webapp.py +0 -0
  277. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/llm/test_azure_client.py +0 -0
  278. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/llm/test_azure_embedding_client.py +0 -0
  279. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/llm/test_llm_types.py +0 -0
  280. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/llm/test_openai_client.py +0 -0
  281. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/llm/test_openai_embedding_client.py +0 -0
  282. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/llm/test_pricing.py +0 -0
  283. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/llm/test_retry_observability.py +0 -0
  284. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/llm/test_retry_policy_api.py +0 -0
  285. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/llm/test_retryable_error_substrings.py +0 -0
  286. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/memory/test_memory.py +0 -0
  287. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/middleware/test_context_compaction.py +0 -0
  288. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/middleware/test_deduplicate_tool_result.py +0 -0
  289. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/middleware/test_middleware_chain.py +0 -0
  290. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/middleware/test_otel.py +0 -0
  291. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/middleware/test_retry_middleware.py +0 -0
  292. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/middleware/test_sql_usage.py +0 -0
  293. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/middleware/test_usage_logger.py +0 -0
  294. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/__init__.py +0 -0
  295. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_base.py +0 -0
  296. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_base_integration.py +0 -0
  297. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_config.py +0 -0
  298. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_description_tunable.py +0 -0
  299. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_gepa.py +0 -0
  300. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_mipro.py +0 -0
  301. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_orchestrator_optim.py +0 -0
  302. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_pareto.py +0 -0
  303. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_reflective.py +0 -0
  304. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_score_integrity.py +0 -0
  305. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_spec.py +0 -0
  306. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/optim/test_trace.py +0 -0
  307. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_ai_orchestrator.py +0 -0
  308. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_base_orchestrator.py +0 -0
  309. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_handoff_orchestrator.py +0 -0
  310. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_history_tool_call_pairing.py +0 -0
  311. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_orchestration_usage_breakdown.py +0 -0
  312. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_orchestrator_agent_contract.py +0 -0
  313. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_orchestrator_finalization.py +0 -0
  314. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_orchestrator_member_events.py +0 -0
  315. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_orchestrator_otel.py +0 -0
  316. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_orchestrator_synthesis.py +0 -0
  317. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_plan_orchestrator.py +0 -0
  318. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/orchestration/test_round_robin.py +0 -0
  319. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/presets/test_agents.py +0 -0
  320. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/presets/test_clients.py +0 -0
  321. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/presets/test_instruction_registry.py +0 -0
  322. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/presets/test_orchestration.py +0 -0
  323. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/presets/test_streaming.py +0 -0
  324. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/presets/test_workflow.py +0 -0
  325. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/skills/__init__.py +0 -0
  326. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/skills/test_base.py +0 -0
  327. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/skills/test_resources.py +0 -0
  328. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/skills/test_scripts.py +0 -0
  329. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/skills/test_sources.py +0 -0
  330. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_base.py +0 -0
  331. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_cancellation.py +0 -0
  332. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_composite.py +0 -0
  333. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_consecutive_agent.py +0 -0
  334. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_external.py +0 -0
  335. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_function_call.py +0 -0
  336. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_handoff.py +0 -0
  337. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_max_message.py +0 -0
  338. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_predicate.py +0 -0
  339. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_source.py +0 -0
  340. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_text_mention.py +0 -0
  341. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_timeout.py +0 -0
  342. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/termination/test_token_usage.py +0 -0
  343. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/test_cancellation_token.py +0 -0
  344. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/test_context.py +0 -0
  345. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/test_logger.py +0 -0
  346. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/test_messages.py +0 -0
  347. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/test_optional_extras.py +0 -0
  348. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/test_package_api.py +0 -0
  349. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/test_session_store.py +0 -0
  350. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/test_types.py +0 -0
  351. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/test_vanilla_chunker.py +0 -0
  352. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/tools/test_coding_tools.py +0 -0
  353. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/tools/test_memory_tool.py +0 -0
  354. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/tools/test_research_tools.py +0 -0
  355. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/tools/test_tools.py +0 -0
  356. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/webui/__init__.py +0 -0
  357. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/webui/helpers.py +0 -0
  358. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/webui/test_eval_routes.py +0 -0
  359. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/webui/test_execution.py +0 -0
  360. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/webui/test_package_api.py +0 -0
  361. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/webui/test_registry.py +0 -0
  362. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/webui/test_server.py +0 -0
  363. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/webui/test_sessions.py +0 -0
  364. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/webui/test_workflow_streaming.py +0 -0
  365. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/recovery_worker.py +0 -0
  366. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/test_agent_step_imports.py +0 -0
  367. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/test_checkpoint.py +0 -0
  368. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/test_subworkflow_step.py +0 -0
  369. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/test_workflow_agent.py +0 -0
  370. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/test_workflow_class.py +0 -0
  371. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/test_workflow_models.py +0 -0
  372. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/test_workflow_reliability.py +0 -0
  373. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/test_workflow_runner.py +0 -0
  374. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/test_workflow_schema.py +0 -0
  375. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/test_workflow_steps.py +0 -0
  376. {agentbyte-0.44.0 → agentbyte-0.45.0}/tests/workflow/test_workflow_visualizer.py +0 -0
@@ -72,5 +72,8 @@ data/flatfiles/*
72
72
  *.sqlite-shm
73
73
  *.writer.lock
74
74
 
75
+ # Optimization reports written by notebooks (report.md, report.json, trace.json)
76
+ optim-reports/
77
+
75
78
  # marimo local session cache
76
79
  __marimo__/
@@ -6,6 +6,48 @@ The format follows Keep a Changelog principles and semantic versioning.
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [0.45.0] - 2026-10-05
10
+
11
+ ### Added
12
+
13
+ - Optimization report (spec 0068): `result.report(title=..., pass_score=...)` /
14
+ `agentbyte.optim.build_report(trace)` return an `OptimizationReport` — summary, proposed changes
15
+ (seed vs best text per tuned component), per-task outcomes (`TaskStatus`: fixed, regressed,
16
+ still_failing, passing), remaining failures with the judge's reasoning, every reflector diagnosis
17
+ and edit with its outcome, candidates and cost. `to_markdown()` is written for a reviewer or AI
18
+ coding agent; `save(dir)` writes `report.md`, `report.json` and `trace.json`. Built from the trace
19
+ alone, so a saved trace reproduces the same report.
20
+ - The optimization trace ends with a `result` event (best, rounds, rollouts, cost, latency).
21
+ - Optimization runs in the evaluation history: `OptimizationRunRecord` and
22
+ `save_optimization` / `list_optimizations(suite=...)` / `get_optimization` on the memory, SQLite and
23
+ SQLAlchemy stores; `record.report()` rebuilds the report. Conformance check
24
+ `optimization_runs_round_trip_per_suite`.
25
+ - CLI: `agentbyte optim report <trace.json | run-id> [--history] [--pass-score] [--format] [--out]`
26
+ and `agentbyte optim list [--suite] [--history]`.
27
+
28
+ ### Changed
29
+
30
+ - History database layout version 2 (`STORE_SCHEMA_VERSION`) adds the `optimization_runs` table.
31
+ Opening a layout-1 file as a writer migrates it; a reader on a layout-1 file asks for one writer
32
+ open first; Agentbyte 0.44 refuses a layout-2 file. Run/item records keep `SCHEMA_VERSION` 1.
33
+ The new store methods are not abstract, so stores written against the run-only contract still
34
+ instantiate (they raise `NotImplementedError` for optimization runs).
35
+
36
+ ## [0.44.1] - 2026-10-05
37
+
38
+ ### Added
39
+
40
+ - `agentbyte.execution_trace.SpanKind` (spec 0067): `StrEnum` of the framework's own span kinds
41
+ (`agent`, `invocation`, `orchestrator`, `workflow`, `workflow_agent`, `step`), used by
42
+ `trace_stream` and the collector. `ExecutionSpan.kind` stays an open `str`, so
43
+ `trace_scope(kind=...)` / `TraceCollector.start` still accept caller-defined kinds.
44
+
45
+ ### Fixed
46
+
47
+ - Flaky `test_cli_interrupt_exits_130_and_records_cancelled_run`: it sent SIGINT as soon as the run
48
+ was admitted, sometimes before the item started, so the item was recorded `not_started` instead
49
+ of `cancelled`. The test now waits (read-only history store) until the item is running.
50
+
9
51
  ## [0.44.0] - 2026-10-05
10
52
 
11
53
  ### Changed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: agentbyte
3
- Version: 0.44.0
3
+ Version: 0.45.0
4
4
  Summary: A toolkit for designing multiagent systems
5
5
  Author-email: MrDataPsycho <mr.data.psycho@gmail.com>
6
6
  License-Expression: LicenseRef-Proprietary
@@ -77,7 +77,7 @@ Description-Content-Type: text/markdown
77
77
 
78
78
  Agentbyte is an observability-first agentic AI framework for building and studying multiagent systems with a learning-first, implementation-oriented workflow.
79
79
 
80
- Current release: **0.44.0**
80
+ Current release: **0.45.0**
81
81
 
82
82
  ## Building an Agent
83
83
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  Agentbyte is an observability-first agentic AI framework for building and studying multiagent systems with a learning-first, implementation-oriented workflow.
4
4
 
5
- Current release: **0.44.0**
5
+ Current release: **0.45.0**
6
6
 
7
7
  ## Building an Agent
8
8
 
@@ -0,0 +1,2 @@
1
+ __version__ = "0.45.0"
2
+ VERSION = __version__
@@ -12,7 +12,7 @@ from typing import List, Optional, Union
12
12
 
13
13
  from agentbyte.cancellation_token import CancellationToken
14
14
  from agentbyte.context import AgentContext
15
- from agentbyte.execution_trace import trace_stream
15
+ from agentbyte.execution_trace import SpanKind, trace_stream
16
16
  from agentbyte.llm.types import ChatCompletionChunk
17
17
  from agentbyte.messages import (
18
18
  AssistantMessage,
@@ -445,7 +445,7 @@ class Agent(BaseAgent):
445
445
  )
446
446
  yield ToolApprovalEvent(source=self.name, approval_request=request)
447
447
 
448
- @trace_stream("agent")
448
+ @trace_stream(SpanKind.AGENT)
449
449
  async def run_stream(
450
450
  self,
451
451
  task: Optional[Union[str, UserMessage, List[Message]]] = None,
@@ -9,6 +9,7 @@ import sys
9
9
  from agentbyte.__about__ import VERSION
10
10
  from agentbyte.catalog import BaseInstructionCatalog
11
11
  from agentbyte.cli.eval_commands import add_eval_parser, cmd_eval
12
+ from agentbyte.cli.optim_commands import add_optim_parser, cmd_optim
12
13
  from agentbyte.cli.loading import ObjectImportError, import_object
13
14
 
14
15
 
@@ -302,6 +303,7 @@ def _build_parser() -> argparse.ArgumentParser:
302
303
 
303
304
  # eval
304
305
  add_eval_parser(subparsers)
306
+ add_optim_parser(subparsers)
305
307
 
306
308
  return parser
307
309
 
@@ -329,6 +331,10 @@ def main() -> None:
329
331
  if not args.eval_command:
330
332
  parser.parse_args(["eval", "--help"])
331
333
  sys.exit(cmd_eval(args))
334
+ if args.command == "optim":
335
+ if not args.optim_command:
336
+ parser.parse_args(["optim", "--help"])
337
+ sys.exit(cmd_optim(args))
332
338
 
333
339
  parser.print_help()
334
340
  sys.exit(1)
@@ -0,0 +1,160 @@
1
+ """``agentbyte optim`` sub-commands: report and list optimization runs (spec 0068).
2
+
3
+ ``report`` prints or saves the report of an optimization run, read from a saved trace file
4
+ (``trace.json``) or from a run stored in the evaluation history. ``list`` shows the stored runs,
5
+ optionally for one suite.
6
+
7
+ Exit codes: 0 = done, 2 = the source could not be read or is not an optimization run.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import argparse
13
+ import asyncio
14
+ import json
15
+ import sys
16
+ from pathlib import Path
17
+ from typing import Any
18
+
19
+ EXIT_OK = 0
20
+ EXIT_ERROR = 2
21
+
22
+ DEFAULT_HISTORY = "eval.sqlite"
23
+
24
+
25
+ class _CliError(Exception):
26
+ """A configuration or input problem reported with exit code 2."""
27
+
28
+
29
+ def add_optim_parser(subparsers: Any) -> None:
30
+ """Register ``agentbyte optim`` and its sub-commands."""
31
+ optim_parser = subparsers.add_parser("optim", help="Report optimization runs")
32
+ optim_sub = optim_parser.add_subparsers(dest="optim_command", metavar="<subcommand>")
33
+ history_help = f"SQLite evaluation history file (default: ./{DEFAULT_HISTORY})"
34
+
35
+ report_parser = optim_sub.add_parser(
36
+ "report", help="Print or save the report of an optimization run"
37
+ )
38
+ report_parser.add_argument(
39
+ "source",
40
+ help="A trace file (*.json, from report.save() or trace.save()) or a stored run ID",
41
+ )
42
+ report_parser.add_argument("--history", default=DEFAULT_HISTORY, help=history_help)
43
+ report_parser.add_argument(
44
+ "--pass-score", type=float, default=None,
45
+ help="Score a task needs to pass (default: the stored run's, else 10.0)",
46
+ )
47
+ report_parser.add_argument("--title", default=None, help="Report title")
48
+ report_parser.add_argument("--format", choices=["markdown", "json"], default="markdown")
49
+ report_parser.add_argument(
50
+ "--out", default=None,
51
+ help="Directory to write report.md, report.json and trace.json instead of printing",
52
+ )
53
+
54
+ list_parser = optim_sub.add_parser("list", help="List optimization runs in a history file")
55
+ list_parser.add_argument("--suite", default=None, help="Only runs recorded for this suite")
56
+ list_parser.add_argument("--history", default=DEFAULT_HISTORY, help=history_help)
57
+ list_parser.add_argument("--limit", type=int, default=50)
58
+ list_parser.add_argument("--format", choices=["text", "json"], default="text")
59
+
60
+
61
+ def cmd_optim(args: argparse.Namespace) -> int:
62
+ """Dispatch ``agentbyte optim <subcommand>``."""
63
+ commands = {"report": _cmd_report, "list": _cmd_list}
64
+ command = commands.get(getattr(args, "optim_command", None) or "")
65
+ if command is None:
66
+ print("Usage: agentbyte optim <report|list>", file=sys.stderr)
67
+ return EXIT_ERROR
68
+ try:
69
+ return command(args)
70
+ except _CliError as exc:
71
+ print(f"Error: {exc}", file=sys.stderr)
72
+ return EXIT_ERROR
73
+
74
+
75
+ def _cmd_report(args: argparse.Namespace) -> int:
76
+ path = Path(args.source)
77
+ if path.suffix == ".json" or path.is_file():
78
+ report = _report_from_trace(path, args)
79
+ else:
80
+ report = asyncio.run(_report_from_history(args))
81
+ return _emit(report, args)
82
+
83
+
84
+ def _report_from_trace(path: Path, args: argparse.Namespace) -> Any:
85
+ from agentbyte.optim import DEFAULT_PASS_SCORE, build_report, load_trace
86
+
87
+ if not path.is_file():
88
+ raise _CliError(f"No trace file at {path}")
89
+ try:
90
+ return build_report(
91
+ load_trace(path),
92
+ title=args.title or path.parent.name or "Optimization run",
93
+ pass_score=DEFAULT_PASS_SCORE if args.pass_score is None else args.pass_score,
94
+ )
95
+ except (ValueError, KeyError) as exc:
96
+ raise _CliError(f"{path} is not a reportable optimization trace: {exc}") from exc
97
+
98
+
99
+ async def _report_from_history(args: argparse.Namespace) -> Any:
100
+ async with _open_history(args.history) as store:
101
+ record = await store.get_optimization(args.source)
102
+ if record is None:
103
+ raise _CliError(f"No optimization run {args.source!r} in {args.history}")
104
+ updates = {k: v for k, v in (("title", args.title), ("pass_score", args.pass_score)) if v is not None}
105
+ return record.model_copy(update=updates).report()
106
+
107
+
108
+ def _cmd_list(args: argparse.Namespace) -> int:
109
+ records = asyncio.run(_list(args))
110
+ if args.format == "json":
111
+ print(json.dumps([r.model_dump(mode="json", exclude={"trace"}) for r in records], indent=2))
112
+ return EXIT_OK
113
+ if not records:
114
+ print("No optimization runs recorded" + (f" for suite {args.suite!r}." if args.suite else "."))
115
+ return EXIT_OK
116
+ for r in records:
117
+ cost = "-" if r.cost_usd is None else f"${r.cost_usd:.4f}"
118
+ print(
119
+ f"{r.id} {r.created_at:%Y-%m-%d %H:%M} {r.suite:<20} {r.optimizer or '?':<22} "
120
+ f"{_avg(r.seed_avg)} -> {_avg(r.best_avg)} best={r.best} rollouts={r.eval_count} {cost}"
121
+ )
122
+ return EXIT_OK
123
+
124
+
125
+ async def _list(args: argparse.Namespace) -> list[Any]:
126
+ async with _open_history(args.history) as store:
127
+ return await store.list_optimizations(suite=args.suite, limit=args.limit)
128
+
129
+
130
+ def _open_history(history: str) -> Any:
131
+ from agentbyte.eval.history import EvalHistoryError, SQLiteEvalRunStore
132
+
133
+ if not Path(history).is_file():
134
+ raise _CliError(f"No evaluation history at {history}")
135
+
136
+ class _Reader:
137
+ async def __aenter__(self) -> Any:
138
+ self.store = SQLiteEvalRunStore(history, writer=False)
139
+ try:
140
+ return await self.store.__aenter__()
141
+ except EvalHistoryError as exc:
142
+ raise _CliError(f"Cannot read {history}: {exc}") from exc
143
+
144
+ async def __aexit__(self, *exc: Any) -> None:
145
+ await self.store.__aexit__(*exc)
146
+
147
+ return _Reader()
148
+
149
+
150
+ def _avg(value: float | None) -> str:
151
+ return "—" if value is None else f"{value:.1f}"
152
+
153
+
154
+ def _emit(report: Any, args: argparse.Namespace) -> int:
155
+ if args.out:
156
+ out = report.save(args.out)
157
+ print(f"Wrote {out / 'report.md'}, {out / 'report.json'} and {out / 'trace.json'}")
158
+ return EXIT_OK
159
+ print(report.to_json() if args.format == "json" else report.to_markdown(), end="")
160
+ return EXIT_OK
@@ -22,11 +22,13 @@ from .errors import (
22
22
  from .models import (
23
23
  EVIDENCE_VERSION,
24
24
  SCHEMA_VERSION,
25
+ STORE_SCHEMA_VERSION,
25
26
  CaptureMode,
26
27
  EvalItemRecord,
27
28
  EvalRunRecord,
28
29
  EvidenceStatus,
29
30
  ItemState,
31
+ OptimizationRunRecord,
30
32
  Redactor,
31
33
  RunStatus,
32
34
  StructuredPayload,
@@ -50,6 +52,7 @@ def __getattr__(name: str) -> Any:
50
52
  __all__ = [
51
53
  "EVIDENCE_VERSION",
52
54
  "SCHEMA_VERSION",
55
+ "STORE_SCHEMA_VERSION",
53
56
  "CaptureMode",
54
57
  "EvalHistoryConflictError",
55
58
  "EvalHistoryError",
@@ -67,6 +70,7 @@ __all__ = [
67
70
  "EvidenceStatus",
68
71
  "ItemState",
69
72
  "MemoryEvalRunStore",
73
+ "OptimizationRunRecord",
70
74
  "Redactor",
71
75
  "RunStatus",
72
76
  "SQLiteEvalRunStore",
@@ -17,13 +17,14 @@ from __future__ import annotations
17
17
  import asyncio
18
18
  from collections.abc import Awaitable, Callable
19
19
  from contextlib import AbstractAsyncContextManager
20
+ from typing import Any
20
21
 
21
22
  from pydantic import BaseModel
22
23
 
23
24
  from agentbyte.eval.base import BaseEvalJudge, BaseEvalTarget, JudgeScoringError
24
25
  from agentbyte.eval.runner import EvalRunner
25
26
  from agentbyte.eval.types import EvalScore, EvalTask, EvalTrajectory, ScoringStatus, WorkflowEvalTask
26
- from agentbyte.execution_trace.models import ExecutionEvent, ExecutionSpan, ExecutionTrace
27
+ from agentbyte.execution_trace.models import ExecutionEvent, ExecutionSpan, ExecutionTrace, SpanKind
27
28
  from agentbyte.messages import AssistantMessage, UserMessage, Usage
28
29
 
29
30
  from .errors import (
@@ -32,7 +33,7 @@ from .errors import (
32
33
  EvalRunNotFoundError,
33
34
  EvalSerializationError,
34
35
  )
35
- from .models import EvalItemRecord, EvalRunRecord, StructuredPayload
36
+ from .models import EvalItemRecord, EvalRunRecord, OptimizationRunRecord, StructuredPayload
36
37
  from .recorder import EvalRunRecorder
37
38
  from .store import EvalRunStore
38
39
 
@@ -59,7 +60,7 @@ class _Target(BaseEvalTarget):
59
60
  await asyncio.sleep(task.metadata.get("delay", 0))
60
61
  if task.metadata.get("target_fails"):
61
62
  raise RuntimeError("target failed")
62
- span = ExecutionSpan(kind="agent", name="conformance", status="completed")
63
+ span = ExecutionSpan(kind=SpanKind.AGENT, name="conformance", status="completed")
63
64
  trace = ExecutionTrace(spans=[span], events=[ExecutionEvent(span_id=span.id, kind="step")])
64
65
  return EvalTrajectory(
65
66
  task=task,
@@ -222,7 +223,7 @@ async def check_full_evidence_round_trips_as_data(store: EvalRunStore) -> None:
222
223
  task=task,
223
224
  messages=[*turn, *turn, AssistantMessage(content="", source="a", structured_content=_Answer(city="Rome"))],
224
225
  success=True,
225
- trace=ExecutionTrace(spans=[ExecutionSpan(kind="agent", name="a")]),
226
+ trace=ExecutionTrace(spans=[ExecutionSpan(kind=SpanKind.AGENT, name="a")]),
226
227
  )
227
228
  score = EvalScore(overall=8.0, reasoning={"q": "why"}, trajectory=trajectory)
228
229
  run = await _started(store, 1)
@@ -322,6 +323,40 @@ async def check_recorder_bounds_concurrency_without_lost_writes(store: EvalRunSt
322
323
  assert [i.overall for i in items] == [float(i % 10) for i in range(16)]
323
324
 
324
325
 
326
+ def _optimization_trace(seed_avg: float, best_avg: float) -> Any:
327
+ """A minimal reportable trace: seed, one better candidate, and the closing result."""
328
+ from agentbyte.optim.trace import OptimizationTrace # optim depends on eval; import late
329
+
330
+ trace = OptimizationTrace()
331
+ trace.record("candidate", 0, name="seed", parent=None, rationale="seed", avg=seed_avg,
332
+ eligible=True, task_scores={"t": seed_avg}, components={"instructions": "old"})
333
+ trace.record("candidate", 1, name="next", parent="seed", rationale="r", avg=best_avg,
334
+ eligible=True, task_scores={"t": best_avg}, components={"instructions": "new"})
335
+ trace.record("result", 1, best="next", best_avg=best_avg, optimizer="Scripted", rounds=1,
336
+ eval_count=2, cost={"total": {"usd": 0.25}})
337
+ return trace
338
+
339
+
340
+ async def check_optimization_runs_round_trip_per_suite(store: EvalRunStore) -> None:
341
+ first = OptimizationRunRecord.from_trace(_optimization_trace(2.0, 6.0), suite="alpha")
342
+ second = OptimizationRunRecord.from_trace(_optimization_trace(3.0, 9.0), suite="beta")
343
+ third = OptimizationRunRecord.from_trace(_optimization_trace(6.0, 8.0), suite="alpha")
344
+ for record in (first, second, third):
345
+ assert await store.save_optimization(record) == record
346
+ await _raises(EvalHistoryConflictError, store.save_optimization(first))
347
+
348
+ listed = await store.list_optimizations(suite="alpha")
349
+ assert [r.id for r in listed] == [third.id, first.id]
350
+ assert all(r.trace is None for r in listed)
351
+ assert [r.id for r in await store.list_optimizations(limit=1, offset=1)] == [second.id]
352
+
353
+ loaded = await store.get_optimization(first.id)
354
+ assert loaded == first
355
+ assert (loaded.best, loaded.best_avg, loaded.cost_usd) == ("next", 6.0, 0.25)
356
+ assert loaded.report().changed_components[0].best == "new"
357
+ assert await store.get_optimization("missing") is None
358
+
359
+
325
360
  CHECKS: dict[str, Check] = {
326
361
  name.removeprefix("check_"): check
327
362
  for name, check in dict(globals()).items()
@@ -27,6 +27,9 @@ from .errors import EvalSchemaVersionError, EvalSerializationError
27
27
  SCHEMA_VERSION = 1
28
28
  """Version of the stored run/item record layout."""
29
29
 
30
+ STORE_SCHEMA_VERSION = 2
31
+ """Version of the history database layout. 2 adds the ``optimization_runs`` table (spec 0068)."""
32
+
30
33
  EVIDENCE_VERSION = 1
31
34
  """Version of the serialized full-capture evidence envelope."""
32
35
 
@@ -300,6 +303,72 @@ def _restore_structured(value: Any) -> None:
300
303
  _restore_structured(item)
301
304
 
302
305
 
306
+ class OptimizationRunRecord(BaseModel):
307
+ """One optimization run, stored next to the suite it optimized (spec 0068).
308
+
309
+ The summary fields are derived from the run's trace; ``trace`` is the full
310
+ ``OptimizationTrace.to_dict()`` and is ``None`` in listings. ``report()`` rebuilds the
311
+ ``OptimizationReport`` from the stored trace.
312
+ """
313
+
314
+ model_config = ConfigDict(frozen=True)
315
+
316
+ id: str = Field(default_factory=lambda: str(uuid4()))
317
+ suite: str
318
+ created_at: datetime = Field(default_factory=utc_now)
319
+ title: str = "Optimization run"
320
+ optimizer: str | None = None
321
+ seed: str
322
+ best: str
323
+ seed_avg: float | None = None
324
+ best_avg: float | None = None
325
+ rounds: int = 0
326
+ eval_count: int | None = None
327
+ cost_usd: float | None = None
328
+ pass_score: float = 10.0
329
+ trace: dict[str, Any] | None = None
330
+
331
+ @classmethod
332
+ def from_result(
333
+ cls, result: Any, *, suite: str, pass_score: float = 10.0, title: str | None = None
334
+ ) -> OptimizationRunRecord:
335
+ """Record an ``OptimizationResult`` under ``suite``."""
336
+ return cls.from_trace(result.trace, suite=suite, pass_score=pass_score, title=title)
337
+
338
+ @classmethod
339
+ def from_trace(
340
+ cls, trace: Any, *, suite: str, pass_score: float = 10.0, title: str | None = None
341
+ ) -> OptimizationRunRecord:
342
+ """Record an ``OptimizationTrace`` (live or loaded) under ``suite``."""
343
+ from agentbyte.optim.report import build_report
344
+
345
+ report = build_report(trace, title=title or suite, pass_score=pass_score)
346
+ return cls(
347
+ suite=suite,
348
+ title=report.title,
349
+ optimizer=report.optimizer,
350
+ seed=report.seed,
351
+ best=report.best,
352
+ seed_avg=report.seed_avg,
353
+ best_avg=report.best_avg,
354
+ rounds=report.rounds,
355
+ eval_count=report.eval_count,
356
+ cost_usd=((report.cost or {}).get("total") or {}).get("usd"),
357
+ pass_score=pass_score,
358
+ trace=json.loads(trace.to_json(indent=None)),
359
+ )
360
+
361
+ def report(self) -> Any:
362
+ """The ``OptimizationReport`` rebuilt from the stored trace."""
363
+ if self.trace is None:
364
+ raise ValueError("This record has no trace; load it with get_optimization(id)")
365
+ from agentbyte.optim.report import build_report
366
+ from agentbyte.optim.trace import OptimizationTrace
367
+
368
+ trace = OptimizationTrace(events=list(self.trace.get("events", [])))
369
+ return build_report(trace, title=self.title, pass_score=self.pass_score)
370
+
371
+
303
372
  def deserialize_evidence(text: str) -> EvalScore:
304
373
  """Load evidence JSON as data only; unknown versions raise."""
305
374
  envelope = json.loads(text)
@@ -315,7 +384,9 @@ __all__ = [
315
384
  "ACTIVE_RUN_STATUSES",
316
385
  "EVIDENCE_VERSION",
317
386
  "SCHEMA_VERSION",
387
+ "STORE_SCHEMA_VERSION",
318
388
  "TERMINAL_ITEM_STATES",
389
+ "OptimizationRunRecord",
319
390
  "CaptureMode",
320
391
  "EvalItemRecord",
321
392
  "EvalRunRecord",
@@ -51,13 +51,14 @@ from .errors import (
51
51
  from .models import (
52
52
  ACTIVE_RUN_STATUSES,
53
53
  SCHEMA_VERSION,
54
+ STORE_SCHEMA_VERSION,
54
55
  EvalItemRecord,
55
56
  EvalRunRecord,
56
57
  RunStatus,
57
58
  deserialize_evidence,
58
59
  serialize_evidence,
59
60
  )
60
- from .store import EvalRunStore, _uninterrupted
61
+ from .store import EvalRunStore, _uninterrupted, dump_optimization, load_optimization
61
62
  from .transitions import (
62
63
  admit,
63
64
  admitted_duplicate,
@@ -77,7 +78,11 @@ SessionFactory = Callable[[], "AbstractAsyncContextManager[AsyncSession] | Async
77
78
 
78
79
  # Forward migrations keyed by the version they upgrade from; each is a callable
79
80
  # run on the sync connection inside the opening transaction.
80
- _MIGRATIONS: dict[int, Callable[[Any, "HistoryTables"], None]] = {}
81
+ _MIGRATIONS: dict[int, Callable[[Any, "HistoryTables"], None]] = {
82
+ # spec 0068: optimization runs stored next to suites. checkfirst: a user-managed schema
83
+ # built from history_metadata() may already have the table.
84
+ 1: lambda connection, tables: tables.optimizations.create(connection, checkfirst=True),
85
+ }
81
86
 
82
87
 
83
88
  class HistoryTables:
@@ -109,6 +114,14 @@ class HistoryTables:
109
114
  Column("payload", Text, nullable=False),
110
115
  Column("evidence", Text),
111
116
  )
117
+ self.optimizations = Table(
118
+ "optimization_runs", self.metadata,
119
+ Column("seq", Integer, primary_key=True, autoincrement=True),
120
+ Column("id", String(64), nullable=False, unique=True),
121
+ Column("suite", Text, nullable=False, index=True),
122
+ Column("payload", Text, nullable=False),
123
+ Column("trace", Text),
124
+ )
112
125
 
113
126
 
114
127
  def history_metadata(schema: str | None = None) -> MetaData:
@@ -267,16 +280,18 @@ class SqlEvalRunStore(EvalRunStore):
267
280
  if not (self.writer and self.create_schema):
268
281
  raise EvalSchemaVersionError("Evaluation history tables are not initialized")
269
282
  tables.metadata.create_all(connection)
270
- connection.execute(insert(tables.meta).values(key="schema_version", value=str(SCHEMA_VERSION)))
283
+ connection.execute(
284
+ insert(tables.meta).values(key="schema_version", value=str(STORE_SCHEMA_VERSION))
285
+ )
271
286
  return
272
287
  version = int(row[0])
273
- if version > SCHEMA_VERSION:
288
+ if version > STORE_SCHEMA_VERSION:
274
289
  raise EvalSchemaVersionError(
275
- f"History schema {version} is newer than supported {SCHEMA_VERSION}"
290
+ f"History schema {version} is newer than supported {STORE_SCHEMA_VERSION}"
276
291
  )
277
- if version < SCHEMA_VERSION and not self.writer:
292
+ if version < STORE_SCHEMA_VERSION and not self.writer:
278
293
  raise EvalSchemaVersionError(f"History schema {version} needs migration; open once as writer")
279
- while version < SCHEMA_VERSION:
294
+ while version < STORE_SCHEMA_VERSION:
280
295
  if version not in _MIGRATIONS:
281
296
  raise EvalSchemaVersionError(f"No migration from history schema {version}")
282
297
  _MIGRATIONS[version](connection, tables)
@@ -565,5 +580,35 @@ class SqlEvalRunStore(EvalRunStore):
565
580
 
566
581
  return await self._write(run_id, "delete evaluation run", body)
567
582
 
583
+ async def save_optimization(self, record):
584
+ table = self.tables.optimizations
585
+ payload, trace = dump_optimization(record)
586
+
587
+ async def body(session: AsyncSession) -> Any:
588
+ existing = await session.execute(select(table.c.id).where(table.c.id == record.id))
589
+ if existing.first() is not None:
590
+ raise EvalHistoryConflictError(f"Optimization run {record.id} already exists")
591
+ await session.execute(
592
+ insert(table).values(id=record.id, suite=record.suite, payload=payload, trace=trace)
593
+ )
594
+ return load_optimization(payload, trace)
595
+
596
+ return await self._write(None, "save optimization run", body)
597
+
598
+ async def list_optimizations(self, *, suite=None, limit=50, offset=0):
599
+ table = self.tables.optimizations
600
+ query = select(table.c.payload)
601
+ if suite is not None:
602
+ query = query.where(table.c.suite == suite)
603
+ query = query.order_by(table.c.seq.desc()).limit(max(0, limit)).offset(max(0, offset))
604
+ return [load_optimization(row[0], None) for row in await self._read(None, query)]
605
+
606
+ async def get_optimization(self, optimization_id):
607
+ table = self.tables.optimizations
608
+ rows = await self._read(
609
+ None, select(table.c.payload, table.c.trace).where(table.c.id == optimization_id)
610
+ )
611
+ return load_optimization(rows[0][0], rows[0][1]) if rows else None
612
+
568
613
 
569
614
  __all__ = ["HistoryTables", "SessionFactory", "SqlEvalRunStore", "history_metadata"]