agno 1.8.0__py3-none-any.whl → 2.0.0a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/__init__.py +8 -0
- agno/agent/__init__.py +19 -27
- agno/agent/agent.py +2781 -4126
- agno/api/agent.py +9 -65
- agno/api/api.py +5 -46
- agno/api/evals.py +6 -17
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -41
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +5 -21
- agno/api/schemas/evals.py +7 -16
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +5 -21
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +11 -7
- agno/api/settings.py +53 -0
- agno/api/team.py +9 -64
- agno/api/workflow.py +28 -0
- agno/cloud/aws/base.py +214 -0
- agno/cloud/aws/s3/__init__.py +2 -0
- agno/cloud/aws/s3/api_client.py +43 -0
- agno/cloud/aws/s3/bucket.py +195 -0
- agno/cloud/aws/s3/object.py +57 -0
- agno/db/__init__.py +24 -0
- agno/db/base.py +245 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +1749 -0
- agno/db/dynamo/schemas.py +278 -0
- agno/db/dynamo/utils.py +684 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +1438 -0
- agno/db/firestore/schemas.py +130 -0
- agno/db/firestore/utils.py +278 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1001 -0
- agno/db/gcs_json/utils.py +194 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +888 -0
- agno/db/in_memory/utils.py +172 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1051 -0
- agno/db/json/utils.py +196 -0
- agno/db/migrations/v1_to_v2.py +162 -0
- agno/db/mongo/__init__.py +3 -0
- agno/db/mongo/mongo.py +1417 -0
- agno/db/mongo/schemas.py +77 -0
- agno/db/mongo/utils.py +204 -0
- agno/db/mysql/__init__.py +3 -0
- agno/db/mysql/mysql.py +1719 -0
- agno/db/mysql/schemas.py +124 -0
- agno/db/mysql/utils.py +298 -0
- agno/db/postgres/__init__.py +3 -0
- agno/db/postgres/postgres.py +1720 -0
- agno/db/postgres/schemas.py +124 -0
- agno/db/postgres/utils.py +281 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1371 -0
- agno/db/redis/schemas.py +109 -0
- agno/db/redis/utils.py +288 -0
- agno/db/schemas/__init__.py +3 -0
- agno/db/schemas/evals.py +33 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +46 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +116 -0
- agno/db/singlestore/singlestore.py +1722 -0
- agno/db/singlestore/utils.py +327 -0
- agno/db/sqlite/__init__.py +3 -0
- agno/db/sqlite/schemas.py +119 -0
- agno/db/sqlite/sqlite.py +1680 -0
- agno/db/sqlite/utils.py +269 -0
- agno/db/utils.py +88 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +142 -43
- agno/eval/performance.py +88 -23
- agno/eval/reliability.py +73 -20
- agno/eval/utils.py +23 -13
- agno/integrations/discord/__init__.py +3 -0
- agno/{app → integrations}/discord/client.py +10 -10
- agno/knowledge/__init__.py +2 -2
- agno/{document → knowledge}/chunking/agentic.py +2 -2
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +3 -3
- agno/{document → knowledge}/chunking/markdown.py +2 -2
- agno/{document → knowledge}/chunking/recursive.py +2 -2
- agno/{document → knowledge}/chunking/row.py +2 -2
- agno/knowledge/chunking/semantic.py +59 -0
- agno/knowledge/chunking/strategy.py +121 -0
- agno/knowledge/content.py +74 -0
- agno/knowledge/document/__init__.py +5 -0
- agno/{document → knowledge/document}/base.py +12 -2
- agno/knowledge/embedder/__init__.py +5 -0
- agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
- agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
- agno/{embedder → knowledge/embedder}/base.py +6 -0
- agno/{embedder → knowledge/embedder}/cohere.py +72 -1
- agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/{embedder → knowledge/embedder}/google.py +74 -1
- agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
- agno/{embedder → knowledge/embedder}/jina.py +48 -2
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +139 -0
- agno/{embedder → knowledge/embedder}/nebius.py +1 -1
- agno/{embedder → knowledge/embedder}/ollama.py +54 -3
- agno/knowledge/embedder/openai.py +223 -0
- agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
- agno/knowledge/knowledge.py +1515 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
- agno/knowledge/reader/base.py +88 -0
- agno/{document → knowledge}/reader/csv_reader.py +68 -15
- agno/knowledge/reader/docx_reader.py +83 -0
- agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
- agno/knowledge/reader/gcs_reader.py +67 -0
- agno/{document → knowledge}/reader/json_reader.py +30 -9
- agno/{document → knowledge}/reader/markdown_reader.py +36 -9
- agno/{document → knowledge}/reader/pdf_reader.py +79 -21
- agno/knowledge/reader/reader_factory.py +275 -0
- agno/knowledge/reader/s3_reader.py +171 -0
- agno/{document → knowledge}/reader/text_reader.py +31 -10
- agno/knowledge/reader/url_reader.py +84 -0
- agno/knowledge/reader/web_search_reader.py +389 -0
- agno/{document → knowledge}/reader/website_reader.py +37 -10
- agno/knowledge/reader/wikipedia_reader.py +59 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/{reranker → knowledge/reranker}/infinity.py +2 -2
- agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
- agno/knowledge/types.py +30 -0
- agno/knowledge/utils.py +169 -0
- agno/media.py +2 -2
- agno/memory/__init__.py +2 -10
- agno/memory/manager.py +1003 -148
- agno/models/aimlapi/__init__.py +2 -2
- agno/models/aimlapi/aimlapi.py +6 -6
- agno/models/anthropic/claude.py +129 -82
- agno/models/aws/bedrock.py +107 -175
- agno/models/aws/claude.py +64 -18
- agno/models/azure/ai_foundry.py +73 -23
- agno/models/base.py +347 -287
- agno/models/cerebras/cerebras.py +84 -27
- agno/models/cohere/chat.py +106 -98
- agno/models/dashscope/dashscope.py +14 -5
- agno/models/google/gemini.py +123 -53
- agno/models/groq/groq.py +97 -35
- agno/models/huggingface/huggingface.py +92 -27
- agno/models/ibm/watsonx.py +72 -13
- agno/models/litellm/chat.py +85 -13
- agno/models/message.py +38 -144
- agno/models/meta/llama.py +85 -49
- agno/models/metrics.py +120 -0
- agno/models/mistral/mistral.py +90 -21
- agno/models/ollama/__init__.py +0 -2
- agno/models/ollama/chat.py +84 -46
- agno/models/openai/chat.py +135 -27
- agno/models/openai/responses.py +233 -115
- agno/models/perplexity/perplexity.py +26 -2
- agno/models/portkey/portkey.py +0 -7
- agno/models/response.py +14 -8
- agno/models/utils.py +20 -0
- agno/models/vercel/__init__.py +2 -2
- agno/models/vercel/v0.py +1 -1
- agno/models/vllm/__init__.py +2 -2
- agno/models/vllm/vllm.py +3 -3
- agno/models/xai/xai.py +10 -10
- agno/os/__init__.py +3 -0
- agno/os/app.py +393 -0
- agno/os/auth.py +47 -0
- agno/os/config.py +103 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +31 -0
- agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
- agno/{app → os/interfaces}/agui/utils.py +65 -28
- agno/os/interfaces/base.py +21 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
- agno/os/interfaces/slack/slack.py +33 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
- agno/os/interfaces/whatsapp/whatsapp.py +30 -0
- agno/os/router.py +843 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +204 -0
- agno/os/routers/evals/schemas.py +142 -0
- agno/os/routers/evals/utils.py +161 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +413 -0
- agno/os/routers/knowledge/schemas.py +118 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +179 -0
- agno/os/routers/memory/schemas.py +58 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +58 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +163 -0
- agno/os/schema.py +892 -0
- agno/{app/playground → os}/settings.py +8 -15
- agno/os/utils.py +270 -0
- agno/reasoning/azure_ai_foundry.py +4 -4
- agno/reasoning/deepseek.py +4 -4
- agno/reasoning/default.py +6 -11
- agno/reasoning/groq.py +4 -4
- agno/reasoning/helpers.py +4 -6
- agno/reasoning/ollama.py +4 -4
- agno/reasoning/openai.py +4 -4
- agno/run/{response.py → agent.py} +144 -72
- agno/run/base.py +44 -58
- agno/run/cancel.py +83 -0
- agno/run/team.py +133 -77
- agno/run/workflow.py +537 -12
- agno/session/__init__.py +10 -0
- agno/session/agent.py +244 -0
- agno/session/summary.py +225 -0
- agno/session/team.py +262 -0
- agno/{storage/session/v2 → session}/workflow.py +47 -24
- agno/team/__init__.py +15 -16
- agno/team/team.py +2967 -4243
- agno/tools/agentql.py +14 -5
- agno/tools/airflow.py +9 -4
- agno/tools/api.py +7 -3
- agno/tools/apify.py +2 -46
- agno/tools/arxiv.py +8 -3
- agno/tools/aws_lambda.py +7 -5
- agno/tools/aws_ses.py +7 -1
- agno/tools/baidusearch.py +4 -1
- agno/tools/bitbucket.py +4 -4
- agno/tools/brandfetch.py +14 -11
- agno/tools/bravesearch.py +4 -1
- agno/tools/brightdata.py +42 -22
- agno/tools/browserbase.py +13 -4
- agno/tools/calcom.py +12 -10
- agno/tools/calculator.py +10 -27
- agno/tools/cartesia.py +18 -13
- agno/tools/{clickup_tool.py → clickup.py} +12 -25
- agno/tools/confluence.py +71 -18
- agno/tools/crawl4ai.py +7 -1
- agno/tools/csv_toolkit.py +9 -8
- agno/tools/dalle.py +18 -11
- agno/tools/daytona.py +13 -16
- agno/tools/decorator.py +6 -3
- agno/tools/desi_vocal.py +16 -7
- agno/tools/discord.py +11 -8
- agno/tools/docker.py +30 -42
- agno/tools/duckdb.py +34 -53
- agno/tools/duckduckgo.py +8 -7
- agno/tools/e2b.py +62 -62
- agno/tools/eleven_labs.py +35 -28
- agno/tools/email.py +4 -1
- agno/tools/evm.py +7 -1
- agno/tools/exa.py +19 -14
- agno/tools/fal.py +29 -29
- agno/tools/file.py +9 -8
- agno/tools/financial_datasets.py +25 -44
- agno/tools/firecrawl.py +22 -22
- agno/tools/function.py +68 -17
- agno/tools/giphy.py +22 -10
- agno/tools/github.py +48 -126
- agno/tools/gmail.py +46 -62
- agno/tools/google_bigquery.py +7 -6
- agno/tools/google_maps.py +11 -26
- agno/tools/googlesearch.py +7 -2
- agno/tools/googlesheets.py +21 -17
- agno/tools/hackernews.py +9 -5
- agno/tools/jina.py +5 -4
- agno/tools/jira.py +18 -9
- agno/tools/knowledge.py +31 -32
- agno/tools/linear.py +18 -33
- agno/tools/linkup.py +5 -1
- agno/tools/local_file_system.py +8 -5
- agno/tools/lumalab.py +31 -19
- agno/tools/mem0.py +18 -12
- agno/tools/memori.py +14 -10
- agno/tools/mlx_transcribe.py +3 -2
- agno/tools/models/azure_openai.py +32 -14
- agno/tools/models/gemini.py +58 -31
- agno/tools/models/groq.py +29 -20
- agno/tools/models/nebius.py +27 -11
- agno/tools/models_labs.py +39 -15
- agno/tools/moviepy_video.py +7 -6
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +7 -2
- agno/tools/newspaper4k.py +8 -3
- agno/tools/openai.py +57 -26
- agno/tools/openbb.py +12 -11
- agno/tools/opencv.py +62 -46
- agno/tools/openweather.py +14 -12
- agno/tools/pandas.py +11 -3
- agno/tools/postgres.py +4 -12
- agno/tools/pubmed.py +4 -1
- agno/tools/python.py +9 -22
- agno/tools/reasoning.py +35 -27
- agno/tools/reddit.py +11 -26
- agno/tools/replicate.py +54 -41
- agno/tools/resend.py +4 -1
- agno/tools/scrapegraph.py +15 -14
- agno/tools/searxng.py +10 -23
- agno/tools/serpapi.py +6 -3
- agno/tools/serper.py +13 -4
- agno/tools/shell.py +9 -2
- agno/tools/slack.py +12 -11
- agno/tools/sleep.py +3 -2
- agno/tools/spider.py +24 -4
- agno/tools/sql.py +7 -6
- agno/tools/tavily.py +6 -4
- agno/tools/telegram.py +12 -4
- agno/tools/todoist.py +11 -31
- agno/tools/toolkit.py +1 -1
- agno/tools/trafilatura.py +22 -6
- agno/tools/trello.py +9 -22
- agno/tools/twilio.py +10 -3
- agno/tools/user_control_flow.py +6 -1
- agno/tools/valyu.py +34 -5
- agno/tools/visualization.py +19 -28
- agno/tools/webbrowser.py +4 -3
- agno/tools/webex.py +11 -7
- agno/tools/website.py +15 -46
- agno/tools/webtools.py +12 -4
- agno/tools/whatsapp.py +5 -9
- agno/tools/wikipedia.py +20 -13
- agno/tools/x.py +14 -13
- agno/tools/yfinance.py +13 -40
- agno/tools/youtube.py +26 -20
- agno/tools/zendesk.py +7 -2
- agno/tools/zep.py +10 -7
- agno/tools/zoom.py +10 -9
- agno/utils/common.py +1 -19
- agno/utils/events.py +95 -118
- agno/utils/knowledge.py +29 -0
- agno/utils/location.py +2 -2
- agno/utils/log.py +2 -2
- agno/utils/mcp.py +11 -5
- agno/utils/media.py +39 -0
- agno/utils/message.py +12 -1
- agno/utils/models/claude.py +6 -4
- agno/utils/models/mistral.py +8 -7
- agno/utils/models/schema_utils.py +3 -3
- agno/utils/pprint.py +33 -32
- agno/utils/print_response/agent.py +779 -0
- agno/utils/print_response/team.py +1565 -0
- agno/utils/print_response/workflow.py +1451 -0
- agno/utils/prompts.py +14 -14
- agno/utils/reasoning.py +87 -0
- agno/utils/response.py +42 -42
- agno/utils/string.py +8 -22
- agno/utils/team.py +50 -0
- agno/utils/timer.py +2 -2
- agno/vectordb/base.py +33 -21
- agno/vectordb/cassandra/cassandra.py +287 -23
- agno/vectordb/chroma/chromadb.py +482 -59
- agno/vectordb/clickhouse/clickhousedb.py +270 -63
- agno/vectordb/couchbase/couchbase.py +309 -29
- agno/vectordb/lancedb/lance_db.py +360 -21
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +145 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +374 -0
- agno/vectordb/llamaindex/llamaindexdb.py +127 -0
- agno/vectordb/milvus/milvus.py +242 -32
- agno/vectordb/mongodb/mongodb.py +200 -24
- agno/vectordb/pgvector/pgvector.py +319 -37
- agno/vectordb/pineconedb/pineconedb.py +221 -27
- agno/vectordb/qdrant/qdrant.py +356 -14
- agno/vectordb/singlestore/singlestore.py +286 -29
- agno/vectordb/surrealdb/surrealdb.py +187 -7
- agno/vectordb/upstashdb/upstashdb.py +342 -26
- agno/vectordb/weaviate/weaviate.py +227 -165
- agno/workflow/__init__.py +17 -13
- agno/workflow/{v2/condition.py → condition.py} +135 -32
- agno/workflow/{v2/loop.py → loop.py} +115 -28
- agno/workflow/{v2/parallel.py → parallel.py} +138 -108
- agno/workflow/{v2/router.py → router.py} +133 -32
- agno/workflow/{v2/step.py → step.py} +200 -42
- agno/workflow/{v2/steps.py → steps.py} +147 -66
- agno/workflow/types.py +482 -0
- agno/workflow/workflow.py +2394 -696
- agno-2.0.0a1.dist-info/METADATA +355 -0
- agno-2.0.0a1.dist-info/RECORD +514 -0
- agno/agent/metrics.py +0 -107
- agno/api/app.py +0 -35
- agno/api/playground.py +0 -92
- agno/api/schemas/app.py +0 -12
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -35
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workflows.py +0 -33
- agno/api/workspace.py +0 -175
- agno/app/agui/__init__.py +0 -3
- agno/app/agui/app.py +0 -17
- agno/app/agui/sync_router.py +0 -120
- agno/app/base.py +0 -186
- agno/app/discord/__init__.py +0 -3
- agno/app/fastapi/__init__.py +0 -3
- agno/app/fastapi/app.py +0 -107
- agno/app/fastapi/async_router.py +0 -457
- agno/app/fastapi/sync_router.py +0 -448
- agno/app/playground/app.py +0 -228
- agno/app/playground/async_router.py +0 -1050
- agno/app/playground/deploy.py +0 -249
- agno/app/playground/operator.py +0 -183
- agno/app/playground/schemas.py +0 -220
- agno/app/playground/serve.py +0 -55
- agno/app/playground/sync_router.py +0 -1042
- agno/app/playground/utils.py +0 -46
- agno/app/settings.py +0 -15
- agno/app/slack/__init__.py +0 -3
- agno/app/slack/app.py +0 -19
- agno/app/slack/sync_router.py +0 -92
- agno/app/utils.py +0 -54
- agno/app/whatsapp/__init__.py +0 -3
- agno/app/whatsapp/app.py +0 -15
- agno/app/whatsapp/sync_router.py +0 -197
- agno/cli/auth_server.py +0 -249
- agno/cli/config.py +0 -274
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -357
- agno/cli/settings.py +0 -96
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -5
- agno/document/chunking/semantic.py +0 -45
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -5
- agno/document/reader/base.py +0 -47
- agno/document/reader/docx_reader.py +0 -60
- agno/document/reader/gcs/pdf_reader.py +0 -44
- agno/document/reader/s3/pdf_reader.py +0 -59
- agno/document/reader/s3/text_reader.py +0 -63
- agno/document/reader/url_reader.py +0 -59
- agno/document/reader/youtube_reader.py +0 -58
- agno/embedder/__init__.py +0 -5
- agno/embedder/langdb.py +0 -80
- agno/embedder/mistral.py +0 -82
- agno/embedder/openai.py +0 -78
- agno/file/__init__.py +0 -5
- agno/file/file.py +0 -16
- agno/file/local/csv.py +0 -32
- agno/file/local/txt.py +0 -19
- agno/infra/app.py +0 -240
- agno/infra/base.py +0 -144
- agno/infra/context.py +0 -20
- agno/infra/db_app.py +0 -52
- agno/infra/resource.py +0 -205
- agno/infra/resources.py +0 -55
- agno/knowledge/agent.py +0 -698
- agno/knowledge/arxiv.py +0 -33
- agno/knowledge/combined.py +0 -36
- agno/knowledge/csv.py +0 -144
- agno/knowledge/csv_url.py +0 -124
- agno/knowledge/document.py +0 -223
- agno/knowledge/docx.py +0 -137
- agno/knowledge/firecrawl.py +0 -34
- agno/knowledge/gcs/__init__.py +0 -0
- agno/knowledge/gcs/base.py +0 -39
- agno/knowledge/gcs/pdf.py +0 -125
- agno/knowledge/json.py +0 -137
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/light_rag.py +0 -273
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/markdown.py +0 -154
- agno/knowledge/pdf.py +0 -164
- agno/knowledge/pdf_bytes.py +0 -42
- agno/knowledge/pdf_url.py +0 -148
- agno/knowledge/s3/__init__.py +0 -0
- agno/knowledge/s3/base.py +0 -64
- agno/knowledge/s3/pdf.py +0 -33
- agno/knowledge/s3/text.py +0 -34
- agno/knowledge/text.py +0 -141
- agno/knowledge/url.py +0 -46
- agno/knowledge/website.py +0 -179
- agno/knowledge/wikipedia.py +0 -32
- agno/knowledge/youtube.py +0 -35
- agno/memory/agent.py +0 -423
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -5
- agno/memory/db/base.py +0 -42
- agno/memory/db/mongodb.py +0 -189
- agno/memory/db/postgres.py +0 -203
- agno/memory/db/sqlite.py +0 -193
- agno/memory/memory.py +0 -22
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -201
- agno/memory/summary.py +0 -19
- agno/memory/team.py +0 -415
- agno/memory/v2/__init__.py +0 -2
- agno/memory/v2/db/__init__.py +0 -1
- agno/memory/v2/db/base.py +0 -42
- agno/memory/v2/db/firestore.py +0 -339
- agno/memory/v2/db/mongodb.py +0 -196
- agno/memory/v2/db/postgres.py +0 -214
- agno/memory/v2/db/redis.py +0 -187
- agno/memory/v2/db/schema.py +0 -54
- agno/memory/v2/db/sqlite.py +0 -209
- agno/memory/v2/manager.py +0 -437
- agno/memory/v2/memory.py +0 -1097
- agno/memory/v2/schema.py +0 -55
- agno/memory/v2/summarizer.py +0 -215
- agno/memory/workflow.py +0 -38
- agno/models/ollama/tools.py +0 -430
- agno/models/qwen/__init__.py +0 -5
- agno/playground/__init__.py +0 -10
- agno/playground/deploy.py +0 -3
- agno/playground/playground.py +0 -3
- agno/playground/serve.py +0 -3
- agno/playground/settings.py +0 -3
- agno/reranker/__init__.py +0 -0
- agno/run/v2/__init__.py +0 -0
- agno/run/v2/workflow.py +0 -567
- agno/storage/__init__.py +0 -0
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/dynamodb.py +0 -1
- agno/storage/agent/json.py +0 -1
- agno/storage/agent/mongodb.py +0 -1
- agno/storage/agent/postgres.py +0 -1
- agno/storage/agent/singlestore.py +0 -1
- agno/storage/agent/sqlite.py +0 -1
- agno/storage/agent/yaml.py +0 -1
- agno/storage/base.py +0 -60
- agno/storage/dynamodb.py +0 -673
- agno/storage/firestore.py +0 -297
- agno/storage/gcs_json.py +0 -261
- agno/storage/in_memory.py +0 -234
- agno/storage/json.py +0 -237
- agno/storage/mongodb.py +0 -328
- agno/storage/mysql.py +0 -685
- agno/storage/postgres.py +0 -682
- agno/storage/redis.py +0 -336
- agno/storage/session/__init__.py +0 -16
- agno/storage/session/agent.py +0 -64
- agno/storage/session/team.py +0 -63
- agno/storage/session/v2/__init__.py +0 -5
- agno/storage/session/workflow.py +0 -61
- agno/storage/singlestore.py +0 -606
- agno/storage/sqlite.py +0 -646
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/mongodb.py +0 -1
- agno/storage/workflow/postgres.py +0 -1
- agno/storage/workflow/sqlite.py +0 -1
- agno/storage/yaml.py +0 -241
- agno/tools/thinking.py +0 -73
- agno/utils/defaults.py +0 -57
- agno/utils/filesystem.py +0 -39
- agno/utils/git.py +0 -52
- agno/utils/json_io.py +0 -30
- agno/utils/load_env.py +0 -19
- agno/utils/py_io.py +0 -19
- agno/utils/pyproject.py +0 -18
- agno/utils/resource_filter.py +0 -31
- agno/workflow/v2/__init__.py +0 -21
- agno/workflow/v2/types.py +0 -357
- agno/workflow/v2/workflow.py +0 -3312
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -52
- agno/workspace/operator.py +0 -757
- agno/workspace/settings.py +0 -158
- agno-1.8.0.dist-info/METADATA +0 -979
- agno-1.8.0.dist-info/RECORD +0 -565
- agno-1.8.0.dist-info/entry_points.txt +0 -3
- /agno/{app → db/migrations}/__init__.py +0 -0
- /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{cli → integrations}/__init__.py +0 -0
- /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
- /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
- /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
- /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
- /agno/{app → os/interfaces}/slack/security.py +0 -0
- /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
- /agno/{file/local → utils/print_response}/__init__.py +0 -0
- /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
- {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import math
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
from uuid import uuid4
|
|
5
|
+
|
|
6
|
+
from fastapi import Depends, HTTPException, Path, Query
|
|
7
|
+
from fastapi.routing import APIRouter
|
|
8
|
+
|
|
9
|
+
from agno.db.base import BaseDb
|
|
10
|
+
from agno.db.schemas import UserMemory
|
|
11
|
+
from agno.os.auth import get_authentication_dependency
|
|
12
|
+
from agno.os.routers.memory.schemas import (
|
|
13
|
+
DeleteMemoriesRequest,
|
|
14
|
+
UserMemoryCreateSchema,
|
|
15
|
+
UserMemorySchema,
|
|
16
|
+
UserStatsSchema,
|
|
17
|
+
)
|
|
18
|
+
from agno.os.schema import PaginatedResponse, PaginationInfo, SortOrder
|
|
19
|
+
from agno.os.settings import AgnoAPISettings
|
|
20
|
+
from agno.os.utils import get_db
|
|
21
|
+
|
|
22
|
+
logger = logging.getLogger(__name__)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_memory_router(dbs: dict[str, BaseDb], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs) -> APIRouter:
|
|
26
|
+
router = APIRouter(dependencies=[Depends(get_authentication_dependency(settings))], tags=["Memory"])
|
|
27
|
+
return attach_routes(router=router, dbs=dbs)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
|
|
31
|
+
@router.post("/memories", response_model=UserMemorySchema, status_code=200)
|
|
32
|
+
async def create_memory(
|
|
33
|
+
payload: UserMemoryCreateSchema,
|
|
34
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
35
|
+
) -> UserMemorySchema:
|
|
36
|
+
db = get_db(dbs, db_id)
|
|
37
|
+
user_memory = db.upsert_user_memory(
|
|
38
|
+
memory=UserMemory(
|
|
39
|
+
memory_id=str(uuid4()),
|
|
40
|
+
memory=payload.memory,
|
|
41
|
+
topics=payload.topics or [],
|
|
42
|
+
user_id=payload.user_id,
|
|
43
|
+
),
|
|
44
|
+
deserialize=False,
|
|
45
|
+
)
|
|
46
|
+
if not user_memory:
|
|
47
|
+
raise HTTPException(status_code=500, detail="Failed to create memory")
|
|
48
|
+
|
|
49
|
+
return UserMemorySchema.from_dict(user_memory) # type: ignore
|
|
50
|
+
|
|
51
|
+
@router.delete("/memories/{memory_id}", status_code=204)
|
|
52
|
+
async def delete_memory(
|
|
53
|
+
memory_id: str = Path(), db_id: Optional[str] = Query(default=None, description="The ID of the database to use")
|
|
54
|
+
) -> None:
|
|
55
|
+
db = get_db(dbs, db_id)
|
|
56
|
+
db.delete_user_memory(memory_id=memory_id)
|
|
57
|
+
|
|
58
|
+
@router.delete("/memories", status_code=204)
|
|
59
|
+
async def delete_memories(
|
|
60
|
+
request: DeleteMemoriesRequest,
|
|
61
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
62
|
+
) -> None:
|
|
63
|
+
db = get_db(dbs, db_id)
|
|
64
|
+
db.delete_user_memories(memory_ids=request.memory_ids)
|
|
65
|
+
|
|
66
|
+
@router.get("/memories", response_model=PaginatedResponse[UserMemorySchema], status_code=200)
|
|
67
|
+
async def get_memories(
|
|
68
|
+
user_id: Optional[str] = Query(default=None, description="Filter memories by user ID"),
|
|
69
|
+
agent_id: Optional[str] = Query(default=None, description="Filter memories by agent ID"),
|
|
70
|
+
team_id: Optional[str] = Query(default=None, description="Filter memories by team ID"),
|
|
71
|
+
topics: Optional[List[str]] = Depends(parse_topics),
|
|
72
|
+
search_content: Optional[str] = Query(default=None, description="Fuzzy search memory content"),
|
|
73
|
+
limit: Optional[int] = Query(default=20, description="Number of memories to return"),
|
|
74
|
+
page: Optional[int] = Query(default=1, description="Page number"),
|
|
75
|
+
sort_by: Optional[str] = Query(default="updated_at", description="Field to sort by"),
|
|
76
|
+
sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
|
|
77
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
78
|
+
) -> PaginatedResponse[UserMemorySchema]:
|
|
79
|
+
db = get_db(dbs, db_id)
|
|
80
|
+
user_memories, total_count = db.get_user_memories(
|
|
81
|
+
limit=limit,
|
|
82
|
+
page=page,
|
|
83
|
+
user_id=user_id,
|
|
84
|
+
agent_id=agent_id,
|
|
85
|
+
team_id=team_id,
|
|
86
|
+
topics=topics,
|
|
87
|
+
search_content=search_content,
|
|
88
|
+
sort_by=sort_by,
|
|
89
|
+
sort_order=sort_order,
|
|
90
|
+
deserialize=False,
|
|
91
|
+
)
|
|
92
|
+
return PaginatedResponse(
|
|
93
|
+
data=[UserMemorySchema.from_dict(user_memory) for user_memory in user_memories], # type: ignore
|
|
94
|
+
meta=PaginationInfo(
|
|
95
|
+
page=page,
|
|
96
|
+
limit=limit,
|
|
97
|
+
total_count=total_count, # type: ignore
|
|
98
|
+
total_pages=math.ceil(total_count / limit) if limit is not None and limit > 0 else 0, # type: ignore
|
|
99
|
+
),
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
@router.get("/memories/{memory_id}", response_model=UserMemorySchema, status_code=200)
|
|
103
|
+
async def get_memory(
|
|
104
|
+
memory_id: str = Path(),
|
|
105
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
106
|
+
) -> UserMemorySchema:
|
|
107
|
+
db = get_db(dbs, db_id)
|
|
108
|
+
user_memory = db.get_user_memory(memory_id=memory_id, deserialize=False)
|
|
109
|
+
if not user_memory:
|
|
110
|
+
raise HTTPException(status_code=404, detail=f"Memory with ID {memory_id} not found")
|
|
111
|
+
|
|
112
|
+
return UserMemorySchema.from_dict(user_memory) # type: ignore
|
|
113
|
+
|
|
114
|
+
@router.get("/memories/topics", response_model=List[str], status_code=200)
|
|
115
|
+
async def get_topics(
|
|
116
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
117
|
+
) -> List[str]:
|
|
118
|
+
db = get_db(dbs, db_id)
|
|
119
|
+
return db.get_all_memory_topics()
|
|
120
|
+
|
|
121
|
+
@router.patch("/memories/{memory_id}", response_model=UserMemorySchema, status_code=200)
|
|
122
|
+
async def update_memory(
|
|
123
|
+
payload: UserMemoryCreateSchema,
|
|
124
|
+
memory_id: str = Path(),
|
|
125
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
126
|
+
) -> UserMemorySchema:
|
|
127
|
+
db = get_db(dbs, db_id)
|
|
128
|
+
user_memory = db.upsert_user_memory(
|
|
129
|
+
memory=UserMemory(
|
|
130
|
+
memory_id=memory_id,
|
|
131
|
+
memory=payload.memory,
|
|
132
|
+
topics=payload.topics or [],
|
|
133
|
+
user_id=payload.user_id,
|
|
134
|
+
),
|
|
135
|
+
deserialize=False,
|
|
136
|
+
)
|
|
137
|
+
if not user_memory:
|
|
138
|
+
raise HTTPException(status_code=500, detail="Failed to update memory")
|
|
139
|
+
|
|
140
|
+
return UserMemorySchema.from_dict(user_memory) # type: ignore
|
|
141
|
+
|
|
142
|
+
@router.get("/user_memory_stats", response_model=PaginatedResponse[UserStatsSchema], status_code=200)
|
|
143
|
+
async def get_user_memory_stats(
|
|
144
|
+
limit: Optional[int] = Query(default=20, description="Number of items to return"),
|
|
145
|
+
page: Optional[int] = Query(default=1, description="Page number"),
|
|
146
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
147
|
+
) -> PaginatedResponse[UserStatsSchema]:
|
|
148
|
+
db = get_db(dbs, db_id)
|
|
149
|
+
try:
|
|
150
|
+
user_stats, total_count = db.get_user_memory_stats(
|
|
151
|
+
limit=limit,
|
|
152
|
+
page=page,
|
|
153
|
+
)
|
|
154
|
+
return PaginatedResponse(
|
|
155
|
+
data=[UserStatsSchema.from_dict(stats) for stats in user_stats],
|
|
156
|
+
meta=PaginationInfo(
|
|
157
|
+
page=page,
|
|
158
|
+
limit=limit,
|
|
159
|
+
total_count=total_count,
|
|
160
|
+
total_pages=(total_count + limit - 1) // limit if limit is not None and limit > 0 else 0,
|
|
161
|
+
),
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
except Exception as e:
|
|
165
|
+
raise HTTPException(status_code=500, detail=f"Failed to get user statistics: {str(e)}")
|
|
166
|
+
|
|
167
|
+
return router
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
def parse_topics(topics: Optional[List[str]] = Query(default=None)) -> Optional[List[str]]:
|
|
171
|
+
"""Parse a comma-separated string of topics into a list of topics"""
|
|
172
|
+
if not topics:
|
|
173
|
+
return None
|
|
174
|
+
|
|
175
|
+
try:
|
|
176
|
+
return [topic.strip() for topic in topics[0].split(",") if topic.strip()]
|
|
177
|
+
|
|
178
|
+
except Exception as e:
|
|
179
|
+
raise HTTPException(status_code=422, detail=f"Invalid topics: {e}")
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
from typing import Any, Dict, List, Optional
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DeleteMemoriesRequest(BaseModel):
|
|
8
|
+
memory_ids: List[str]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class UserMemorySchema(BaseModel):
|
|
12
|
+
memory_id: str
|
|
13
|
+
memory: str
|
|
14
|
+
topics: Optional[List[str]]
|
|
15
|
+
|
|
16
|
+
agent_id: Optional[str]
|
|
17
|
+
team_id: Optional[str]
|
|
18
|
+
user_id: Optional[str]
|
|
19
|
+
|
|
20
|
+
updated_at: Optional[datetime]
|
|
21
|
+
|
|
22
|
+
@classmethod
|
|
23
|
+
def from_dict(cls, memory_dict: Dict[str, Any]) -> "UserMemorySchema":
|
|
24
|
+
return cls(
|
|
25
|
+
memory_id=memory_dict["memory_id"],
|
|
26
|
+
user_id=str(memory_dict["user_id"]),
|
|
27
|
+
agent_id=memory_dict.get("agent_id"),
|
|
28
|
+
team_id=memory_dict.get("team_id"),
|
|
29
|
+
memory=memory_dict["memory"],
|
|
30
|
+
topics=memory_dict.get("topics", []),
|
|
31
|
+
updated_at=memory_dict["updated_at"],
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
class UserMemoryCreateSchema(BaseModel):
|
|
36
|
+
"""Define the payload expected for creating a new user memory"""
|
|
37
|
+
|
|
38
|
+
memory: str
|
|
39
|
+
user_id: str
|
|
40
|
+
topics: Optional[List[str]] = None
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
class UserStatsSchema(BaseModel):
|
|
44
|
+
"""Schema for user memory statistics"""
|
|
45
|
+
|
|
46
|
+
user_id: str
|
|
47
|
+
total_memories: int
|
|
48
|
+
last_memory_updated_at: Optional[datetime] = None
|
|
49
|
+
|
|
50
|
+
@classmethod
|
|
51
|
+
def from_dict(cls, user_stats_dict: Dict[str, Any]) -> "UserStatsSchema":
|
|
52
|
+
updated_at = user_stats_dict.get("last_memory_updated_at")
|
|
53
|
+
|
|
54
|
+
return cls(
|
|
55
|
+
user_id=str(user_stats_dict["user_id"]),
|
|
56
|
+
total_memories=user_stats_dict["total_memories"],
|
|
57
|
+
last_memory_updated_at=datetime.fromtimestamp(updated_at, tz=timezone.utc) if updated_at else None,
|
|
58
|
+
)
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from datetime import date, datetime, timezone
|
|
3
|
+
from typing import List, Optional
|
|
4
|
+
|
|
5
|
+
from fastapi import Depends, HTTPException, Query
|
|
6
|
+
from fastapi.routing import APIRouter
|
|
7
|
+
|
|
8
|
+
from agno.db.base import BaseDb
|
|
9
|
+
from agno.os.auth import get_authentication_dependency
|
|
10
|
+
from agno.os.routers.metrics.schemas import DayAggregatedMetrics, MetricsResponse
|
|
11
|
+
from agno.os.settings import AgnoAPISettings
|
|
12
|
+
from agno.os.utils import get_db
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_metrics_router(dbs: dict[str, BaseDb], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs) -> APIRouter:
|
|
18
|
+
router = APIRouter(dependencies=[Depends(get_authentication_dependency(settings))], tags=["Metrics"])
|
|
19
|
+
return attach_routes(router=router, dbs=dbs)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
|
|
23
|
+
@router.get("/metrics", response_model=MetricsResponse, status_code=200)
|
|
24
|
+
async def get_metrics(
|
|
25
|
+
starting_date: Optional[date] = Query(default=None, description="Starting date to filter metrics (YYYY-MM-DD)"),
|
|
26
|
+
ending_date: Optional[date] = Query(default=None, description="Ending date to filter metrics (YYYY-MM-DD)"),
|
|
27
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
28
|
+
) -> MetricsResponse:
|
|
29
|
+
try:
|
|
30
|
+
db = get_db(dbs, db_id)
|
|
31
|
+
metrics, latest_updated_at = db.get_metrics(starting_date=starting_date, ending_date=ending_date)
|
|
32
|
+
|
|
33
|
+
return MetricsResponse(
|
|
34
|
+
metrics=[DayAggregatedMetrics.from_dict(metric) for metric in metrics],
|
|
35
|
+
updated_at=datetime.fromtimestamp(latest_updated_at, tz=timezone.utc)
|
|
36
|
+
if latest_updated_at is not None
|
|
37
|
+
else None,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
except Exception as e:
|
|
41
|
+
raise HTTPException(status_code=500, detail=f"Error getting metrics: {str(e)}")
|
|
42
|
+
|
|
43
|
+
@router.post("/metrics/refresh", response_model=List[DayAggregatedMetrics], status_code=200)
|
|
44
|
+
async def calculate_metrics(
|
|
45
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
46
|
+
) -> List[DayAggregatedMetrics]:
|
|
47
|
+
try:
|
|
48
|
+
db = get_db(dbs, db_id)
|
|
49
|
+
result = db.calculate_metrics()
|
|
50
|
+
if result is None:
|
|
51
|
+
return []
|
|
52
|
+
|
|
53
|
+
return [DayAggregatedMetrics.from_dict(metric) for metric in result]
|
|
54
|
+
|
|
55
|
+
except Exception as e:
|
|
56
|
+
raise HTTPException(status_code=500, detail=f"Error refreshing metrics: {str(e)}")
|
|
57
|
+
|
|
58
|
+
return router
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from typing import Any, Dict, List, Optional
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class DayAggregatedMetrics(BaseModel):
|
|
8
|
+
"""Aggregated metrics for a given day"""
|
|
9
|
+
|
|
10
|
+
id: str
|
|
11
|
+
|
|
12
|
+
agent_runs_count: int
|
|
13
|
+
agent_sessions_count: int
|
|
14
|
+
team_runs_count: int
|
|
15
|
+
team_sessions_count: int
|
|
16
|
+
workflow_runs_count: int
|
|
17
|
+
workflow_sessions_count: int
|
|
18
|
+
users_count: int
|
|
19
|
+
token_metrics: Dict[str, Any]
|
|
20
|
+
model_metrics: List[Dict[str, Any]]
|
|
21
|
+
|
|
22
|
+
date: datetime
|
|
23
|
+
created_at: int
|
|
24
|
+
updated_at: int
|
|
25
|
+
|
|
26
|
+
@classmethod
|
|
27
|
+
def from_dict(cls, metrics_dict: Dict[str, Any]) -> "DayAggregatedMetrics":
|
|
28
|
+
return cls(
|
|
29
|
+
agent_runs_count=metrics_dict.get("agent_runs_count", 0),
|
|
30
|
+
agent_sessions_count=metrics_dict.get("agent_sessions_count", 0),
|
|
31
|
+
created_at=metrics_dict.get("created_at", 0),
|
|
32
|
+
date=metrics_dict.get("date", datetime.now()),
|
|
33
|
+
id=metrics_dict.get("id", ""),
|
|
34
|
+
model_metrics=metrics_dict.get("model_metrics", {}),
|
|
35
|
+
team_runs_count=metrics_dict.get("team_runs_count", 0),
|
|
36
|
+
team_sessions_count=metrics_dict.get("team_sessions_count", 0),
|
|
37
|
+
token_metrics=metrics_dict.get("token_metrics", {}),
|
|
38
|
+
updated_at=metrics_dict.get("updated_at", 0),
|
|
39
|
+
users_count=metrics_dict.get("users_count", 0),
|
|
40
|
+
workflow_runs_count=metrics_dict.get("workflow_runs_count", 0),
|
|
41
|
+
workflow_sessions_count=metrics_dict.get("workflow_sessions_count", 0),
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
class MetricsResponse(BaseModel):
|
|
46
|
+
metrics: List[DayAggregatedMetrics]
|
|
47
|
+
updated_at: Optional[datetime]
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import List, Optional, Union
|
|
3
|
+
|
|
4
|
+
from fastapi import APIRouter, Body, Depends, HTTPException, Path, Query
|
|
5
|
+
|
|
6
|
+
from agno.db.base import BaseDb, SessionType
|
|
7
|
+
from agno.os.auth import get_authentication_dependency
|
|
8
|
+
from agno.os.schema import (
|
|
9
|
+
AgentSessionDetailSchema,
|
|
10
|
+
DeleteSessionRequest,
|
|
11
|
+
PaginatedResponse,
|
|
12
|
+
PaginationInfo,
|
|
13
|
+
RunSchema,
|
|
14
|
+
SessionSchema,
|
|
15
|
+
SortOrder,
|
|
16
|
+
TeamRunSchema,
|
|
17
|
+
TeamSessionDetailSchema,
|
|
18
|
+
WorkflowRunSchema,
|
|
19
|
+
WorkflowSessionDetailSchema,
|
|
20
|
+
)
|
|
21
|
+
from agno.os.settings import AgnoAPISettings
|
|
22
|
+
from agno.os.utils import get_db
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def get_session_router(dbs: dict[str, BaseDb], settings: AgnoAPISettings = AgnoAPISettings()) -> APIRouter:
|
|
28
|
+
session_router = APIRouter(dependencies=[Depends(get_authentication_dependency(settings))], tags=["Sessions"])
|
|
29
|
+
return attach_routes(router=session_router, dbs=dbs)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def attach_routes(router: APIRouter, dbs: dict[str, BaseDb]) -> APIRouter:
|
|
33
|
+
@router.get("/sessions", response_model=PaginatedResponse[SessionSchema], status_code=200)
|
|
34
|
+
async def get_sessions(
|
|
35
|
+
session_type: SessionType = Query(default=SessionType.AGENT, alias="type"),
|
|
36
|
+
component_id: Optional[str] = Query(default=None, description="Filter sessions by component ID"),
|
|
37
|
+
user_id: Optional[str] = Query(default=None, description="Filter sessions by user ID"),
|
|
38
|
+
session_name: Optional[str] = Query(default=None, description="Filter sessions by name"),
|
|
39
|
+
limit: Optional[int] = Query(default=20, description="Number of sessions to return"),
|
|
40
|
+
page: Optional[int] = Query(default=1, description="Page number"),
|
|
41
|
+
sort_by: Optional[str] = Query(default="created_at", description="Field to sort by"),
|
|
42
|
+
sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
|
|
43
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
44
|
+
) -> PaginatedResponse[SessionSchema]:
|
|
45
|
+
db = get_db(dbs, db_id)
|
|
46
|
+
sessions, total_count = db.get_sessions(
|
|
47
|
+
session_type=session_type,
|
|
48
|
+
component_id=component_id,
|
|
49
|
+
user_id=user_id,
|
|
50
|
+
session_name=session_name,
|
|
51
|
+
limit=limit,
|
|
52
|
+
page=page,
|
|
53
|
+
sort_by=sort_by,
|
|
54
|
+
sort_order=sort_order,
|
|
55
|
+
deserialize=False,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
return PaginatedResponse(
|
|
59
|
+
data=[SessionSchema.from_dict(session) for session in sessions], # type: ignore
|
|
60
|
+
meta=PaginationInfo(
|
|
61
|
+
page=page,
|
|
62
|
+
limit=limit,
|
|
63
|
+
total_count=total_count, # type: ignore
|
|
64
|
+
total_pages=(total_count + limit - 1) // limit if limit is not None and limit > 0 else 0, # type: ignore
|
|
65
|
+
),
|
|
66
|
+
)
|
|
67
|
+
|
|
68
|
+
@router.get(
|
|
69
|
+
"/sessions/{session_id}",
|
|
70
|
+
response_model=Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema],
|
|
71
|
+
status_code=200,
|
|
72
|
+
)
|
|
73
|
+
async def get_session_by_id(
|
|
74
|
+
session_id: str = Path(...),
|
|
75
|
+
session_type: SessionType = Query(default=SessionType.AGENT, description="Session type filter", alias="type"),
|
|
76
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
77
|
+
) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
|
|
78
|
+
db = get_db(dbs, db_id)
|
|
79
|
+
session = db.get_session(session_id=session_id, session_type=session_type)
|
|
80
|
+
if not session:
|
|
81
|
+
raise HTTPException(status_code=404, detail=f"Session with id '{session_id}' not found")
|
|
82
|
+
|
|
83
|
+
if session_type == SessionType.AGENT:
|
|
84
|
+
return AgentSessionDetailSchema.from_session(session) # type: ignore
|
|
85
|
+
elif session_type == SessionType.TEAM:
|
|
86
|
+
return TeamSessionDetailSchema.from_session(session) # type: ignore
|
|
87
|
+
else:
|
|
88
|
+
return WorkflowSessionDetailSchema.from_session(session) # type: ignore
|
|
89
|
+
|
|
90
|
+
@router.get(
|
|
91
|
+
"/sessions/{session_id}/runs",
|
|
92
|
+
response_model=Union[List[RunSchema], List[TeamRunSchema], List[WorkflowRunSchema]],
|
|
93
|
+
status_code=200,
|
|
94
|
+
)
|
|
95
|
+
async def get_session_runs(
|
|
96
|
+
session_id: str = Path(..., description="Session ID", alias="session_id"),
|
|
97
|
+
session_type: SessionType = Query(default=SessionType.AGENT, description="Session type filter", alias="type"),
|
|
98
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
99
|
+
) -> Union[List[RunSchema], List[TeamRunSchema], List[WorkflowRunSchema]]:
|
|
100
|
+
db = get_db(dbs, db_id)
|
|
101
|
+
session = db.get_session(session_id=session_id, session_type=session_type, deserialize=False)
|
|
102
|
+
if not session:
|
|
103
|
+
raise HTTPException(status_code=404, detail=f"Session with ID {session_id} not found")
|
|
104
|
+
|
|
105
|
+
runs = session.get("runs") # type: ignore
|
|
106
|
+
if not runs:
|
|
107
|
+
raise HTTPException(status_code=404, detail=f"Session with ID {session_id} has no runs")
|
|
108
|
+
|
|
109
|
+
if session_type == SessionType.AGENT:
|
|
110
|
+
return [RunSchema.from_dict(run) for run in runs]
|
|
111
|
+
|
|
112
|
+
elif session_type == SessionType.TEAM:
|
|
113
|
+
return [TeamRunSchema.from_dict(run) for run in runs]
|
|
114
|
+
|
|
115
|
+
elif session_type == SessionType.WORKFLOW:
|
|
116
|
+
return [WorkflowRunSchema.from_dict(run) for run in runs]
|
|
117
|
+
|
|
118
|
+
else:
|
|
119
|
+
return [RunSchema.from_dict(run) for run in runs]
|
|
120
|
+
|
|
121
|
+
@router.delete("/sessions/{session_id}", status_code=204)
|
|
122
|
+
async def delete_session(
|
|
123
|
+
session_id: str = Path(...),
|
|
124
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
125
|
+
) -> None:
|
|
126
|
+
db = get_db(dbs, db_id)
|
|
127
|
+
db.delete_session(session_id=session_id)
|
|
128
|
+
|
|
129
|
+
@router.delete("/sessions", status_code=204)
|
|
130
|
+
async def delete_sessions(
|
|
131
|
+
request: DeleteSessionRequest,
|
|
132
|
+
session_type: SessionType = Query(default=SessionType.AGENT, description="Session type filter", alias="type"),
|
|
133
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
134
|
+
) -> None:
|
|
135
|
+
if len(request.session_ids) != len(request.session_types):
|
|
136
|
+
raise HTTPException(status_code=400, detail="Session IDs and session types must have the same length")
|
|
137
|
+
|
|
138
|
+
db = get_db(dbs, db_id)
|
|
139
|
+
db.delete_sessions(session_ids=request.session_ids)
|
|
140
|
+
|
|
141
|
+
@router.post(
|
|
142
|
+
"/sessions/{session_id}/rename",
|
|
143
|
+
response_model=Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema],
|
|
144
|
+
)
|
|
145
|
+
async def rename_session(
|
|
146
|
+
session_id: str = Path(...),
|
|
147
|
+
session_type: SessionType = Query(default=SessionType.AGENT, description="Session type filter", alias="type"),
|
|
148
|
+
session_name: str = Body(embed=True),
|
|
149
|
+
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
150
|
+
) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
|
|
151
|
+
db = get_db(dbs, db_id)
|
|
152
|
+
session = db.rename_session(session_id=session_id, session_type=session_type, session_name=session_name)
|
|
153
|
+
if not session:
|
|
154
|
+
raise HTTPException(status_code=404, detail=f"Session with id '{session_id}' not found")
|
|
155
|
+
|
|
156
|
+
if session_type == SessionType.AGENT:
|
|
157
|
+
return AgentSessionDetailSchema.from_session(session) # type: ignore
|
|
158
|
+
elif session_type == SessionType.TEAM:
|
|
159
|
+
return TeamSessionDetailSchema.from_session(session) # type: ignore
|
|
160
|
+
else:
|
|
161
|
+
return WorkflowSessionDetailSchema.from_session(session) # type: ignore
|
|
162
|
+
|
|
163
|
+
return router
|