agentbyte 0.7.0__tar.gz → 0.8.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.7.0 → agentbyte-0.8.0}/CHANGELOG.md +21 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/PKG-INFO +16 -3
- {agentbyte-0.7.0 → agentbyte-0.8.0}/README.md +11 -2
- {agentbyte-0.7.0 → agentbyte-0.8.0}/pyproject.toml +8 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/__about__.py +1 -1
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/agents/agent.py +3 -0
- agentbyte-0.8.0/src/agentbyte/middleware/sql_usage.py +140 -0
- agentbyte-0.8.0/src/agentbyte/middleware/usage_logger.py +177 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/presets/workflow.py +53 -6
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/__init__.py +4 -1
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/execution.py +29 -3
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/index.html +1 -1
- agentbyte-0.8.0/src/agentbyte/webui/frontend/package-lock.json +4893 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/package.json +4 -2
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/App.tsx +22 -48
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/agent/agent-view.tsx +21 -4
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/orchestrator/orchestrator-view.tsx +32 -5
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/shared/app-header.tsx +4 -7
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/shared/chat-base.tsx +26 -6
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/shared/debug-panel.tsx +55 -11
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/shared/entity-selector.tsx +2 -24
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/shared/session-switcher.tsx +7 -3
- agentbyte-0.8.0/src/agentbyte/webui/frontend/src/components/workflow/workflow-result-renderer.tsx +508 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/workflow/workflow-view.tsx +97 -33
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/hooks/messageHandlers.ts +41 -10
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/hooks/useEntityExecution.ts +125 -24
- agentbyte-0.8.0/src/agentbyte/webui/frontend/src/lib/format-utils.ts +3 -0
- agentbyte-0.8.0/src/agentbyte/webui/frontend/src/lib/user-id.ts +23 -0
- agentbyte-0.8.0/src/agentbyte/webui/frontend/src/lib/utils.ts +6 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/services/api.ts +99 -26
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/types/index.ts +2 -2
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/types/picoagents.ts +19 -11
- agentbyte-0.8.0/src/agentbyte/webui/frontend/yarn.lock +2401 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/models.py +13 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/server.py +100 -48
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/sessions.py +69 -4
- agentbyte-0.8.0/src/agentbyte/webui/ui/assets/index-CPLl1y5f.js +82 -0
- agentbyte-0.8.0/src/agentbyte/webui/ui/assets/index-DLCk-jRl.css +1 -0
- {agentbyte-0.7.0/src/agentbyte/webui/agent_framework_devui → agentbyte-0.8.0/src/agentbyte/webui}/ui/index.html +3 -3
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/core/models.py +1 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/core/runner.py +11 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/steps/agentbyte_agent.py +20 -3
- agentbyte-0.8.0/tests/middleware/test_sql_usage.py +245 -0
- agentbyte-0.8.0/tests/middleware/test_usage_logger.py +221 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/presets/test_orchestration.py +38 -0
- agentbyte-0.8.0/tests/presets/test_workflow.py +96 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_source.py +1 -1
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/webui/test_execution.py +32 -1
- agentbyte-0.8.0/tests/webui/test_server.py +185 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/webui/test_sessions.py +51 -1
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/workflow/test_workflow_models.py +21 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/workflow/test_workflow_runner.py +15 -0
- agentbyte-0.7.0/src/agentbyte/webui/agent_framework_devui/ui/assets/index-BzhEszHZ.css +0 -1
- agentbyte-0.7.0/src/agentbyte/webui/agent_framework_devui/ui/assets/index-DByFJNGD.js +0 -245
- agentbyte-0.7.0/src/agentbyte/webui/frontend/src/components/shared/examples-gallery.tsx +0 -268
- agentbyte-0.7.0/src/agentbyte/webui/frontend/yarn.lock +0 -2282
- agentbyte-0.7.0/src/agentbyte/webui/ui/assets/index-CWk64UM3.js +0 -359
- agentbyte-0.7.0/src/agentbyte/webui/ui/assets/index-vt1cujlT.css +0 -1
- agentbyte-0.7.0/src/agentbyte/webui/ui/index.html +0 -14
- agentbyte-0.7.0/src/agentbyte/webui/ui/vite.svg +0 -1
- agentbyte-0.7.0/tests/presets/test_workflow.py +0 -30
- agentbyte-0.7.0/tests/webui/test_server.py +0 -54
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-agent-as-tool/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-ai-driven-orchestration/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-dataset/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-fastapi-sse-streaming/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-function-tools/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-handoff-orchestration/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-list-memory/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-llm-client/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-memory-tool/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-middleware/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-multi-turn-context/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-otel-tracing/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-plan-based-orchestration/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-round-robin-orchestration/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-simple-agent/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-tool-approval/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/agentbyte-workflow/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.github/skills/skill-authoring/SKILL.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/.gitignore +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/LICENSE +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/agents/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/agents/agent_as_tool.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/agents/base.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/agents/types.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/cancellation_token.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/cli/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/cli/main.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/component.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/context.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/dataset/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/dataset/base.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/dataset/config.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/dataset/json.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/dataset/loader.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/dataset/loaders.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/dataset/sources.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/dataset/sqlite.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/entity.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/_retry_observability.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/auth.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/azure/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/azure/auth.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/azure/chat.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/azure/embedding.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/azure/settings.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/azure_openai.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/azure_openai_embedding.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/base.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/embeddings_base.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/openai/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/openai/chat.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/openai/embedding.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/openai/settings.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/openai.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/openai_embedding.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/pricing.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/retry_policy.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/settings.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/llm/types.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/memory/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/memory/base.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/messages.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/microwebui/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/microwebui/server.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/microwebui/ui/index.html +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/middleware/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/middleware/base.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/middleware/otel.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/middleware/retry.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/notebook.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/orchestration/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/orchestration/ai.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/orchestration/base.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/orchestration/handoff.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/orchestration/plan.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/orchestration/policies.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/orchestration/round_robin.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/presets/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/presets/agents.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/presets/clients.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/presets/orchestration.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/session_store.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/base.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/cancellation.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/composite.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/consecutive_agent.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/external.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/function_call.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/handoff.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/max_message.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/predicate.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/source.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/text_mention.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/timeout.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/termination/token_usage.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/tools/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/tools/base.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/tools/core_tools.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/tools/decorator.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/tools/memory_tool.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/types.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/discovery.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/.gitignore +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/README.md +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/components.json +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/eslint.config.js +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/plan.md +0 -0
- {agentbyte-0.7.0/src/agentbyte/webui/agent_framework_devui/ui → agentbyte-0.8.0/src/agentbyte/webui/frontend/public}/vite.svg +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/App.css +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/assets/react.svg +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/message_renderer/ContentRenderer.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/message_renderer/MessageRenderer.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/message_renderer/index.ts +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/message_renderer/types.ts +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/mode-toggle.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/shared/context-inspector.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/shared/example-tasks-display.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/shared/tool-approval-banner.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/theme-provider.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/attachment-gallery.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/badge.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/button.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/card.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/dialog.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/dropdown-menu.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/file-upload.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/input.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/label.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/loading-spinner.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/loading-state.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/message-input.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/scroll-area.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/slider.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/tabs.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/components/ui/textarea.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/index.css +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/main.tsx +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/utils/message-utils.ts +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/src/vite-env.d.ts +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/tsconfig.app.json +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/tsconfig.json +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/tsconfig.node.json +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/frontend/vite.config.ts +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/registry.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/webui/session_store.py +0 -0
- {agentbyte-0.7.0/src/agentbyte/webui/frontend/public → agentbyte-0.8.0/src/agentbyte/webui/ui}/vite.svg +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/agent.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/core/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/core/_structure_hash.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/core/checkpoint.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/core/workflow.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/defaults.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/loader.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/schema.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/schema_utils.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/steps/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/steps/echo.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/steps/function.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/steps/http.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/steps/step.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/steps/subworkflow.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/steps/transform.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/src/agentbyte/workflow/visualizer.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/agents/test_agent_as_tool.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/agents/test_agent_basic.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/agents/test_agent_event_types.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/agents/test_agent_memory_integration.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/agents/test_agent_middleware_integration.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/agents/test_agent_retry_middleware.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/agents/test_agent_stream_events.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/agents/test_tool_approval.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/cli/test_create_skills.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/dataset/test_loader.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/llm/test_azure_client.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/llm/test_azure_embedding_client.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/llm/test_llm_types.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/llm/test_openai_client.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/llm/test_openai_embedding_client.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/llm/test_retry_observability.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/llm/test_retry_policy_api.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/memory/test_memory.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/middleware/test_middleware_chain.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/middleware/test_otel.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/middleware/test_retry_middleware.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/orchestration/test_ai_orchestrator.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/orchestration/test_base_orchestrator.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/orchestration/test_handoff_orchestrator.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/orchestration/test_plan_orchestrator.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/orchestration/test_round_robin.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/presets/test_agents.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/presets/test_clients.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_base.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_cancellation.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_composite.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_consecutive_agent.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_external.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_function_call.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_handoff.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_max_message.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_predicate.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_text_mention.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_timeout.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/termination/test_token_usage.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/test_cancellation_token.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/test_context.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/test_messages.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/test_package_api.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/test_session_store.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/test_types.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/tools/test_memory_tool.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/tools/test_tools.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/webui/__init__.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/webui/helpers.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/webui/test_package_api.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/webui/test_registry.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/workflow/test_checkpoint.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/workflow/test_subworkflow_step.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/workflow/test_workflow_agent.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/workflow/test_workflow_class.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/workflow/test_workflow_schema.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/workflow/test_workflow_steps.py +0 -0
- {agentbyte-0.7.0 → agentbyte-0.8.0}/tests/workflow/test_workflow_visualizer.py +0 -0
|
@@ -4,6 +4,27 @@ All notable changes to Agentbyte are documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format follows Keep a Changelog principles and semantic versioning.
|
|
6
6
|
|
|
7
|
+
## [0.8.0] - 2026-04-13
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Added SQL-backed usage logging middleware with a typed persistence contract plus SQLModel-backed storage for LLM usage records.
|
|
12
|
+
- Added `examples/webui/in_memory.py` and `examples/webui/presets_webui.py` as concrete launchers for the packaged AgentByte WebUI.
|
|
13
|
+
- Added plan-based orchestration to the preset-backed WebUI catalog so round-robin, AI-driven, and plan-based teams are all selectable from the same real-entities launcher.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Completed the `agentbyte.webui` session contract: WebUI sessions now support `user_id`, stricter session/entity binding, and injected durable session stores for persisted `AgentContext` reload across restarts.
|
|
18
|
+
- Rebased and adapted the packaged WebUI frontend to AgentByte's backend contracts, including fixed session query handling, stable post-stream message refresh, richer workflow result rendering, cleaner orchestration event classification, and improved debug-panel payload inspection.
|
|
19
|
+
- Extended agent and orchestrator WebUI usage surfaces to show both token counts and cost estimates when providers supply pricing data.
|
|
20
|
+
- Removed the unused bundled examples-gallery flow and other stale picoagents-only frontend assumptions from the packaged WebUI.
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- Fixed agent stream completion handling in the WebUI so final agent state events no longer fall through to `unknown`, immediate UI finalization works again, and post-stream session refresh reliably recalculates session totals.
|
|
25
|
+
- Fixed round-robin and other orchestrator debug events so lifecycle payloads render as labeled orchestration events instead of opaque `unknown` entries.
|
|
26
|
+
- Fixed workflow completion rendering so the WebUI shows terminal workflow outputs directly instead of dumping the raw completion envelope.
|
|
27
|
+
|
|
7
28
|
## [0.7.0] - 2026-04-09
|
|
8
29
|
|
|
9
30
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentbyte
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.8.0
|
|
4
4
|
Summary: A toolkit for designing multiagent systems
|
|
5
5
|
Project-URL: Homepage, https://gitlab.com/pyninja/aiengineering/agentbyte
|
|
6
6
|
Project-URL: Repository, https://gitlab.com/pyninja/aiengineering/agentbyte
|
|
@@ -42,6 +42,10 @@ Provides-Extra: otel
|
|
|
42
42
|
Requires-Dist: opentelemetry-api>=1.39.1; extra == 'otel'
|
|
43
43
|
Requires-Dist: opentelemetry-exporter-otlp-proto-http>=1.39.1; extra == 'otel'
|
|
44
44
|
Requires-Dist: opentelemetry-sdk>=1.39.1; extra == 'otel'
|
|
45
|
+
Provides-Extra: sql
|
|
46
|
+
Requires-Dist: aiosqlite>=0.22.1; extra == 'sql'
|
|
47
|
+
Requires-Dist: asyncpg>=0.31.0; extra == 'sql'
|
|
48
|
+
Requires-Dist: sqlmodel>=0.0.38; extra == 'sql'
|
|
45
49
|
Provides-Extra: test
|
|
46
50
|
Requires-Dist: pytest-asyncio>=1.3.0; extra == 'test'
|
|
47
51
|
Requires-Dist: pytest-cov>=7.0.0; extra == 'test'
|
|
@@ -55,17 +59,26 @@ Requires-Dist: uvicorn[standard]>=0.44.0; extra == 'webui'
|
|
|
55
59
|
Description-Content-Type: text/markdown
|
|
56
60
|
|
|
57
61
|
<p align="center">
|
|
58
|
-
<img src="https://gitlab.com/pyninja/aiengineering/agentbyte/-/raw/v0.
|
|
62
|
+
<img src="https://gitlab.com/pyninja/aiengineering/agentbyte/-/raw/v0.8.0/logo/agent-byte-avatar-low.png" alt="Agentbyte" width="200"/>
|
|
59
63
|
</p>
|
|
60
64
|
|
|
61
65
|
# Agentbyte
|
|
62
66
|
|
|
63
67
|
Agentbyte is an observability-first agentic AI framework for building and studying multiagent systems with a learning-first, implementation-oriented workflow.
|
|
64
68
|
|
|
65
|
-
Current release: **0.
|
|
69
|
+
Current release: **0.8.0**
|
|
66
70
|
|
|
67
71
|
Repository: [gitlab.com/pyninja/aiengineering/agentbyte](https://gitlab.com/pyninja/aiengineering/agentbyte)
|
|
68
72
|
|
|
73
|
+
## What's New in 0.8.0
|
|
74
|
+
|
|
75
|
+
**WebUI maturity + preset expansion + SQL usage logging**
|
|
76
|
+
|
|
77
|
+
- Completed the server-side WebUI session contract with user-scoped sessions, stricter `session_id` binding to `entity_id`, and injectable session stores for durable context reload.
|
|
78
|
+
- Rebased and adopted the bundled WebUI frontend to AgentByte's backend contract, including fixed session lookup, post-stream session refresh, richer workflow result rendering, improved debug panel behavior, and visible usage cost for agent and orchestrator sessions.
|
|
79
|
+
- Added real-entity WebUI launchers under `examples/webui/`, including preset-backed agents, workflows, and all three top-level orchestration patterns: round-robin, AI-driven, and plan-based.
|
|
80
|
+
- Added SQL-backed usage logging middleware so provider usage records can be persisted through a typed backend contract instead of staying in-memory only.
|
|
81
|
+
|
|
69
82
|
## What's New in 0.7.0
|
|
70
83
|
|
|
71
84
|
**MicroWebUI streaming polish + bundled SSE skill**
|
|
@@ -1,15 +1,24 @@
|
|
|
1
1
|
<p align="center">
|
|
2
|
-
<img src="https://gitlab.com/pyninja/aiengineering/agentbyte/-/raw/v0.
|
|
2
|
+
<img src="https://gitlab.com/pyninja/aiengineering/agentbyte/-/raw/v0.8.0/logo/agent-byte-avatar-low.png" alt="Agentbyte" width="200"/>
|
|
3
3
|
</p>
|
|
4
4
|
|
|
5
5
|
# Agentbyte
|
|
6
6
|
|
|
7
7
|
Agentbyte is an observability-first agentic AI framework for building and studying multiagent systems with a learning-first, implementation-oriented workflow.
|
|
8
8
|
|
|
9
|
-
Current release: **0.
|
|
9
|
+
Current release: **0.8.0**
|
|
10
10
|
|
|
11
11
|
Repository: [gitlab.com/pyninja/aiengineering/agentbyte](https://gitlab.com/pyninja/aiengineering/agentbyte)
|
|
12
12
|
|
|
13
|
+
## What's New in 0.8.0
|
|
14
|
+
|
|
15
|
+
**WebUI maturity + preset expansion + SQL usage logging**
|
|
16
|
+
|
|
17
|
+
- Completed the server-side WebUI session contract with user-scoped sessions, stricter `session_id` binding to `entity_id`, and injectable session stores for durable context reload.
|
|
18
|
+
- Rebased and adopted the bundled WebUI frontend to AgentByte's backend contract, including fixed session lookup, post-stream session refresh, richer workflow result rendering, improved debug panel behavior, and visible usage cost for agent and orchestrator sessions.
|
|
19
|
+
- Added real-entity WebUI launchers under `examples/webui/`, including preset-backed agents, workflows, and all three top-level orchestration patterns: round-robin, AI-driven, and plan-based.
|
|
20
|
+
- Added SQL-backed usage logging middleware so provider usage records can be persisted through a typed backend contract instead of staying in-memory only.
|
|
21
|
+
|
|
13
22
|
## What's New in 0.7.0
|
|
14
23
|
|
|
15
24
|
**MicroWebUI streaming polish + bundled SSE skill**
|
|
@@ -44,6 +44,11 @@ webui = [
|
|
|
44
44
|
"fastapi>=0.135.2",
|
|
45
45
|
"uvicorn[standard]>=0.44.0",
|
|
46
46
|
]
|
|
47
|
+
sql = [
|
|
48
|
+
"sqlmodel>=0.0.38",
|
|
49
|
+
"asyncpg>=0.31.0",
|
|
50
|
+
"aiosqlite>=0.22.1",
|
|
51
|
+
]
|
|
47
52
|
viz = [
|
|
48
53
|
"graphviz>=0.21",
|
|
49
54
|
]
|
|
@@ -120,6 +125,9 @@ test = [
|
|
|
120
125
|
"pytest-asyncio>=1.3.0",
|
|
121
126
|
"pytest-cov>=7.0.0",
|
|
122
127
|
"ruff>=0.15.0",
|
|
128
|
+
"aiosqlite>=0.22.1",
|
|
129
|
+
"sqlmodel>=0.0.38",
|
|
130
|
+
"greenlet>=3.0.0",
|
|
123
131
|
]
|
|
124
132
|
viz = [
|
|
125
133
|
"graphviz>=0.21",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
__version__ = "0.
|
|
1
|
+
__version__ = "0.8.0"
|
|
2
2
|
VERSION = __version__
|
|
@@ -5,6 +5,7 @@ Concrete Agent implementation with core execution loop.
|
|
|
5
5
|
import asyncio
|
|
6
6
|
import os
|
|
7
7
|
import time
|
|
8
|
+
import uuid
|
|
8
9
|
import warnings
|
|
9
10
|
from collections.abc import AsyncGenerator
|
|
10
11
|
from typing import List, Optional, Union
|
|
@@ -74,6 +75,8 @@ class Agent(BaseAgent):
|
|
|
74
75
|
cancellation_token: Optional[CancellationToken] = None,
|
|
75
76
|
) -> AgentResponse:
|
|
76
77
|
working_context = context if context is not None else AgentContext()
|
|
78
|
+
if "run_id" not in working_context.metadata:
|
|
79
|
+
working_context.metadata["run_id"] = str(uuid.uuid4())
|
|
77
80
|
if not task and working_context.is_empty:
|
|
78
81
|
raise AgentConfigurationError(
|
|
79
82
|
"Either 'task' must be provided or 'context' must be non-empty."
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
"""SQL backend for UsageLoggerMiddleware.
|
|
2
|
+
|
|
3
|
+
Persists :class:`~agentbyte.middleware.usage_logger.UsageEvent` rows to any
|
|
4
|
+
SQLAlchemy-supported database using SQLModel for table definitions and
|
|
5
|
+
SQLAlchemy's async session for writes.
|
|
6
|
+
|
|
7
|
+
Requires the ``sql`` optional extra::
|
|
8
|
+
|
|
9
|
+
uv sync --extra sql
|
|
10
|
+
|
|
11
|
+
Supports both PostgreSQL (via asyncpg) and SQLite (via aiosqlite).
|
|
12
|
+
|
|
13
|
+
Usage::
|
|
14
|
+
|
|
15
|
+
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
|
|
16
|
+
from sqlalchemy.orm import sessionmaker
|
|
17
|
+
from agentbyte.middleware.sql_usage import SqlUsageBackend, create_usage_tables
|
|
18
|
+
|
|
19
|
+
engine = create_async_engine("postgresql+asyncpg://user:pass@host/db")
|
|
20
|
+
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
|
|
21
|
+
|
|
22
|
+
async def get_session():
|
|
23
|
+
async with AsyncSessionLocal() as session:
|
|
24
|
+
yield session
|
|
25
|
+
|
|
26
|
+
await create_usage_tables(engine)
|
|
27
|
+
backend = SqlUsageBackend(session_factory=get_session)
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
from __future__ import annotations
|
|
31
|
+
|
|
32
|
+
from collections.abc import AsyncGenerator, Callable
|
|
33
|
+
from datetime import datetime, timezone
|
|
34
|
+
from typing import Optional
|
|
35
|
+
|
|
36
|
+
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession
|
|
37
|
+
from sqlmodel import Field, SQLModel
|
|
38
|
+
|
|
39
|
+
from .usage_logger import UsageEvent, UsagePersistenceBackend
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class LlmUsageEvent(SQLModel, table=True):
|
|
43
|
+
"""SQLModel table that stores one row per LLM call.
|
|
44
|
+
|
|
45
|
+
This class is internal to :class:`SqlUsageBackend`. Callers who need
|
|
46
|
+
direct DB access can import it for read-only queries.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
__tablename__ = "llm_usage_events"
|
|
50
|
+
|
|
51
|
+
id: Optional[int] = Field(default=None, primary_key=True)
|
|
52
|
+
run_id: Optional[str] = Field(default=None, index=True)
|
|
53
|
+
session_id: Optional[str] = Field(default=None, index=True)
|
|
54
|
+
user_id: Optional[str] = Field(default=None)
|
|
55
|
+
identifier: Optional[str] = Field(default=None, index=True)
|
|
56
|
+
agent_name: str
|
|
57
|
+
model: str
|
|
58
|
+
duration_ms: int = Field(default=0)
|
|
59
|
+
llm_calls: int = Field(default=0)
|
|
60
|
+
tokens_input: int = Field(default=0)
|
|
61
|
+
tokens_output: int = Field(default=0)
|
|
62
|
+
tool_calls: int = Field(default=0)
|
|
63
|
+
memory_operations: int = Field(default=0)
|
|
64
|
+
cost_estimate: Optional[float] = Field(default=None)
|
|
65
|
+
recorded_at: datetime = Field(
|
|
66
|
+
default_factory=lambda: datetime.now(timezone.utc),
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
async def create_usage_tables(engine: AsyncEngine) -> None:
|
|
71
|
+
"""Create the ``llm_usage_events`` table if it does not exist.
|
|
72
|
+
|
|
73
|
+
Call this once at application startup before any agents run::
|
|
74
|
+
|
|
75
|
+
await create_usage_tables(engine)
|
|
76
|
+
"""
|
|
77
|
+
async with engine.begin() as conn:
|
|
78
|
+
await conn.run_sync(SQLModel.metadata.create_all)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
class SqlUsageBackend(UsagePersistenceBackend):
|
|
82
|
+
"""Persists :class:`~agentbyte.middleware.usage_logger.UsageEvent` rows
|
|
83
|
+
to a SQL database via an async SQLAlchemy session.
|
|
84
|
+
|
|
85
|
+
The caller is responsible for creating the engine and session factory.
|
|
86
|
+
This backend holds only a reference to the factory — it does not own the
|
|
87
|
+
connection pool.
|
|
88
|
+
|
|
89
|
+
Args:
|
|
90
|
+
session_factory: Zero-argument async generator factory that yields one
|
|
91
|
+
:class:`~sqlalchemy.ext.asyncio.AsyncSession` per call. The
|
|
92
|
+
factory should handle its own cleanup (e.g. via ``async with``).
|
|
93
|
+
|
|
94
|
+
Example::
|
|
95
|
+
|
|
96
|
+
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
|
|
97
|
+
from sqlalchemy.orm import sessionmaker
|
|
98
|
+
|
|
99
|
+
engine = create_async_engine("postgresql+asyncpg://user:pass@host/db")
|
|
100
|
+
AsyncSessionLocal = sessionmaker(
|
|
101
|
+
engine, class_=AsyncSession, expire_on_commit=False
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
async def get_session():
|
|
105
|
+
async with AsyncSessionLocal() as session:
|
|
106
|
+
yield session
|
|
107
|
+
|
|
108
|
+
backend = SqlUsageBackend(session_factory=get_session)
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
def __init__(
|
|
112
|
+
self,
|
|
113
|
+
session_factory: Callable[[], AsyncGenerator[AsyncSession, None]],
|
|
114
|
+
) -> None:
|
|
115
|
+
self._session_factory = session_factory
|
|
116
|
+
|
|
117
|
+
async def write(self, event: UsageEvent) -> None:
|
|
118
|
+
gen = self._session_factory()
|
|
119
|
+
session: AsyncSession = await gen.__anext__()
|
|
120
|
+
try:
|
|
121
|
+
row = LlmUsageEvent(
|
|
122
|
+
run_id=event.run_id,
|
|
123
|
+
session_id=event.session_id,
|
|
124
|
+
user_id=event.user_id,
|
|
125
|
+
identifier=event.identifier,
|
|
126
|
+
agent_name=event.agent_name,
|
|
127
|
+
model=event.model,
|
|
128
|
+
duration_ms=event.duration_ms,
|
|
129
|
+
llm_calls=event.llm_calls,
|
|
130
|
+
tokens_input=event.tokens_input,
|
|
131
|
+
tokens_output=event.tokens_output,
|
|
132
|
+
tool_calls=event.tool_calls,
|
|
133
|
+
memory_operations=event.memory_operations,
|
|
134
|
+
cost_estimate=event.cost_estimate,
|
|
135
|
+
recorded_at=event.recorded_at,
|
|
136
|
+
)
|
|
137
|
+
session.add(row)
|
|
138
|
+
await session.commit()
|
|
139
|
+
finally:
|
|
140
|
+
await gen.aclose()
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"""Usage logging middleware with a pluggable persistence backend.
|
|
2
|
+
|
|
3
|
+
Writes one :class:`UsageEvent` per LLM ``MODEL_CALL`` to whatever
|
|
4
|
+
:class:`UsagePersistenceBackend` the caller supplies. The first concrete
|
|
5
|
+
backend is :class:`~agentbyte.middleware.sql_usage.SqlUsageBackend`; future
|
|
6
|
+
backends (CosmosDB, DynamoDB, …) implement the same interface.
|
|
7
|
+
|
|
8
|
+
Usage::
|
|
9
|
+
|
|
10
|
+
from agentbyte.middleware.usage_logger import UsageLoggerMiddleware
|
|
11
|
+
from agentbyte.middleware.sql_usage import SqlUsageBackend, create_usage_tables
|
|
12
|
+
|
|
13
|
+
backend = SqlUsageBackend(session_factory=get_session)
|
|
14
|
+
mw = UsageLoggerMiddleware(backend=backend, identifier="my-app")
|
|
15
|
+
agent = Agent(..., middlewares=[mw])
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import asyncio
|
|
21
|
+
import warnings
|
|
22
|
+
from abc import ABC, abstractmethod
|
|
23
|
+
from datetime import datetime, timezone
|
|
24
|
+
from typing import Any, Optional
|
|
25
|
+
|
|
26
|
+
from pydantic import BaseModel, Field
|
|
27
|
+
|
|
28
|
+
from .base import BaseMiddleware, MiddlewareContext, OperationType
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class UsageEvent(BaseModel):
|
|
32
|
+
"""Data contract passed to every :class:`UsagePersistenceBackend`.
|
|
33
|
+
|
|
34
|
+
All fields are derived from the :class:`~agentbyte.middleware.base.MiddlewareContext`
|
|
35
|
+
and the :class:`~agentbyte.llm.types.ChatCompletionResult` returned by a
|
|
36
|
+
``MODEL_CALL`` operation. Backends receive this object and persist it in
|
|
37
|
+
whatever form suits their storage technology.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
run_id: Optional[str] = Field(
|
|
41
|
+
default=None,
|
|
42
|
+
description="Groups all LLM calls that belong to one agent.run() invocation",
|
|
43
|
+
)
|
|
44
|
+
session_id: Optional[str] = Field(
|
|
45
|
+
default=None,
|
|
46
|
+
description="Session identifier from AgentContext",
|
|
47
|
+
)
|
|
48
|
+
user_id: Optional[str] = Field(
|
|
49
|
+
default=None,
|
|
50
|
+
description="User identifier from AgentContext",
|
|
51
|
+
)
|
|
52
|
+
identifier: Optional[str] = Field(
|
|
53
|
+
default=None,
|
|
54
|
+
description="Application or service label set at middleware init",
|
|
55
|
+
)
|
|
56
|
+
agent_name: str = Field(description="Name of the agent that made the call")
|
|
57
|
+
model: str = Field(description="Model name used for the call")
|
|
58
|
+
# Full Usage fields
|
|
59
|
+
duration_ms: int = Field(default=0, description="Wall-clock time in milliseconds")
|
|
60
|
+
llm_calls: int = Field(default=0, description="LLM call count (typically 1 per event)")
|
|
61
|
+
tokens_input: int = Field(default=0, description="Prompt tokens consumed")
|
|
62
|
+
tokens_output: int = Field(default=0, description="Completion tokens generated")
|
|
63
|
+
tool_calls: int = Field(default=0, description="Tool invocations in Usage")
|
|
64
|
+
memory_operations: int = Field(default=0, description="Memory operations in Usage")
|
|
65
|
+
cost_estimate: Optional[float] = Field(
|
|
66
|
+
default=None,
|
|
67
|
+
description="Estimated USD cost (None when provider does not supply pricing)",
|
|
68
|
+
)
|
|
69
|
+
recorded_at: datetime = Field(
|
|
70
|
+
default_factory=lambda: datetime.now(timezone.utc),
|
|
71
|
+
description="UTC timestamp when the event was created",
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
class UsagePersistenceBackend(ABC):
|
|
76
|
+
"""Interface that all usage storage backends must satisfy.
|
|
77
|
+
|
|
78
|
+
Implement :meth:`write` to persist a :class:`UsageEvent`. The optional
|
|
79
|
+
:meth:`setup` and :meth:`close` hooks let backends manage connection
|
|
80
|
+
lifecycle when the caller needs explicit control.
|
|
81
|
+
|
|
82
|
+
Example — minimal custom backend::
|
|
83
|
+
|
|
84
|
+
class PrintBackend(UsagePersistenceBackend):
|
|
85
|
+
async def write(self, event: UsageEvent) -> None:
|
|
86
|
+
print(event.model_dump_json())
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
@abstractmethod
|
|
90
|
+
async def write(self, event: UsageEvent) -> None:
|
|
91
|
+
"""Persist one usage event. Must not raise — errors should be handled internally."""
|
|
92
|
+
|
|
93
|
+
async def setup(self) -> None:
|
|
94
|
+
"""Optional: initialise connections, create tables, etc."""
|
|
95
|
+
|
|
96
|
+
async def close(self) -> None:
|
|
97
|
+
"""Optional: clean up connections and flush buffers."""
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
class UsageLoggerMiddleware(BaseMiddleware):
|
|
101
|
+
"""Middleware that writes one :class:`UsageEvent` per LLM call to a backend.
|
|
102
|
+
|
|
103
|
+
Writes are fire-and-forget (``asyncio.create_task``). Backend failures are
|
|
104
|
+
swallowed as ``RuntimeWarning`` and never interrupt agent execution.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
backend: Any :class:`UsagePersistenceBackend` implementation.
|
|
108
|
+
identifier: Optional application/service label stored on every event.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
def __init__(
|
|
112
|
+
self,
|
|
113
|
+
backend: UsagePersistenceBackend,
|
|
114
|
+
identifier: Optional[str] = None,
|
|
115
|
+
) -> None:
|
|
116
|
+
self._backend = backend
|
|
117
|
+
self._identifier = identifier
|
|
118
|
+
|
|
119
|
+
async def _write(self, event: UsageEvent) -> None:
|
|
120
|
+
try:
|
|
121
|
+
await self._backend.write(event)
|
|
122
|
+
except Exception as exc:
|
|
123
|
+
warnings.warn(
|
|
124
|
+
f"UsageLoggerMiddleware: backend write failed: {exc}",
|
|
125
|
+
RuntimeWarning,
|
|
126
|
+
stacklevel=2,
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
async def process_request(self, context: MiddlewareContext) -> MiddlewareContext:
|
|
130
|
+
return context
|
|
131
|
+
|
|
132
|
+
async def process_response(
|
|
133
|
+
self,
|
|
134
|
+
context: MiddlewareContext,
|
|
135
|
+
result: Any,
|
|
136
|
+
) -> Any:
|
|
137
|
+
if context.operation != OperationType.MODEL_CALL:
|
|
138
|
+
return result
|
|
139
|
+
|
|
140
|
+
usage = getattr(result, "usage", None)
|
|
141
|
+
if usage is None:
|
|
142
|
+
return result
|
|
143
|
+
|
|
144
|
+
agent_ctx = context.agent_context
|
|
145
|
+
run_id: Optional[str] = None
|
|
146
|
+
if agent_ctx is not None:
|
|
147
|
+
raw = agent_ctx.metadata.get("run_id")
|
|
148
|
+
if raw is not None:
|
|
149
|
+
run_id = str(raw)
|
|
150
|
+
|
|
151
|
+
model: str = context.metadata.get("model") or getattr(result, "model", "unknown")
|
|
152
|
+
|
|
153
|
+
event = UsageEvent(
|
|
154
|
+
run_id=run_id,
|
|
155
|
+
session_id=agent_ctx.session_id if agent_ctx is not None else None,
|
|
156
|
+
user_id=agent_ctx.user_id if agent_ctx is not None else None,
|
|
157
|
+
identifier=self._identifier,
|
|
158
|
+
agent_name=context.agent_name,
|
|
159
|
+
model=model,
|
|
160
|
+
duration_ms=usage.duration_ms,
|
|
161
|
+
llm_calls=usage.llm_calls,
|
|
162
|
+
tokens_input=usage.tokens_input,
|
|
163
|
+
tokens_output=usage.tokens_output,
|
|
164
|
+
tool_calls=usage.tool_calls,
|
|
165
|
+
memory_operations=usage.memory_operations,
|
|
166
|
+
cost_estimate=usage.cost_estimate,
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
asyncio.create_task(self._write(event))
|
|
170
|
+
return result
|
|
171
|
+
|
|
172
|
+
async def process_error(
|
|
173
|
+
self,
|
|
174
|
+
context: MiddlewareContext,
|
|
175
|
+
error: Exception,
|
|
176
|
+
) -> Optional[Any]:
|
|
177
|
+
return None
|
|
@@ -6,7 +6,7 @@ from typing import Any
|
|
|
6
6
|
|
|
7
7
|
from agentbyte.llm import BaseChatCompletionClient
|
|
8
8
|
from agentbyte.workflow import Workflow, WorkflowConfig
|
|
9
|
-
from agentbyte.workflow.core.models import StepMetadata
|
|
9
|
+
from agentbyte.workflow.core.models import StepMetadata, WorkflowContext
|
|
10
10
|
from agentbyte.workflow.steps import AgentStep, FunctionStep
|
|
11
11
|
from agentbyte.workflow.steps.agentbyte_agent import (
|
|
12
12
|
AgentbyteAgentInput,
|
|
@@ -17,6 +17,42 @@ from .agents import get_researcher, get_reviewer, get_writer
|
|
|
17
17
|
from .clients import build_chat_client
|
|
18
18
|
|
|
19
19
|
|
|
20
|
+
def _writer_to_reviewer_fn(
|
|
21
|
+
output: AgentbyteAgentOutput, context: WorkflowContext
|
|
22
|
+
) -> dict:
|
|
23
|
+
"""Transform writer output into reviewer input; store draft for later retrieval."""
|
|
24
|
+
context.set("writer_draft", output.response or "")
|
|
25
|
+
return {
|
|
26
|
+
"task": output.response or "",
|
|
27
|
+
"additional_context": {"messages": output.messages, "usage": output.usage},
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def _reviewer_to_writer_fn(
|
|
32
|
+
output: AgentbyteAgentOutput, context: WorkflowContext
|
|
33
|
+
) -> dict:
|
|
34
|
+
"""Transform reviewer output into writer_final input.
|
|
35
|
+
|
|
36
|
+
Passes the original draft plus reviewer feedback so the writer can
|
|
37
|
+
produce an improved final version. If the reviewer approved, the writer
|
|
38
|
+
is asked to confirm and present the polished version.
|
|
39
|
+
"""
|
|
40
|
+
draft = context.get("writer_draft") or ""
|
|
41
|
+
feedback = (output.response or "").strip()
|
|
42
|
+
approved = feedback.upper() == "APPROVED"
|
|
43
|
+
if approved:
|
|
44
|
+
task = f"Your draft was approved by the reviewer. Output the final polished version:\n\n{draft}"
|
|
45
|
+
else:
|
|
46
|
+
task = (
|
|
47
|
+
f"Revise your draft based on the reviewer's feedback.\n\n"
|
|
48
|
+
f"Your draft:\n{draft}\n\nReviewer feedback:\n{feedback}"
|
|
49
|
+
)
|
|
50
|
+
return {
|
|
51
|
+
"task": task,
|
|
52
|
+
"additional_context": {"messages": output.messages, "usage": output.usage},
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
|
|
20
56
|
def _create_linear_research_writer_reviewer_workflow(
|
|
21
57
|
*,
|
|
22
58
|
name: str,
|
|
@@ -25,7 +61,7 @@ def _create_linear_research_writer_reviewer_workflow(
|
|
|
25
61
|
writer,
|
|
26
62
|
reviewer,
|
|
27
63
|
) -> Workflow:
|
|
28
|
-
"""Create the default researcher -> writer -> reviewer workflow."""
|
|
64
|
+
"""Create the default researcher -> writer -> reviewer -> writer_final workflow."""
|
|
29
65
|
workflow = Workflow(WorkflowConfig(name=name, description=description))
|
|
30
66
|
researcher_step = AgentStep(
|
|
31
67
|
step_id="researcher",
|
|
@@ -57,10 +93,19 @@ def _create_linear_research_writer_reviewer_workflow(
|
|
|
57
93
|
metadata=StepMetadata(name="writer_to_reviewer"),
|
|
58
94
|
input_type=AgentbyteAgentOutput,
|
|
59
95
|
output_type=AgentbyteAgentInput,
|
|
60
|
-
func=
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
96
|
+
func=_writer_to_reviewer_fn,
|
|
97
|
+
)
|
|
98
|
+
reviewer_to_writer = FunctionStep(
|
|
99
|
+
step_id="reviewer_to_writer",
|
|
100
|
+
metadata=StepMetadata(name="reviewer_to_writer"),
|
|
101
|
+
input_type=AgentbyteAgentOutput,
|
|
102
|
+
output_type=AgentbyteAgentInput,
|
|
103
|
+
func=_reviewer_to_writer_fn,
|
|
104
|
+
)
|
|
105
|
+
writer_final_step = AgentStep(
|
|
106
|
+
step_id="writer_final",
|
|
107
|
+
metadata=StepMetadata(name="writer_final"),
|
|
108
|
+
agent=writer,
|
|
64
109
|
)
|
|
65
110
|
workflow.chain(
|
|
66
111
|
researcher_step,
|
|
@@ -68,6 +113,8 @@ def _create_linear_research_writer_reviewer_workflow(
|
|
|
68
113
|
writer_step,
|
|
69
114
|
writer_to_reviewer,
|
|
70
115
|
reviewer_step,
|
|
116
|
+
reviewer_to_writer,
|
|
117
|
+
writer_final_step,
|
|
71
118
|
)
|
|
72
119
|
return workflow
|
|
73
120
|
|
|
@@ -4,6 +4,7 @@ from agentbyte.webui.discovery import AgentbyteScanner
|
|
|
4
4
|
from agentbyte.webui.execution import ExecutionEngine
|
|
5
5
|
from agentbyte.webui.models import (
|
|
6
6
|
AgentInfo,
|
|
7
|
+
CreateSessionRequest,
|
|
7
8
|
Entity,
|
|
8
9
|
EntityInfo,
|
|
9
10
|
HealthResponse,
|
|
@@ -29,12 +30,13 @@ from agentbyte.webui.session_store import (
|
|
|
29
30
|
InMemorySessionStore,
|
|
30
31
|
SessionStore,
|
|
31
32
|
)
|
|
32
|
-
from agentbyte.webui.sessions import SessionManager
|
|
33
|
+
from agentbyte.webui.sessions import SessionBindingError, SessionManager
|
|
33
34
|
|
|
34
35
|
__all__ = [
|
|
35
36
|
"AgentInfo",
|
|
36
37
|
"AgentbyteScanner",
|
|
37
38
|
"AgentbyteWebUIServer",
|
|
39
|
+
"CreateSessionRequest",
|
|
38
40
|
"Entity",
|
|
39
41
|
"EntityInfo",
|
|
40
42
|
"EntityRegistry",
|
|
@@ -46,6 +48,7 @@ __all__ = [
|
|
|
46
48
|
"OrchestratorInfo",
|
|
47
49
|
"RunEntityRequest",
|
|
48
50
|
"SessionInfo",
|
|
51
|
+
"SessionBindingError",
|
|
49
52
|
"SessionManager",
|
|
50
53
|
"SessionStore",
|
|
51
54
|
"StatsResponse",
|