agentbyte 0.33.0__tar.gz → 0.34.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.33.0 → agentbyte-0.34.0}/.gitignore +7 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/CHANGELOG.md +17 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/PKG-INFO +49 -72
- {agentbyte-0.33.0 → agentbyte-0.34.0}/README.md +48 -71
- agentbyte-0.34.0/src/agentbyte/__about__.py +2 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/cli/eval_commands.py +65 -7
- agentbyte-0.34.0/src/agentbyte/cli/loading.py +115 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/cli/main.py +18 -9
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/__init__.py +2 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/eval_dataset.py +61 -58
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/webui/eval_routes.py +26 -3
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/webui/models.py +8 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/webui/server.py +13 -2
- agentbyte-0.34.0/src/agentbyte/webui/ui/assets/index-C-wj-OzO.js +82 -0
- agentbyte-0.34.0/src/agentbyte/webui/ui/assets/index-DW8IDODJ.css +1 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/webui/ui/index.html +2 -2
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/cli/test_loading.py +49 -3
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/cli/test_registry_check.py +4 -1
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_eval_dataset.py +22 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_eval_workbench.py +16 -1
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/webui/test_eval_routes.py +83 -4
- agentbyte-0.33.0/src/agentbyte/__about__.py +0 -2
- agentbyte-0.33.0/src/agentbyte/cli/loading.py +0 -49
- agentbyte-0.33.0/src/agentbyte/webui/ui/assets/index-BF3DwXaF.js +0 -82
- agentbyte-0.33.0/src/agentbyte/webui/ui/assets/index-ar5tOeqt.css +0 -1
- {agentbyte-0.33.0 → agentbyte-0.34.0}/LICENSE +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/pyproject.toml +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/_optional.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/agents/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/agents/agent.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/agents/agent_as_tool.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/agents/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/agents/embedding_agent.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/agents/types.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/cancellation_token.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/catalog.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/cli/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/cli/__main__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/compaction/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/compaction/counters.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/compaction/errors.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/compaction/grouping.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/compaction/strategies.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/component.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/context.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/context_providers/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/context_providers/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/context_providers/skill_tools.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/context_providers/skills.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/_aiosqlite.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/config.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/importer.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/json.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/loader.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/publish.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/publish_config.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/publishers.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/s3.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/sources.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/sqlite.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/sqlite_db.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/write_config.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/dataset/writers.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/entity.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/checks/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/checks/decorator.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/checks/keyword.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/checks/local.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/checks/process.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/checks/tool.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/checks/types.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/comparison.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/history/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/history/conformance.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/history/errors.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/history/models.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/history/recorder.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/history/sql.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/history/sqlite.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/history/store.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/history/transitions.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/judges/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/judges/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/judges/composite.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/judges/llm.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/judges/pairwise.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/judges/reference.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/judges/trajectory.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/judges/validation.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/pairwise.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/report.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/runner.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/splitting.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/targets/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/targets/agent.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/targets/model.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/targets/multi_turn.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/targets/orchestrator.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/targets/runtime.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/targets/workflow.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/types.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/workbench/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/workbench/coordinator.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/workbench/jobs.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/workbench/smoke.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/workbench/smoke_tasks.json +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/workbench/suite.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/eval/workbench/verdict.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/execution_trace/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/execution_trace/collector.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/execution_trace/models.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/_retry_observability.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/auth.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/azure/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/azure/auth.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/azure/chat.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/azure/embedding.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/azure/settings.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/azure_openai.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/azure_openai_embedding.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/embeddings_base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/openai/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/openai/chat.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/openai/embedding.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/openai/settings.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/openai_embedding.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/pricing.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/retry_policy.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/settings.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/llm/types.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/logger.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/memory/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/memory/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/messages.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/middleware/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/middleware/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/middleware/otel.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/middleware/retry.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/middleware/sql_usage.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/middleware/usage_logger.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/notebook.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/optim/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/optim/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/optim/config.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/optim/gepa.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/optim/mipro.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/optim/pareto.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/optim/reflective.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/optim/spec.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/optim/trace.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/orchestration/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/orchestration/ai.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/orchestration/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/orchestration/handoff.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/orchestration/plan.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/orchestration/policies.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/orchestration/round_robin.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/agents.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/clients.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/instruction_registry.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/instructions/orchestrator.yaml +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/instructions/query_rewriter.yaml +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/instructions/researcher.yaml +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/instructions/reviewer.yaml +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/instructions/writer.yaml +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/orchestration.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/skills/contracts-analyst/SKILL.md +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/skills/hr-analyst/SKILL.md +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/skills/hr-analyst/resources/departments.md +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/skills/hr-analyst/resources/employees.md +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/skills/hr-analyst/resources/payroll.md +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/streaming.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/presets/workflow.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/session_store.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/skills/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/skills/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/skills/resources.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/skills/scripts.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/skills/sources.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/skills/validation.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/cancellation.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/composite.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/consecutive_agent.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/external.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/function_call.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/handoff.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/max_message.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/predicate.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/source.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/text_mention.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/timeout.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/termination/token_usage.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/tools/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/tools/base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/tools/coding_tools.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/tools/core_tools.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/tools/decorator.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/tools/memory_tool.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/tools/research_tools.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/types.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/webui/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/webui/discovery.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/webui/execution.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/webui/registry.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/webui/session_store.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/webui/sessions.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/webui/ui/vite.svg +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/agent.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/core/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/core/_structure_hash.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/core/checkpoint.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/core/models.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/core/runner.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/core/workflow.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/defaults.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/errors.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/loader.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/schema.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/schema_utils.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/sqlite_checkpoint.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/steps/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/steps/agent.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/steps/echo.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/steps/function.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/steps/http.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/steps/step.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/steps/subworkflow.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/steps/transform.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/src/agentbyte/workflow/visualizer.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_agent_as_tool.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_agent_basic.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_agent_context_providers.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_agent_error_response.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_agent_event_types.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_agent_memory_integration.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_agent_middleware_integration.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_agent_response_accessors.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_agent_retry_middleware.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_agent_stream_events.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_embedding_agent.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_tool_approval.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_tool_batch_resolution.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/agents/test_tool_metadata.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/compaction/test_compaction.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/context_providers/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/context_providers/test_skill_tools.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/context_providers/test_skills_provider.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/dataset/fake_s3.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/dataset/test_dataset_exit.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/dataset/test_loader.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/dataset/test_multi_table.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/dataset/test_publish.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/dataset/test_sqlite_db.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_eval_history.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_eval_history_backends.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_eval_jobs.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_execution_trajectories.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_multi_turn.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_pairwise.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_phase1_runner_and_targets.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_phase2_checks_and_reports.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_score_integrity.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_splitting.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/eval/test_types_and_judges.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/examples/test_compaction_webapp.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/llm/test_azure_client.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/llm/test_azure_embedding_client.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/llm/test_llm_types.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/llm/test_openai_client.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/llm/test_openai_embedding_client.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/llm/test_pricing.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/llm/test_retry_observability.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/llm/test_retry_policy_api.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/llm/test_retryable_error_substrings.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/memory/test_memory.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/middleware/test_context_compaction.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/middleware/test_deduplicate_tool_result.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/middleware/test_middleware_chain.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/middleware/test_otel.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/middleware/test_retry_middleware.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/middleware/test_sql_usage.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/middleware/test_usage_logger.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/optim/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/optim/test_base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/optim/test_base_integration.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/optim/test_config.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/optim/test_gepa.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/optim/test_mipro.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/optim/test_pareto.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/optim/test_reflective.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/optim/test_score_integrity.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/optim/test_spec.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/optim/test_trace.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/orchestration/test_ai_orchestrator.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/orchestration/test_base_orchestrator.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/orchestration/test_handoff_orchestrator.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/orchestration/test_orchestrator_finalization.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/orchestration/test_plan_orchestrator.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/orchestration/test_round_robin.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/presets/test_agents.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/presets/test_clients.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/presets/test_instruction_registry.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/presets/test_orchestration.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/presets/test_streaming.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/presets/test_workflow.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/skills/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/skills/test_base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/skills/test_resources.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/skills/test_scripts.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/skills/test_sources.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_base.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_cancellation.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_composite.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_consecutive_agent.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_external.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_function_call.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_handoff.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_max_message.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_predicate.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_source.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_text_mention.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_timeout.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/termination/test_token_usage.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/test_cancellation_token.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/test_context.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/test_logger.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/test_messages.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/test_optional_extras.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/test_package_api.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/test_session_store.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/test_types.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/test_vanilla_chunker.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/tools/test_coding_tools.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/tools/test_memory_tool.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/tools/test_research_tools.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/tools/test_tools.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/webui/__init__.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/webui/helpers.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/webui/test_execution.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/webui/test_package_api.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/webui/test_registry.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/webui/test_server.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/webui/test_sessions.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/webui/test_workflow_streaming.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/recovery_worker.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/test_agent_step_imports.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/test_checkpoint.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/test_subworkflow_step.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/test_workflow_agent.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/test_workflow_class.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/test_workflow_models.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/test_workflow_reliability.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/test_workflow_runner.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/test_workflow_schema.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/test_workflow_steps.py +0 -0
- {agentbyte-0.33.0 → agentbyte-0.34.0}/tests/workflow/test_workflow_visualizer.py +0 -0
|
@@ -6,6 +6,23 @@ The format follows Keep a Changelog principles and semantic versioning.
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
+
## [0.34.0] - 2026-10-01
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Evaluation workbench, step 3 (spec 0052): WebUI Evaluations section next to the Playground — registered suites with Run (summary or full evidence), run history with pass/fail verdicts and filters, a live run page (durable snapshots, outcome counts, Cancel) and an item page (transcript, judge scores and reasoning, execution facts, labelled evidence state). Pages have shareable `#/evals/...` links. A server with evaluations but no agents or workflows opens on Evaluations.
|
|
14
|
+
- `/api/health` reports `eval_enabled`; `GET /api/eval/runs` entries include a `verdict` with pass/fail and outcome counts.
|
|
15
|
+
- Simpler eval commands: `--catalog` / `--eval-catalog` (and `registry check`) accept a `.py` file path as well as a module, and `:name` is optional when the module defines exactly one matching object. `agentbyte eval run|results` and `agentbyte webui --eval-catalog` store runs in `./eval.sqlite` unless a history path is given. Example: `agentbyte webui --eval-catalog examples/eval/workbench_catalog.py`.
|
|
16
|
+
- `agentbyte eval ui [--catalog CATALOG] [--history PATH] [--port 8090]`: the Evaluations pages on their own, without the Playground (`AgentbyteWebUIServer(playground=False)`, `serve`/`webui(playground=False)`); `/api/health` reports `playground_enabled`. It refuses to start, with exit code 2, when another process holds the history file.
|
|
17
|
+
- `agentbyte.eval.tasks_from_eval_records(records)`: the tasks a saved eval dataset would produce, built synchronously from in-memory `EvalDatasetRecord`s (for suite catalogs). Saving and loading now share one record/row mapping.
|
|
18
|
+
- Evaluation guide `docs/guides/evaluation-end-to-end.md` (how datasets, suites, runners, history, CLI, HTTP and the UI connect; on-the-fly vs stored runs; CI), the real-model example catalog `examples/eval/acme_support.py` with its fake FAQ dataset (`data/datasets/examples/acme-support`), and the notebook `notebooks/usecases/eval/06-eval-end-to-end.ipynb`.
|
|
19
|
+
- The sample WebUI launchers (`examples/webui/in_memory.py`, `presets_webui.py`) accept `--eval-history`, `--eval-catalog`, `--port` and `--no-open`, serving the demo entities and the Evaluations pages together.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- The packaged WebUI called `http://localhost:8080` regardless of the port it was served from; it now calls its own origin, so `agentbyte webui --port N` works.
|
|
24
|
+
- README "Run The WebUI": removed the `--dir examples` suggestion (discovery finds no entities there) and documented the sample launchers, Evaluations and the discovery convention.
|
|
25
|
+
|
|
9
26
|
## [0.33.0] - 2026-10-01
|
|
10
27
|
|
|
11
28
|
Upgrade notes (breaking):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: agentbyte
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.34.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
|
|
@@ -72,7 +72,7 @@ Description-Content-Type: text/markdown
|
|
|
72
72
|
|
|
73
73
|
Agentbyte is an observability-first agentic AI framework for building and studying multiagent systems with a learning-first, implementation-oriented workflow.
|
|
74
74
|
|
|
75
|
-
Current release: **0.
|
|
75
|
+
Current release: **0.34.0**
|
|
76
76
|
|
|
77
77
|
## Building an Agent
|
|
78
78
|
|
|
@@ -323,110 +323,87 @@ uv sync --all-extras --all-groups
|
|
|
323
323
|
|
|
324
324
|
## Run The WebUI
|
|
325
325
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
This is the easiest way to see the WebUI working end to end with real preset entities:
|
|
329
|
-
- preset agents
|
|
330
|
-
- preset orchestrators
|
|
331
|
-
- preset workflow
|
|
332
|
-
|
|
333
|
-
Step 1. Install the WebUI extra:
|
|
334
|
-
|
|
335
|
-
```bash
|
|
336
|
-
uv sync --extra webui
|
|
337
|
-
```
|
|
338
|
-
|
|
339
|
-
Step 2. Start the preset-backed app:
|
|
326
|
+
The WebUI has two sections: the **Playground** (chat with agents, orchestrators and workflows) and
|
|
327
|
+
**Evaluations** (run registered evaluation suites and inspect the results). Install the extra first:
|
|
340
328
|
|
|
341
329
|
```bash
|
|
342
|
-
uv
|
|
330
|
+
uv sync --extra webui # add --extra sqlite for Evaluations
|
|
343
331
|
```
|
|
344
332
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
```text
|
|
348
|
-
http://127.0.0.1:8080
|
|
349
|
-
```
|
|
333
|
+
### Option 1: Sample apps
|
|
350
334
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
### Option 2: Run the WebUI against your current project directory
|
|
354
|
-
|
|
355
|
-
Use this when you want Agentbyte to scan a directory for exported `agent`, `workflow`, or `orchestrator` objects.
|
|
356
|
-
|
|
357
|
-
Important: discovery is convention-based. The scanned directory must contain Python modules that expose top-level variables literally named `agent`, `workflow`, or `orchestrator`. If you point `--dir` at a folder that does not export those names, the UI will load but show `No entities found`.
|
|
358
|
-
|
|
359
|
-
Step 1. Install the WebUI extra:
|
|
335
|
+
No API key needed: three demo agents, a team and a workflow on a fake model client.
|
|
360
336
|
|
|
361
337
|
```bash
|
|
362
|
-
uv
|
|
338
|
+
uv run python examples/webui/in_memory.py # http://127.0.0.1:8070
|
|
339
|
+
uv run python examples/webui/in_memory.py --eval-history eval.sqlite # plus Evaluations
|
|
363
340
|
```
|
|
364
341
|
|
|
365
|
-
|
|
342
|
+
With your OpenAI or Azure OpenAI credentials, the preset agents, teams and workflow:
|
|
366
343
|
|
|
367
344
|
```bash
|
|
368
|
-
uv
|
|
345
|
+
uv sync --extra webui --extra openai # or --extra azureopenai
|
|
346
|
+
uv run python examples/webui/presets_webui.py # http://127.0.0.1:8080
|
|
347
|
+
uv run python examples/webui/presets_webui.py --eval-history eval.sqlite
|
|
369
348
|
```
|
|
370
349
|
|
|
371
|
-
|
|
350
|
+
Both launchers accept `--port`, `--no-open`, `--eval-history PATH` and `--eval-catalog CATALOG`
|
|
351
|
+
(default: the example suites in `examples/eval/workbench_catalog.py`).
|
|
372
352
|
|
|
373
|
-
|
|
374
|
-
http://127.0.0.1:8080
|
|
375
|
-
```
|
|
353
|
+
### Option 2: Evaluations for your suites
|
|
376
354
|
|
|
377
|
-
|
|
355
|
+
`agentbyte eval ui` opens the Evaluations pages on their own (no Playground). Point it at the
|
|
356
|
+
Python file that defines your `EvalSuiteRegistry`:
|
|
378
357
|
|
|
379
358
|
```bash
|
|
380
|
-
uv
|
|
381
|
-
uv run agentbyte
|
|
382
|
-
# evaluation API under /api/eval (needs the sqlite extra; default suite: built-in smoke)
|
|
383
|
-
uv run agentbyte webui --eval-history ./eval.sqlite --eval-catalog myapp.evaluations:registry
|
|
359
|
+
uv sync --extra webui --extra sqlite
|
|
360
|
+
uv run agentbyte eval ui --catalog examples/eval/workbench_catalog.py # http://127.0.0.1:8090
|
|
384
361
|
```
|
|
385
362
|
|
|
386
|
-
|
|
363
|
+
- `--catalog` takes a `.py` file or a module path (`myapp.evaluations`); add `:name` only when the
|
|
364
|
+
file defines more than one registry. Without `--catalog` it serves the built-in smoke suite.
|
|
365
|
+
- Runs are stored in `./eval.sqlite` unless you pass `--history PATH`. Only one process can write
|
|
366
|
+
a history file: stop the UI before `agentbyte eval run` on the same file, or use another file.
|
|
367
|
+
- The same catalog works in the terminal: `uv run agentbyte eval run capitals --catalog examples/eval/workbench_catalog.py`.
|
|
368
|
+
- To serve agents and Evaluations together: `agentbyte webui --dir my_entities --eval-catalog myapp/evaluations.py`.
|
|
387
369
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
```
|
|
370
|
+
Start with the end-to-end guide, `docs/guides/evaluation-end-to-end.md` (dataset → suite → history → UI), and the
|
|
371
|
+
notebook `notebooks/usecases/eval/06-eval-end-to-end.ipynb` (real OpenAI/Azure model). Details: `docs/study/05-eval_topics/`.
|
|
391
372
|
|
|
392
|
-
|
|
373
|
+
### Option 3: Scan a project directory
|
|
374
|
+
|
|
375
|
+
`agentbyte webui --dir PATH` loads entities from Python files. Discovery is convention-based: each
|
|
376
|
+
module (or package) must define a top-level variable named `agent`, `orchestrator` or `workflow`
|
|
377
|
+
holding an Agentbyte object. Folders without those names show "No agents, orchestrators, or
|
|
378
|
+
workflows found"; this is the case for `examples/`, which uses the launchers above instead.
|
|
393
379
|
|
|
394
380
|
```python
|
|
395
|
-
# my_entities.py
|
|
396
|
-
agent = ...
|
|
397
|
-
workflow = ...
|
|
398
|
-
orchestrator = ...
|
|
381
|
+
# my_entities/support.py
|
|
382
|
+
agent = Agent(name="support", ...)
|
|
399
383
|
```
|
|
400
384
|
|
|
401
|
-
|
|
385
|
+
```bash
|
|
386
|
+
uv run agentbyte webui --dir my_entities
|
|
387
|
+
uv run agentbyte webui --dir my_entities --eval-catalog myapp/evaluations.py # both sections
|
|
388
|
+
```
|
|
402
389
|
|
|
403
|
-
|
|
390
|
+
### Option 4: From Python
|
|
404
391
|
|
|
405
392
|
```python
|
|
406
393
|
from agentbyte.webui import serve
|
|
407
394
|
|
|
408
|
-
serve(entities=[agent], port=8080
|
|
395
|
+
serve(entities=[agent], port=8080)
|
|
396
|
+
serve(entities=[agent], eval_registry=registry, eval_history="eval.sqlite") # with Evaluations
|
|
409
397
|
```
|
|
410
398
|
|
|
411
399
|
### Quick Troubleshooting
|
|
412
400
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
If port `8080` is already in use:
|
|
420
|
-
|
|
421
|
-
```bash
|
|
422
|
-
uv run agentbyte webui --dir . --port 8090
|
|
423
|
-
```
|
|
424
|
-
|
|
425
|
-
If you do not want the browser to open automatically:
|
|
426
|
-
|
|
427
|
-
```bash
|
|
428
|
-
uv run agentbyte webui --dir . --no-open
|
|
429
|
-
```
|
|
401
|
+
- Port in use: add `--port 8090`. The UI works on any port.
|
|
402
|
+
- No browser wanted: add `--no-open`.
|
|
403
|
+
- "No agents, orchestrators, or workflows found": the `--dir` folder has no module with a top-level
|
|
404
|
+
`agent`, `orchestrator` or `workflow`; use a launcher from Option 1 to see the samples.
|
|
405
|
+
- No Evaluations switch in the header: start `agentbyte webui` with `--eval-catalog`, or use `agentbyte eval ui`.
|
|
406
|
+
- After upgrading, hard-reload the page (Cmd/Ctrl-Shift-R) to load the new UI.
|
|
430
407
|
|
|
431
408
|
## Development
|
|
432
409
|
|
|
@@ -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.
|
|
5
|
+
Current release: **0.34.0**
|
|
6
6
|
|
|
7
7
|
## Building an Agent
|
|
8
8
|
|
|
@@ -253,110 +253,87 @@ uv sync --all-extras --all-groups
|
|
|
253
253
|
|
|
254
254
|
## Run The WebUI
|
|
255
255
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
This is the easiest way to see the WebUI working end to end with real preset entities:
|
|
259
|
-
- preset agents
|
|
260
|
-
- preset orchestrators
|
|
261
|
-
- preset workflow
|
|
262
|
-
|
|
263
|
-
Step 1. Install the WebUI extra:
|
|
264
|
-
|
|
265
|
-
```bash
|
|
266
|
-
uv sync --extra webui
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
Step 2. Start the preset-backed app:
|
|
256
|
+
The WebUI has two sections: the **Playground** (chat with agents, orchestrators and workflows) and
|
|
257
|
+
**Evaluations** (run registered evaluation suites and inspect the results). Install the extra first:
|
|
270
258
|
|
|
271
259
|
```bash
|
|
272
|
-
uv
|
|
260
|
+
uv sync --extra webui # add --extra sqlite for Evaluations
|
|
273
261
|
```
|
|
274
262
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
```text
|
|
278
|
-
http://127.0.0.1:8080
|
|
279
|
-
```
|
|
263
|
+
### Option 1: Sample apps
|
|
280
264
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
### Option 2: Run the WebUI against your current project directory
|
|
284
|
-
|
|
285
|
-
Use this when you want Agentbyte to scan a directory for exported `agent`, `workflow`, or `orchestrator` objects.
|
|
286
|
-
|
|
287
|
-
Important: discovery is convention-based. The scanned directory must contain Python modules that expose top-level variables literally named `agent`, `workflow`, or `orchestrator`. If you point `--dir` at a folder that does not export those names, the UI will load but show `No entities found`.
|
|
288
|
-
|
|
289
|
-
Step 1. Install the WebUI extra:
|
|
265
|
+
No API key needed: three demo agents, a team and a workflow on a fake model client.
|
|
290
266
|
|
|
291
267
|
```bash
|
|
292
|
-
uv
|
|
268
|
+
uv run python examples/webui/in_memory.py # http://127.0.0.1:8070
|
|
269
|
+
uv run python examples/webui/in_memory.py --eval-history eval.sqlite # plus Evaluations
|
|
293
270
|
```
|
|
294
271
|
|
|
295
|
-
|
|
272
|
+
With your OpenAI or Azure OpenAI credentials, the preset agents, teams and workflow:
|
|
296
273
|
|
|
297
274
|
```bash
|
|
298
|
-
uv
|
|
275
|
+
uv sync --extra webui --extra openai # or --extra azureopenai
|
|
276
|
+
uv run python examples/webui/presets_webui.py # http://127.0.0.1:8080
|
|
277
|
+
uv run python examples/webui/presets_webui.py --eval-history eval.sqlite
|
|
299
278
|
```
|
|
300
279
|
|
|
301
|
-
|
|
280
|
+
Both launchers accept `--port`, `--no-open`, `--eval-history PATH` and `--eval-catalog CATALOG`
|
|
281
|
+
(default: the example suites in `examples/eval/workbench_catalog.py`).
|
|
302
282
|
|
|
303
|
-
|
|
304
|
-
http://127.0.0.1:8080
|
|
305
|
-
```
|
|
283
|
+
### Option 2: Evaluations for your suites
|
|
306
284
|
|
|
307
|
-
|
|
285
|
+
`agentbyte eval ui` opens the Evaluations pages on their own (no Playground). Point it at the
|
|
286
|
+
Python file that defines your `EvalSuiteRegistry`:
|
|
308
287
|
|
|
309
288
|
```bash
|
|
310
|
-
uv
|
|
311
|
-
uv run agentbyte
|
|
312
|
-
# evaluation API under /api/eval (needs the sqlite extra; default suite: built-in smoke)
|
|
313
|
-
uv run agentbyte webui --eval-history ./eval.sqlite --eval-catalog myapp.evaluations:registry
|
|
289
|
+
uv sync --extra webui --extra sqlite
|
|
290
|
+
uv run agentbyte eval ui --catalog examples/eval/workbench_catalog.py # http://127.0.0.1:8090
|
|
314
291
|
```
|
|
315
292
|
|
|
316
|
-
|
|
293
|
+
- `--catalog` takes a `.py` file or a module path (`myapp.evaluations`); add `:name` only when the
|
|
294
|
+
file defines more than one registry. Without `--catalog` it serves the built-in smoke suite.
|
|
295
|
+
- Runs are stored in `./eval.sqlite` unless you pass `--history PATH`. Only one process can write
|
|
296
|
+
a history file: stop the UI before `agentbyte eval run` on the same file, or use another file.
|
|
297
|
+
- The same catalog works in the terminal: `uv run agentbyte eval run capitals --catalog examples/eval/workbench_catalog.py`.
|
|
298
|
+
- To serve agents and Evaluations together: `agentbyte webui --dir my_entities --eval-catalog myapp/evaluations.py`.
|
|
317
299
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
```
|
|
300
|
+
Start with the end-to-end guide, `docs/guides/evaluation-end-to-end.md` (dataset → suite → history → UI), and the
|
|
301
|
+
notebook `notebooks/usecases/eval/06-eval-end-to-end.ipynb` (real OpenAI/Azure model). Details: `docs/study/05-eval_topics/`.
|
|
321
302
|
|
|
322
|
-
|
|
303
|
+
### Option 3: Scan a project directory
|
|
304
|
+
|
|
305
|
+
`agentbyte webui --dir PATH` loads entities from Python files. Discovery is convention-based: each
|
|
306
|
+
module (or package) must define a top-level variable named `agent`, `orchestrator` or `workflow`
|
|
307
|
+
holding an Agentbyte object. Folders without those names show "No agents, orchestrators, or
|
|
308
|
+
workflows found"; this is the case for `examples/`, which uses the launchers above instead.
|
|
323
309
|
|
|
324
310
|
```python
|
|
325
|
-
# my_entities.py
|
|
326
|
-
agent = ...
|
|
327
|
-
workflow = ...
|
|
328
|
-
orchestrator = ...
|
|
311
|
+
# my_entities/support.py
|
|
312
|
+
agent = Agent(name="support", ...)
|
|
329
313
|
```
|
|
330
314
|
|
|
331
|
-
|
|
315
|
+
```bash
|
|
316
|
+
uv run agentbyte webui --dir my_entities
|
|
317
|
+
uv run agentbyte webui --dir my_entities --eval-catalog myapp/evaluations.py # both sections
|
|
318
|
+
```
|
|
332
319
|
|
|
333
|
-
|
|
320
|
+
### Option 4: From Python
|
|
334
321
|
|
|
335
322
|
```python
|
|
336
323
|
from agentbyte.webui import serve
|
|
337
324
|
|
|
338
|
-
serve(entities=[agent], port=8080
|
|
325
|
+
serve(entities=[agent], port=8080)
|
|
326
|
+
serve(entities=[agent], eval_registry=registry, eval_history="eval.sqlite") # with Evaluations
|
|
339
327
|
```
|
|
340
328
|
|
|
341
329
|
### Quick Troubleshooting
|
|
342
330
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
If port `8080` is already in use:
|
|
350
|
-
|
|
351
|
-
```bash
|
|
352
|
-
uv run agentbyte webui --dir . --port 8090
|
|
353
|
-
```
|
|
354
|
-
|
|
355
|
-
If you do not want the browser to open automatically:
|
|
356
|
-
|
|
357
|
-
```bash
|
|
358
|
-
uv run agentbyte webui --dir . --no-open
|
|
359
|
-
```
|
|
331
|
+
- Port in use: add `--port 8090`. The UI works on any port.
|
|
332
|
+
- No browser wanted: add `--no-open`.
|
|
333
|
+
- "No agents, orchestrators, or workflows found": the `--dir` folder has no module with a top-level
|
|
334
|
+
`agent`, `orchestrator` or `workflow`; use a launcher from Option 1 to see the samples.
|
|
335
|
+
- No Evaluations switch in the header: start `agentbyte webui` with `--eval-catalog`, or use `agentbyte eval ui`.
|
|
336
|
+
- After upgrading, hard-reload the page (Cmd/Ctrl-Shift-R) to load the new UI.
|
|
360
337
|
|
|
361
338
|
## Development
|
|
362
339
|
|
|
@@ -19,7 +19,9 @@ EXIT_FAILED = 1
|
|
|
19
19
|
EXIT_ERROR = 2
|
|
20
20
|
EXIT_INTERRUPTED = 130
|
|
21
21
|
|
|
22
|
-
DEFAULT_CATALOG = "agentbyte.eval.workbench.smoke
|
|
22
|
+
DEFAULT_CATALOG = "agentbyte.eval.workbench.smoke"
|
|
23
|
+
DEFAULT_HISTORY = "eval.sqlite"
|
|
24
|
+
DEFAULT_UI_PORT = 8090
|
|
23
25
|
|
|
24
26
|
|
|
25
27
|
class _CliError(Exception):
|
|
@@ -32,9 +34,11 @@ def add_eval_parser(subparsers: Any) -> None:
|
|
|
32
34
|
eval_sub = eval_parser.add_subparsers(dest="eval_command", metavar="<subcommand>")
|
|
33
35
|
|
|
34
36
|
catalog_help = (
|
|
35
|
-
"
|
|
37
|
+
"Where the EvalSuiteRegistry is: a .py file (myapp/evaluations.py) or a module "
|
|
38
|
+
"(myapp.evaluations); add ':name' if it defines more than one "
|
|
36
39
|
f"(default: the built-in smoke suite, {DEFAULT_CATALOG})"
|
|
37
40
|
)
|
|
41
|
+
history_help = f"SQLite evaluation history file (default: ./{DEFAULT_HISTORY})"
|
|
38
42
|
|
|
39
43
|
list_parser = eval_sub.add_parser("list", help="List the suites in a catalog")
|
|
40
44
|
list_parser.add_argument("--catalog", default=DEFAULT_CATALOG, help=catalog_help)
|
|
@@ -43,7 +47,7 @@ def add_eval_parser(subparsers: Any) -> None:
|
|
|
43
47
|
run_parser = eval_sub.add_parser("run", help="Run one suite and record it")
|
|
44
48
|
run_parser.add_argument("suite", help="Registered suite name")
|
|
45
49
|
run_parser.add_argument("--catalog", default=DEFAULT_CATALOG, help=catalog_help)
|
|
46
|
-
run_parser.add_argument("--history",
|
|
50
|
+
run_parser.add_argument("--history", default=DEFAULT_HISTORY, help=history_help)
|
|
47
51
|
run_parser.add_argument(
|
|
48
52
|
"--capture",
|
|
49
53
|
choices=["summary", "full"],
|
|
@@ -55,16 +59,27 @@ def add_eval_parser(subparsers: Any) -> None:
|
|
|
55
59
|
|
|
56
60
|
results_parser = eval_sub.add_parser("results", help="Show the verdict of a recorded run")
|
|
57
61
|
results_parser.add_argument("run_id", help="Run ID printed by 'agentbyte eval run'")
|
|
58
|
-
results_parser.add_argument("--history",
|
|
62
|
+
results_parser.add_argument("--history", default=DEFAULT_HISTORY, help=history_help)
|
|
59
63
|
results_parser.add_argument("--format", choices=["text", "json"], default="text")
|
|
60
64
|
|
|
65
|
+
ui_parser = eval_sub.add_parser(
|
|
66
|
+
"ui", help="Open the evaluation pages in the browser (Evaluations only, no Playground)"
|
|
67
|
+
)
|
|
68
|
+
ui_parser.add_argument("--catalog", default=DEFAULT_CATALOG, help=catalog_help)
|
|
69
|
+
ui_parser.add_argument("--history", default=DEFAULT_HISTORY, help=history_help)
|
|
70
|
+
ui_parser.add_argument("--port", "-p", type=int, default=DEFAULT_UI_PORT,
|
|
71
|
+
help=f"Port to serve on (default: {DEFAULT_UI_PORT})")
|
|
72
|
+
ui_parser.add_argument("--host", default="127.0.0.1", help="Host to bind (default: 127.0.0.1)")
|
|
73
|
+
ui_parser.add_argument("--no-open", action="store_true", help="Do not open the browser")
|
|
74
|
+
ui_parser.add_argument("--log-level", choices=["debug", "info", "warning", "error"], default="warning")
|
|
75
|
+
|
|
61
76
|
|
|
62
77
|
def cmd_eval(args: argparse.Namespace) -> int:
|
|
63
78
|
"""Dispatch ``agentbyte eval <subcommand>``."""
|
|
64
|
-
commands = {"list": _cmd_list, "run": _cmd_run, "results": _cmd_results}
|
|
79
|
+
commands = {"list": _cmd_list, "run": _cmd_run, "results": _cmd_results, "ui": _cmd_ui}
|
|
65
80
|
command = commands.get(getattr(args, "eval_command", None) or "")
|
|
66
81
|
if command is None:
|
|
67
|
-
print("usage: agentbyte eval {list,run,results} ...", file=sys.stderr)
|
|
82
|
+
print("usage: agentbyte eval {list,run,results,ui} ...", file=sys.stderr)
|
|
68
83
|
return EXIT_ERROR
|
|
69
84
|
try:
|
|
70
85
|
return command(args)
|
|
@@ -73,6 +88,49 @@ def cmd_eval(args: argparse.Namespace) -> int:
|
|
|
73
88
|
return EXIT_ERROR
|
|
74
89
|
|
|
75
90
|
|
|
91
|
+
# -- ui ---------------------------------------------------------------------------
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _cmd_ui(args: argparse.Namespace) -> int:
|
|
95
|
+
"""Serve the Evaluations pages only; returns when the server stops."""
|
|
96
|
+
from agentbyte._optional import MissingExtraError, require
|
|
97
|
+
|
|
98
|
+
registry = load_registry(args.catalog)
|
|
99
|
+
try:
|
|
100
|
+
require("aiosqlite", extra="sqlite", feature="Evaluation history")
|
|
101
|
+
from agentbyte.webui import launch
|
|
102
|
+
except (MissingExtraError, ImportError) as exc:
|
|
103
|
+
raise _CliError(str(exc)) from exc
|
|
104
|
+
asyncio.run(_check_history_is_free(args.history))
|
|
105
|
+
print(f"Evaluations: http://{args.host}:{args.port} (history {args.history}; Ctrl-C to stop)", file=sys.stderr)
|
|
106
|
+
try:
|
|
107
|
+
launch(
|
|
108
|
+
port=args.port,
|
|
109
|
+
host=args.host,
|
|
110
|
+
auto_open=not args.no_open,
|
|
111
|
+
log_level=args.log_level,
|
|
112
|
+
eval_registry=registry,
|
|
113
|
+
eval_history=args.history,
|
|
114
|
+
playground=False,
|
|
115
|
+
)
|
|
116
|
+
except KeyboardInterrupt:
|
|
117
|
+
return EXIT_PASSED
|
|
118
|
+
except Exception as exc: # boundary: report server start-up failures (port in use, locked history)
|
|
119
|
+
raise _CliError(f"Could not start the evaluation UI: {exc}") from exc
|
|
120
|
+
return EXIT_PASSED
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
async def _check_history_is_free(path: str) -> None:
|
|
124
|
+
"""Fail fast when another process (a CLI run, another server) holds the history file."""
|
|
125
|
+
from agentbyte.eval.history import EvalHistoryError
|
|
126
|
+
|
|
127
|
+
try:
|
|
128
|
+
async with _open_store(path, writer=True):
|
|
129
|
+
pass
|
|
130
|
+
except EvalHistoryError as exc:
|
|
131
|
+
raise _CliError(f"{exc} (only one process can write {path!r} at a time)") from exc
|
|
132
|
+
|
|
133
|
+
|
|
76
134
|
# -- list -------------------------------------------------------------------------
|
|
77
135
|
|
|
78
136
|
|
|
@@ -188,7 +246,7 @@ def load_registry(import_path: str) -> Any:
|
|
|
188
246
|
from agentbyte.eval.workbench import EvalSuiteRegistry
|
|
189
247
|
|
|
190
248
|
try:
|
|
191
|
-
return import_object(import_path, EvalSuiteRegistry, example=
|
|
249
|
+
return import_object(import_path, EvalSuiteRegistry, example="myapp/evaluations.py")
|
|
192
250
|
except ObjectImportError as exc:
|
|
193
251
|
raise _CliError(str(exc)) from exc
|
|
194
252
|
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"""Load trusted objects named on the command line (catalogs, registries)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import hashlib
|
|
6
|
+
import importlib
|
|
7
|
+
import importlib.util
|
|
8
|
+
import os
|
|
9
|
+
import sys
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from types import ModuleType
|
|
12
|
+
from typing import TypeVar
|
|
13
|
+
|
|
14
|
+
T = TypeVar("T")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ObjectImportError(ValueError):
|
|
18
|
+
"""A command-line reference could not be loaded as the expected type."""
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def import_object(reference: str, expected_type: type[T], *, example: str | None = None) -> T:
|
|
22
|
+
"""Load an ``expected_type`` instance from a module or a Python file.
|
|
23
|
+
|
|
24
|
+
``reference`` is ``SOURCE`` or ``SOURCE:NAME``, where ``SOURCE`` is a dotted module
|
|
25
|
+
path (``myapp.evaluations``) or a ``.py`` file path (``myapp/evaluations.py``).
|
|
26
|
+
Without ``:NAME`` the module must define exactly one ``expected_type`` instance.
|
|
27
|
+
Like ``python -m``, modules in the current working directory are importable.
|
|
28
|
+
|
|
29
|
+
Only for trusted configuration such as CLI arguments: importing runs module code.
|
|
30
|
+
Every failure raises ``ObjectImportError`` with a message suitable for the user.
|
|
31
|
+
"""
|
|
32
|
+
kind = expected_type.__name__
|
|
33
|
+
hint = f" Example: {example}" if example else ""
|
|
34
|
+
source, name = _split(reference)
|
|
35
|
+
if not source or name == "":
|
|
36
|
+
raise ObjectImportError(
|
|
37
|
+
f"Expected 'module.path', 'path/to/file.py' or either with ':object_name' for a {kind}, "
|
|
38
|
+
f"got {reference!r}.{hint}"
|
|
39
|
+
)
|
|
40
|
+
module = _load_file(source) if _is_file_reference(source) else _load_module(source)
|
|
41
|
+
if name is None:
|
|
42
|
+
return _only_instance(module, source, expected_type)
|
|
43
|
+
if not hasattr(module, name):
|
|
44
|
+
raise ObjectImportError(f"{name!r} not found in {source!r}.")
|
|
45
|
+
value = getattr(module, name)
|
|
46
|
+
if not isinstance(value, expected_type):
|
|
47
|
+
raise ObjectImportError(f"{reference!r} is a {type(value).__name__!r}, not a {kind} instance.")
|
|
48
|
+
return value
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _split(reference: str) -> tuple[str, str | None]:
|
|
52
|
+
"""``SOURCE`` and the optional ``NAME``; a Windows drive colon is not a separator."""
|
|
53
|
+
if ":" not in reference:
|
|
54
|
+
return reference, None
|
|
55
|
+
source, name = reference.rsplit(":", 1)
|
|
56
|
+
if any(sep in name for sep in ("/", "\\")) or name.endswith(".py"):
|
|
57
|
+
return reference, None
|
|
58
|
+
return source, name
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def _is_file_reference(source: str) -> bool:
|
|
62
|
+
return source.endswith(".py") or "/" in source or "\\" in source
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _load_module(module_path: str) -> ModuleType:
|
|
66
|
+
_import_from_working_directory()
|
|
67
|
+
try:
|
|
68
|
+
return importlib.import_module(module_path)
|
|
69
|
+
except Exception as exc: # boundary: any import-time failure is a configuration error
|
|
70
|
+
raise ObjectImportError(f"Could not import module {module_path!r}: {exc}") from exc
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def _load_file(file_path: str) -> ModuleType:
|
|
74
|
+
path = Path(file_path).expanduser().resolve()
|
|
75
|
+
if path.suffix != ".py" or not path.is_file():
|
|
76
|
+
raise ObjectImportError(f"No Python file at {file_path!r}.")
|
|
77
|
+
# One stable module name per file, so loading the same file twice reuses it.
|
|
78
|
+
digest = hashlib.sha1(str(path).encode()).hexdigest()[:12]
|
|
79
|
+
module_name = f"_agentbyte_cli_{path.stem}_{digest}"
|
|
80
|
+
if module_name in sys.modules:
|
|
81
|
+
return sys.modules[module_name]
|
|
82
|
+
_import_from_working_directory()
|
|
83
|
+
spec = importlib.util.spec_from_file_location(module_name, path)
|
|
84
|
+
if spec is None or spec.loader is None:
|
|
85
|
+
raise ObjectImportError(f"Could not load {file_path!r} as a Python module.")
|
|
86
|
+
module = importlib.util.module_from_spec(spec)
|
|
87
|
+
sys.modules[module_name] = module
|
|
88
|
+
try:
|
|
89
|
+
spec.loader.exec_module(module)
|
|
90
|
+
except Exception as exc: # boundary: any import-time failure is a configuration error
|
|
91
|
+
del sys.modules[module_name]
|
|
92
|
+
raise ObjectImportError(f"Could not load {file_path!r}: {exc}") from exc
|
|
93
|
+
return module
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def _only_instance(module: ModuleType, source: str, expected_type: type[T]) -> T:
|
|
97
|
+
found = {
|
|
98
|
+
name: value
|
|
99
|
+
for name, value in vars(module).items()
|
|
100
|
+
if not name.startswith("__") and isinstance(value, expected_type)
|
|
101
|
+
}
|
|
102
|
+
unique = {id(value): name for name, value in found.items()}
|
|
103
|
+
if len(unique) == 1:
|
|
104
|
+
return next(iter(found.values()))
|
|
105
|
+
kind = expected_type.__name__
|
|
106
|
+
if not found:
|
|
107
|
+
raise ObjectImportError(f"No {kind} found in {source!r}.")
|
|
108
|
+
names = ", ".join(sorted(found))
|
|
109
|
+
raise ObjectImportError(f"{source!r} defines several {kind} objects ({names}); add ':name' to pick one.")
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _import_from_working_directory() -> None:
|
|
113
|
+
cwd = os.getcwd()
|
|
114
|
+
if cwd not in sys.path and "" not in sys.path:
|
|
115
|
+
sys.path.insert(0, cwd)
|