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
agno/storage/singlestore.py
DELETED
|
@@ -1,606 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
from typing import Any, List, Literal, Optional
|
|
3
|
-
|
|
4
|
-
from agno.storage.base import Storage
|
|
5
|
-
from agno.storage.session import Session
|
|
6
|
-
from agno.storage.session.agent import AgentSession
|
|
7
|
-
from agno.storage.session.team import TeamSession
|
|
8
|
-
from agno.storage.session.v2.workflow import WorkflowSession as WorkflowSessionV2
|
|
9
|
-
from agno.storage.session.workflow import WorkflowSession
|
|
10
|
-
from agno.utils.log import log_debug, log_info, log_warning, logger
|
|
11
|
-
|
|
12
|
-
try:
|
|
13
|
-
from sqlalchemy.dialects import mysql
|
|
14
|
-
from sqlalchemy.engine import Engine, create_engine
|
|
15
|
-
from sqlalchemy.engine.row import Row
|
|
16
|
-
from sqlalchemy.inspection import inspect
|
|
17
|
-
from sqlalchemy.orm import Session as SqlSession
|
|
18
|
-
from sqlalchemy.orm import sessionmaker
|
|
19
|
-
from sqlalchemy.schema import Column, MetaData, Table
|
|
20
|
-
from sqlalchemy.sql.expression import select, text
|
|
21
|
-
except ImportError:
|
|
22
|
-
raise ImportError("`sqlalchemy` not installed")
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
class SingleStoreStorage(Storage):
|
|
26
|
-
def __init__(
|
|
27
|
-
self,
|
|
28
|
-
table_name: str,
|
|
29
|
-
schema: Optional[str] = "ai",
|
|
30
|
-
db_url: Optional[str] = None,
|
|
31
|
-
db_engine: Optional[Engine] = None,
|
|
32
|
-
schema_version: int = 1,
|
|
33
|
-
auto_upgrade_schema: bool = False,
|
|
34
|
-
mode: Optional[Literal["agent", "team", "workflow", "workflow_v2"]] = "agent",
|
|
35
|
-
):
|
|
36
|
-
"""
|
|
37
|
-
This class provides Agent storage using a singlestore table.
|
|
38
|
-
|
|
39
|
-
The following order is used to determine the database connection:
|
|
40
|
-
1. Use the db_engine if provided
|
|
41
|
-
2. Use the db_url if provided
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
table_name (str): The name of the table to store the agent data.
|
|
45
|
-
schema (Optional[str], optional): The schema of the table. Defaults to "ai".
|
|
46
|
-
db_url (Optional[str], optional): The database URL. Defaults to None.
|
|
47
|
-
db_engine (Optional[Engine], optional): The database engine. Defaults to None.
|
|
48
|
-
schema_version (int, optional): The schema version. Defaults to 1.
|
|
49
|
-
auto_upgrade_schema (bool, optional): Automatically upgrade the schema. Defaults to False.
|
|
50
|
-
mode (Optional[Literal["agent", "team", "workflow", "workflow_v2"]], optional): The mode of the storage. Defaults to "agent".
|
|
51
|
-
"""
|
|
52
|
-
super().__init__(mode)
|
|
53
|
-
_engine: Optional[Engine] = db_engine
|
|
54
|
-
if _engine is None and db_url is not None:
|
|
55
|
-
_engine = create_engine(db_url, connect_args={"charset": "utf8mb4"})
|
|
56
|
-
|
|
57
|
-
if _engine is None:
|
|
58
|
-
raise ValueError("Must provide either db_url or db_engine")
|
|
59
|
-
|
|
60
|
-
# Database attributes
|
|
61
|
-
self.table_name: str = table_name
|
|
62
|
-
self.schema: Optional[str] = schema
|
|
63
|
-
self.db_url: Optional[str] = db_url
|
|
64
|
-
self.db_engine: Engine = _engine
|
|
65
|
-
self.metadata: MetaData = MetaData(schema=self.schema)
|
|
66
|
-
|
|
67
|
-
# Table schema version
|
|
68
|
-
self.schema_version: int = schema_version
|
|
69
|
-
# Automatically upgrade schema if True
|
|
70
|
-
self.auto_upgrade_schema: bool = auto_upgrade_schema
|
|
71
|
-
self._schema_up_to_date: bool = False
|
|
72
|
-
|
|
73
|
-
# Database session
|
|
74
|
-
self.SqlSession: sessionmaker[SqlSession] = sessionmaker(bind=self.db_engine)
|
|
75
|
-
# Database table for storage
|
|
76
|
-
self.table: Table = self.get_table()
|
|
77
|
-
|
|
78
|
-
@property
|
|
79
|
-
def mode(self) -> Literal["agent", "team", "workflow", "workflow_v2"]:
|
|
80
|
-
"""Get the mode of the storage."""
|
|
81
|
-
return super().mode
|
|
82
|
-
|
|
83
|
-
@mode.setter
|
|
84
|
-
def mode(self, value: Optional[Literal["agent", "team", "workflow", "workflow_v2"]]) -> None:
|
|
85
|
-
"""Set the mode and refresh the table if mode changes."""
|
|
86
|
-
super(SingleStoreStorage, type(self)).mode.fset(self, value) # type: ignore
|
|
87
|
-
if value is not None:
|
|
88
|
-
self.table = self.get_table()
|
|
89
|
-
|
|
90
|
-
def get_table_v1(self) -> Table:
|
|
91
|
-
common_columns = [
|
|
92
|
-
Column("session_id", mysql.TEXT, primary_key=True),
|
|
93
|
-
Column("user_id", mysql.TEXT),
|
|
94
|
-
Column("memory", mysql.JSON),
|
|
95
|
-
Column("session_data", mysql.JSON),
|
|
96
|
-
Column("extra_data", mysql.JSON),
|
|
97
|
-
Column("created_at", mysql.BIGINT),
|
|
98
|
-
Column("updated_at", mysql.BIGINT),
|
|
99
|
-
]
|
|
100
|
-
|
|
101
|
-
specific_columns = []
|
|
102
|
-
if self.mode == "agent":
|
|
103
|
-
specific_columns = [
|
|
104
|
-
Column("agent_id", mysql.TEXT),
|
|
105
|
-
Column("team_session_id", mysql.TEXT, nullable=True),
|
|
106
|
-
Column("agent_data", mysql.JSON),
|
|
107
|
-
]
|
|
108
|
-
elif self.mode == "team":
|
|
109
|
-
specific_columns = [
|
|
110
|
-
Column("team_id", mysql.TEXT),
|
|
111
|
-
Column("team_session_id", mysql.TEXT, nullable=True),
|
|
112
|
-
Column("team_data", mysql.JSON),
|
|
113
|
-
]
|
|
114
|
-
elif self.mode == "workflow":
|
|
115
|
-
specific_columns = [
|
|
116
|
-
Column("workflow_id", mysql.TEXT),
|
|
117
|
-
Column("workflow_data", mysql.JSON),
|
|
118
|
-
]
|
|
119
|
-
elif self.mode == "workflow_v2":
|
|
120
|
-
specific_columns = [
|
|
121
|
-
Column("workflow_id", mysql.TEXT),
|
|
122
|
-
Column("workflow_data", mysql.JSON),
|
|
123
|
-
Column("runs", mysql.JSON),
|
|
124
|
-
]
|
|
125
|
-
|
|
126
|
-
# Create table with all columns
|
|
127
|
-
table = Table(
|
|
128
|
-
self.table_name,
|
|
129
|
-
self.metadata,
|
|
130
|
-
*common_columns,
|
|
131
|
-
*specific_columns,
|
|
132
|
-
extend_existing=True,
|
|
133
|
-
schema=self.schema, # type: ignore
|
|
134
|
-
)
|
|
135
|
-
|
|
136
|
-
return table
|
|
137
|
-
|
|
138
|
-
def get_table(self) -> Table:
|
|
139
|
-
if self.schema_version == 1:
|
|
140
|
-
return self.get_table_v1()
|
|
141
|
-
else:
|
|
142
|
-
raise ValueError(f"Unsupported schema version: {self.schema_version}")
|
|
143
|
-
|
|
144
|
-
def table_exists(self) -> bool:
|
|
145
|
-
log_debug(f"Checking if table exists: {self.table.name}")
|
|
146
|
-
try:
|
|
147
|
-
return inspect(self.db_engine).has_table(self.table.name, schema=self.schema)
|
|
148
|
-
except Exception as e:
|
|
149
|
-
logger.error(e)
|
|
150
|
-
return False
|
|
151
|
-
|
|
152
|
-
def create(self) -> None:
|
|
153
|
-
self.table = self.get_table()
|
|
154
|
-
if not self.table_exists():
|
|
155
|
-
log_info(f"Creating table: {self.table_name}\n")
|
|
156
|
-
self.table.create(self.db_engine)
|
|
157
|
-
|
|
158
|
-
def _read(self, session: SqlSession, session_id: str, user_id: Optional[str] = None) -> Optional[Row[Any]]:
|
|
159
|
-
stmt = select(self.table).where(self.table.c.session_id == session_id)
|
|
160
|
-
if user_id is not None:
|
|
161
|
-
stmt = stmt.where(self.table.c.user_id == user_id)
|
|
162
|
-
try:
|
|
163
|
-
return session.execute(stmt).first()
|
|
164
|
-
except Exception as e:
|
|
165
|
-
log_debug(f"Exception reading from table: {e}")
|
|
166
|
-
log_debug(f"Table does not exist: {self.table.name}")
|
|
167
|
-
log_debug(f"Creating table: {self.table_name}")
|
|
168
|
-
self.create()
|
|
169
|
-
return None
|
|
170
|
-
|
|
171
|
-
def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[Session]:
|
|
172
|
-
with self.SqlSession.begin() as sess:
|
|
173
|
-
existing_row: Optional[Row[Any]] = self._read(session=sess, session_id=session_id, user_id=user_id)
|
|
174
|
-
if existing_row is not None:
|
|
175
|
-
if self.mode == "agent":
|
|
176
|
-
return AgentSession.from_dict(existing_row._mapping) # type: ignore
|
|
177
|
-
elif self.mode == "team":
|
|
178
|
-
return TeamSession.from_dict(existing_row._mapping) # type: ignore
|
|
179
|
-
elif self.mode == "workflow":
|
|
180
|
-
return WorkflowSession.from_dict(existing_row._mapping) # type: ignore
|
|
181
|
-
elif self.mode == "workflow_v2":
|
|
182
|
-
return WorkflowSessionV2.from_dict(existing_row._mapping) # type: ignore
|
|
183
|
-
return None
|
|
184
|
-
|
|
185
|
-
def get_all_session_ids(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[str]:
|
|
186
|
-
session_ids: List[str] = []
|
|
187
|
-
try:
|
|
188
|
-
with self.SqlSession.begin() as sess:
|
|
189
|
-
# get all session_ids for this user
|
|
190
|
-
stmt = select(self.table)
|
|
191
|
-
if user_id is not None:
|
|
192
|
-
stmt = stmt.where(self.table.c.user_id == user_id)
|
|
193
|
-
if entity_id is not None:
|
|
194
|
-
if self.mode == "agent":
|
|
195
|
-
stmt = stmt.where(self.table.c.agent_id == entity_id)
|
|
196
|
-
elif self.mode == "team":
|
|
197
|
-
stmt = stmt.where(self.table.c.team_id == entity_id)
|
|
198
|
-
elif self.mode == "workflow":
|
|
199
|
-
stmt = stmt.where(self.table.c.workflow_id == entity_id)
|
|
200
|
-
elif self.mode == "workflow_v2":
|
|
201
|
-
stmt = stmt.where(self.table.c.workflow_id == entity_id)
|
|
202
|
-
# order by created_at desc
|
|
203
|
-
stmt = stmt.order_by(self.table.c.created_at.desc())
|
|
204
|
-
# execute query
|
|
205
|
-
rows = sess.execute(stmt).fetchall()
|
|
206
|
-
for row in rows:
|
|
207
|
-
if row is not None and row.session_id is not None:
|
|
208
|
-
session_ids.append(row.session_id)
|
|
209
|
-
except Exception as e:
|
|
210
|
-
logger.error(f"An unexpected error occurred: {str(e)}")
|
|
211
|
-
return session_ids
|
|
212
|
-
|
|
213
|
-
def get_all_sessions(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[Session]:
|
|
214
|
-
sessions: List[Session] = []
|
|
215
|
-
try:
|
|
216
|
-
with self.SqlSession.begin() as sess:
|
|
217
|
-
# get all sessions for this user
|
|
218
|
-
stmt = select(self.table)
|
|
219
|
-
if user_id is not None:
|
|
220
|
-
stmt = stmt.where(self.table.c.user_id == user_id)
|
|
221
|
-
if entity_id is not None:
|
|
222
|
-
if self.mode == "agent":
|
|
223
|
-
stmt = stmt.where(self.table.c.agent_id == entity_id)
|
|
224
|
-
elif self.mode == "team":
|
|
225
|
-
stmt = stmt.where(self.table.c.team_id == entity_id)
|
|
226
|
-
elif self.mode == "workflow":
|
|
227
|
-
stmt = stmt.where(self.table.c.workflow_id == entity_id)
|
|
228
|
-
elif self.mode == "workflow_v2":
|
|
229
|
-
stmt = stmt.where(self.table.c.workflow_id == entity_id)
|
|
230
|
-
# order by created_at desc
|
|
231
|
-
stmt = stmt.order_by(self.table.c.created_at.desc())
|
|
232
|
-
# execute query
|
|
233
|
-
rows = sess.execute(stmt).fetchall()
|
|
234
|
-
for row in rows:
|
|
235
|
-
if row.session_id is not None:
|
|
236
|
-
if self.mode == "agent":
|
|
237
|
-
_agent_session = AgentSession.from_dict(row._mapping) # type: ignore
|
|
238
|
-
if _agent_session is not None:
|
|
239
|
-
sessions.append(_agent_session)
|
|
240
|
-
elif self.mode == "team":
|
|
241
|
-
_team_session = TeamSession.from_dict(row._mapping) # type: ignore
|
|
242
|
-
if _team_session is not None:
|
|
243
|
-
sessions.append(_team_session)
|
|
244
|
-
elif self.mode == "workflow":
|
|
245
|
-
_workflow_session = WorkflowSession.from_dict(row._mapping) # type: ignore
|
|
246
|
-
if _workflow_session is not None:
|
|
247
|
-
sessions.append(_workflow_session)
|
|
248
|
-
elif self.mode == "workflow_v2":
|
|
249
|
-
_workflow_session = WorkflowSessionV2.from_dict(row._mapping) # type: ignore
|
|
250
|
-
if _workflow_session is not None:
|
|
251
|
-
sessions.append(_workflow_session)
|
|
252
|
-
except Exception:
|
|
253
|
-
log_debug(f"Table does not exist: {self.table.name}")
|
|
254
|
-
return sessions
|
|
255
|
-
|
|
256
|
-
def get_recent_sessions(
|
|
257
|
-
self,
|
|
258
|
-
user_id: Optional[str] = None,
|
|
259
|
-
entity_id: Optional[str] = None,
|
|
260
|
-
limit: Optional[int] = 2,
|
|
261
|
-
) -> List[Session]:
|
|
262
|
-
"""Get the last N sessions, ordered by created_at descending.
|
|
263
|
-
|
|
264
|
-
Args:
|
|
265
|
-
num_history_sessions: Number of most recent sessions to return
|
|
266
|
-
user_id: Filter by user ID
|
|
267
|
-
entity_id: Filter by entity ID (agent_id, team_id, or workflow_id)
|
|
268
|
-
|
|
269
|
-
Returns:
|
|
270
|
-
List[Session]: List of most recent sessions
|
|
271
|
-
"""
|
|
272
|
-
sessions: List[Session] = []
|
|
273
|
-
try:
|
|
274
|
-
with self.SqlSession.begin() as sess:
|
|
275
|
-
# Build base query
|
|
276
|
-
stmt = select(self.table)
|
|
277
|
-
|
|
278
|
-
# Add filters
|
|
279
|
-
if user_id is not None:
|
|
280
|
-
stmt = stmt.where(self.table.c.user_id == user_id)
|
|
281
|
-
if entity_id is not None:
|
|
282
|
-
if self.mode == "agent":
|
|
283
|
-
stmt = stmt.where(self.table.c.agent_id == entity_id)
|
|
284
|
-
elif self.mode == "team":
|
|
285
|
-
stmt = stmt.where(self.table.c.team_id == entity_id)
|
|
286
|
-
elif self.mode == "workflow":
|
|
287
|
-
stmt = stmt.where(self.table.c.workflow_id == entity_id)
|
|
288
|
-
elif self.mode == "workflow_v2":
|
|
289
|
-
stmt = stmt.where(self.table.c.workflow_id == entity_id)
|
|
290
|
-
# Order by created_at desc and limit results
|
|
291
|
-
stmt = stmt.order_by(self.table.c.created_at.desc())
|
|
292
|
-
if limit is not None:
|
|
293
|
-
stmt = stmt.limit(limit)
|
|
294
|
-
|
|
295
|
-
# Execute query
|
|
296
|
-
rows = sess.execute(stmt).fetchall()
|
|
297
|
-
for row in rows:
|
|
298
|
-
if row.session_id is not None:
|
|
299
|
-
if self.mode == "agent":
|
|
300
|
-
session = AgentSession.from_dict(row._mapping) # type: ignore
|
|
301
|
-
if session is not None:
|
|
302
|
-
sessions.append(session)
|
|
303
|
-
elif self.mode == "team":
|
|
304
|
-
session = TeamSession.from_dict(row._mapping) # type: ignore
|
|
305
|
-
if session is not None:
|
|
306
|
-
sessions.append(session)
|
|
307
|
-
elif self.mode == "workflow":
|
|
308
|
-
session = WorkflowSession.from_dict(row._mapping) # type: ignore
|
|
309
|
-
if session is not None:
|
|
310
|
-
sessions.append(session)
|
|
311
|
-
elif self.mode == "workflow_v2":
|
|
312
|
-
session = WorkflowSessionV2.from_dict(row._mapping) # type: ignore
|
|
313
|
-
if session is not None:
|
|
314
|
-
sessions.append(session)
|
|
315
|
-
except Exception as e:
|
|
316
|
-
if "doesn't exist" in str(e):
|
|
317
|
-
log_debug(f"Table does not exist: {self.table.name}")
|
|
318
|
-
self.create()
|
|
319
|
-
else:
|
|
320
|
-
logger.error(f"Error getting last {limit} sessions: {e}")
|
|
321
|
-
|
|
322
|
-
return sessions
|
|
323
|
-
|
|
324
|
-
def upgrade_schema(self) -> None:
|
|
325
|
-
"""
|
|
326
|
-
Upgrade the schema to the latest version.
|
|
327
|
-
Currently handles adding the team_session_id column for agent mode.
|
|
328
|
-
"""
|
|
329
|
-
if not self.auto_upgrade_schema:
|
|
330
|
-
log_debug("Auto schema upgrade disabled. Skipping upgrade.")
|
|
331
|
-
return
|
|
332
|
-
|
|
333
|
-
try:
|
|
334
|
-
if self.mode == "agent" and self.table_exists():
|
|
335
|
-
with self.SqlSession() as sess:
|
|
336
|
-
# Check if team_session_id column exists
|
|
337
|
-
column_exists_query = text(
|
|
338
|
-
"""
|
|
339
|
-
SELECT 1 FROM information_schema.columns
|
|
340
|
-
WHERE table_schema = :schema AND table_name = :table
|
|
341
|
-
AND column_name = 'team_session_id'
|
|
342
|
-
"""
|
|
343
|
-
)
|
|
344
|
-
column_exists = (
|
|
345
|
-
sess.execute(column_exists_query, {"schema": self.schema, "table": self.table_name}).scalar()
|
|
346
|
-
is not None
|
|
347
|
-
)
|
|
348
|
-
|
|
349
|
-
if not column_exists:
|
|
350
|
-
log_info(f"Adding 'team_session_id' column to {self.schema}.{self.table_name}")
|
|
351
|
-
alter_table_query = text(
|
|
352
|
-
f"ALTER TABLE {self.schema}.{self.table_name} ADD COLUMN team_session_id TEXT"
|
|
353
|
-
)
|
|
354
|
-
sess.execute(alter_table_query)
|
|
355
|
-
sess.commit()
|
|
356
|
-
self._schema_up_to_date = True
|
|
357
|
-
log_info("Schema upgrade completed successfully")
|
|
358
|
-
except Exception as e:
|
|
359
|
-
logger.error(f"Error during schema upgrade: {e}")
|
|
360
|
-
raise
|
|
361
|
-
|
|
362
|
-
def upsert(self, session: Session) -> Optional[Session]:
|
|
363
|
-
"""
|
|
364
|
-
Create a new session if it does not exist, otherwise update the existing session.
|
|
365
|
-
"""
|
|
366
|
-
# Perform schema upgrade if auto_upgrade_schema is enabled
|
|
367
|
-
if self.auto_upgrade_schema and not self._schema_up_to_date:
|
|
368
|
-
self.upgrade_schema()
|
|
369
|
-
|
|
370
|
-
with self.SqlSession.begin() as sess:
|
|
371
|
-
# Create an insert statement using MySQL's ON DUPLICATE KEY UPDATE syntax
|
|
372
|
-
if self.mode == "agent":
|
|
373
|
-
upsert_sql = text(
|
|
374
|
-
f"""
|
|
375
|
-
INSERT INTO {self.schema}.{self.table_name}
|
|
376
|
-
(session_id, agent_id, team_session_id, user_id, memory, agent_data, session_data, extra_data, created_at, updated_at)
|
|
377
|
-
VALUES
|
|
378
|
-
(:session_id, :agent_id, :team_session_id, :user_id, :memory, :agent_data, :session_data, :extra_data, UNIX_TIMESTAMP(), NULL)
|
|
379
|
-
ON DUPLICATE KEY UPDATE
|
|
380
|
-
agent_id = VALUES(agent_id),
|
|
381
|
-
team_session_id = VALUES(team_session_id),
|
|
382
|
-
user_id = VALUES(user_id),
|
|
383
|
-
memory = VALUES(memory),
|
|
384
|
-
agent_data = VALUES(agent_data),
|
|
385
|
-
session_data = VALUES(session_data),
|
|
386
|
-
extra_data = VALUES(extra_data),
|
|
387
|
-
updated_at = UNIX_TIMESTAMP();
|
|
388
|
-
"""
|
|
389
|
-
)
|
|
390
|
-
elif self.mode == "team":
|
|
391
|
-
upsert_sql = text(
|
|
392
|
-
f"""
|
|
393
|
-
INSERT INTO {self.schema}.{self.table_name}
|
|
394
|
-
(session_id, team_id, user_id, team_session_id, memory, team_data, session_data, extra_data, created_at, updated_at)
|
|
395
|
-
VALUES
|
|
396
|
-
(:session_id, :team_id, :user_id, :team_session_id, :memory, :team_data, :session_data, :extra_data, UNIX_TIMESTAMP(), NULL)
|
|
397
|
-
ON DUPLICATE KEY UPDATE
|
|
398
|
-
team_id = VALUES(team_id),
|
|
399
|
-
team_session_id = VALUES(team_session_id),
|
|
400
|
-
user_id = VALUES(user_id),
|
|
401
|
-
memory = VALUES(memory),
|
|
402
|
-
team_data = VALUES(team_data),
|
|
403
|
-
session_data = VALUES(session_data),
|
|
404
|
-
extra_data = VALUES(extra_data),
|
|
405
|
-
updated_at = UNIX_TIMESTAMP();
|
|
406
|
-
"""
|
|
407
|
-
)
|
|
408
|
-
elif self.mode == "workflow":
|
|
409
|
-
upsert_sql = text(
|
|
410
|
-
f"""
|
|
411
|
-
INSERT INTO {self.schema}.{self.table_name}
|
|
412
|
-
(session_id, workflow_id, user_id, memory, workflow_data, session_data, extra_data, created_at, updated_at)
|
|
413
|
-
VALUES
|
|
414
|
-
(:session_id, :workflow_id, :user_id, :memory, :workflow_data, :session_data, :extra_data, UNIX_TIMESTAMP(), NULL)
|
|
415
|
-
ON DUPLICATE KEY UPDATE
|
|
416
|
-
workflow_id = VALUES(workflow_id),
|
|
417
|
-
user_id = VALUES(user_id),
|
|
418
|
-
memory = VALUES(memory),
|
|
419
|
-
workflow_data = VALUES(workflow_data),
|
|
420
|
-
session_data = VALUES(session_data),
|
|
421
|
-
extra_data = VALUES(extra_data),
|
|
422
|
-
updated_at = UNIX_TIMESTAMP();
|
|
423
|
-
"""
|
|
424
|
-
)
|
|
425
|
-
elif self.mode == "workflow_v2":
|
|
426
|
-
# Convert session to dict to ensure proper serialization
|
|
427
|
-
upsert_sql = text(
|
|
428
|
-
f"""
|
|
429
|
-
INSERT INTO {self.schema}.{self.table_name}
|
|
430
|
-
(session_id, workflow_id, user_id, workflow_name, runs, workflow_data, session_data, extra_data, created_at, updated_at)
|
|
431
|
-
VALUES
|
|
432
|
-
(:session_id, :workflow_id, :user_id, :workflow_name, :runs, :workflow_data, :session_data, :extra_data, UNIX_TIMESTAMP(), NULL)
|
|
433
|
-
ON DUPLICATE KEY UPDATE
|
|
434
|
-
workflow_id = VALUES(workflow_id),
|
|
435
|
-
user_id = VALUES(user_id),
|
|
436
|
-
workflow_name = VALUES(workflow_name),
|
|
437
|
-
runs = VALUES(runs),
|
|
438
|
-
workflow_data = VALUES(workflow_data),
|
|
439
|
-
session_data = VALUES(session_data),
|
|
440
|
-
extra_data = VALUES(extra_data),
|
|
441
|
-
updated_at = UNIX_TIMESTAMP();
|
|
442
|
-
"""
|
|
443
|
-
)
|
|
444
|
-
|
|
445
|
-
try:
|
|
446
|
-
if self.mode == "agent":
|
|
447
|
-
sess.execute(
|
|
448
|
-
upsert_sql,
|
|
449
|
-
{
|
|
450
|
-
"session_id": session.session_id,
|
|
451
|
-
"agent_id": session.agent_id, # type: ignore
|
|
452
|
-
"team_session_id": session.team_session_id, # type: ignore
|
|
453
|
-
"user_id": session.user_id,
|
|
454
|
-
"memory": json.dumps(getattr(session, "memory", None), ensure_ascii=False)
|
|
455
|
-
if getattr(session, "memory", None) is not None
|
|
456
|
-
else None,
|
|
457
|
-
"agent_data": json.dumps(session.agent_data, ensure_ascii=False) # type: ignore
|
|
458
|
-
if session.agent_data is not None # type: ignore
|
|
459
|
-
else None,
|
|
460
|
-
"session_data": json.dumps(session.session_data, ensure_ascii=False)
|
|
461
|
-
if session.session_data is not None
|
|
462
|
-
else None,
|
|
463
|
-
"extra_data": json.dumps(session.extra_data, ensure_ascii=False)
|
|
464
|
-
if session.extra_data is not None
|
|
465
|
-
else None,
|
|
466
|
-
},
|
|
467
|
-
)
|
|
468
|
-
elif self.mode == "team":
|
|
469
|
-
sess.execute(
|
|
470
|
-
upsert_sql,
|
|
471
|
-
{
|
|
472
|
-
"session_id": session.session_id,
|
|
473
|
-
"team_id": session.team_id, # type: ignore
|
|
474
|
-
"user_id": session.user_id,
|
|
475
|
-
"team_session_id": session.team_session_id, # type: ignore
|
|
476
|
-
"memory": json.dumps(getattr(session, "memory", None), ensure_ascii=False)
|
|
477
|
-
if getattr(session, "memory", None) is not None
|
|
478
|
-
else None,
|
|
479
|
-
"team_data": json.dumps(session.team_data, ensure_ascii=False) # type: ignore
|
|
480
|
-
if session.team_data is not None # type: ignore
|
|
481
|
-
else None,
|
|
482
|
-
"session_data": json.dumps(session.session_data, ensure_ascii=False)
|
|
483
|
-
if session.session_data is not None
|
|
484
|
-
else None,
|
|
485
|
-
"extra_data": json.dumps(session.extra_data, ensure_ascii=False)
|
|
486
|
-
if session.extra_data is not None
|
|
487
|
-
else None,
|
|
488
|
-
},
|
|
489
|
-
)
|
|
490
|
-
elif self.mode == "workflow":
|
|
491
|
-
sess.execute(
|
|
492
|
-
upsert_sql,
|
|
493
|
-
{
|
|
494
|
-
"session_id": session.session_id,
|
|
495
|
-
"workflow_id": session.workflow_id, # type: ignore
|
|
496
|
-
"user_id": session.user_id,
|
|
497
|
-
"memory": json.dumps(getattr(session, "memory", None), ensure_ascii=False)
|
|
498
|
-
if getattr(session, "memory", None) is not None
|
|
499
|
-
else None,
|
|
500
|
-
"workflow_data": json.dumps(session.workflow_data, ensure_ascii=False) # type: ignore
|
|
501
|
-
if session.workflow_data is not None # type: ignore
|
|
502
|
-
else None,
|
|
503
|
-
"session_data": json.dumps(session.session_data, ensure_ascii=False)
|
|
504
|
-
if session.session_data is not None
|
|
505
|
-
else None,
|
|
506
|
-
"extra_data": json.dumps(session.extra_data, ensure_ascii=False)
|
|
507
|
-
if session.extra_data is not None
|
|
508
|
-
else None,
|
|
509
|
-
},
|
|
510
|
-
)
|
|
511
|
-
elif self.mode == "workflow_v2":
|
|
512
|
-
# Convert session to dict to ensure proper serialization
|
|
513
|
-
session_dict = session.to_dict()
|
|
514
|
-
|
|
515
|
-
sess.execute(
|
|
516
|
-
upsert_sql,
|
|
517
|
-
{
|
|
518
|
-
"session_id": session.session_id,
|
|
519
|
-
"workflow_id": session.workflow_id, # type: ignore
|
|
520
|
-
"user_id": session.user_id,
|
|
521
|
-
"workflow_name": session.workflow_name, # type: ignore
|
|
522
|
-
"runs": json.dumps(session_dict.get("runs"), ensure_ascii=False)
|
|
523
|
-
if session_dict.get("runs")
|
|
524
|
-
else None,
|
|
525
|
-
"workflow_data": json.dumps(session.workflow_data, ensure_ascii=False) # type: ignore
|
|
526
|
-
if session.workflow_data is not None # type: ignore
|
|
527
|
-
else None,
|
|
528
|
-
"session_data": json.dumps(session.session_data, ensure_ascii=False)
|
|
529
|
-
if session.session_data is not None
|
|
530
|
-
else None,
|
|
531
|
-
"extra_data": json.dumps(session.extra_data, ensure_ascii=False)
|
|
532
|
-
if session.extra_data is not None
|
|
533
|
-
else None,
|
|
534
|
-
},
|
|
535
|
-
)
|
|
536
|
-
except Exception as e:
|
|
537
|
-
# Create table and try again
|
|
538
|
-
if not self.table_exists():
|
|
539
|
-
log_debug(f"Table does not exist: {self.table.name}")
|
|
540
|
-
log_debug("Creating table and retrying upsert")
|
|
541
|
-
self.create()
|
|
542
|
-
return self.upsert(session)
|
|
543
|
-
else:
|
|
544
|
-
log_warning(f"Exception upserting into table: {e}")
|
|
545
|
-
log_warning(
|
|
546
|
-
"A table upgrade might be required, please review these docs for more information: https://agno.link/upgrade-schema"
|
|
547
|
-
)
|
|
548
|
-
return None
|
|
549
|
-
return self.read(session_id=session.session_id)
|
|
550
|
-
|
|
551
|
-
def delete_session(self, session_id: Optional[str] = None):
|
|
552
|
-
if session_id is None:
|
|
553
|
-
logger.warning("No session_id provided for deletion.")
|
|
554
|
-
return
|
|
555
|
-
|
|
556
|
-
with self.SqlSession() as sess, sess.begin():
|
|
557
|
-
try:
|
|
558
|
-
# Delete the session with the given session_id
|
|
559
|
-
delete_stmt = self.table.delete().where(self.table.c.session_id == session_id)
|
|
560
|
-
result = sess.execute(delete_stmt)
|
|
561
|
-
|
|
562
|
-
if result.rowcount == 0:
|
|
563
|
-
logger.warning(f"No session found with session_id: {session_id}")
|
|
564
|
-
else:
|
|
565
|
-
log_info(f"Successfully deleted session with session_id: {session_id}")
|
|
566
|
-
except Exception as e:
|
|
567
|
-
logger.error(f"Error deleting session: {e}")
|
|
568
|
-
raise
|
|
569
|
-
|
|
570
|
-
def drop(self) -> None:
|
|
571
|
-
if self.table_exists():
|
|
572
|
-
log_info(f"Deleting table: {self.table_name}")
|
|
573
|
-
self.table.drop(self.db_engine)
|
|
574
|
-
|
|
575
|
-
def __deepcopy__(self, memo):
|
|
576
|
-
"""
|
|
577
|
-
Create a deep copy of the SingleStoreAgentStorage instance, handling unpickleable attributes.
|
|
578
|
-
|
|
579
|
-
Args:
|
|
580
|
-
memo (dict): A dictionary of objects already copied during the current copying pass.
|
|
581
|
-
|
|
582
|
-
Returns:
|
|
583
|
-
SingleStoreStorage: A deep-copied instance of SingleStoreAgentStorage.
|
|
584
|
-
"""
|
|
585
|
-
from copy import deepcopy
|
|
586
|
-
|
|
587
|
-
# Create a new instance without calling __init__
|
|
588
|
-
cls = self.__class__
|
|
589
|
-
copied_obj = cls.__new__(cls)
|
|
590
|
-
memo[id(self)] = copied_obj
|
|
591
|
-
|
|
592
|
-
# Deep copy attributes
|
|
593
|
-
for k, v in self.__dict__.items():
|
|
594
|
-
if k in {"metadata", "table"}:
|
|
595
|
-
continue
|
|
596
|
-
# Reuse db_engine and Session without copying
|
|
597
|
-
elif k in {"db_engine", "SqlSession"}:
|
|
598
|
-
setattr(copied_obj, k, v)
|
|
599
|
-
else:
|
|
600
|
-
setattr(copied_obj, k, deepcopy(v, memo))
|
|
601
|
-
|
|
602
|
-
# Recreate metadata and table for the copied instance
|
|
603
|
-
copied_obj.metadata = MetaData(schema=self.schema)
|
|
604
|
-
copied_obj.table = copied_obj.get_table()
|
|
605
|
-
|
|
606
|
-
return copied_obj
|