agno 0.1.2__py3-none-any.whl → 2.3.13__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 +44 -5
- agno/agent/agent.py +10531 -2975
- agno/api/agent.py +14 -53
- agno/api/api.py +7 -46
- agno/api/evals.py +22 -0
- agno/api/os.py +17 -0
- agno/api/routes.py +6 -25
- agno/api/schemas/__init__.py +9 -0
- agno/api/schemas/agent.py +6 -9
- agno/api/schemas/evals.py +16 -0
- agno/api/schemas/os.py +14 -0
- agno/api/schemas/team.py +10 -10
- agno/api/schemas/utils.py +21 -0
- agno/api/schemas/workflows.py +16 -0
- agno/api/settings.py +53 -0
- agno/api/team.py +22 -26
- 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/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -0
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +956 -0
- agno/db/__init__.py +24 -0
- agno/db/async_postgres/__init__.py +3 -0
- agno/db/base.py +946 -0
- agno/db/dynamo/__init__.py +3 -0
- agno/db/dynamo/dynamo.py +2781 -0
- agno/db/dynamo/schemas.py +442 -0
- agno/db/dynamo/utils.py +743 -0
- agno/db/firestore/__init__.py +3 -0
- agno/db/firestore/firestore.py +2379 -0
- agno/db/firestore/schemas.py +181 -0
- agno/db/firestore/utils.py +376 -0
- agno/db/gcs_json/__init__.py +3 -0
- agno/db/gcs_json/gcs_json_db.py +1791 -0
- agno/db/gcs_json/utils.py +228 -0
- agno/db/in_memory/__init__.py +3 -0
- agno/db/in_memory/in_memory_db.py +1312 -0
- agno/db/in_memory/utils.py +230 -0
- agno/db/json/__init__.py +3 -0
- agno/db/json/json_db.py +1777 -0
- agno/db/json/utils.py +230 -0
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/v1_to_v2.py +635 -0
- agno/db/migrations/versions/v2_3_0.py +938 -0
- agno/db/mongo/__init__.py +17 -0
- agno/db/mongo/async_mongo.py +2760 -0
- agno/db/mongo/mongo.py +2597 -0
- agno/db/mongo/schemas.py +119 -0
- agno/db/mongo/utils.py +276 -0
- agno/db/mysql/__init__.py +4 -0
- agno/db/mysql/async_mysql.py +2912 -0
- agno/db/mysql/mysql.py +2923 -0
- agno/db/mysql/schemas.py +186 -0
- agno/db/mysql/utils.py +488 -0
- agno/db/postgres/__init__.py +4 -0
- agno/db/postgres/async_postgres.py +2579 -0
- agno/db/postgres/postgres.py +2870 -0
- agno/db/postgres/schemas.py +187 -0
- agno/db/postgres/utils.py +442 -0
- agno/db/redis/__init__.py +3 -0
- agno/db/redis/redis.py +2141 -0
- agno/db/redis/schemas.py +159 -0
- agno/db/redis/utils.py +346 -0
- agno/db/schemas/__init__.py +4 -0
- agno/db/schemas/culture.py +120 -0
- agno/db/schemas/evals.py +34 -0
- agno/db/schemas/knowledge.py +40 -0
- agno/db/schemas/memory.py +61 -0
- agno/db/singlestore/__init__.py +3 -0
- agno/db/singlestore/schemas.py +179 -0
- agno/db/singlestore/singlestore.py +2877 -0
- agno/db/singlestore/utils.py +384 -0
- agno/db/sqlite/__init__.py +4 -0
- agno/db/sqlite/async_sqlite.py +2911 -0
- agno/db/sqlite/schemas.py +181 -0
- agno/db/sqlite/sqlite.py +2908 -0
- agno/db/sqlite/utils.py +429 -0
- agno/db/surrealdb/__init__.py +3 -0
- agno/db/surrealdb/metrics.py +292 -0
- agno/db/surrealdb/models.py +334 -0
- agno/db/surrealdb/queries.py +71 -0
- agno/db/surrealdb/surrealdb.py +1908 -0
- agno/db/surrealdb/utils.py +147 -0
- agno/db/utils.py +118 -0
- agno/eval/__init__.py +24 -0
- agno/eval/accuracy.py +666 -276
- agno/eval/agent_as_judge.py +861 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +779 -0
- agno/eval/reliability.py +241 -62
- agno/eval/utils.py +120 -0
- agno/exceptions.py +143 -1
- agno/filters.py +354 -0
- agno/guardrails/__init__.py +6 -0
- agno/guardrails/base.py +19 -0
- agno/guardrails/openai.py +144 -0
- agno/guardrails/pii.py +94 -0
- agno/guardrails/prompt_injection.py +52 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/__init__.py +3 -0
- agno/integrations/discord/client.py +203 -0
- agno/knowledge/__init__.py +5 -1
- agno/{document → knowledge}/chunking/agentic.py +22 -14
- agno/{document → knowledge}/chunking/document.py +2 -2
- agno/{document → knowledge}/chunking/fixed.py +7 -6
- agno/knowledge/chunking/markdown.py +151 -0
- agno/{document → knowledge}/chunking/recursive.py +15 -3
- agno/knowledge/chunking/row.py +39 -0
- agno/knowledge/chunking/semantic.py +91 -0
- agno/knowledge/chunking/strategy.py +165 -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/knowledge/embedder/aws_bedrock.py +343 -0
- agno/knowledge/embedder/azure_openai.py +210 -0
- agno/{embedder → knowledge/embedder}/base.py +8 -0
- agno/knowledge/embedder/cohere.py +323 -0
- agno/knowledge/embedder/fastembed.py +62 -0
- agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
- agno/knowledge/embedder/google.py +258 -0
- agno/knowledge/embedder/huggingface.py +94 -0
- agno/knowledge/embedder/jina.py +182 -0
- agno/knowledge/embedder/langdb.py +22 -0
- agno/knowledge/embedder/mistral.py +206 -0
- agno/knowledge/embedder/nebius.py +13 -0
- agno/knowledge/embedder/ollama.py +154 -0
- agno/knowledge/embedder/openai.py +195 -0
- agno/knowledge/embedder/sentence_transformer.py +63 -0
- agno/{embedder → knowledge/embedder}/together.py +1 -1
- agno/knowledge/embedder/vllm.py +262 -0
- agno/knowledge/embedder/voyageai.py +165 -0
- agno/knowledge/knowledge.py +3006 -0
- agno/knowledge/reader/__init__.py +7 -0
- agno/knowledge/reader/arxiv_reader.py +81 -0
- agno/knowledge/reader/base.py +95 -0
- agno/knowledge/reader/csv_reader.py +164 -0
- agno/knowledge/reader/docx_reader.py +82 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +290 -0
- agno/knowledge/reader/firecrawl_reader.py +201 -0
- agno/knowledge/reader/json_reader.py +88 -0
- agno/knowledge/reader/markdown_reader.py +137 -0
- agno/knowledge/reader/pdf_reader.py +431 -0
- agno/knowledge/reader/pptx_reader.py +101 -0
- agno/knowledge/reader/reader_factory.py +313 -0
- agno/knowledge/reader/s3_reader.py +89 -0
- agno/knowledge/reader/tavily_reader.py +193 -0
- agno/knowledge/reader/text_reader.py +127 -0
- agno/knowledge/reader/web_search_reader.py +325 -0
- agno/knowledge/reader/website_reader.py +455 -0
- agno/knowledge/reader/wikipedia_reader.py +91 -0
- agno/knowledge/reader/youtube_reader.py +78 -0
- agno/knowledge/remote_content/remote_content.py +88 -0
- agno/knowledge/reranker/__init__.py +3 -0
- agno/{reranker → knowledge/reranker}/base.py +1 -1
- agno/{reranker → knowledge/reranker}/cohere.py +2 -2
- agno/knowledge/reranker/infinity.py +195 -0
- agno/knowledge/reranker/sentence_transformer.py +54 -0
- agno/knowledge/types.py +39 -0
- agno/knowledge/utils.py +234 -0
- agno/media.py +439 -95
- agno/memory/__init__.py +16 -3
- agno/memory/manager.py +1474 -123
- agno/memory/strategies/__init__.py +15 -0
- agno/memory/strategies/base.py +66 -0
- agno/memory/strategies/summarize.py +196 -0
- agno/memory/strategies/types.py +37 -0
- agno/models/aimlapi/__init__.py +5 -0
- agno/models/aimlapi/aimlapi.py +62 -0
- agno/models/anthropic/__init__.py +4 -0
- agno/models/anthropic/claude.py +960 -496
- agno/models/aws/__init__.py +15 -0
- agno/models/aws/bedrock.py +686 -451
- agno/models/aws/claude.py +190 -183
- agno/models/azure/__init__.py +18 -1
- agno/models/azure/ai_foundry.py +489 -0
- agno/models/azure/openai_chat.py +89 -40
- agno/models/base.py +2477 -550
- agno/models/cerebras/__init__.py +12 -0
- agno/models/cerebras/cerebras.py +565 -0
- agno/models/cerebras/cerebras_openai.py +131 -0
- agno/models/cohere/__init__.py +4 -0
- agno/models/cohere/chat.py +306 -492
- agno/models/cometapi/__init__.py +5 -0
- agno/models/cometapi/cometapi.py +74 -0
- agno/models/dashscope/__init__.py +5 -0
- agno/models/dashscope/dashscope.py +90 -0
- agno/models/deepinfra/__init__.py +5 -0
- agno/models/deepinfra/deepinfra.py +45 -0
- agno/models/deepseek/__init__.py +4 -0
- agno/models/deepseek/deepseek.py +110 -9
- agno/models/fireworks/__init__.py +4 -0
- agno/models/fireworks/fireworks.py +19 -22
- agno/models/google/__init__.py +3 -7
- agno/models/google/gemini.py +1717 -662
- agno/models/google/utils.py +22 -0
- agno/models/groq/__init__.py +4 -0
- agno/models/groq/groq.py +391 -666
- agno/models/huggingface/__init__.py +4 -0
- agno/models/huggingface/huggingface.py +266 -538
- agno/models/ibm/__init__.py +5 -0
- agno/models/ibm/watsonx.py +432 -0
- agno/models/internlm/__init__.py +3 -0
- agno/models/internlm/internlm.py +20 -3
- agno/models/langdb/__init__.py +1 -0
- agno/models/langdb/langdb.py +60 -0
- agno/models/litellm/__init__.py +14 -0
- agno/models/litellm/chat.py +503 -0
- agno/models/litellm/litellm_openai.py +42 -0
- agno/models/llama_cpp/__init__.py +5 -0
- agno/models/llama_cpp/llama_cpp.py +22 -0
- agno/models/lmstudio/__init__.py +5 -0
- agno/models/lmstudio/lmstudio.py +25 -0
- agno/models/message.py +361 -39
- agno/models/meta/__init__.py +12 -0
- agno/models/meta/llama.py +502 -0
- agno/models/meta/llama_openai.py +79 -0
- agno/models/metrics.py +120 -0
- agno/models/mistral/__init__.py +4 -0
- agno/models/mistral/mistral.py +293 -393
- agno/models/nebius/__init__.py +3 -0
- agno/models/nebius/nebius.py +53 -0
- agno/models/nexus/__init__.py +3 -0
- agno/models/nexus/nexus.py +22 -0
- agno/models/nvidia/__init__.py +4 -0
- agno/models/nvidia/nvidia.py +22 -3
- agno/models/ollama/__init__.py +4 -2
- agno/models/ollama/chat.py +257 -492
- agno/models/openai/__init__.py +7 -0
- agno/models/openai/chat.py +725 -770
- agno/models/openai/like.py +16 -2
- agno/models/openai/responses.py +1121 -0
- agno/models/openrouter/__init__.py +4 -0
- agno/models/openrouter/openrouter.py +62 -5
- agno/models/perplexity/__init__.py +5 -0
- agno/models/perplexity/perplexity.py +203 -0
- agno/models/portkey/__init__.py +3 -0
- agno/models/portkey/portkey.py +82 -0
- agno/models/requesty/__init__.py +5 -0
- agno/models/requesty/requesty.py +69 -0
- agno/models/response.py +177 -7
- agno/models/sambanova/__init__.py +4 -0
- agno/models/sambanova/sambanova.py +23 -4
- agno/models/siliconflow/__init__.py +5 -0
- agno/models/siliconflow/siliconflow.py +42 -0
- agno/models/together/__init__.py +4 -0
- agno/models/together/together.py +21 -164
- agno/models/utils.py +266 -0
- agno/models/vercel/__init__.py +3 -0
- agno/models/vercel/v0.py +43 -0
- agno/models/vertexai/__init__.py +0 -1
- agno/models/vertexai/claude.py +190 -0
- agno/models/vllm/__init__.py +3 -0
- agno/models/vllm/vllm.py +83 -0
- agno/models/xai/__init__.py +2 -0
- agno/models/xai/xai.py +111 -7
- agno/os/__init__.py +3 -0
- agno/os/app.py +1027 -0
- agno/os/auth.py +244 -0
- agno/os/config.py +126 -0
- agno/os/interfaces/__init__.py +1 -0
- agno/os/interfaces/a2a/__init__.py +3 -0
- agno/os/interfaces/a2a/a2a.py +42 -0
- agno/os/interfaces/a2a/router.py +249 -0
- agno/os/interfaces/a2a/utils.py +924 -0
- agno/os/interfaces/agui/__init__.py +3 -0
- agno/os/interfaces/agui/agui.py +47 -0
- agno/os/interfaces/agui/router.py +147 -0
- agno/os/interfaces/agui/utils.py +574 -0
- agno/os/interfaces/base.py +25 -0
- agno/os/interfaces/slack/__init__.py +3 -0
- agno/os/interfaces/slack/router.py +148 -0
- agno/os/interfaces/slack/security.py +30 -0
- agno/os/interfaces/slack/slack.py +47 -0
- agno/os/interfaces/whatsapp/__init__.py +3 -0
- agno/os/interfaces/whatsapp/router.py +210 -0
- agno/os/interfaces/whatsapp/security.py +55 -0
- agno/os/interfaces/whatsapp/whatsapp.py +36 -0
- agno/os/mcp.py +293 -0
- agno/os/middleware/__init__.py +9 -0
- agno/os/middleware/jwt.py +797 -0
- agno/os/router.py +258 -0
- agno/os/routers/__init__.py +3 -0
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +599 -0
- agno/os/routers/agents/schema.py +261 -0
- agno/os/routers/evals/__init__.py +3 -0
- agno/os/routers/evals/evals.py +450 -0
- agno/os/routers/evals/schemas.py +174 -0
- agno/os/routers/evals/utils.py +231 -0
- agno/os/routers/health.py +31 -0
- agno/os/routers/home.py +52 -0
- agno/os/routers/knowledge/__init__.py +3 -0
- agno/os/routers/knowledge/knowledge.py +1008 -0
- agno/os/routers/knowledge/schemas.py +178 -0
- agno/os/routers/memory/__init__.py +3 -0
- agno/os/routers/memory/memory.py +661 -0
- agno/os/routers/memory/schemas.py +88 -0
- agno/os/routers/metrics/__init__.py +3 -0
- agno/os/routers/metrics/metrics.py +190 -0
- agno/os/routers/metrics/schemas.py +47 -0
- agno/os/routers/session/__init__.py +3 -0
- agno/os/routers/session/session.py +997 -0
- agno/os/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +512 -0
- agno/os/routers/teams/schema.py +257 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +499 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +624 -0
- agno/os/routers/workflows/schema.py +75 -0
- agno/os/schema.py +534 -0
- agno/os/scopes.py +469 -0
- agno/{playground → os}/settings.py +7 -15
- agno/os/utils.py +973 -0
- agno/reasoning/anthropic.py +80 -0
- agno/reasoning/azure_ai_foundry.py +67 -0
- agno/reasoning/deepseek.py +63 -0
- agno/reasoning/default.py +97 -0
- agno/reasoning/gemini.py +73 -0
- agno/reasoning/groq.py +71 -0
- agno/reasoning/helpers.py +24 -1
- agno/reasoning/ollama.py +67 -0
- agno/reasoning/openai.py +86 -0
- agno/reasoning/step.py +2 -1
- agno/reasoning/vertexai.py +76 -0
- agno/run/__init__.py +6 -0
- agno/run/agent.py +822 -0
- agno/run/base.py +247 -0
- agno/run/cancel.py +81 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +767 -0
- agno/run/workflow.py +708 -0
- agno/session/__init__.py +10 -0
- agno/session/agent.py +260 -0
- agno/session/summary.py +265 -0
- agno/session/team.py +342 -0
- agno/session/workflow.py +501 -0
- agno/table.py +10 -0
- agno/team/__init__.py +37 -0
- agno/team/team.py +9536 -0
- agno/tools/__init__.py +7 -0
- agno/tools/agentql.py +120 -0
- agno/tools/airflow.py +22 -12
- agno/tools/api.py +122 -0
- agno/tools/apify.py +276 -83
- agno/tools/{arxiv_toolkit.py → arxiv.py} +20 -12
- agno/tools/aws_lambda.py +28 -7
- agno/tools/aws_ses.py +66 -0
- agno/tools/baidusearch.py +11 -4
- agno/tools/bitbucket.py +292 -0
- agno/tools/brandfetch.py +213 -0
- agno/tools/bravesearch.py +106 -0
- agno/tools/brightdata.py +367 -0
- agno/tools/browserbase.py +209 -0
- agno/tools/calcom.py +32 -23
- agno/tools/calculator.py +24 -37
- agno/tools/cartesia.py +187 -0
- agno/tools/{clickup_tool.py → clickup.py} +17 -28
- agno/tools/confluence.py +91 -26
- agno/tools/crawl4ai.py +139 -43
- agno/tools/csv_toolkit.py +28 -22
- agno/tools/dalle.py +36 -22
- agno/tools/daytona.py +475 -0
- agno/tools/decorator.py +169 -14
- agno/tools/desi_vocal.py +23 -11
- agno/tools/discord.py +32 -29
- agno/tools/docker.py +716 -0
- agno/tools/duckdb.py +76 -81
- agno/tools/duckduckgo.py +43 -40
- agno/tools/e2b.py +703 -0
- agno/tools/eleven_labs.py +65 -54
- agno/tools/email.py +13 -5
- agno/tools/evm.py +129 -0
- agno/tools/exa.py +324 -42
- agno/tools/fal.py +39 -35
- agno/tools/file.py +196 -30
- agno/tools/file_generation.py +356 -0
- agno/tools/financial_datasets.py +288 -0
- agno/tools/firecrawl.py +108 -33
- agno/tools/function.py +960 -122
- agno/tools/giphy.py +34 -12
- agno/tools/github.py +1294 -97
- agno/tools/gmail.py +922 -0
- agno/tools/google_bigquery.py +117 -0
- agno/tools/google_drive.py +271 -0
- agno/tools/google_maps.py +253 -0
- agno/tools/googlecalendar.py +607 -107
- agno/tools/googlesheets.py +377 -0
- agno/tools/hackernews.py +20 -12
- agno/tools/jina.py +24 -14
- agno/tools/jira.py +48 -19
- agno/tools/knowledge.py +218 -0
- agno/tools/linear.py +82 -43
- agno/tools/linkup.py +58 -0
- agno/tools/local_file_system.py +15 -7
- agno/tools/lumalab.py +41 -26
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +331 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/mcp_toolbox.py +284 -0
- agno/tools/mem0.py +193 -0
- agno/tools/memory.py +419 -0
- agno/tools/mlx_transcribe.py +11 -9
- agno/tools/models/azure_openai.py +190 -0
- agno/tools/models/gemini.py +203 -0
- agno/tools/models/groq.py +158 -0
- agno/tools/models/morph.py +186 -0
- agno/tools/models/nebius.py +124 -0
- agno/tools/models_labs.py +163 -82
- agno/tools/moviepy_video.py +18 -13
- agno/tools/nano_banana.py +151 -0
- agno/tools/neo4j.py +134 -0
- agno/tools/newspaper.py +15 -4
- agno/tools/newspaper4k.py +19 -6
- agno/tools/notion.py +204 -0
- agno/tools/openai.py +181 -17
- agno/tools/openbb.py +27 -20
- agno/tools/opencv.py +321 -0
- agno/tools/openweather.py +233 -0
- agno/tools/oxylabs.py +385 -0
- agno/tools/pandas.py +25 -15
- agno/tools/parallel.py +314 -0
- agno/tools/postgres.py +238 -185
- agno/tools/pubmed.py +125 -13
- agno/tools/python.py +48 -35
- agno/tools/reasoning.py +283 -0
- agno/tools/reddit.py +207 -29
- agno/tools/redshift.py +406 -0
- agno/tools/replicate.py +69 -26
- agno/tools/resend.py +11 -6
- agno/tools/scrapegraph.py +179 -19
- agno/tools/searxng.py +23 -31
- agno/tools/serpapi.py +15 -10
- agno/tools/serper.py +255 -0
- agno/tools/shell.py +23 -12
- agno/tools/shopify.py +1519 -0
- agno/tools/slack.py +56 -14
- agno/tools/sleep.py +8 -6
- agno/tools/spider.py +35 -11
- agno/tools/spotify.py +919 -0
- agno/tools/sql.py +34 -19
- agno/tools/tavily.py +158 -8
- agno/tools/telegram.py +18 -8
- agno/tools/todoist.py +218 -0
- agno/tools/toolkit.py +134 -9
- agno/tools/trafilatura.py +388 -0
- agno/tools/trello.py +25 -28
- agno/tools/twilio.py +18 -9
- agno/tools/user_control_flow.py +78 -0
- agno/tools/valyu.py +228 -0
- agno/tools/visualization.py +467 -0
- agno/tools/webbrowser.py +28 -0
- agno/tools/webex.py +76 -0
- agno/tools/website.py +23 -19
- agno/tools/webtools.py +45 -0
- agno/tools/whatsapp.py +286 -0
- agno/tools/wikipedia.py +28 -19
- agno/tools/workflow.py +285 -0
- agno/tools/{twitter.py → x.py} +142 -46
- agno/tools/yfinance.py +41 -39
- agno/tools/youtube.py +34 -17
- agno/tools/zendesk.py +15 -5
- agno/tools/zep.py +454 -0
- agno/tools/zoom.py +86 -37
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +157 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +111 -0
- agno/utils/agent.py +938 -0
- agno/utils/audio.py +37 -1
- agno/utils/certs.py +27 -0
- agno/utils/code_execution.py +11 -0
- agno/utils/common.py +103 -20
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +700 -0
- agno/utils/functions.py +107 -37
- agno/utils/gemini.py +426 -0
- agno/utils/hooks.py +171 -0
- agno/utils/http.py +185 -0
- agno/utils/json_schema.py +159 -37
- agno/utils/knowledge.py +36 -0
- agno/utils/location.py +19 -0
- agno/utils/log.py +221 -8
- agno/utils/mcp.py +214 -0
- agno/utils/media.py +335 -14
- agno/utils/merge_dict.py +22 -1
- agno/utils/message.py +77 -2
- agno/utils/models/ai_foundry.py +50 -0
- agno/utils/models/claude.py +373 -0
- agno/utils/models/cohere.py +94 -0
- agno/utils/models/llama.py +85 -0
- agno/utils/models/mistral.py +100 -0
- agno/utils/models/openai_responses.py +140 -0
- agno/utils/models/schema_utils.py +153 -0
- agno/utils/models/watsonx.py +41 -0
- agno/utils/openai.py +257 -0
- agno/utils/pickle.py +1 -1
- agno/utils/pprint.py +124 -8
- agno/utils/print_response/agent.py +930 -0
- agno/utils/print_response/team.py +1914 -0
- agno/utils/print_response/workflow.py +1668 -0
- agno/utils/prompts.py +111 -0
- agno/utils/reasoning.py +108 -0
- agno/utils/response.py +163 -0
- agno/utils/serialize.py +32 -0
- agno/utils/shell.py +4 -4
- agno/utils/streamlit.py +487 -0
- agno/utils/string.py +204 -51
- agno/utils/team.py +139 -0
- agno/utils/timer.py +9 -2
- agno/utils/tokens.py +657 -0
- agno/utils/tools.py +19 -1
- agno/utils/whatsapp.py +305 -0
- agno/utils/yaml_io.py +3 -3
- agno/vectordb/__init__.py +2 -0
- agno/vectordb/base.py +87 -9
- agno/vectordb/cassandra/__init__.py +5 -1
- agno/vectordb/cassandra/cassandra.py +383 -27
- agno/vectordb/chroma/__init__.py +4 -0
- agno/vectordb/chroma/chromadb.py +748 -83
- agno/vectordb/clickhouse/__init__.py +7 -1
- agno/vectordb/clickhouse/clickhousedb.py +554 -53
- agno/vectordb/couchbase/__init__.py +3 -0
- agno/vectordb/couchbase/couchbase.py +1446 -0
- agno/vectordb/lancedb/__init__.py +5 -0
- agno/vectordb/lancedb/lance_db.py +730 -98
- agno/vectordb/langchaindb/__init__.py +5 -0
- agno/vectordb/langchaindb/langchaindb.py +163 -0
- agno/vectordb/lightrag/__init__.py +5 -0
- agno/vectordb/lightrag/lightrag.py +388 -0
- agno/vectordb/llamaindex/__init__.py +3 -0
- agno/vectordb/llamaindex/llamaindexdb.py +166 -0
- agno/vectordb/milvus/__init__.py +3 -0
- agno/vectordb/milvus/milvus.py +966 -78
- agno/vectordb/mongodb/__init__.py +9 -1
- agno/vectordb/mongodb/mongodb.py +1175 -172
- agno/vectordb/pgvector/__init__.py +8 -0
- agno/vectordb/pgvector/pgvector.py +599 -115
- agno/vectordb/pineconedb/__init__.py +5 -1
- agno/vectordb/pineconedb/pineconedb.py +406 -43
- agno/vectordb/qdrant/__init__.py +4 -0
- agno/vectordb/qdrant/qdrant.py +914 -61
- agno/vectordb/redis/__init__.py +9 -0
- agno/vectordb/redis/redisdb.py +682 -0
- agno/vectordb/singlestore/__init__.py +8 -1
- agno/vectordb/singlestore/singlestore.py +771 -0
- agno/vectordb/surrealdb/__init__.py +3 -0
- agno/vectordb/surrealdb/surrealdb.py +663 -0
- agno/vectordb/upstashdb/__init__.py +5 -0
- agno/vectordb/upstashdb/upstashdb.py +718 -0
- agno/vectordb/weaviate/__init__.py +8 -0
- agno/vectordb/weaviate/index.py +15 -0
- agno/vectordb/weaviate/weaviate.py +1009 -0
- agno/workflow/__init__.py +23 -1
- agno/workflow/agent.py +299 -0
- agno/workflow/condition.py +759 -0
- agno/workflow/loop.py +756 -0
- agno/workflow/parallel.py +853 -0
- agno/workflow/router.py +723 -0
- agno/workflow/step.py +1564 -0
- agno/workflow/steps.py +613 -0
- agno/workflow/types.py +556 -0
- agno/workflow/workflow.py +4327 -514
- agno-2.3.13.dist-info/METADATA +639 -0
- agno-2.3.13.dist-info/RECORD +613 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/WHEEL +1 -1
- agno-2.3.13.dist-info/licenses/LICENSE +201 -0
- agno/api/playground.py +0 -91
- agno/api/schemas/playground.py +0 -22
- agno/api/schemas/user.py +0 -22
- agno/api/schemas/workspace.py +0 -46
- agno/api/user.py +0 -160
- agno/api/workspace.py +0 -151
- agno/cli/auth_server.py +0 -118
- agno/cli/config.py +0 -275
- agno/cli/console.py +0 -88
- agno/cli/credentials.py +0 -23
- agno/cli/entrypoint.py +0 -571
- agno/cli/operator.py +0 -355
- agno/cli/settings.py +0 -85
- agno/cli/ws/ws_cli.py +0 -817
- agno/constants.py +0 -13
- agno/document/__init__.py +0 -1
- agno/document/chunking/semantic.py +0 -47
- agno/document/chunking/strategy.py +0 -31
- agno/document/reader/__init__.py +0 -1
- agno/document/reader/arxiv_reader.py +0 -41
- agno/document/reader/base.py +0 -22
- agno/document/reader/csv_reader.py +0 -84
- agno/document/reader/docx_reader.py +0 -46
- agno/document/reader/firecrawl_reader.py +0 -99
- agno/document/reader/json_reader.py +0 -43
- agno/document/reader/pdf_reader.py +0 -219
- agno/document/reader/s3/pdf_reader.py +0 -46
- agno/document/reader/s3/text_reader.py +0 -51
- agno/document/reader/text_reader.py +0 -41
- agno/document/reader/website_reader.py +0 -175
- agno/document/reader/youtube_reader.py +0 -50
- agno/embedder/__init__.py +0 -1
- agno/embedder/azure_openai.py +0 -86
- agno/embedder/cohere.py +0 -72
- agno/embedder/fastembed.py +0 -37
- agno/embedder/google.py +0 -73
- agno/embedder/huggingface.py +0 -54
- agno/embedder/mistral.py +0 -80
- agno/embedder/ollama.py +0 -57
- agno/embedder/openai.py +0 -74
- agno/embedder/sentence_transformer.py +0 -38
- agno/embedder/voyageai.py +0 -64
- agno/eval/perf.py +0 -201
- agno/file/__init__.py +0 -1
- 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 -230
- agno/knowledge/arxiv.py +0 -22
- agno/knowledge/combined.py +0 -22
- agno/knowledge/csv.py +0 -28
- agno/knowledge/csv_url.py +0 -19
- agno/knowledge/document.py +0 -20
- agno/knowledge/docx.py +0 -30
- agno/knowledge/json.py +0 -28
- agno/knowledge/langchain.py +0 -71
- agno/knowledge/llamaindex.py +0 -66
- agno/knowledge/pdf.py +0 -28
- agno/knowledge/pdf_url.py +0 -26
- agno/knowledge/s3/base.py +0 -60
- agno/knowledge/s3/pdf.py +0 -21
- agno/knowledge/s3/text.py +0 -23
- agno/knowledge/text.py +0 -30
- agno/knowledge/website.py +0 -88
- agno/knowledge/wikipedia.py +0 -31
- agno/knowledge/youtube.py +0 -22
- agno/memory/agent.py +0 -392
- agno/memory/classifier.py +0 -104
- agno/memory/db/__init__.py +0 -1
- 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 -15
- agno/memory/row.py +0 -36
- agno/memory/summarizer.py +0 -192
- agno/memory/summary.py +0 -19
- agno/memory/workflow.py +0 -38
- agno/models/google/gemini_openai.py +0 -26
- agno/models/ollama/hermes.py +0 -221
- agno/models/ollama/tools.py +0 -362
- agno/models/vertexai/gemini.py +0 -595
- agno/playground/__init__.py +0 -3
- agno/playground/async_router.py +0 -421
- agno/playground/deploy.py +0 -249
- agno/playground/operator.py +0 -92
- agno/playground/playground.py +0 -91
- agno/playground/schemas.py +0 -76
- agno/playground/serve.py +0 -55
- agno/playground/sync_router.py +0 -405
- agno/reasoning/agent.py +0 -68
- agno/run/response.py +0 -112
- agno/storage/agent/__init__.py +0 -0
- agno/storage/agent/base.py +0 -38
- agno/storage/agent/dynamodb.py +0 -350
- agno/storage/agent/json.py +0 -92
- agno/storage/agent/mongodb.py +0 -228
- agno/storage/agent/postgres.py +0 -367
- agno/storage/agent/session.py +0 -79
- agno/storage/agent/singlestore.py +0 -303
- agno/storage/agent/sqlite.py +0 -357
- agno/storage/agent/yaml.py +0 -93
- agno/storage/workflow/__init__.py +0 -0
- agno/storage/workflow/base.py +0 -40
- agno/storage/workflow/mongodb.py +0 -233
- agno/storage/workflow/postgres.py +0 -366
- agno/storage/workflow/session.py +0 -60
- agno/storage/workflow/sqlite.py +0 -359
- agno/tools/googlesearch.py +0 -88
- 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/vectordb/singlestore/s2vectordb.py +0 -390
- agno/vectordb/singlestore/s2vectordb2.py +0 -355
- agno/workspace/__init__.py +0 -0
- agno/workspace/config.py +0 -325
- agno/workspace/enums.py +0 -6
- agno/workspace/helpers.py +0 -48
- agno/workspace/operator.py +0 -758
- agno/workspace/settings.py +0 -63
- agno-0.1.2.dist-info/LICENSE +0 -375
- agno-0.1.2.dist-info/METADATA +0 -502
- agno-0.1.2.dist-info/RECORD +0 -352
- agno-0.1.2.dist-info/entry_points.txt +0 -3
- /agno/{cli → db/migrations}/__init__.py +0 -0
- /agno/{cli/ws → db/migrations/versions}/__init__.py +0 -0
- /agno/{document/chunking/__init__.py → db/schemas/metrics.py} +0 -0
- /agno/{document/reader/s3 → integrations}/__init__.py +0 -0
- /agno/{file/local → knowledge/chunking}/__init__.py +0 -0
- /agno/{infra → knowledge/remote_content}/__init__.py +0 -0
- /agno/{knowledge/s3 → tools/models}/__init__.py +0 -0
- /agno/{reranker → utils/models}/__init__.py +0 -0
- /agno/{storage → utils/print_response}/__init__.py +0 -0
- {agno-0.1.2.dist-info → agno-2.3.13.dist-info}/top_level.txt +0 -0
agno/storage/agent/dynamodb.py
DELETED
|
@@ -1,350 +0,0 @@
|
|
|
1
|
-
import time
|
|
2
|
-
from dataclasses import asdict
|
|
3
|
-
from decimal import Decimal
|
|
4
|
-
from typing import Any, Dict, List, Optional
|
|
5
|
-
|
|
6
|
-
from agno.storage.agent.base import AgentStorage
|
|
7
|
-
from agno.storage.agent.session import AgentSession
|
|
8
|
-
from agno.utils.log import logger
|
|
9
|
-
|
|
10
|
-
try:
|
|
11
|
-
import boto3
|
|
12
|
-
from boto3.dynamodb.conditions import Key
|
|
13
|
-
from botocore.exceptions import ClientError
|
|
14
|
-
except ImportError:
|
|
15
|
-
raise ImportError("`boto3` not installed. Please install using `pip install boto3`.")
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class DynamoDbAgentStorage(AgentStorage):
|
|
19
|
-
def __init__(
|
|
20
|
-
self,
|
|
21
|
-
table_name: str,
|
|
22
|
-
region_name: Optional[str] = None,
|
|
23
|
-
aws_access_key_id: Optional[str] = None,
|
|
24
|
-
aws_secret_access_key: Optional[str] = None,
|
|
25
|
-
endpoint_url: Optional[str] = None,
|
|
26
|
-
create_table_if_not_exists: bool = True,
|
|
27
|
-
):
|
|
28
|
-
"""
|
|
29
|
-
Initialize the DynamoDbAgentStorage.
|
|
30
|
-
|
|
31
|
-
Args:
|
|
32
|
-
table_name (str): The name of the DynamoDB table.
|
|
33
|
-
region_name (Optional[str]): AWS region name.
|
|
34
|
-
aws_access_key_id (Optional[str]): AWS access key ID.
|
|
35
|
-
aws_secret_access_key (Optional[str]): AWS secret access key.
|
|
36
|
-
endpoint_url (Optional[str]): The complete URL to use for the constructed client.
|
|
37
|
-
create_table_if_not_exists (bool): Whether to create the table if it does not exist.
|
|
38
|
-
"""
|
|
39
|
-
self.table_name = table_name
|
|
40
|
-
self.region_name = region_name
|
|
41
|
-
self.endpoint_url = endpoint_url
|
|
42
|
-
self.aws_access_key_id = aws_access_key_id
|
|
43
|
-
self.aws_secret_access_key = aws_secret_access_key
|
|
44
|
-
self.create_table_if_not_exists = create_table_if_not_exists
|
|
45
|
-
|
|
46
|
-
# Initialize DynamoDB resource
|
|
47
|
-
self.dynamodb = boto3.resource(
|
|
48
|
-
"dynamodb",
|
|
49
|
-
region_name=self.region_name,
|
|
50
|
-
aws_access_key_id=self.aws_access_key_id,
|
|
51
|
-
aws_secret_access_key=self.aws_secret_access_key,
|
|
52
|
-
endpoint_url=self.endpoint_url,
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
# Initialize table
|
|
56
|
-
self.table = self.dynamodb.Table(self.table_name)
|
|
57
|
-
|
|
58
|
-
# Optionally create table if it does not exist
|
|
59
|
-
if self.create_table_if_not_exists:
|
|
60
|
-
self.create()
|
|
61
|
-
logger.debug(f"Initialized DynamoDbAgentStorage with table '{self.table_name}'")
|
|
62
|
-
|
|
63
|
-
def create(self) -> None:
|
|
64
|
-
"""
|
|
65
|
-
Create the DynamoDB table if it does not exist.
|
|
66
|
-
"""
|
|
67
|
-
try:
|
|
68
|
-
# Check if table exists
|
|
69
|
-
self.dynamodb.meta.client.describe_table(TableName=self.table_name)
|
|
70
|
-
logger.debug(f"Table '{self.table_name}' already exists.")
|
|
71
|
-
except ClientError as e:
|
|
72
|
-
if e.response["Error"]["Code"] == "ResourceNotFoundException":
|
|
73
|
-
logger.debug(f"Creating table '{self.table_name}'.")
|
|
74
|
-
# Create the table
|
|
75
|
-
self.table = self.dynamodb.create_table(
|
|
76
|
-
TableName=self.table_name,
|
|
77
|
-
KeySchema=[{"AttributeName": "session_id", "KeyType": "HASH"}],
|
|
78
|
-
AttributeDefinitions=[
|
|
79
|
-
{"AttributeName": "session_id", "AttributeType": "S"},
|
|
80
|
-
{"AttributeName": "user_id", "AttributeType": "S"},
|
|
81
|
-
{"AttributeName": "agent_id", "AttributeType": "S"},
|
|
82
|
-
{"AttributeName": "created_at", "AttributeType": "N"},
|
|
83
|
-
],
|
|
84
|
-
GlobalSecondaryIndexes=[
|
|
85
|
-
{
|
|
86
|
-
"IndexName": "user_id-index",
|
|
87
|
-
"KeySchema": [
|
|
88
|
-
{"AttributeName": "user_id", "KeyType": "HASH"},
|
|
89
|
-
{"AttributeName": "created_at", "KeyType": "RANGE"},
|
|
90
|
-
],
|
|
91
|
-
"Projection": {"ProjectionType": "ALL"},
|
|
92
|
-
"ProvisionedThroughput": {
|
|
93
|
-
"ReadCapacityUnits": 5,
|
|
94
|
-
"WriteCapacityUnits": 5,
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
"IndexName": "agent_id-index",
|
|
99
|
-
"KeySchema": [
|
|
100
|
-
{"AttributeName": "agent_id", "KeyType": "HASH"},
|
|
101
|
-
{"AttributeName": "created_at", "KeyType": "RANGE"},
|
|
102
|
-
],
|
|
103
|
-
"Projection": {"ProjectionType": "ALL"},
|
|
104
|
-
"ProvisionedThroughput": {
|
|
105
|
-
"ReadCapacityUnits": 5,
|
|
106
|
-
"WriteCapacityUnits": 5,
|
|
107
|
-
},
|
|
108
|
-
},
|
|
109
|
-
],
|
|
110
|
-
ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
|
|
111
|
-
)
|
|
112
|
-
# Wait until the table exists.
|
|
113
|
-
self.table.wait_until_exists()
|
|
114
|
-
logger.debug(f"Table '{self.table_name}' created successfully.")
|
|
115
|
-
else:
|
|
116
|
-
logger.error(f"Unable to create table '{self.table_name}': {e.response['Error']['Message']}")
|
|
117
|
-
except Exception as e:
|
|
118
|
-
logger.error(f"Exception during table creation: {e}")
|
|
119
|
-
|
|
120
|
-
def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[AgentSession]:
|
|
121
|
-
"""
|
|
122
|
-
Read and return an AgentSession from the database.
|
|
123
|
-
|
|
124
|
-
Args:
|
|
125
|
-
session_id (str): ID of the session to read.
|
|
126
|
-
user_id (Optional[str]): User ID to filter by. Defaults to None.
|
|
127
|
-
|
|
128
|
-
Returns:
|
|
129
|
-
Optional[AgentSession]: AgentSession object if found, None otherwise.
|
|
130
|
-
"""
|
|
131
|
-
try:
|
|
132
|
-
key = {"session_id": session_id}
|
|
133
|
-
if user_id is not None:
|
|
134
|
-
key["user_id"] = user_id
|
|
135
|
-
|
|
136
|
-
response = self.table.get_item(Key=key)
|
|
137
|
-
item = response.get("Item", None)
|
|
138
|
-
if item is not None:
|
|
139
|
-
# Convert Decimal to int or float
|
|
140
|
-
item = self._deserialize_item(item)
|
|
141
|
-
return AgentSession.from_dict(item)
|
|
142
|
-
except Exception as e:
|
|
143
|
-
logger.error(f"Error reading session_id '{session_id}' with user_id '{user_id}': {e}")
|
|
144
|
-
return None
|
|
145
|
-
|
|
146
|
-
def get_all_session_ids(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[str]:
|
|
147
|
-
"""
|
|
148
|
-
Retrieve all session IDs, optionally filtered by user_id and/or agent_id.
|
|
149
|
-
|
|
150
|
-
Args:
|
|
151
|
-
user_id (Optional[str], optional): User ID to filter by. Defaults to None.
|
|
152
|
-
agent_id (Optional[str], optional): Agent ID to filter by. Defaults to None.
|
|
153
|
-
|
|
154
|
-
Returns:
|
|
155
|
-
List[str]: List of session IDs matching the criteria.
|
|
156
|
-
"""
|
|
157
|
-
session_ids: List[str] = []
|
|
158
|
-
try:
|
|
159
|
-
if user_id is not None:
|
|
160
|
-
# Query using user_id index
|
|
161
|
-
response = self.table.query(
|
|
162
|
-
IndexName="user_id-index",
|
|
163
|
-
KeyConditionExpression=Key("user_id").eq(user_id),
|
|
164
|
-
ProjectionExpression="session_id",
|
|
165
|
-
)
|
|
166
|
-
items = response.get("Items", [])
|
|
167
|
-
session_ids.extend([item["session_id"] for item in items if "session_id" in item])
|
|
168
|
-
elif agent_id is not None:
|
|
169
|
-
# Query using agent_id index
|
|
170
|
-
response = self.table.query(
|
|
171
|
-
IndexName="agent_id-index",
|
|
172
|
-
KeyConditionExpression=Key("agent_id").eq(agent_id),
|
|
173
|
-
ProjectionExpression="session_id",
|
|
174
|
-
)
|
|
175
|
-
items = response.get("Items", [])
|
|
176
|
-
session_ids.extend([item["session_id"] for item in items if "session_id" in item])
|
|
177
|
-
else:
|
|
178
|
-
# Scan the whole table
|
|
179
|
-
response = self.table.scan(ProjectionExpression="session_id")
|
|
180
|
-
items = response.get("Items", [])
|
|
181
|
-
session_ids.extend([item["session_id"] for item in items if "session_id" in item])
|
|
182
|
-
except Exception as e:
|
|
183
|
-
logger.error(f"Error retrieving session IDs: {e}")
|
|
184
|
-
return session_ids
|
|
185
|
-
|
|
186
|
-
def get_all_sessions(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[AgentSession]:
|
|
187
|
-
"""
|
|
188
|
-
Retrieve all sessions, optionally filtered by user_id and/or agent_id.
|
|
189
|
-
|
|
190
|
-
Args:
|
|
191
|
-
user_id (Optional[str], optional): User ID to filter by. Defaults to None.
|
|
192
|
-
agent_id (Optional[str], optional): Agent ID to filter by. Defaults to None.
|
|
193
|
-
|
|
194
|
-
Returns:
|
|
195
|
-
List[AgentSession]: List of AgentSession objects matching the criteria.
|
|
196
|
-
"""
|
|
197
|
-
sessions: List[AgentSession] = []
|
|
198
|
-
try:
|
|
199
|
-
if user_id is not None:
|
|
200
|
-
# Query using user_id index
|
|
201
|
-
response = self.table.query(
|
|
202
|
-
IndexName="user_id-index",
|
|
203
|
-
KeyConditionExpression=Key("user_id").eq(user_id),
|
|
204
|
-
ProjectionExpression="session_id, agent_id, user_id, memory, agent_data, session_data, extra_data, created_at, updated_at",
|
|
205
|
-
)
|
|
206
|
-
items = response.get("Items", [])
|
|
207
|
-
for item in items:
|
|
208
|
-
item = self._deserialize_item(item)
|
|
209
|
-
_agent_session = AgentSession.from_dict(item)
|
|
210
|
-
if _agent_session is not None:
|
|
211
|
-
sessions.append(_agent_session)
|
|
212
|
-
elif agent_id is not None:
|
|
213
|
-
# Query using agent_id index
|
|
214
|
-
response = self.table.query(
|
|
215
|
-
IndexName="agent_id-index",
|
|
216
|
-
KeyConditionExpression=Key("agent_id").eq(agent_id),
|
|
217
|
-
ProjectionExpression="session_id, agent_id, user_id, memory, agent_data, session_data, extra_data, created_at, updated_at",
|
|
218
|
-
)
|
|
219
|
-
items = response.get("Items", [])
|
|
220
|
-
for item in items:
|
|
221
|
-
item = self._deserialize_item(item)
|
|
222
|
-
_agent_session = AgentSession.from_dict(item)
|
|
223
|
-
if _agent_session is not None:
|
|
224
|
-
sessions.append(_agent_session)
|
|
225
|
-
else:
|
|
226
|
-
# Scan the whole table
|
|
227
|
-
response = self.table.scan(
|
|
228
|
-
ProjectionExpression="session_id, agent_id, user_id, memory, agent_data, session_data, extra_data, created_at, updated_at"
|
|
229
|
-
)
|
|
230
|
-
items = response.get("Items", [])
|
|
231
|
-
for item in items:
|
|
232
|
-
item = self._deserialize_item(item)
|
|
233
|
-
_agent_session = AgentSession.from_dict(item)
|
|
234
|
-
if _agent_session is not None:
|
|
235
|
-
sessions.append(_agent_session)
|
|
236
|
-
except Exception as e:
|
|
237
|
-
logger.error(f"Error retrieving sessions: {e}")
|
|
238
|
-
return sessions
|
|
239
|
-
|
|
240
|
-
def upsert(self, session: AgentSession) -> Optional[AgentSession]:
|
|
241
|
-
"""
|
|
242
|
-
Create or update an AgentSession in the database.
|
|
243
|
-
|
|
244
|
-
Args:
|
|
245
|
-
session (AgentSession): The session data to upsert.
|
|
246
|
-
|
|
247
|
-
Returns:
|
|
248
|
-
Optional[AgentSession]: The upserted AgentSession, or None if operation failed.
|
|
249
|
-
"""
|
|
250
|
-
try:
|
|
251
|
-
item = asdict(session)
|
|
252
|
-
|
|
253
|
-
# Add timestamps
|
|
254
|
-
current_time = int(time.time())
|
|
255
|
-
if "created_at" not in item or item["created_at"] is None:
|
|
256
|
-
item["created_at"] = current_time
|
|
257
|
-
item["updated_at"] = current_time
|
|
258
|
-
|
|
259
|
-
# Convert data to DynamoDB compatible format
|
|
260
|
-
item = self._serialize_item(item)
|
|
261
|
-
|
|
262
|
-
# Put item into DynamoDB
|
|
263
|
-
self.table.put_item(Item=item)
|
|
264
|
-
return self.read(session.session_id)
|
|
265
|
-
except Exception as e:
|
|
266
|
-
logger.error(f"Error upserting session: {e}")
|
|
267
|
-
return None
|
|
268
|
-
|
|
269
|
-
def delete_session(self, session_id: Optional[str] = None):
|
|
270
|
-
"""
|
|
271
|
-
Delete a session from the database.
|
|
272
|
-
|
|
273
|
-
Args:
|
|
274
|
-
session_id (Optional[str], optional): ID of the session to delete. Defaults to None.
|
|
275
|
-
"""
|
|
276
|
-
if session_id is None:
|
|
277
|
-
logger.warning("No session_id provided for deletion.")
|
|
278
|
-
return
|
|
279
|
-
try:
|
|
280
|
-
self.table.delete_item(Key={"session_id": session_id})
|
|
281
|
-
logger.info(f"Successfully deleted session with session_id: {session_id}")
|
|
282
|
-
except Exception as e:
|
|
283
|
-
logger.error(f"Error deleting session: {e}")
|
|
284
|
-
|
|
285
|
-
def drop(self) -> None:
|
|
286
|
-
"""
|
|
287
|
-
Drop the table from the database if it exists.
|
|
288
|
-
"""
|
|
289
|
-
try:
|
|
290
|
-
self.table.delete()
|
|
291
|
-
self.table.wait_until_not_exists()
|
|
292
|
-
logger.debug(f"Table '{self.table_name}' deleted successfully.")
|
|
293
|
-
except Exception as e:
|
|
294
|
-
logger.error(f"Error deleting table '{self.table_name}': {e}")
|
|
295
|
-
|
|
296
|
-
def upgrade_schema(self) -> None:
|
|
297
|
-
"""
|
|
298
|
-
Upgrade the schema to the latest version.
|
|
299
|
-
This method is currently a placeholder and does not perform any actions.
|
|
300
|
-
"""
|
|
301
|
-
pass
|
|
302
|
-
|
|
303
|
-
def _serialize_item(self, item: Dict[str, Any]) -> Dict[str, Any]:
|
|
304
|
-
"""
|
|
305
|
-
Serialize item to be compatible with DynamoDB.
|
|
306
|
-
|
|
307
|
-
Args:
|
|
308
|
-
item (Dict[str, Any]): The item to serialize.
|
|
309
|
-
|
|
310
|
-
Returns:
|
|
311
|
-
Dict[str, Any]: The serialized item.
|
|
312
|
-
"""
|
|
313
|
-
|
|
314
|
-
def serialize_value(value):
|
|
315
|
-
if isinstance(value, float):
|
|
316
|
-
return Decimal(str(value))
|
|
317
|
-
elif isinstance(value, dict):
|
|
318
|
-
return {k: serialize_value(v) for k, v in value.items()}
|
|
319
|
-
elif isinstance(value, list):
|
|
320
|
-
return [serialize_value(v) for v in value]
|
|
321
|
-
else:
|
|
322
|
-
return value
|
|
323
|
-
|
|
324
|
-
return {k: serialize_value(v) for k, v in item.items() if v is not None}
|
|
325
|
-
|
|
326
|
-
def _deserialize_item(self, item: Dict[str, Any]) -> Dict[str, Any]:
|
|
327
|
-
"""
|
|
328
|
-
Deserialize item from DynamoDB format.
|
|
329
|
-
|
|
330
|
-
Args:
|
|
331
|
-
item (Dict[str, Any]): The item to deserialize.
|
|
332
|
-
|
|
333
|
-
Returns:
|
|
334
|
-
Dict[str, Any]: The deserialized item.
|
|
335
|
-
"""
|
|
336
|
-
|
|
337
|
-
def deserialize_value(value):
|
|
338
|
-
if isinstance(value, Decimal):
|
|
339
|
-
if value % 1 == 0:
|
|
340
|
-
return int(value)
|
|
341
|
-
else:
|
|
342
|
-
return float(value)
|
|
343
|
-
elif isinstance(value, dict):
|
|
344
|
-
return {k: deserialize_value(v) for k, v in value.items()}
|
|
345
|
-
elif isinstance(value, list):
|
|
346
|
-
return [deserialize_value(v) for v in value]
|
|
347
|
-
else:
|
|
348
|
-
return value
|
|
349
|
-
|
|
350
|
-
return {k: deserialize_value(v) for k, v in item.items()}
|
agno/storage/agent/json.py
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
import json
|
|
2
|
-
import time
|
|
3
|
-
from dataclasses import asdict
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import List, Optional, Union
|
|
6
|
-
|
|
7
|
-
from agno.storage.agent.base import AgentStorage
|
|
8
|
-
from agno.storage.agent.session import AgentSession
|
|
9
|
-
from agno.utils.log import logger
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class JsonAgentStorage(AgentStorage):
|
|
13
|
-
def __init__(self, dir_path: Union[str, Path]):
|
|
14
|
-
self.dir_path = Path(dir_path)
|
|
15
|
-
self.dir_path.mkdir(parents=True, exist_ok=True)
|
|
16
|
-
|
|
17
|
-
def serialize(self, data: dict) -> str:
|
|
18
|
-
return json.dumps(data, ensure_ascii=False, indent=4)
|
|
19
|
-
|
|
20
|
-
def deserialize(self, data: str) -> dict:
|
|
21
|
-
return json.loads(data)
|
|
22
|
-
|
|
23
|
-
def create(self) -> None:
|
|
24
|
-
"""Create the storage if it doesn't exist."""
|
|
25
|
-
if not self.dir_path.exists():
|
|
26
|
-
self.dir_path.mkdir(parents=True, exist_ok=True)
|
|
27
|
-
|
|
28
|
-
def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[AgentSession]:
|
|
29
|
-
"""Read an AgentSession from storage."""
|
|
30
|
-
try:
|
|
31
|
-
with open(self.dir_path / f"{session_id}.json", "r", encoding="utf-8") as f:
|
|
32
|
-
data = self.deserialize(f.read())
|
|
33
|
-
if user_id and data["user_id"] != user_id:
|
|
34
|
-
return None
|
|
35
|
-
return AgentSession.from_dict(data)
|
|
36
|
-
except FileNotFoundError:
|
|
37
|
-
return None
|
|
38
|
-
|
|
39
|
-
def get_all_session_ids(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[str]:
|
|
40
|
-
"""Get all session IDs, optionally filtered by user_id and/or agent_id."""
|
|
41
|
-
session_ids = []
|
|
42
|
-
for file in self.dir_path.glob("*.json"):
|
|
43
|
-
with open(file, "r", encoding="utf-8") as f:
|
|
44
|
-
data = self.deserialize(f.read())
|
|
45
|
-
if (not user_id or data["user_id"] == user_id) and (not agent_id or data["agent_id"] == agent_id):
|
|
46
|
-
session_ids.append(data["session_id"])
|
|
47
|
-
return session_ids
|
|
48
|
-
|
|
49
|
-
def get_all_sessions(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[AgentSession]:
|
|
50
|
-
"""Get all sessions, optionally filtered by user_id and/or agent_id."""
|
|
51
|
-
sessions = []
|
|
52
|
-
for file in self.dir_path.glob("*.json"):
|
|
53
|
-
with open(file, "r", encoding="utf-8") as f:
|
|
54
|
-
data = self.deserialize(f.read())
|
|
55
|
-
if (not user_id or data["user_id"] == user_id) and (not agent_id or data["agent_id"] == agent_id):
|
|
56
|
-
_agent_session = AgentSession.from_dict(data)
|
|
57
|
-
if _agent_session is not None:
|
|
58
|
-
sessions.append(_agent_session)
|
|
59
|
-
return sessions
|
|
60
|
-
|
|
61
|
-
def upsert(self, session: AgentSession) -> Optional[AgentSession]:
|
|
62
|
-
"""Insert or update an AgentSession in storage."""
|
|
63
|
-
try:
|
|
64
|
-
data = asdict(session)
|
|
65
|
-
data["updated_at"] = int(time.time())
|
|
66
|
-
if "created_at" not in data:
|
|
67
|
-
data["created_at"] = data["updated_at"]
|
|
68
|
-
|
|
69
|
-
with open(self.dir_path / f"{session.session_id}.json", "w", encoding="utf-8") as f:
|
|
70
|
-
f.write(self.serialize(data))
|
|
71
|
-
return session
|
|
72
|
-
except Exception as e:
|
|
73
|
-
logger.error(f"Error upserting session: {e}")
|
|
74
|
-
return None
|
|
75
|
-
|
|
76
|
-
def delete_session(self, session_id: Optional[str] = None):
|
|
77
|
-
"""Delete a session from storage."""
|
|
78
|
-
if session_id is None:
|
|
79
|
-
return
|
|
80
|
-
try:
|
|
81
|
-
(self.dir_path / f"{session_id}.json").unlink(missing_ok=True)
|
|
82
|
-
except Exception as e:
|
|
83
|
-
logger.error(f"Error deleting session: {e}")
|
|
84
|
-
|
|
85
|
-
def drop(self) -> None:
|
|
86
|
-
"""Drop all sessions from storage."""
|
|
87
|
-
for file in self.dir_path.glob("*.json"):
|
|
88
|
-
file.unlink()
|
|
89
|
-
|
|
90
|
-
def upgrade_schema(self) -> None:
|
|
91
|
-
"""Upgrade the schema of the storage."""
|
|
92
|
-
pass
|
agno/storage/agent/mongodb.py
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
from datetime import datetime, timezone
|
|
2
|
-
from typing import List, Optional
|
|
3
|
-
from uuid import UUID
|
|
4
|
-
|
|
5
|
-
try:
|
|
6
|
-
from pymongo import MongoClient
|
|
7
|
-
from pymongo.collection import Collection
|
|
8
|
-
from pymongo.database import Database
|
|
9
|
-
from pymongo.errors import PyMongoError
|
|
10
|
-
except ImportError:
|
|
11
|
-
raise ImportError("`pymongo` not installed. Please install it with `pip install pymongo`")
|
|
12
|
-
|
|
13
|
-
from agno.storage.agent.base import AgentStorage
|
|
14
|
-
from agno.storage.agent.session import AgentSession
|
|
15
|
-
from agno.utils.log import logger
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class MongoDbAgentStorage(AgentStorage):
|
|
19
|
-
def __init__(
|
|
20
|
-
self,
|
|
21
|
-
collection_name: str,
|
|
22
|
-
db_url: Optional[str] = None,
|
|
23
|
-
db_name: str = "agno",
|
|
24
|
-
client: Optional[MongoClient] = None,
|
|
25
|
-
):
|
|
26
|
-
"""
|
|
27
|
-
This class provides agent storage using MongoDB.
|
|
28
|
-
|
|
29
|
-
Args:
|
|
30
|
-
collection_name: Name of the collection to store agent sessions
|
|
31
|
-
db_url: MongoDB connection URL
|
|
32
|
-
db_name: Name of the database
|
|
33
|
-
client: Optional existing MongoDB client
|
|
34
|
-
"""
|
|
35
|
-
self._client: Optional[MongoClient] = client
|
|
36
|
-
if self._client is None and db_url is not None:
|
|
37
|
-
self._client = MongoClient(db_url)
|
|
38
|
-
elif self._client is None:
|
|
39
|
-
self._client = MongoClient()
|
|
40
|
-
|
|
41
|
-
if self._client is None:
|
|
42
|
-
raise ValueError("Must provide either db_url or client")
|
|
43
|
-
|
|
44
|
-
self.collection_name: str = collection_name
|
|
45
|
-
self.db_name: str = db_name
|
|
46
|
-
self.db: Database = self._client[self.db_name]
|
|
47
|
-
self.collection: Collection = self.db[self.collection_name]
|
|
48
|
-
|
|
49
|
-
def create(self) -> None:
|
|
50
|
-
"""Create necessary indexes for the collection"""
|
|
51
|
-
try:
|
|
52
|
-
# Create indexes
|
|
53
|
-
self.collection.create_index("session_id", unique=True)
|
|
54
|
-
self.collection.create_index("user_id")
|
|
55
|
-
self.collection.create_index("agent_id")
|
|
56
|
-
self.collection.create_index("created_at")
|
|
57
|
-
except PyMongoError as e:
|
|
58
|
-
logger.error(f"Error creating indexes: {e}")
|
|
59
|
-
raise
|
|
60
|
-
|
|
61
|
-
def read(self, session_id: str, user_id: Optional[str] = None) -> Optional[AgentSession]:
|
|
62
|
-
"""Read an agent session from MongoDB
|
|
63
|
-
Args:
|
|
64
|
-
session_id: ID of the session to read
|
|
65
|
-
user_id: ID of the user to read
|
|
66
|
-
Returns:
|
|
67
|
-
AgentSession: The session if found, otherwise None
|
|
68
|
-
"""
|
|
69
|
-
try:
|
|
70
|
-
query = {"session_id": session_id}
|
|
71
|
-
if user_id:
|
|
72
|
-
query["user_id"] = user_id
|
|
73
|
-
|
|
74
|
-
doc = self.collection.find_one(query)
|
|
75
|
-
if doc:
|
|
76
|
-
# Remove MongoDB _id before converting to AgentSession
|
|
77
|
-
doc.pop("_id", None)
|
|
78
|
-
return AgentSession.from_dict(doc)
|
|
79
|
-
return None
|
|
80
|
-
except PyMongoError as e:
|
|
81
|
-
logger.error(f"Error reading session: {e}")
|
|
82
|
-
return None
|
|
83
|
-
|
|
84
|
-
def get_all_session_ids(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[str]:
|
|
85
|
-
"""Get all session IDs matching the criteria
|
|
86
|
-
Args:
|
|
87
|
-
user_id: ID of the user to read
|
|
88
|
-
agent_id: ID of the agent to read
|
|
89
|
-
Returns:
|
|
90
|
-
List[str]: List of session IDs
|
|
91
|
-
"""
|
|
92
|
-
try:
|
|
93
|
-
query = {}
|
|
94
|
-
if user_id is not None:
|
|
95
|
-
query["user_id"] = user_id
|
|
96
|
-
if agent_id is not None:
|
|
97
|
-
query["agent_id"] = agent_id
|
|
98
|
-
|
|
99
|
-
cursor = self.collection.find(query, {"session_id": 1}).sort("created_at", -1)
|
|
100
|
-
|
|
101
|
-
return [str(doc["session_id"]) for doc in cursor]
|
|
102
|
-
except PyMongoError as e:
|
|
103
|
-
logger.error(f"Error getting session IDs: {e}")
|
|
104
|
-
return []
|
|
105
|
-
|
|
106
|
-
def get_all_sessions(self, user_id: Optional[str] = None, agent_id: Optional[str] = None) -> List[AgentSession]:
|
|
107
|
-
"""Get all sessions matching the criteria
|
|
108
|
-
Args:
|
|
109
|
-
user_id: ID of the user to read
|
|
110
|
-
agent_id: ID of the agent to read
|
|
111
|
-
Returns:
|
|
112
|
-
List[AgentSession]: List of sessions
|
|
113
|
-
"""
|
|
114
|
-
try:
|
|
115
|
-
query = {}
|
|
116
|
-
if user_id is not None:
|
|
117
|
-
query["user_id"] = user_id
|
|
118
|
-
if agent_id is not None:
|
|
119
|
-
query["agent_id"] = agent_id
|
|
120
|
-
|
|
121
|
-
cursor = self.collection.find(query).sort("created_at", -1)
|
|
122
|
-
sessions = []
|
|
123
|
-
for doc in cursor:
|
|
124
|
-
# Remove MongoDB _id before converting to AgentSession
|
|
125
|
-
doc.pop("_id", None)
|
|
126
|
-
_agent_session = AgentSession.from_dict(doc)
|
|
127
|
-
if _agent_session is not None:
|
|
128
|
-
sessions.append(_agent_session)
|
|
129
|
-
return sessions
|
|
130
|
-
except PyMongoError as e:
|
|
131
|
-
logger.error(f"Error getting sessions: {e}")
|
|
132
|
-
return []
|
|
133
|
-
|
|
134
|
-
def upsert(self, session: AgentSession, create_and_retry: bool = True) -> Optional[AgentSession]:
|
|
135
|
-
"""Upsert an agent session
|
|
136
|
-
Args:
|
|
137
|
-
session: AgentSession to upsert
|
|
138
|
-
create_and_retry: Whether to create a new session if the session_id already exists
|
|
139
|
-
Returns:
|
|
140
|
-
AgentSession: The session if upserted, otherwise None
|
|
141
|
-
"""
|
|
142
|
-
try:
|
|
143
|
-
# Convert session to dict and add timestamps
|
|
144
|
-
session_dict = session.to_dict()
|
|
145
|
-
now = datetime.now(timezone.utc)
|
|
146
|
-
timestamp = int(now.timestamp())
|
|
147
|
-
|
|
148
|
-
# Handle UUID serialization
|
|
149
|
-
if isinstance(session.session_id, UUID):
|
|
150
|
-
session_dict["session_id"] = str(session.session_id)
|
|
151
|
-
|
|
152
|
-
# Add version field for optimistic locking
|
|
153
|
-
if "_version" not in session_dict:
|
|
154
|
-
session_dict["_version"] = 1
|
|
155
|
-
else:
|
|
156
|
-
session_dict["_version"] += 1
|
|
157
|
-
|
|
158
|
-
update_data = {**session_dict, "updated_at": timestamp}
|
|
159
|
-
|
|
160
|
-
# For new documents, set created_at
|
|
161
|
-
query = {"session_id": session_dict["session_id"]}
|
|
162
|
-
|
|
163
|
-
doc = self.collection.find_one(query)
|
|
164
|
-
if not doc:
|
|
165
|
-
update_data["created_at"] = timestamp
|
|
166
|
-
|
|
167
|
-
result = self.collection.update_one(query, {"$set": update_data}, upsert=True)
|
|
168
|
-
|
|
169
|
-
if result.acknowledged:
|
|
170
|
-
return self.read(session_id=session_dict["session_id"])
|
|
171
|
-
return None
|
|
172
|
-
|
|
173
|
-
except PyMongoError as e:
|
|
174
|
-
logger.error(f"Error upserting session: {e}")
|
|
175
|
-
return None
|
|
176
|
-
|
|
177
|
-
def delete_session(self, session_id: Optional[str] = None) -> None:
|
|
178
|
-
"""Delete an agent session
|
|
179
|
-
Args:
|
|
180
|
-
session_id: ID of the session to delete
|
|
181
|
-
Returns:
|
|
182
|
-
None
|
|
183
|
-
"""
|
|
184
|
-
if session_id is None:
|
|
185
|
-
logger.warning("No session_id provided for deletion")
|
|
186
|
-
return
|
|
187
|
-
|
|
188
|
-
try:
|
|
189
|
-
result = self.collection.delete_one({"session_id": session_id})
|
|
190
|
-
if result.deleted_count == 0:
|
|
191
|
-
logger.debug(f"No session found with session_id: {session_id}")
|
|
192
|
-
else:
|
|
193
|
-
logger.debug(f"Successfully deleted session with session_id: {session_id}")
|
|
194
|
-
except PyMongoError as e:
|
|
195
|
-
logger.error(f"Error deleting session: {e}")
|
|
196
|
-
|
|
197
|
-
def drop(self) -> None:
|
|
198
|
-
"""Drop the collection
|
|
199
|
-
Returns:
|
|
200
|
-
None
|
|
201
|
-
"""
|
|
202
|
-
try:
|
|
203
|
-
self.collection.drop()
|
|
204
|
-
except PyMongoError as e:
|
|
205
|
-
logger.error(f"Error dropping collection: {e}")
|
|
206
|
-
|
|
207
|
-
def upgrade_schema(self) -> None:
|
|
208
|
-
"""Placeholder for schema upgrades"""
|
|
209
|
-
pass
|
|
210
|
-
|
|
211
|
-
def __deepcopy__(self, memo):
|
|
212
|
-
"""Create a deep copy of the MongoDbAgentStorage instance"""
|
|
213
|
-
from copy import deepcopy
|
|
214
|
-
|
|
215
|
-
# Create a new instance without calling __init__
|
|
216
|
-
cls = self.__class__
|
|
217
|
-
copied_obj = cls.__new__(cls)
|
|
218
|
-
memo[id(self)] = copied_obj
|
|
219
|
-
|
|
220
|
-
# Deep copy attributes
|
|
221
|
-
for k, v in self.__dict__.items():
|
|
222
|
-
if k in {"_client", "db", "collection"}:
|
|
223
|
-
# Reuse MongoDB connections without copying
|
|
224
|
-
setattr(copied_obj, k, v)
|
|
225
|
-
else:
|
|
226
|
-
setattr(copied_obj, k, deepcopy(v, memo))
|
|
227
|
-
|
|
228
|
-
return copied_obj
|