agentbyte 0.44.1__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.
- {agentbyte-0.44.1 → agentbyte-0.45.0}/.gitignore +3 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/CHANGELOG.md +27 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/PKG-INFO +2 -2
- {agentbyte-0.44.1 → agentbyte-0.45.0}/README.md +1 -1
- agentbyte-0.45.0/src/agentbyte/__about__.py +2 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/cli/main.py +6 -0
- agentbyte-0.45.0/src/agentbyte/cli/optim_commands.py +160 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/history/__init__.py +4 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/history/conformance.py +36 -1
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/history/models.py +71 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/history/sql.py +52 -7
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/history/sqlite.py +47 -7
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/history/store.py +52 -1
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/optim/__init__.py +18 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/optim/base.py +20 -1
- agentbyte-0.45.0/src/agentbyte/optim/report.py +462 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_eval_history_backends.py +62 -0
- agentbyte-0.45.0/tests/optim/test_report.py +263 -0
- agentbyte-0.44.1/src/agentbyte/__about__.py +0 -2
- {agentbyte-0.44.1 → agentbyte-0.45.0}/LICENSE +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/pyproject.toml +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/_optional.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/agents/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/agents/agent.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/agents/agent_as_tool.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/agents/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/agents/embedding_agent.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/agents/types.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/cancellation_token.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/catalog.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/cli/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/cli/__main__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/cli/eval_commands.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/cli/loading.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/compaction/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/compaction/counters.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/compaction/errors.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/compaction/grouping.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/compaction/strategies.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/component.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/context.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/context_providers/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/context_providers/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/context_providers/skill_tools.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/context_providers/skills.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/_aiosqlite.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/config.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/importer.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/json.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/loader.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/publish.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/publish_config.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/publishers.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/s3.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/sources.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/sqlite.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/sqlite_db.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/write_config.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/dataset/writers.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/entity.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/checks/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/checks/decorator.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/checks/keyword.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/checks/local.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/checks/process.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/checks/tool.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/checks/types.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/comparison.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/eval_dataset.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/history/errors.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/history/recorder.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/history/transitions.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/judges/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/judges/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/judges/composite.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/judges/llm.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/judges/pairwise.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/judges/reference.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/judges/trajectory.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/judges/validation.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/pairwise.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/report.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/runner.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/splitting.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/targets/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/targets/agent.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/targets/model.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/targets/multi_turn.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/targets/orchestrator.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/targets/runtime.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/targets/workflow.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/types.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/coordinator.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/jobs.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/smoke.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/smoke_tasks.json +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/suite.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/eval/workbench/verdict.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/execution_trace/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/execution_trace/collector.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/execution_trace/models.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/_retry_observability.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/auth.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/azure/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/azure/auth.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/azure/chat.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/azure/embedding.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/azure/settings.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/azure_openai.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/azure_openai_embedding.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/embeddings_base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/openai/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/openai/chat.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/openai/embedding.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/openai/settings.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/openai_embedding.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/pricing.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/retry_policy.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/settings.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/llm/types.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/logger.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/memory/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/memory/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/messages.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/middleware/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/middleware/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/middleware/otel.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/middleware/retry.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/middleware/sql_usage.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/middleware/usage_logger.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/notebook.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/optim/config.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/optim/gepa.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/optim/mipro.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/optim/pareto.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/optim/reflective.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/optim/spec.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/optim/trace.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/orchestration/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/orchestration/ai.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/orchestration/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/orchestration/handoff.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/orchestration/plan.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/orchestration/policies.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/orchestration/round_robin.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/agents.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/clients.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/instruction_registry.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/instructions/orchestrator.yaml +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/instructions/query_rewriter.yaml +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/instructions/researcher.yaml +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/instructions/reviewer.yaml +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/instructions/writer.yaml +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/orchestration.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/skills/contracts-analyst/SKILL.md +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/skills/hr-analyst/SKILL.md +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/skills/hr-analyst/resources/departments.md +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/skills/hr-analyst/resources/employees.md +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/skills/hr-analyst/resources/payroll.md +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/streaming.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/presets/workflow.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/session_store.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/skills/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/skills/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/skills/resources.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/skills/scripts.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/skills/sources.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/skills/validation.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/cancellation.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/composite.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/consecutive_agent.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/external.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/function_call.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/handoff.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/max_message.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/predicate.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/source.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/text_mention.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/timeout.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/termination/token_usage.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/tools/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/tools/base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/tools/coding_tools.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/tools/core_tools.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/tools/decorator.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/tools/memory_tool.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/tools/research_tools.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/types.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/discovery.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/eval_routes.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/execution.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/models.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/registry.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/server.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/session_store.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/sessions.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/ui/assets/index-BsS4WYZu.css +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/ui/assets/index-tGvO1yue.js +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/ui/index.html +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/webui/ui/vite.svg +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/agent.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/core/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/core/_structure_hash.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/core/checkpoint.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/core/models.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/core/runner.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/core/workflow.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/defaults.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/errors.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/loader.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/schema.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/schema_utils.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/sqlite_checkpoint.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/agent.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/echo.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/function.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/http.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/step.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/subworkflow.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/steps/transform.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/src/agentbyte/workflow/visualizer.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_agent_as_tool.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_agent_basic.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_agent_context_providers.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_agent_error_response.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_agent_event_types.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_agent_memory_integration.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_agent_middleware_integration.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_agent_response_accessors.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_agent_retry_middleware.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_agent_stop_at_tools.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_agent_stream_events.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_embedding_agent.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_tool_approval.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_tool_batch_resolution.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/agents/test_tool_metadata.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/cli/test_loading.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/cli/test_registry_check.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/compaction/test_compaction.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/context_providers/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/context_providers/test_skill_tools.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/context_providers/test_skills_provider.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/dataset/fake_s3.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/dataset/test_dataset_exit.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/dataset/test_loader.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/dataset/test_multi_table.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/dataset/test_publish.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/dataset/test_sqlite_db.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_eval_dataset.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_eval_history.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_eval_jobs.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_eval_workbench.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_execution_trajectories.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_multi_turn.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_pairwise.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_phase1_runner_and_targets.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_phase2_checks_and_reports.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_score_integrity.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_splitting.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/eval/test_types_and_judges.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/examples/test_compaction_webapp.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/llm/test_azure_client.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/llm/test_azure_embedding_client.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/llm/test_llm_types.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/llm/test_openai_client.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/llm/test_openai_embedding_client.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/llm/test_pricing.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/llm/test_retry_observability.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/llm/test_retry_policy_api.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/llm/test_retryable_error_substrings.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/memory/test_memory.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/middleware/test_context_compaction.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/middleware/test_deduplicate_tool_result.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/middleware/test_middleware_chain.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/middleware/test_otel.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/middleware/test_retry_middleware.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/middleware/test_sql_usage.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/middleware/test_usage_logger.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_base_integration.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_config.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_description_tunable.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_gepa.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_mipro.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_orchestrator_optim.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_pareto.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_reflective.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_score_integrity.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_spec.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/optim/test_trace.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_ai_orchestrator.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_base_orchestrator.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_handoff_orchestrator.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_history_tool_call_pairing.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_orchestration_usage_breakdown.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_orchestrator_agent_contract.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_orchestrator_finalization.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_orchestrator_member_events.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_orchestrator_otel.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_orchestrator_synthesis.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_plan_orchestrator.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/orchestration/test_round_robin.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/presets/test_agents.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/presets/test_clients.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/presets/test_instruction_registry.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/presets/test_orchestration.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/presets/test_streaming.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/presets/test_workflow.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/skills/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/skills/test_base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/skills/test_resources.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/skills/test_scripts.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/skills/test_sources.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_base.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_cancellation.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_composite.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_consecutive_agent.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_external.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_function_call.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_handoff.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_max_message.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_predicate.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_source.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_text_mention.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_timeout.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/termination/test_token_usage.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/test_cancellation_token.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/test_context.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/test_logger.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/test_messages.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/test_option_enums.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/test_optional_extras.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/test_package_api.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/test_session_store.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/test_types.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/test_vanilla_chunker.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/tools/test_coding_tools.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/tools/test_memory_tool.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/tools/test_research_tools.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/tools/test_tools.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/webui/__init__.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/webui/helpers.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/webui/test_eval_routes.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/webui/test_execution.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/webui/test_package_api.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/webui/test_registry.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/webui/test_server.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/webui/test_sessions.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/webui/test_workflow_streaming.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/recovery_worker.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/test_agent_step_imports.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/test_checkpoint.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/test_subworkflow_step.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/test_workflow_agent.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/test_workflow_class.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/test_workflow_models.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/test_workflow_reliability.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/test_workflow_runner.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/test_workflow_schema.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/test_workflow_steps.py +0 -0
- {agentbyte-0.44.1 → agentbyte-0.45.0}/tests/workflow/test_workflow_visualizer.py +0 -0
|
@@ -6,6 +6,33 @@ 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
|
+
|
|
9
36
|
## [0.44.1] - 2026-10-05
|
|
10
37
|
|
|
11
38
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agentbyte
|
|
3
|
-
Version: 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.
|
|
80
|
+
Current release: **0.45.0**
|
|
81
81
|
|
|
82
82
|
## Building an Agent
|
|
83
83
|
|
|
@@ -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,6 +17,7 @@ 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
|
|
|
@@ -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
|
|
|
@@ -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(
|
|
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 >
|
|
288
|
+
if version > STORE_SCHEMA_VERSION:
|
|
274
289
|
raise EvalSchemaVersionError(
|
|
275
|
-
f"History schema {version} is newer than supported {
|
|
290
|
+
f"History schema {version} is newer than supported {STORE_SCHEMA_VERSION}"
|
|
276
291
|
)
|
|
277
|
-
if version <
|
|
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 <
|
|
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"]
|
|
@@ -23,13 +23,14 @@ from .errors import (
|
|
|
23
23
|
from .models import (
|
|
24
24
|
ACTIVE_RUN_STATUSES,
|
|
25
25
|
SCHEMA_VERSION,
|
|
26
|
+
STORE_SCHEMA_VERSION,
|
|
26
27
|
EvalItemRecord,
|
|
27
28
|
EvalRunRecord,
|
|
28
29
|
RunStatus,
|
|
29
30
|
deserialize_evidence,
|
|
30
31
|
serialize_evidence,
|
|
31
32
|
)
|
|
32
|
-
from .store import EvalRunStore, _uninterrupted
|
|
33
|
+
from .store import EvalRunStore, _uninterrupted, dump_optimization, load_optimization
|
|
33
34
|
from .transitions import (
|
|
34
35
|
admit,
|
|
35
36
|
admitted_duplicate,
|
|
@@ -56,8 +57,16 @@ _SCHEMA_V1 = (
|
|
|
56
57
|
)
|
|
57
58
|
|
|
58
59
|
# Forward migrations keyed by the version they upgrade from. Each runs inside the
|
|
59
|
-
# opening transaction, so a failure leaves the previous schema untouched.
|
|
60
|
-
|
|
60
|
+
# opening transaction, so a failure leaves the previous schema untouched. A new file is
|
|
61
|
+
# created at version 1 and migrated forward like an existing one.
|
|
62
|
+
_MIGRATIONS: dict[int, tuple[str, ...]] = {
|
|
63
|
+
1: ( # spec 0068: optimization runs stored next to suites
|
|
64
|
+
"CREATE TABLE optimization_runs ("
|
|
65
|
+
"seq INTEGER PRIMARY KEY AUTOINCREMENT, id TEXT NOT NULL UNIQUE, suite TEXT NOT NULL, "
|
|
66
|
+
"payload TEXT NOT NULL, trace TEXT)",
|
|
67
|
+
"CREATE INDEX optimization_runs_suite ON optimization_runs(suite)",
|
|
68
|
+
),
|
|
69
|
+
}
|
|
61
70
|
|
|
62
71
|
|
|
63
72
|
def _admission_key(run: EvalRunRecord) -> str | None:
|
|
@@ -165,15 +174,15 @@ class SQLiteEvalRunStore(EvalRunStore):
|
|
|
165
174
|
version = 1
|
|
166
175
|
else:
|
|
167
176
|
version = int(row[0])
|
|
168
|
-
if version >
|
|
177
|
+
if version > STORE_SCHEMA_VERSION:
|
|
169
178
|
raise EvalSchemaVersionError(
|
|
170
|
-
f"History schema {version} is newer than supported {
|
|
179
|
+
f"History schema {version} is newer than supported {STORE_SCHEMA_VERSION}"
|
|
171
180
|
)
|
|
172
|
-
if version <
|
|
181
|
+
if version < STORE_SCHEMA_VERSION and not self.writer:
|
|
173
182
|
raise EvalSchemaVersionError(
|
|
174
183
|
f"History schema {version} needs migration; open once as writer"
|
|
175
184
|
)
|
|
176
|
-
while version <
|
|
185
|
+
while version < STORE_SCHEMA_VERSION:
|
|
177
186
|
if version not in _MIGRATIONS:
|
|
178
187
|
raise EvalSchemaVersionError(f"No migration from history schema {version}")
|
|
179
188
|
for statement in _MIGRATIONS[version]:
|
|
@@ -452,5 +461,36 @@ class SQLiteEvalRunStore(EvalRunStore):
|
|
|
452
461
|
|
|
453
462
|
return await self._write(run_id, "delete evaluation run", body)
|
|
454
463
|
|
|
464
|
+
async def save_optimization(self, record):
|
|
465
|
+
payload, trace = dump_optimization(record)
|
|
466
|
+
|
|
467
|
+
async def body(connection: Any) -> Any:
|
|
468
|
+
async with connection.execute(
|
|
469
|
+
"SELECT 1 FROM optimization_runs WHERE id = ?", (record.id,)
|
|
470
|
+
) as cursor:
|
|
471
|
+
if await cursor.fetchone() is not None:
|
|
472
|
+
raise EvalHistoryConflictError(f"Optimization run {record.id} already exists")
|
|
473
|
+
await connection.execute(
|
|
474
|
+
"INSERT INTO optimization_runs(id, suite, payload, trace) VALUES (?, ?, ?, ?)",
|
|
475
|
+
(record.id, record.suite, payload, trace),
|
|
476
|
+
)
|
|
477
|
+
return load_optimization(payload, trace)
|
|
478
|
+
|
|
479
|
+
return await self._write(None, "save optimization run", body)
|
|
480
|
+
|
|
481
|
+
async def list_optimizations(self, *, suite=None, limit=50, offset=0):
|
|
482
|
+
sql, params = "SELECT payload FROM optimization_runs", []
|
|
483
|
+
if suite is not None:
|
|
484
|
+
sql, params = sql + " WHERE suite = ?", [suite]
|
|
485
|
+
sql += " ORDER BY seq DESC LIMIT ? OFFSET ?"
|
|
486
|
+
rows = await self._read(None, sql, (*params, max(0, limit), max(0, offset)))
|
|
487
|
+
return [load_optimization(row[0], None) for row in rows]
|
|
488
|
+
|
|
489
|
+
async def get_optimization(self, optimization_id):
|
|
490
|
+
rows = await self._read(
|
|
491
|
+
None, "SELECT payload, trace FROM optimization_runs WHERE id = ?", (optimization_id,)
|
|
492
|
+
)
|
|
493
|
+
return load_optimization(rows[0][0], rows[0][1]) if rows else None
|
|
494
|
+
|
|
455
495
|
|
|
456
496
|
__all__ = ["SQLiteEvalRunStore"]
|