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/utils/whatsapp.py
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Optional, Union
|
|
3
|
+
|
|
4
|
+
import httpx
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
from agno.utils.log import log_debug, log_error
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def get_access_token() -> str:
|
|
11
|
+
access_token = os.getenv("WHATSAPP_ACCESS_TOKEN")
|
|
12
|
+
if not access_token:
|
|
13
|
+
raise ValueError("WHATSAPP_ACCESS_TOKEN is not set")
|
|
14
|
+
return access_token
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_phone_number_id() -> str:
|
|
18
|
+
phone_number_id = os.getenv("WHATSAPP_PHONE_NUMBER_ID")
|
|
19
|
+
if not phone_number_id:
|
|
20
|
+
raise ValueError("WHATSAPP_PHONE_NUMBER_ID is not set")
|
|
21
|
+
return phone_number_id
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def get_media(media_id: str) -> Union[dict, bytes]:
|
|
25
|
+
"""
|
|
26
|
+
Sends a GET request to the Facebook Graph API to retrieve media information.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
media_id (str): The ID of the media to retrieve.
|
|
30
|
+
"""
|
|
31
|
+
url = f"https://graph.facebook.com/v22.0/{media_id}"
|
|
32
|
+
|
|
33
|
+
access_token = get_access_token()
|
|
34
|
+
|
|
35
|
+
headers = {"Authorization": f"Bearer {access_token}"}
|
|
36
|
+
try:
|
|
37
|
+
response = requests.get(url, headers=headers)
|
|
38
|
+
response.raise_for_status() # Raise an HTTPError for bad responses (4xx and 5xx)
|
|
39
|
+
data = response.json()
|
|
40
|
+
|
|
41
|
+
media_url = data.get("url")
|
|
42
|
+
except requests.exceptions.RequestException as e:
|
|
43
|
+
return {"error": str(e)}
|
|
44
|
+
|
|
45
|
+
try:
|
|
46
|
+
response = requests.get(media_url, headers=headers)
|
|
47
|
+
response.raise_for_status() # Raise an HTTPError for bad responses (4xx and 5xx)
|
|
48
|
+
data = response.content
|
|
49
|
+
return data
|
|
50
|
+
except requests.exceptions.RequestException as e:
|
|
51
|
+
return {"error": str(e)}
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
async def get_media_async(media_id: str) -> Union[dict, bytes]:
|
|
55
|
+
"""
|
|
56
|
+
Sends a GET request to the Facebook Graph API to retrieve media information.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
media_id (str): The ID of the media to retrieve.
|
|
60
|
+
"""
|
|
61
|
+
url = f"https://graph.facebook.com/v22.0/{media_id}"
|
|
62
|
+
|
|
63
|
+
access_token = get_access_token()
|
|
64
|
+
|
|
65
|
+
headers = {"Authorization": f"Bearer {access_token}"}
|
|
66
|
+
try:
|
|
67
|
+
async with httpx.AsyncClient() as client:
|
|
68
|
+
response = await client.get(url, headers=headers)
|
|
69
|
+
response.raise_for_status() # Raise an HTTPError for bad responses (4xx and 5xx)
|
|
70
|
+
data = response.json()
|
|
71
|
+
|
|
72
|
+
media_url = data.get("url")
|
|
73
|
+
except httpx.HTTPStatusError as e:
|
|
74
|
+
return {"error": str(e)}
|
|
75
|
+
|
|
76
|
+
try:
|
|
77
|
+
async with httpx.AsyncClient() as client:
|
|
78
|
+
response = await client.get(media_url, headers=headers)
|
|
79
|
+
response.raise_for_status() # Raise an HTTPError for bad responses (4xx and 5xx)
|
|
80
|
+
data = response.content
|
|
81
|
+
return data
|
|
82
|
+
except httpx.HTTPStatusError as e:
|
|
83
|
+
return {"error": str(e)}
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def upload_media(media_data: bytes, mime_type: str, filename: str = "file"):
|
|
87
|
+
"""
|
|
88
|
+
Sends a POST request to the Facebook Graph API to upload media for WhatsApp.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
media_data: Bytes buffer containing the file data
|
|
92
|
+
mime_type (str): The MIME type of the file
|
|
93
|
+
filename (str): The name to use for the file in the upload. Defaults to "file"
|
|
94
|
+
"""
|
|
95
|
+
phone_number_id = get_phone_number_id()
|
|
96
|
+
|
|
97
|
+
url = f"https://graph.facebook.com/v22.0/{phone_number_id}/media"
|
|
98
|
+
|
|
99
|
+
access_token = get_access_token()
|
|
100
|
+
|
|
101
|
+
headers = {"Authorization": f"Bearer {access_token}"}
|
|
102
|
+
|
|
103
|
+
data = {"messaging_product": "whatsapp", "type": mime_type}
|
|
104
|
+
try:
|
|
105
|
+
from io import BytesIO
|
|
106
|
+
|
|
107
|
+
file_data = BytesIO(media_data)
|
|
108
|
+
files = {"file": (filename, file_data, mime_type)}
|
|
109
|
+
|
|
110
|
+
response = requests.post(url, headers=headers, data=data, files=files)
|
|
111
|
+
response.raise_for_status() # Raise an error for bad responses
|
|
112
|
+
json_resp = response.json()
|
|
113
|
+
media_id = json_resp.get("id")
|
|
114
|
+
if not media_id:
|
|
115
|
+
return {"error": "Media ID not found in response", "response": json_resp}
|
|
116
|
+
return media_id
|
|
117
|
+
except requests.exceptions.RequestException as e:
|
|
118
|
+
return {"error": str(e)}
|
|
119
|
+
except Exception as e:
|
|
120
|
+
return {"error": str(e)}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
async def upload_media_async(media_data: bytes, mime_type: str, filename: str = "file"):
|
|
124
|
+
"""
|
|
125
|
+
Sends a POST request to the Facebook Graph API to upload media for WhatsApp.
|
|
126
|
+
|
|
127
|
+
Args:
|
|
128
|
+
media_data: Bytes buffer containing the file data
|
|
129
|
+
mime_type (str): The MIME type of the file
|
|
130
|
+
filename (str): The name to use for the file in the upload. Defaults to "file"
|
|
131
|
+
"""
|
|
132
|
+
phone_number_id = get_phone_number_id()
|
|
133
|
+
|
|
134
|
+
url = f"https://graph.facebook.com/v22.0/{phone_number_id}/media"
|
|
135
|
+
|
|
136
|
+
access_token = get_access_token()
|
|
137
|
+
|
|
138
|
+
headers = {"Authorization": f"Bearer {access_token}"}
|
|
139
|
+
|
|
140
|
+
data = {"messaging_product": "whatsapp", "type": mime_type}
|
|
141
|
+
try:
|
|
142
|
+
from io import BytesIO
|
|
143
|
+
|
|
144
|
+
file_data = BytesIO(media_data)
|
|
145
|
+
files = {"file": (filename, file_data, mime_type)}
|
|
146
|
+
|
|
147
|
+
async with httpx.AsyncClient() as client:
|
|
148
|
+
response = await client.post(url, headers=headers, data=data, files=files)
|
|
149
|
+
response.raise_for_status() # Raise an error for bad responses
|
|
150
|
+
json_resp = response.json()
|
|
151
|
+
media_id = json_resp.get("id")
|
|
152
|
+
if not media_id:
|
|
153
|
+
return {"error": "Media ID not found in response", "response": json_resp}
|
|
154
|
+
return media_id
|
|
155
|
+
except httpx.HTTPStatusError as e:
|
|
156
|
+
return {"error": str(e)}
|
|
157
|
+
except Exception as e:
|
|
158
|
+
return {"error": str(e)}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
async def send_image_message_async(
|
|
162
|
+
media_id: str,
|
|
163
|
+
recipient: str,
|
|
164
|
+
text: Optional[str] = None,
|
|
165
|
+
):
|
|
166
|
+
"""Send an image message to a WhatsApp user (asynchronous version).
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
media_id: The media id for the image to send
|
|
170
|
+
recipient: Recipient's WhatsApp ID or phone number (e.g., "+1234567890").
|
|
171
|
+
text: Caption for the image
|
|
172
|
+
|
|
173
|
+
Returns:
|
|
174
|
+
Success message with message ID
|
|
175
|
+
"""
|
|
176
|
+
log_debug(f"Sending WhatsApp image to {recipient}: {text}")
|
|
177
|
+
phone_number_id = get_phone_number_id()
|
|
178
|
+
|
|
179
|
+
url = f"https://graph.facebook.com/v22.0/{phone_number_id}/messages"
|
|
180
|
+
|
|
181
|
+
access_token = get_access_token()
|
|
182
|
+
|
|
183
|
+
headers = {"Authorization": f"Bearer {access_token}"}
|
|
184
|
+
|
|
185
|
+
data = {
|
|
186
|
+
"messaging_product": "whatsapp",
|
|
187
|
+
"recipient_type": "individual",
|
|
188
|
+
"to": recipient,
|
|
189
|
+
"type": "image",
|
|
190
|
+
"image": {"id": media_id, "caption": text},
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
try:
|
|
194
|
+
async with httpx.AsyncClient() as client:
|
|
195
|
+
import json
|
|
196
|
+
|
|
197
|
+
log_debug(f"Request data: {json.dumps(data, indent=2)}")
|
|
198
|
+
response = await client.post(url, headers=headers, json=data)
|
|
199
|
+
response.raise_for_status()
|
|
200
|
+
log_debug(f"Response: {response.text}")
|
|
201
|
+
|
|
202
|
+
except httpx.HTTPStatusError as e:
|
|
203
|
+
log_error(f"Failed to send WhatsApp image message: {e}")
|
|
204
|
+
log_error(f"Error response: {e.response.text if hasattr(e, 'response') else 'No response text'}")
|
|
205
|
+
raise
|
|
206
|
+
except Exception as e:
|
|
207
|
+
log_error(f"Unexpected error sending WhatsApp image message: {str(e)}")
|
|
208
|
+
raise
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def send_image_message(
|
|
212
|
+
media_id: str,
|
|
213
|
+
recipient: str,
|
|
214
|
+
text: Optional[str] = None,
|
|
215
|
+
):
|
|
216
|
+
"""Send an image message to a WhatsApp user (synchronous version).
|
|
217
|
+
|
|
218
|
+
Args:
|
|
219
|
+
image: The media id for the image to send
|
|
220
|
+
recipient: Recipient's WhatsApp ID or phone number (e.g., "+1234567890").
|
|
221
|
+
text: Caption for the image
|
|
222
|
+
|
|
223
|
+
Returns:
|
|
224
|
+
Success message with message ID
|
|
225
|
+
"""
|
|
226
|
+
log_debug(f"Sending WhatsApp image to {recipient}: {text}")
|
|
227
|
+
phone_number_id = get_phone_number_id()
|
|
228
|
+
|
|
229
|
+
url = f"https://graph.facebook.com/v22.0/{phone_number_id}/messages"
|
|
230
|
+
|
|
231
|
+
access_token = get_access_token()
|
|
232
|
+
|
|
233
|
+
headers = {"Authorization": f"Bearer {access_token}"}
|
|
234
|
+
|
|
235
|
+
data = {
|
|
236
|
+
"messaging_product": "whatsapp",
|
|
237
|
+
"recipient_type": "individual",
|
|
238
|
+
"to": recipient,
|
|
239
|
+
"type": "image",
|
|
240
|
+
"image": {"id": media_id, "caption": text},
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
try:
|
|
244
|
+
import json
|
|
245
|
+
|
|
246
|
+
log_debug(f"Request data: {json.dumps(data, indent=2)}")
|
|
247
|
+
response = requests.post(url, headers=headers, json=data)
|
|
248
|
+
response.raise_for_status()
|
|
249
|
+
log_debug(f"Response: {response.text}")
|
|
250
|
+
except requests.exceptions.RequestException as e:
|
|
251
|
+
log_error(f"Failed to send WhatsApp image message: {e}")
|
|
252
|
+
log_error(f"Error response: {e.response.text if hasattr(e, 'response') else 'No response text'}") # type: ignore
|
|
253
|
+
raise
|
|
254
|
+
except Exception as e:
|
|
255
|
+
log_error(f"Unexpected error sending WhatsApp image message: {str(e)}")
|
|
256
|
+
raise
|
|
257
|
+
|
|
258
|
+
|
|
259
|
+
def typing_indicator(message_id: Optional[str] = None):
|
|
260
|
+
if not message_id:
|
|
261
|
+
return
|
|
262
|
+
|
|
263
|
+
phone_number_id = get_phone_number_id()
|
|
264
|
+
|
|
265
|
+
url = f"https://graph.facebook.com/v22.0/{phone_number_id}/messages"
|
|
266
|
+
|
|
267
|
+
access_token = get_access_token()
|
|
268
|
+
|
|
269
|
+
headers = {"Authorization": f"Bearer {access_token}"}
|
|
270
|
+
data = {
|
|
271
|
+
"messaging_product": "whatsapp",
|
|
272
|
+
"status": "read",
|
|
273
|
+
"message_id": f"{message_id}",
|
|
274
|
+
"typing_indicator": {"type": "text"},
|
|
275
|
+
}
|
|
276
|
+
try:
|
|
277
|
+
response = requests.post(url, headers=headers, data=data)
|
|
278
|
+
response.raise_for_status() # Raise an HTTPError for bad responses (4xx and 5xx)
|
|
279
|
+
except requests.exceptions.RequestException as e:
|
|
280
|
+
return {"error": str(e)}
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
async def typing_indicator_async(message_id: Optional[str] = None):
|
|
284
|
+
if not message_id:
|
|
285
|
+
return
|
|
286
|
+
|
|
287
|
+
phone_number_id = get_phone_number_id()
|
|
288
|
+
|
|
289
|
+
url = f"https://graph.facebook.com/v22.0/{phone_number_id}/messages"
|
|
290
|
+
|
|
291
|
+
access_token = get_access_token()
|
|
292
|
+
|
|
293
|
+
headers = {"Authorization": f"Bearer {access_token}"}
|
|
294
|
+
data = {
|
|
295
|
+
"messaging_product": "whatsapp",
|
|
296
|
+
"status": "read",
|
|
297
|
+
"message_id": f"{message_id}",
|
|
298
|
+
"typing_indicator": {"type": "text"},
|
|
299
|
+
}
|
|
300
|
+
try:
|
|
301
|
+
async with httpx.AsyncClient() as client:
|
|
302
|
+
response = await client.post(url, headers=headers, data=data)
|
|
303
|
+
response.raise_for_status() # Raise an HTTPError for bad responses (4xx and 5xx)
|
|
304
|
+
except httpx.HTTPStatusError as e:
|
|
305
|
+
return {"error": str(e)}
|
agno/utils/yaml_io.py
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
from pathlib import Path
|
|
2
2
|
from typing import Any, Dict, Optional
|
|
3
3
|
|
|
4
|
-
from agno.utils.log import logger
|
|
4
|
+
from agno.utils.log import log_debug, logger
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
def read_yaml_file(file_path: Optional[Path]) -> Optional[Dict[str, Any]]:
|
|
8
8
|
if file_path is not None and file_path.exists() and file_path.is_file():
|
|
9
9
|
import yaml
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
log_debug(f"Reading {file_path}")
|
|
12
12
|
data_from_file = yaml.safe_load(file_path.read_text())
|
|
13
13
|
if data_from_file is not None and isinstance(data_from_file, dict):
|
|
14
14
|
return data_from_file
|
|
@@ -21,5 +21,5 @@ def write_yaml_file(file_path: Optional[Path], data: Optional[Dict[str, Any]], *
|
|
|
21
21
|
if file_path is not None and data is not None:
|
|
22
22
|
import yaml
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
log_debug(f"Writing {file_path}")
|
|
25
25
|
file_path.write_text(yaml.safe_dump(data, **kwargs))
|
agno/vectordb/__init__.py
CHANGED
agno/vectordb/base.py
CHANGED
|
@@ -1,62 +1,140 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
2
|
from typing import Any, Dict, List, Optional
|
|
3
3
|
|
|
4
|
-
from agno.document import Document
|
|
4
|
+
from agno.knowledge.document import Document
|
|
5
|
+
from agno.utils.log import log_warning
|
|
6
|
+
from agno.utils.string import generate_id
|
|
5
7
|
|
|
6
8
|
|
|
7
9
|
class VectorDb(ABC):
|
|
8
10
|
"""Base class for Vector Databases"""
|
|
9
11
|
|
|
12
|
+
def __init__(self, *, id: Optional[str] = None, name: Optional[str] = None, description: Optional[str] = None):
|
|
13
|
+
"""Initialize base VectorDb.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
id: Optional custom ID. If not provided, an id will be generated.
|
|
17
|
+
name: Optional name for the vector database.
|
|
18
|
+
description: Optional description for the vector database.
|
|
19
|
+
"""
|
|
20
|
+
if name is None:
|
|
21
|
+
name = self.__class__.__name__
|
|
22
|
+
|
|
23
|
+
self.name = name
|
|
24
|
+
self.description = description
|
|
25
|
+
# Last resort fallback to generate id from name if ID not specified
|
|
26
|
+
self.id = id if id else generate_id(name)
|
|
27
|
+
|
|
10
28
|
@abstractmethod
|
|
11
29
|
def create(self) -> None:
|
|
12
30
|
raise NotImplementedError
|
|
13
31
|
|
|
14
32
|
@abstractmethod
|
|
15
|
-
def
|
|
33
|
+
async def async_create(self) -> None:
|
|
16
34
|
raise NotImplementedError
|
|
17
35
|
|
|
18
36
|
@abstractmethod
|
|
19
37
|
def name_exists(self, name: str) -> bool:
|
|
20
38
|
raise NotImplementedError
|
|
21
39
|
|
|
40
|
+
@abstractmethod
|
|
41
|
+
def async_name_exists(self, name: str) -> bool:
|
|
42
|
+
raise NotImplementedError
|
|
43
|
+
|
|
44
|
+
@abstractmethod
|
|
22
45
|
def id_exists(self, id: str) -> bool:
|
|
23
46
|
raise NotImplementedError
|
|
24
47
|
|
|
25
48
|
@abstractmethod
|
|
26
|
-
def
|
|
49
|
+
def content_hash_exists(self, content_hash: str) -> bool:
|
|
50
|
+
raise NotImplementedError
|
|
51
|
+
|
|
52
|
+
@abstractmethod
|
|
53
|
+
def insert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
54
|
+
raise NotImplementedError
|
|
55
|
+
|
|
56
|
+
@abstractmethod
|
|
57
|
+
async def async_insert(
|
|
58
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
59
|
+
) -> None:
|
|
27
60
|
raise NotImplementedError
|
|
28
61
|
|
|
29
62
|
def upsert_available(self) -> bool:
|
|
30
63
|
return False
|
|
31
64
|
|
|
32
65
|
@abstractmethod
|
|
33
|
-
def upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
66
|
+
def upsert(self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
|
|
34
67
|
raise NotImplementedError
|
|
35
68
|
|
|
36
69
|
@abstractmethod
|
|
37
|
-
def
|
|
70
|
+
async def async_upsert(
|
|
71
|
+
self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
|
|
72
|
+
) -> None:
|
|
38
73
|
raise NotImplementedError
|
|
39
74
|
|
|
40
|
-
|
|
75
|
+
@abstractmethod
|
|
76
|
+
def search(self, query: str, limit: int = 5, filters: Optional[Any] = None) -> List[Document]:
|
|
41
77
|
raise NotImplementedError
|
|
42
78
|
|
|
43
|
-
|
|
79
|
+
@abstractmethod
|
|
80
|
+
async def async_search(self, query: str, limit: int = 5, filters: Optional[Any] = None) -> List[Document]:
|
|
44
81
|
raise NotImplementedError
|
|
45
82
|
|
|
46
|
-
|
|
83
|
+
@abstractmethod
|
|
84
|
+
def drop(self) -> None:
|
|
47
85
|
raise NotImplementedError
|
|
48
86
|
|
|
49
87
|
@abstractmethod
|
|
50
|
-
def
|
|
88
|
+
async def async_drop(self) -> None:
|
|
51
89
|
raise NotImplementedError
|
|
52
90
|
|
|
53
91
|
@abstractmethod
|
|
54
92
|
def exists(self) -> bool:
|
|
55
93
|
raise NotImplementedError
|
|
56
94
|
|
|
95
|
+
@abstractmethod
|
|
96
|
+
async def async_exists(self) -> bool:
|
|
97
|
+
raise NotImplementedError
|
|
98
|
+
|
|
57
99
|
def optimize(self) -> None:
|
|
58
100
|
raise NotImplementedError
|
|
59
101
|
|
|
60
102
|
@abstractmethod
|
|
61
103
|
def delete(self) -> bool:
|
|
62
104
|
raise NotImplementedError
|
|
105
|
+
|
|
106
|
+
@abstractmethod
|
|
107
|
+
def delete_by_id(self, id: str) -> bool:
|
|
108
|
+
raise NotImplementedError
|
|
109
|
+
|
|
110
|
+
@abstractmethod
|
|
111
|
+
def delete_by_name(self, name: str) -> bool:
|
|
112
|
+
raise NotImplementedError
|
|
113
|
+
|
|
114
|
+
@abstractmethod
|
|
115
|
+
def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
|
|
116
|
+
raise NotImplementedError
|
|
117
|
+
|
|
118
|
+
def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
|
|
119
|
+
"""
|
|
120
|
+
Update the metadata for documents with the given content_id.
|
|
121
|
+
|
|
122
|
+
Default implementation logs a warning. Subclasses should override this method
|
|
123
|
+
to provide their specific implementation.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
content_id (str): The content ID to update
|
|
127
|
+
metadata (Dict[str, Any]): The metadata to update
|
|
128
|
+
"""
|
|
129
|
+
log_warning(
|
|
130
|
+
f"{self.__class__.__name__}.update_metadata() is not implemented. "
|
|
131
|
+
f"Metadata update for content_id '{content_id}' was skipped."
|
|
132
|
+
)
|
|
133
|
+
|
|
134
|
+
@abstractmethod
|
|
135
|
+
def delete_by_content_id(self, content_id: str) -> bool:
|
|
136
|
+
raise NotImplementedError
|
|
137
|
+
|
|
138
|
+
@abstractmethod
|
|
139
|
+
def get_supported_search_types(self) -> List[str]:
|
|
140
|
+
raise NotImplementedError
|