agno 1.8.1__py3-none-any.whl → 2.0.0__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 +3143 -4170
- agno/api/agent.py +11 -67
- agno/api/api.py +5 -46
- agno/api/evals.py +8 -19
- 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 +11 -66
- 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 +1743 -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 +1432 -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 +882 -0
- agno/db/in_memory/utils.py +172 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1045 -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 +1416 -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 +297 -0
- agno/db/postgres/__init__.py +3 -0
- agno/db/postgres/postgres.py +1710 -0
- agno/db/postgres/schemas.py +124 -0
- agno/db/postgres/utils.py +280 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +1367 -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 +1712 -0
- agno/db/singlestore/utils.py +326 -0
- agno/db/sqlite/__init__.py +3 -0
- agno/db/sqlite/schemas.py +119 -0
- agno/db/sqlite/sqlite.py +1676 -0
- agno/db/sqlite/utils.py +268 -0
- agno/db/utils.py +88 -0
- agno/eval/__init__.py +14 -0
- agno/eval/accuracy.py +154 -48
- 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 +15 -11
- 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 +1551 -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 +47 -65
- agno/knowledge/reader/docx_reader.py +83 -0
- agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
- agno/{document → knowledge}/reader/json_reader.py +30 -9
- agno/{document → knowledge}/reader/markdown_reader.py +58 -9
- agno/{document → knowledge}/reader/pdf_reader.py +71 -126
- agno/knowledge/reader/reader_factory.py +268 -0
- agno/knowledge/reader/s3_reader.py +101 -0
- agno/{document → knowledge}/reader/text_reader.py +31 -10
- agno/knowledge/reader/url_reader.py +128 -0
- agno/knowledge/reader/web_search_reader.py +366 -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 +269 -268
- 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 +131 -131
- agno/models/aws/bedrock.py +110 -182
- agno/models/aws/claude.py +64 -18
- agno/models/azure/ai_foundry.py +73 -23
- agno/models/base.py +346 -290
- agno/models/cerebras/cerebras.py +84 -27
- agno/models/cohere/chat.py +106 -98
- agno/models/google/gemini.py +105 -46
- 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 +46 -151
- 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 +85 -47
- agno/models/openai/chat.py +154 -37
- agno/models/openai/responses.py +178 -105
- agno/models/perplexity/perplexity.py +26 -2
- agno/models/portkey/portkey.py +0 -7
- agno/models/response.py +15 -9
- 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 +497 -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 +77 -33
- 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 +32 -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 +29 -0
- agno/os/mcp.py +235 -0
- agno/os/router.py +1400 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +393 -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 +850 -0
- agno/os/routers/knowledge/schemas.py +118 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +410 -0
- agno/os/routers/memory/schemas.py +58 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +178 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +536 -0
- agno/os/schema.py +945 -0
- agno/{app/playground → os}/settings.py +7 -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/agent.py +633 -0
- agno/run/base.py +53 -77
- agno/run/cancel.py +81 -0
- agno/run/team.py +243 -96
- agno/run/workflow.py +550 -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 +3260 -4824
- 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 +43 -23
- agno/tools/browserbase.py +13 -4
- agno/tools/calcom.py +12 -10
- agno/tools/calculator.py +10 -27
- agno/tools/cartesia.py +20 -17
- agno/tools/{clickup_tool.py → clickup.py} +12 -25
- agno/tools/confluence.py +8 -8
- agno/tools/crawl4ai.py +7 -1
- agno/tools/csv_toolkit.py +9 -8
- agno/tools/dalle.py +22 -12
- agno/tools/daytona.py +13 -16
- agno/tools/decorator.py +6 -3
- agno/tools/desi_vocal.py +17 -8
- 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 +36 -29
- agno/tools/email.py +4 -1
- agno/tools/evm.py +7 -1
- agno/tools/exa.py +19 -14
- agno/tools/fal.py +30 -30
- agno/tools/file.py +9 -8
- agno/tools/financial_datasets.py +25 -44
- agno/tools/firecrawl.py +22 -22
- agno/tools/function.py +127 -18
- agno/tools/giphy.py +23 -11
- agno/tools/github.py +48 -126
- agno/tools/gmail.py +45 -61
- 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 +19 -34
- agno/tools/linkup.py +5 -1
- agno/tools/local_file_system.py +8 -5
- agno/tools/lumalab.py +32 -20
- agno/tools/mcp.py +1 -2
- 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 +33 -15
- agno/tools/models/gemini.py +59 -32
- agno/tools/models/groq.py +30 -23
- agno/tools/models/nebius.py +28 -12
- agno/tools/models_labs.py +40 -16
- agno/tools/moviepy_video.py +7 -6
- agno/tools/neo4j.py +10 -8
- agno/tools/newspaper.py +7 -2
- agno/tools/newspaper4k.py +8 -3
- agno/tools/openai.py +58 -32
- agno/tools/openbb.py +12 -11
- agno/tools/opencv.py +63 -47
- 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 +55 -42
- 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 +100 -123
- agno/utils/gemini.py +32 -2
- agno/utils/knowledge.py +29 -0
- agno/utils/log.py +54 -4
- agno/utils/mcp.py +68 -10
- agno/utils/media.py +39 -0
- agno/utils/message.py +12 -1
- agno/utils/models/aws_claude.py +1 -1
- agno/utils/models/claude.py +47 -4
- agno/utils/models/cohere.py +1 -1
- agno/utils/models/mistral.py +8 -7
- agno/utils/models/schema_utils.py +3 -3
- agno/utils/models/watsonx.py +1 -1
- agno/utils/openai.py +1 -1
- agno/utils/pprint.py +33 -32
- agno/utils/print_response/agent.py +779 -0
- agno/utils/print_response/team.py +1669 -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/streamlit.py +481 -0
- 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 +334 -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} +207 -49
- agno/workflow/{v2/steps.py → steps.py} +147 -66
- agno/workflow/types.py +482 -0
- agno/workflow/workflow.py +2410 -696
- agno-2.0.0.dist-info/METADATA +494 -0
- agno-2.0.0.dist-info/RECORD +515 -0
- agno-2.0.0.dist-info/licenses/LICENSE +201 -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 -702
- 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/response.py +0 -467
- 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.1.dist-info/METADATA +0 -982
- agno-1.8.1.dist-info/RECORD +0 -566
- agno-1.8.1.dist-info/entry_points.txt +0 -3
- agno-1.8.1.dist-info/licenses/LICENSE +0 -375
- /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.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
- {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
agno/storage/in_memory.py
DELETED
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
from dataclasses import asdict
|
|
3
|
-
from typing import Dict, List, Literal, Optional
|
|
4
|
-
|
|
5
|
-
from agno.storage.base import Storage
|
|
6
|
-
from agno.storage.session import Session
|
|
7
|
-
from agno.storage.session.agent import AgentSession
|
|
8
|
-
from agno.storage.session.team import TeamSession
|
|
9
|
-
from agno.storage.session.v2.workflow import WorkflowSession as WorkflowSessionV2
|
|
10
|
-
from agno.storage.session.workflow import WorkflowSession
|
|
11
|
-
from agno.utils.log import logger
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
class InMemoryStorage(Storage):
|
|
15
|
-
def __init__(
|
|
16
|
-
self,
|
|
17
|
-
mode: Optional[Literal["agent", "team", "workflow", "workflow_v2"]] = "agent",
|
|
18
|
-
storage_dict: Optional[Dict[str, Dict]] = None,
|
|
19
|
-
):
|
|
20
|
-
super().__init__(mode)
|
|
21
|
-
self.storage: Dict[str, Dict] = storage_dict if storage_dict is not None else {}
|
|
22
|
-
|
|
23
|
-
def create(self) -> None:
|
|
24
|
-
"""Create the storage if it doesn't exist."""
|
|
25
|
-
# No-op for in-memory storage
|
|
26
|
-
pass
|
|
27
|
-
|
|
28
|
-
def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[Session]:
|
|
29
|
-
"""Read a Session from storage."""
|
|
30
|
-
try:
|
|
31
|
-
data = self.storage.get(session_id)
|
|
32
|
-
if data is None:
|
|
33
|
-
return None
|
|
34
|
-
if user_id and data["user_id"] != user_id:
|
|
35
|
-
return None
|
|
36
|
-
if self.mode == "agent":
|
|
37
|
-
return AgentSession.from_dict(data)
|
|
38
|
-
elif self.mode == "team":
|
|
39
|
-
return TeamSession.from_dict(data)
|
|
40
|
-
elif self.mode == "workflow":
|
|
41
|
-
return WorkflowSession.from_dict(data)
|
|
42
|
-
elif self.mode == "workflow_v2":
|
|
43
|
-
return WorkflowSessionV2.from_dict(data)
|
|
44
|
-
|
|
45
|
-
except Exception as e:
|
|
46
|
-
logger.error(f"Error reading session {session_id}: {e}")
|
|
47
|
-
return None
|
|
48
|
-
|
|
49
|
-
def get_all_session_ids(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[str]:
|
|
50
|
-
"""Get all session IDs, optionally filtered by user_id and/or entity_id."""
|
|
51
|
-
session_ids = []
|
|
52
|
-
for _, data in self.storage.items():
|
|
53
|
-
if user_id or entity_id:
|
|
54
|
-
if user_id and entity_id:
|
|
55
|
-
if self.mode == "agent" and data["agent_id"] == entity_id and data["user_id"] == user_id:
|
|
56
|
-
session_ids.append(data["session_id"])
|
|
57
|
-
elif self.mode == "team" and data["team_id"] == entity_id and data["user_id"] == user_id:
|
|
58
|
-
session_ids.append(data["session_id"])
|
|
59
|
-
elif self.mode == "workflow" and data["workflow_id"] == entity_id and data["user_id"] == user_id:
|
|
60
|
-
session_ids.append(data["session_id"])
|
|
61
|
-
|
|
62
|
-
elif user_id and data["user_id"] == user_id:
|
|
63
|
-
session_ids.append(data["session_id"])
|
|
64
|
-
|
|
65
|
-
elif entity_id:
|
|
66
|
-
if self.mode == "agent" and data["agent_id"] == entity_id:
|
|
67
|
-
session_ids.append(data["session_id"])
|
|
68
|
-
elif self.mode == "team" and data["team_id"] == entity_id:
|
|
69
|
-
session_ids.append(data["session_id"])
|
|
70
|
-
elif self.mode == "workflow" and data["workflow_id"] == entity_id:
|
|
71
|
-
session_ids.append(data["session_id"])
|
|
72
|
-
elif self.mode == "workflow_v2" and data["workflow_id"] == entity_id:
|
|
73
|
-
session_ids.append(data["session_id"])
|
|
74
|
-
|
|
75
|
-
else:
|
|
76
|
-
# No filters applied, add all session_ids
|
|
77
|
-
session_ids.append(data["session_id"])
|
|
78
|
-
|
|
79
|
-
return session_ids
|
|
80
|
-
|
|
81
|
-
def get_all_sessions(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[Session]:
|
|
82
|
-
"""Get all sessions, optionally filtered by user_id and/or entity_id."""
|
|
83
|
-
sessions: List[Session] = []
|
|
84
|
-
for _, data in self.storage.items():
|
|
85
|
-
if user_id or entity_id:
|
|
86
|
-
_session: Optional[Session] = None
|
|
87
|
-
|
|
88
|
-
if user_id and entity_id:
|
|
89
|
-
if self.mode == "agent" and data["agent_id"] == entity_id and data["user_id"] == user_id:
|
|
90
|
-
_session = AgentSession.from_dict(data)
|
|
91
|
-
elif self.mode == "team" and data["team_id"] == entity_id and data["user_id"] == user_id:
|
|
92
|
-
_session = TeamSession.from_dict(data)
|
|
93
|
-
elif self.mode == "workflow" and data["workflow_id"] == entity_id and data["user_id"] == user_id:
|
|
94
|
-
_session = WorkflowSession.from_dict(data)
|
|
95
|
-
|
|
96
|
-
elif user_id and data["user_id"] == user_id:
|
|
97
|
-
if self.mode == "agent":
|
|
98
|
-
_session = AgentSession.from_dict(data)
|
|
99
|
-
elif self.mode == "team":
|
|
100
|
-
_session = TeamSession.from_dict(data)
|
|
101
|
-
elif self.mode == "workflow":
|
|
102
|
-
_session = WorkflowSession.from_dict(data)
|
|
103
|
-
|
|
104
|
-
elif entity_id:
|
|
105
|
-
if self.mode == "agent" and data["agent_id"] == entity_id:
|
|
106
|
-
_session = AgentSession.from_dict(data)
|
|
107
|
-
elif self.mode == "team" and data["team_id"] == entity_id:
|
|
108
|
-
_session = TeamSession.from_dict(data)
|
|
109
|
-
elif self.mode == "workflow" and data["workflow_id"] == entity_id:
|
|
110
|
-
_session = WorkflowSession.from_dict(data)
|
|
111
|
-
elif self.mode == "workflow_v2" and data["workflow_id"] == entity_id:
|
|
112
|
-
_session = WorkflowSessionV2.from_dict(data)
|
|
113
|
-
|
|
114
|
-
if _session:
|
|
115
|
-
sessions.append(_session)
|
|
116
|
-
|
|
117
|
-
else:
|
|
118
|
-
# No filters applied, add all sessions
|
|
119
|
-
if self.mode == "agent":
|
|
120
|
-
_session = AgentSession.from_dict(data)
|
|
121
|
-
elif self.mode == "team":
|
|
122
|
-
_session = TeamSession.from_dict(data)
|
|
123
|
-
elif self.mode == "workflow":
|
|
124
|
-
_session = WorkflowSession.from_dict(data)
|
|
125
|
-
elif self.mode == "workflow_v2":
|
|
126
|
-
_session = WorkflowSessionV2.from_dict(data)
|
|
127
|
-
|
|
128
|
-
if _session:
|
|
129
|
-
sessions.append(_session)
|
|
130
|
-
|
|
131
|
-
return sessions
|
|
132
|
-
|
|
133
|
-
def get_recent_sessions(
|
|
134
|
-
self,
|
|
135
|
-
user_id: Optional[str] = None,
|
|
136
|
-
entity_id: Optional[str] = None,
|
|
137
|
-
limit: Optional[int] = 2,
|
|
138
|
-
) -> List[Session]:
|
|
139
|
-
"""Get the last N sessions, ordered by created_at descending.
|
|
140
|
-
|
|
141
|
-
Args:
|
|
142
|
-
limit: Number of most recent sessions to return
|
|
143
|
-
user_id: Filter by user ID
|
|
144
|
-
entity_id: Filter by entity ID (agent_id, team_id, or workflow_id)
|
|
145
|
-
|
|
146
|
-
Returns:
|
|
147
|
-
List[Session]: List of most recent sessions
|
|
148
|
-
"""
|
|
149
|
-
sessions: List[Session] = []
|
|
150
|
-
# List of (created_at, data) tuples for sorting
|
|
151
|
-
session_data: List[tuple[int, dict]] = []
|
|
152
|
-
|
|
153
|
-
# First pass: collect and filter sessions
|
|
154
|
-
for session_id, data in self.storage.items():
|
|
155
|
-
try:
|
|
156
|
-
if user_id and data["user_id"] != user_id:
|
|
157
|
-
continue
|
|
158
|
-
|
|
159
|
-
if entity_id:
|
|
160
|
-
if self.mode == "agent" and data["agent_id"] != entity_id:
|
|
161
|
-
continue
|
|
162
|
-
elif self.mode == "team" and data["team_id"] != entity_id:
|
|
163
|
-
continue
|
|
164
|
-
elif self.mode == "workflow" and data["workflow_id"] != entity_id:
|
|
165
|
-
continue
|
|
166
|
-
elif self.mode == "workflow_v2" and data["workflow_id"] != entity_id:
|
|
167
|
-
continue
|
|
168
|
-
|
|
169
|
-
# Store with created_at for sorting
|
|
170
|
-
created_at = data.get("created_at", 0)
|
|
171
|
-
session_data.append((created_at, data))
|
|
172
|
-
|
|
173
|
-
except Exception as e:
|
|
174
|
-
logger.error(f"Error processing session {session_id}: {e}")
|
|
175
|
-
continue
|
|
176
|
-
|
|
177
|
-
# Sort by created_at descending and take only limit sessions
|
|
178
|
-
session_data.sort(key=lambda x: x[0], reverse=True)
|
|
179
|
-
if limit is not None:
|
|
180
|
-
session_data = session_data[:limit]
|
|
181
|
-
|
|
182
|
-
# Convert filtered and sorted data to Session objects
|
|
183
|
-
for _, data in session_data:
|
|
184
|
-
session: Optional[Session] = None
|
|
185
|
-
if self.mode == "agent":
|
|
186
|
-
session = AgentSession.from_dict(data)
|
|
187
|
-
elif self.mode == "team":
|
|
188
|
-
session = TeamSession.from_dict(data)
|
|
189
|
-
elif self.mode == "workflow":
|
|
190
|
-
session = WorkflowSession.from_dict(data)
|
|
191
|
-
elif self.mode == "workflow_v2":
|
|
192
|
-
session = WorkflowSessionV2.from_dict(data)
|
|
193
|
-
if session is not None:
|
|
194
|
-
sessions.append(session)
|
|
195
|
-
|
|
196
|
-
return sessions
|
|
197
|
-
|
|
198
|
-
def upsert(self, session: Session) -> Optional[Session]:
|
|
199
|
-
"""Insert or update a Session in storage."""
|
|
200
|
-
try:
|
|
201
|
-
if self.mode == "workflow_v2":
|
|
202
|
-
data = session.to_dict()
|
|
203
|
-
else:
|
|
204
|
-
data = asdict(session)
|
|
205
|
-
|
|
206
|
-
data["updated_at"] = int(time.time())
|
|
207
|
-
if not data.get("created_at", None):
|
|
208
|
-
data["created_at"] = data["updated_at"]
|
|
209
|
-
|
|
210
|
-
self.storage[session.session_id] = data
|
|
211
|
-
return session
|
|
212
|
-
|
|
213
|
-
except Exception as e:
|
|
214
|
-
logger.error(f"Error upserting session: {e}")
|
|
215
|
-
return None
|
|
216
|
-
|
|
217
|
-
def delete_session(self, session_id: Optional[str] = None):
|
|
218
|
-
"""Delete a session from storage."""
|
|
219
|
-
if session_id is None:
|
|
220
|
-
return
|
|
221
|
-
|
|
222
|
-
try:
|
|
223
|
-
self.storage.pop(session_id, None)
|
|
224
|
-
|
|
225
|
-
except Exception as e:
|
|
226
|
-
logger.error(f"Error deleting session: {e}")
|
|
227
|
-
|
|
228
|
-
def drop(self) -> None:
|
|
229
|
-
"""Drop all sessions from storage."""
|
|
230
|
-
self.storage.clear()
|
|
231
|
-
|
|
232
|
-
def upgrade_schema(self) -> None:
|
|
233
|
-
"""Upgrade the schema of the storage."""
|
|
234
|
-
pass
|
agno/storage/json.py
DELETED
|
@@ -1,237 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import time
|
|
3
|
-
from dataclasses import asdict
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import List, Literal, Optional, Union
|
|
6
|
-
|
|
7
|
-
from agno.storage.base import Storage
|
|
8
|
-
from agno.storage.session import Session
|
|
9
|
-
from agno.storage.session.agent import AgentSession
|
|
10
|
-
from agno.storage.session.team import TeamSession
|
|
11
|
-
from agno.storage.session.v2.workflow import WorkflowSession as WorkflowSessionV2
|
|
12
|
-
from agno.storage.session.workflow import WorkflowSession
|
|
13
|
-
from agno.utils.log import logger
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class JsonStorage(Storage):
|
|
17
|
-
def __init__(
|
|
18
|
-
self, dir_path: Union[str, Path], mode: Optional[Literal["agent", "team", "workflow", "workflow_v2"]] = "agent"
|
|
19
|
-
):
|
|
20
|
-
super().__init__(mode)
|
|
21
|
-
self.dir_path = Path(dir_path)
|
|
22
|
-
self.dir_path.mkdir(parents=True, exist_ok=True)
|
|
23
|
-
|
|
24
|
-
def serialize(self, data: dict) -> str:
|
|
25
|
-
return json.dumps(data, ensure_ascii=False, indent=4)
|
|
26
|
-
|
|
27
|
-
def deserialize(self, data: str) -> dict:
|
|
28
|
-
return json.loads(data)
|
|
29
|
-
|
|
30
|
-
def create(self) -> None:
|
|
31
|
-
"""Create the storage if it doesn't exist."""
|
|
32
|
-
if not self.dir_path.exists():
|
|
33
|
-
self.dir_path.mkdir(parents=True, exist_ok=True)
|
|
34
|
-
|
|
35
|
-
def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[Session]:
|
|
36
|
-
"""Read an AgentSession from storage."""
|
|
37
|
-
try:
|
|
38
|
-
with open(self.dir_path / f"{session_id}.json", "r", encoding="utf-8") as f:
|
|
39
|
-
data = self.deserialize(f.read())
|
|
40
|
-
if user_id and data["user_id"] != user_id:
|
|
41
|
-
return None
|
|
42
|
-
if self.mode == "agent":
|
|
43
|
-
return AgentSession.from_dict(data)
|
|
44
|
-
elif self.mode == "team":
|
|
45
|
-
return TeamSession.from_dict(data)
|
|
46
|
-
elif self.mode == "workflow":
|
|
47
|
-
return WorkflowSession.from_dict(data)
|
|
48
|
-
elif self.mode == "workflow_v2":
|
|
49
|
-
return WorkflowSessionV2.from_dict(data)
|
|
50
|
-
except FileNotFoundError:
|
|
51
|
-
return None
|
|
52
|
-
|
|
53
|
-
def get_all_session_ids(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[str]:
|
|
54
|
-
"""Get all session IDs, optionally filtered by user_id and/or entity_id."""
|
|
55
|
-
session_ids = []
|
|
56
|
-
for file in self.dir_path.glob("*.json"):
|
|
57
|
-
with open(file, "r", encoding="utf-8") as f:
|
|
58
|
-
data = self.deserialize(f.read())
|
|
59
|
-
if user_id or entity_id:
|
|
60
|
-
if user_id and entity_id:
|
|
61
|
-
if self.mode == "agent" and data["agent_id"] == entity_id and data["user_id"] == user_id:
|
|
62
|
-
session_ids.append(data["session_id"])
|
|
63
|
-
elif self.mode == "team" and data["team_id"] == entity_id and data["user_id"] == user_id:
|
|
64
|
-
session_ids.append(data["session_id"])
|
|
65
|
-
elif (
|
|
66
|
-
self.mode == "workflow" and data["workflow_id"] == entity_id and data["user_id"] == user_id
|
|
67
|
-
):
|
|
68
|
-
session_ids.append(data["session_id"])
|
|
69
|
-
elif user_id and data["user_id"] == user_id:
|
|
70
|
-
session_ids.append(data["session_id"])
|
|
71
|
-
elif entity_id:
|
|
72
|
-
if self.mode == "agent" and data["agent_id"] == entity_id:
|
|
73
|
-
session_ids.append(data["session_id"])
|
|
74
|
-
elif self.mode == "team" and data["team_id"] == entity_id:
|
|
75
|
-
session_ids.append(data["session_id"])
|
|
76
|
-
elif self.mode == "workflow" and data["workflow_id"] == entity_id:
|
|
77
|
-
session_ids.append(data["session_id"])
|
|
78
|
-
elif self.mode == "workflow_v2" and data["workflow_id"] == entity_id:
|
|
79
|
-
session_ids.append(data["session_id"])
|
|
80
|
-
else:
|
|
81
|
-
# No filters applied, add all session_ids
|
|
82
|
-
session_ids.append(data["session_id"])
|
|
83
|
-
return session_ids
|
|
84
|
-
|
|
85
|
-
def get_all_sessions(self, user_id: Optional[str] = None, entity_id: Optional[str] = None) -> List[Session]:
|
|
86
|
-
"""Get all sessions, optionally filtered by user_id and/or entity_id."""
|
|
87
|
-
sessions: List[Session] = []
|
|
88
|
-
for file in self.dir_path.glob("*.json"):
|
|
89
|
-
with open(file, "r", encoding="utf-8") as f:
|
|
90
|
-
data = self.deserialize(f.read())
|
|
91
|
-
if user_id or entity_id:
|
|
92
|
-
_session: Optional[Session] = None
|
|
93
|
-
|
|
94
|
-
if user_id and entity_id:
|
|
95
|
-
if self.mode == "agent" and data["agent_id"] == entity_id and data["user_id"] == user_id:
|
|
96
|
-
_session = AgentSession.from_dict(data)
|
|
97
|
-
elif self.mode == "team" and data["team_id"] == entity_id and data["user_id"] == user_id:
|
|
98
|
-
_session = TeamSession.from_dict(data)
|
|
99
|
-
elif (
|
|
100
|
-
self.mode == "workflow" and data["workflow_id"] == entity_id and data["user_id"] == user_id
|
|
101
|
-
):
|
|
102
|
-
_session = WorkflowSession.from_dict(data)
|
|
103
|
-
elif user_id and data["user_id"] == user_id:
|
|
104
|
-
if self.mode == "agent":
|
|
105
|
-
_session = AgentSession.from_dict(data)
|
|
106
|
-
elif self.mode == "team":
|
|
107
|
-
_session = TeamSession.from_dict(data)
|
|
108
|
-
elif self.mode == "workflow":
|
|
109
|
-
_session = WorkflowSession.from_dict(data)
|
|
110
|
-
elif entity_id:
|
|
111
|
-
if self.mode == "agent" and data["agent_id"] == entity_id:
|
|
112
|
-
_session = AgentSession.from_dict(data)
|
|
113
|
-
elif self.mode == "team" and data["team_id"] == entity_id:
|
|
114
|
-
_session = TeamSession.from_dict(data)
|
|
115
|
-
elif self.mode == "workflow" and data["workflow_id"] == entity_id:
|
|
116
|
-
_session = WorkflowSession.from_dict(data)
|
|
117
|
-
elif self.mode == "workflow_v2" and data["workflow_id"] == entity_id:
|
|
118
|
-
_session = WorkflowSessionV2.from_dict(data)
|
|
119
|
-
if _session:
|
|
120
|
-
sessions.append(_session)
|
|
121
|
-
else:
|
|
122
|
-
# No filters applied, add all sessions
|
|
123
|
-
if self.mode == "agent":
|
|
124
|
-
_session = AgentSession.from_dict(data)
|
|
125
|
-
elif self.mode == "team":
|
|
126
|
-
_session = TeamSession.from_dict(data)
|
|
127
|
-
elif self.mode == "workflow":
|
|
128
|
-
_session = WorkflowSession.from_dict(data)
|
|
129
|
-
elif self.mode == "workflow_v2":
|
|
130
|
-
_session = WorkflowSessionV2.from_dict(data)
|
|
131
|
-
if _session:
|
|
132
|
-
sessions.append(_session)
|
|
133
|
-
return sessions
|
|
134
|
-
|
|
135
|
-
def get_recent_sessions(
|
|
136
|
-
self,
|
|
137
|
-
user_id: Optional[str] = None,
|
|
138
|
-
entity_id: Optional[str] = None,
|
|
139
|
-
limit: Optional[int] = 2,
|
|
140
|
-
) -> List[Session]:
|
|
141
|
-
"""Get the last N sessions, ordered by created_at descending.
|
|
142
|
-
|
|
143
|
-
Args:
|
|
144
|
-
num_history_sessions: Number of most recent sessions to return
|
|
145
|
-
user_id: Filter by user ID
|
|
146
|
-
entity_id: Filter by entity ID (agent_id, team_id, or workflow_id)
|
|
147
|
-
|
|
148
|
-
Returns:
|
|
149
|
-
List[Session]: List of most recent sessions
|
|
150
|
-
"""
|
|
151
|
-
sessions: List[Session] = []
|
|
152
|
-
# List of (created_at, data) tuples for sorting
|
|
153
|
-
session_data: List[tuple[int, dict]] = []
|
|
154
|
-
|
|
155
|
-
# First pass: collect and filter sessions
|
|
156
|
-
for file in self.dir_path.glob("*.json"):
|
|
157
|
-
try:
|
|
158
|
-
with open(file, "r", encoding="utf-8") as f:
|
|
159
|
-
data = self.deserialize(f.read())
|
|
160
|
-
|
|
161
|
-
if user_id and data["user_id"] != user_id:
|
|
162
|
-
continue
|
|
163
|
-
|
|
164
|
-
if entity_id:
|
|
165
|
-
if self.mode == "agent" and data["agent_id"] != entity_id:
|
|
166
|
-
continue
|
|
167
|
-
elif self.mode == "team" and data["team_id"] != entity_id:
|
|
168
|
-
continue
|
|
169
|
-
elif self.mode == "workflow" and data["workflow_id"] != entity_id:
|
|
170
|
-
continue
|
|
171
|
-
elif self.mode == "workflow_v2" and data["workflow_id"] != entity_id:
|
|
172
|
-
continue
|
|
173
|
-
# Store with created_at for sorting
|
|
174
|
-
created_at = data.get("created_at", 0)
|
|
175
|
-
session_data.append((created_at, data))
|
|
176
|
-
|
|
177
|
-
except Exception as e:
|
|
178
|
-
logger.error(f"Error reading session file {file}: {e}")
|
|
179
|
-
continue
|
|
180
|
-
|
|
181
|
-
# Sort by created_at descending and take only num_history_sessions
|
|
182
|
-
session_data.sort(key=lambda x: x[0], reverse=True)
|
|
183
|
-
if limit is not None:
|
|
184
|
-
session_data = session_data[:limit]
|
|
185
|
-
|
|
186
|
-
# Convert filtered and sorted data to Session objects
|
|
187
|
-
for _, data in session_data:
|
|
188
|
-
session: Optional[Session] = None
|
|
189
|
-
if self.mode == "agent":
|
|
190
|
-
session = AgentSession.from_dict(data)
|
|
191
|
-
elif self.mode == "team":
|
|
192
|
-
session = TeamSession.from_dict(data)
|
|
193
|
-
elif self.mode == "workflow":
|
|
194
|
-
session = WorkflowSession.from_dict(data)
|
|
195
|
-
elif self.mode == "workflow_v2":
|
|
196
|
-
session = WorkflowSessionV2.from_dict(data)
|
|
197
|
-
if session is not None:
|
|
198
|
-
sessions.append(session)
|
|
199
|
-
|
|
200
|
-
return sessions
|
|
201
|
-
|
|
202
|
-
def upsert(self, session: Session) -> Optional[Session]:
|
|
203
|
-
"""Insert or update a Session in storage."""
|
|
204
|
-
try:
|
|
205
|
-
if self.mode == "workflow_v2":
|
|
206
|
-
data = session.to_dict()
|
|
207
|
-
else:
|
|
208
|
-
data = asdict(session)
|
|
209
|
-
|
|
210
|
-
data["updated_at"] = int(time.time())
|
|
211
|
-
if "created_at" not in data or data["created_at"] is None:
|
|
212
|
-
data["created_at"] = data["updated_at"]
|
|
213
|
-
|
|
214
|
-
with open(self.dir_path / f"{session.session_id}.json", "w", encoding="utf-8") as f:
|
|
215
|
-
f.write(self.serialize(data))
|
|
216
|
-
return session
|
|
217
|
-
except Exception as e:
|
|
218
|
-
logger.error(f"Error upserting session: {e}")
|
|
219
|
-
return None
|
|
220
|
-
|
|
221
|
-
def delete_session(self, session_id: Optional[str] = None):
|
|
222
|
-
"""Delete a session from storage."""
|
|
223
|
-
if session_id is None:
|
|
224
|
-
return
|
|
225
|
-
try:
|
|
226
|
-
(self.dir_path / f"{session_id}.json").unlink(missing_ok=True)
|
|
227
|
-
except Exception as e:
|
|
228
|
-
logger.error(f"Error deleting session: {e}")
|
|
229
|
-
|
|
230
|
-
def drop(self) -> None:
|
|
231
|
-
"""Drop all sessions from storage."""
|
|
232
|
-
for file in self.dir_path.glob("*.json"):
|
|
233
|
-
file.unlink()
|
|
234
|
-
|
|
235
|
-
def upgrade_schema(self) -> None:
|
|
236
|
-
"""Upgrade the schema of the storage."""
|
|
237
|
-
pass
|