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/tools/sql.py
CHANGED
|
@@ -2,7 +2,7 @@ import json
|
|
|
2
2
|
from typing import Any, Dict, List, Optional
|
|
3
3
|
|
|
4
4
|
from agno.tools import Toolkit
|
|
5
|
-
from agno.utils.log import logger
|
|
5
|
+
from agno.utils.log import log_debug, logger
|
|
6
6
|
|
|
7
7
|
try:
|
|
8
8
|
from sqlalchemy import Engine, create_engine
|
|
@@ -25,12 +25,12 @@ class SQLTools(Toolkit):
|
|
|
25
25
|
schema: Optional[str] = None,
|
|
26
26
|
dialect: Optional[str] = None,
|
|
27
27
|
tables: Optional[Dict[str, Any]] = None,
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
enable_list_tables: bool = True,
|
|
29
|
+
enable_describe_table: bool = True,
|
|
30
|
+
enable_run_sql_query: bool = True,
|
|
31
|
+
all: bool = False,
|
|
32
|
+
**kwargs,
|
|
31
33
|
):
|
|
32
|
-
super().__init__(name="sql_tools")
|
|
33
|
-
|
|
34
34
|
# Get the database engine
|
|
35
35
|
_engine: Optional[Engine] = db_engine
|
|
36
36
|
if _engine is None and db_url is not None:
|
|
@@ -48,16 +48,20 @@ class SQLTools(Toolkit):
|
|
|
48
48
|
self.db_engine: Engine = _engine
|
|
49
49
|
self.Session: sessionmaker[Session] = sessionmaker(bind=self.db_engine)
|
|
50
50
|
|
|
51
|
+
self.schema = schema
|
|
52
|
+
|
|
51
53
|
# Tables this toolkit can access
|
|
52
54
|
self.tables: Optional[Dict[str, Any]] = tables
|
|
53
55
|
|
|
54
|
-
|
|
55
|
-
if
|
|
56
|
-
|
|
57
|
-
if
|
|
58
|
-
|
|
59
|
-
if
|
|
60
|
-
|
|
56
|
+
tools: List[Any] = []
|
|
57
|
+
if enable_list_tables or all:
|
|
58
|
+
tools.append(self.list_tables)
|
|
59
|
+
if enable_describe_table or all:
|
|
60
|
+
tools.append(self.describe_table)
|
|
61
|
+
if enable_run_sql_query or all:
|
|
62
|
+
tools.append(self.run_sql_query)
|
|
63
|
+
|
|
64
|
+
super().__init__(name="sql_tools", tools=tools, **kwargs)
|
|
61
65
|
|
|
62
66
|
def list_tables(self) -> str:
|
|
63
67
|
"""Use this function to get a list of table names in the database.
|
|
@@ -69,8 +73,13 @@ class SQLTools(Toolkit):
|
|
|
69
73
|
return json.dumps(self.tables)
|
|
70
74
|
|
|
71
75
|
try:
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
log_debug("listing tables in the database")
|
|
77
|
+
inspector = inspect(self.db_engine)
|
|
78
|
+
if self.schema:
|
|
79
|
+
table_names = inspector.get_table_names(schema=self.schema)
|
|
80
|
+
else:
|
|
81
|
+
table_names = inspector.get_table_names()
|
|
82
|
+
log_debug(f"table_names: {table_names}")
|
|
74
83
|
return json.dumps(table_names)
|
|
75
84
|
except Exception as e:
|
|
76
85
|
logger.error(f"Error getting tables: {e}")
|
|
@@ -87,9 +96,15 @@ class SQLTools(Toolkit):
|
|
|
87
96
|
"""
|
|
88
97
|
|
|
89
98
|
try:
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
99
|
+
log_debug(f"Describing table: {table_name}")
|
|
100
|
+
inspector = inspect(self.db_engine)
|
|
101
|
+
table_schema = inspector.get_columns(table_name, schema=self.schema)
|
|
102
|
+
return json.dumps(
|
|
103
|
+
[
|
|
104
|
+
{"name": column["name"], "type": str(column["type"]), "nullable": column["nullable"]}
|
|
105
|
+
for column in table_schema
|
|
106
|
+
]
|
|
107
|
+
)
|
|
93
108
|
except Exception as e:
|
|
94
109
|
logger.error(f"Error getting table schema: {e}")
|
|
95
110
|
return f"Error getting table schema: {e}"
|
|
@@ -122,7 +137,7 @@ class SQLTools(Toolkit):
|
|
|
122
137
|
Returns:
|
|
123
138
|
List[dict]: The result of the query.
|
|
124
139
|
"""
|
|
125
|
-
|
|
140
|
+
log_debug(f"Running sql |\n{sql}")
|
|
126
141
|
|
|
127
142
|
with self.Session() as sess, sess.begin():
|
|
128
143
|
result = sess.execute(text(sql))
|
agno/tools/tavily.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from os import getenv
|
|
3
|
-
from typing import Any, Dict, Literal, Optional
|
|
3
|
+
from typing import Any, Dict, List, Literal, Optional
|
|
4
4
|
|
|
5
5
|
from agno.tools import Toolkit
|
|
6
6
|
from agno.utils.log import logger
|
|
@@ -15,30 +15,67 @@ class TavilyTools(Toolkit):
|
|
|
15
15
|
def __init__(
|
|
16
16
|
self,
|
|
17
17
|
api_key: Optional[str] = None,
|
|
18
|
-
|
|
18
|
+
enable_search: bool = True,
|
|
19
|
+
enable_search_context: bool = False,
|
|
20
|
+
enable_extract: bool = False,
|
|
21
|
+
all: bool = False,
|
|
19
22
|
max_tokens: int = 6000,
|
|
20
23
|
include_answer: bool = True,
|
|
21
24
|
search_depth: Literal["basic", "advanced"] = "advanced",
|
|
25
|
+
extract_depth: Literal["basic", "advanced"] = "basic",
|
|
26
|
+
include_images: bool = False,
|
|
27
|
+
include_favicon: bool = False,
|
|
28
|
+
extract_timeout: Optional[int] = None,
|
|
29
|
+
extract_format: Literal["markdown", "text"] = "markdown",
|
|
22
30
|
format: Literal["json", "markdown"] = "markdown",
|
|
23
|
-
|
|
31
|
+
**kwargs,
|
|
24
32
|
):
|
|
25
|
-
|
|
33
|
+
"""Initialize TavilyTools with search and extract capabilities.
|
|
26
34
|
|
|
35
|
+
Args:
|
|
36
|
+
api_key: Tavily API key. If not provided, will use TAVILY_API_KEY env var.
|
|
37
|
+
enable_search: Enable web search functionality. Defaults to True.
|
|
38
|
+
enable_search_context: Use search context mode instead of regular search. Defaults to False.
|
|
39
|
+
enable_extract: Enable URL content extraction functionality. Defaults to False.
|
|
40
|
+
all: Enable all available tools. Defaults to False.
|
|
41
|
+
max_tokens: Maximum tokens for search results. Defaults to 6000.
|
|
42
|
+
include_answer: Include AI-generated answer in search results. Defaults to True.
|
|
43
|
+
search_depth: Search depth level - basic (1 credit) or advanced (2 credits). Defaults to "advanced".
|
|
44
|
+
extract_depth: Extract depth level - basic (1 credit/5 URLs) or advanced (2 credits/5 URLs). Defaults to "basic".
|
|
45
|
+
include_images: Include images in extracted content. Defaults to False.
|
|
46
|
+
include_favicon: Include favicon in extracted content. Defaults to False.
|
|
47
|
+
extract_timeout: Timeout in seconds for extraction requests. Defaults to None.
|
|
48
|
+
extract_format: Output format for extracted content - markdown or text. Defaults to "markdown".
|
|
49
|
+
format: Output format for search results - json or markdown. Defaults to "markdown".
|
|
50
|
+
**kwargs: Additional arguments passed to Toolkit.
|
|
51
|
+
"""
|
|
27
52
|
self.api_key = api_key or getenv("TAVILY_API_KEY")
|
|
28
53
|
if not self.api_key:
|
|
29
54
|
logger.error("TAVILY_API_KEY not provided")
|
|
30
55
|
|
|
31
56
|
self.client: TavilyClient = TavilyClient(api_key=self.api_key)
|
|
32
57
|
self.search_depth: Literal["basic", "advanced"] = search_depth
|
|
58
|
+
self.extract_depth: Literal["basic", "advanced"] = extract_depth
|
|
33
59
|
self.max_tokens: int = max_tokens
|
|
34
60
|
self.include_answer: bool = include_answer
|
|
61
|
+
self.include_images: bool = include_images
|
|
62
|
+
self.include_favicon: bool = include_favicon
|
|
63
|
+
self.extract_timeout: Optional[int] = extract_timeout
|
|
64
|
+
self.extract_format: Literal["markdown", "text"] = extract_format
|
|
35
65
|
self.format: Literal["json", "markdown"] = format
|
|
36
66
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
67
|
+
tools: List[Any] = []
|
|
68
|
+
|
|
69
|
+
if enable_search or all:
|
|
70
|
+
if enable_search_context:
|
|
71
|
+
tools.append(self.web_search_with_tavily)
|
|
40
72
|
else:
|
|
41
|
-
|
|
73
|
+
tools.append(self.web_search_using_tavily)
|
|
74
|
+
|
|
75
|
+
if enable_extract or all:
|
|
76
|
+
tools.append(self.extract_url_content)
|
|
77
|
+
|
|
78
|
+
super().__init__(name="tavily_tools", tools=tools, **kwargs)
|
|
42
79
|
|
|
43
80
|
def web_search_using_tavily(self, query: str, max_results: int = 5) -> str:
|
|
44
81
|
"""Use this function to search the web for a given query.
|
|
@@ -102,3 +139,116 @@ class TavilyTools(Toolkit):
|
|
|
102
139
|
return self.client.get_search_context(
|
|
103
140
|
query=query, search_depth=self.search_depth, max_tokens=self.max_tokens, include_answer=self.include_answer
|
|
104
141
|
)
|
|
142
|
+
|
|
143
|
+
def extract_url_content(self, urls: str) -> str:
|
|
144
|
+
"""Extract content from one or more URLs using Tavily's Extract API.
|
|
145
|
+
This function retrieves the main content from web pages in markdown or text format.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
urls (str): Single URL or multiple comma-separated URLs to extract content from.
|
|
149
|
+
Example: "https://example.com" or "https://example.com,https://another.com"
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
str: Extracted content in the specified format (markdown or text).
|
|
153
|
+
For multiple URLs, returns combined content with URL headers.
|
|
154
|
+
Failed extractions are noted in the output.
|
|
155
|
+
"""
|
|
156
|
+
# Parse URLs - handle both single and comma-separated multiple URLs
|
|
157
|
+
url_list = [url.strip() for url in urls.split(",") if url.strip()]
|
|
158
|
+
|
|
159
|
+
if not url_list:
|
|
160
|
+
return "Error: No valid URLs provided."
|
|
161
|
+
|
|
162
|
+
try:
|
|
163
|
+
# Prepare extract parameters
|
|
164
|
+
extract_params: Dict[str, Any] = {
|
|
165
|
+
"urls": url_list,
|
|
166
|
+
"depth": self.extract_depth,
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# Add optional parameters if specified
|
|
170
|
+
if self.include_images:
|
|
171
|
+
extract_params["include_images"] = True
|
|
172
|
+
if self.include_favicon:
|
|
173
|
+
extract_params["include_favicon"] = True
|
|
174
|
+
if self.extract_timeout is not None:
|
|
175
|
+
extract_params["timeout"] = self.extract_timeout
|
|
176
|
+
|
|
177
|
+
# Call Tavily Extract API
|
|
178
|
+
response = self.client.extract(**extract_params)
|
|
179
|
+
|
|
180
|
+
# Process response based on format preference
|
|
181
|
+
if not response or "results" not in response:
|
|
182
|
+
return "Error: No content could be extracted from the provided URL(s)."
|
|
183
|
+
|
|
184
|
+
results = response.get("results", [])
|
|
185
|
+
if not results:
|
|
186
|
+
return "Error: No content could be extracted from the provided URL(s)."
|
|
187
|
+
|
|
188
|
+
# Format output
|
|
189
|
+
if self.extract_format == "markdown":
|
|
190
|
+
return self._format_extract_markdown(results)
|
|
191
|
+
elif self.extract_format == "text":
|
|
192
|
+
return self._format_extract_text(results)
|
|
193
|
+
else:
|
|
194
|
+
# Fallback to JSON if format is unrecognized
|
|
195
|
+
return json.dumps(results, indent=2)
|
|
196
|
+
|
|
197
|
+
except Exception as e:
|
|
198
|
+
logger.error(f"Error extracting content from URLs: {e}")
|
|
199
|
+
return f"Error extracting content: {str(e)}"
|
|
200
|
+
|
|
201
|
+
def _format_extract_markdown(self, results: List[Dict[str, Any]]) -> str:
|
|
202
|
+
"""Format extraction results as markdown.
|
|
203
|
+
|
|
204
|
+
Args:
|
|
205
|
+
results: List of extraction result dictionaries from Tavily API.
|
|
206
|
+
|
|
207
|
+
Returns:
|
|
208
|
+
str: Formatted markdown content.
|
|
209
|
+
"""
|
|
210
|
+
output = []
|
|
211
|
+
|
|
212
|
+
for result in results:
|
|
213
|
+
url = result.get("url", "Unknown URL")
|
|
214
|
+
raw_content = result.get("raw_content", "")
|
|
215
|
+
failed_reason = result.get("failed_reason")
|
|
216
|
+
|
|
217
|
+
if failed_reason:
|
|
218
|
+
output.append(f"## {url}\n\n **Extraction Failed**: {failed_reason}\n\n")
|
|
219
|
+
elif raw_content:
|
|
220
|
+
output.append(f"## {url}\n\n{raw_content}\n\n")
|
|
221
|
+
else:
|
|
222
|
+
output.append(f"## {url}\n\n*No content available*\n\n")
|
|
223
|
+
|
|
224
|
+
return "".join(output) if output else "No content extracted."
|
|
225
|
+
|
|
226
|
+
def _format_extract_text(self, results: List[Dict[str, Any]]) -> str:
|
|
227
|
+
"""Format extraction results as plain text.
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
results: List of extraction result dictionaries from Tavily API.
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
str: Formatted plain text content.
|
|
234
|
+
"""
|
|
235
|
+
output = []
|
|
236
|
+
|
|
237
|
+
for result in results:
|
|
238
|
+
url = result.get("url", "Unknown URL")
|
|
239
|
+
raw_content = result.get("raw_content", "")
|
|
240
|
+
failed_reason = result.get("failed_reason")
|
|
241
|
+
|
|
242
|
+
output.append(f"URL: {url}")
|
|
243
|
+
output.append("-" * 80)
|
|
244
|
+
|
|
245
|
+
if failed_reason:
|
|
246
|
+
output.append(f"EXTRACTION FAILED: {failed_reason}")
|
|
247
|
+
elif raw_content:
|
|
248
|
+
output.append(raw_content)
|
|
249
|
+
else:
|
|
250
|
+
output.append("No content available")
|
|
251
|
+
|
|
252
|
+
output.append("\n")
|
|
253
|
+
|
|
254
|
+
return "\n".join(output) if output else "No content extracted."
|
agno/tools/telegram.py
CHANGED
|
@@ -1,25 +1,34 @@
|
|
|
1
|
-
import
|
|
2
|
-
from typing import Optional, Union
|
|
1
|
+
from os import getenv
|
|
2
|
+
from typing import Any, List, Optional, Union
|
|
3
3
|
|
|
4
4
|
import httpx
|
|
5
5
|
|
|
6
6
|
from agno.tools import Toolkit
|
|
7
|
-
from agno.utils.log import logger
|
|
7
|
+
from agno.utils.log import log_debug, logger
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
class TelegramTools(Toolkit):
|
|
11
11
|
base_url = "https://api.telegram.org"
|
|
12
12
|
|
|
13
|
-
def __init__(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
chat_id: Union[str, int],
|
|
16
|
+
token: Optional[str] = None,
|
|
17
|
+
enable_send_message: bool = True,
|
|
18
|
+
all: bool = False,
|
|
19
|
+
**kwargs,
|
|
20
|
+
):
|
|
21
|
+
self.token = token or getenv("TELEGRAM_TOKEN")
|
|
17
22
|
if not self.token:
|
|
18
23
|
logger.error("TELEGRAM_TOKEN not set. Please set the TELEGRAM_TOKEN environment variable.")
|
|
19
24
|
|
|
20
25
|
self.chat_id = chat_id
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
tools: List[Any] = []
|
|
28
|
+
if all or enable_send_message:
|
|
29
|
+
tools.append(self.send_message)
|
|
30
|
+
|
|
31
|
+
super().__init__(name="telegram", tools=tools, **kwargs)
|
|
23
32
|
|
|
24
33
|
def _call_post_method(self, method, *args, **kwargs):
|
|
25
34
|
return httpx.post(f"{self.base_url}/bot{self.token}/{method}", *args, **kwargs)
|
|
@@ -30,6 +39,7 @@ class TelegramTools(Toolkit):
|
|
|
30
39
|
:param message: The message to send.
|
|
31
40
|
:return: The response from the API.
|
|
32
41
|
"""
|
|
42
|
+
log_debug(f"Sending telegram message: {message}")
|
|
33
43
|
response = self._call_post_method("sendMessage", json={"chat_id": self.chat_id, "text": message})
|
|
34
44
|
try:
|
|
35
45
|
response.raise_for_status()
|
agno/tools/todoist.py
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, Dict, List, Optional
|
|
4
|
+
|
|
5
|
+
from agno.tools import Toolkit
|
|
6
|
+
from agno.utils.log import logger
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from todoist_api_python.api import TodoistAPI
|
|
10
|
+
except ImportError:
|
|
11
|
+
raise ImportError("`todoist-api-python` not installed. Please install using `pip install todoist-api-python`")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TodoistTools(Toolkit):
|
|
15
|
+
"""A toolkit for interacting with Todoist tasks and projects."""
|
|
16
|
+
|
|
17
|
+
def __init__(
|
|
18
|
+
self,
|
|
19
|
+
api_token: Optional[str] = None,
|
|
20
|
+
**kwargs,
|
|
21
|
+
):
|
|
22
|
+
"""Initialize the Todoist toolkit.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
api_token: Optional Todoist API token. If not provided, will look for TODOIST_API_TOKEN env var
|
|
26
|
+
"""
|
|
27
|
+
self.api_token = api_token or getenv("TODOIST_API_TOKEN")
|
|
28
|
+
if not self.api_token:
|
|
29
|
+
raise ValueError("TODOIST_API_TOKEN not set. Please set the TODOIST_API_TOKEN environment variable.")
|
|
30
|
+
|
|
31
|
+
self.api = TodoistAPI(self.api_token)
|
|
32
|
+
|
|
33
|
+
tools: List[Any] = [
|
|
34
|
+
self.create_task,
|
|
35
|
+
self.get_task,
|
|
36
|
+
self.update_task,
|
|
37
|
+
self.close_task,
|
|
38
|
+
self.delete_task,
|
|
39
|
+
self.get_active_tasks,
|
|
40
|
+
self.get_projects,
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
super().__init__(name="todoist", tools=tools, **kwargs)
|
|
44
|
+
|
|
45
|
+
def _task_to_dict(self, task: Any) -> Dict[str, Any]:
|
|
46
|
+
"""Convert a Todoist task to a dictionary with proper typing."""
|
|
47
|
+
task_dict: Dict[str, Any] = {
|
|
48
|
+
"id": task.id,
|
|
49
|
+
"content": task.content,
|
|
50
|
+
"description": task.description,
|
|
51
|
+
"project_id": task.project_id,
|
|
52
|
+
"section_id": task.section_id,
|
|
53
|
+
"parent_id": task.parent_id,
|
|
54
|
+
"order": task.order,
|
|
55
|
+
"priority": task.priority,
|
|
56
|
+
"url": task.url,
|
|
57
|
+
"creator_id": task.creator_id,
|
|
58
|
+
"created_at": task.created_at,
|
|
59
|
+
"labels": task.labels,
|
|
60
|
+
}
|
|
61
|
+
if hasattr(task, "comment_count"):
|
|
62
|
+
task_dict["comment_count"] = task.comment_count
|
|
63
|
+
if task.due:
|
|
64
|
+
task_dict["due"] = {
|
|
65
|
+
"date": task.due.date,
|
|
66
|
+
"string": task.due.string,
|
|
67
|
+
"lang": task.due.lang,
|
|
68
|
+
"is_recurring": task.due.is_recurring,
|
|
69
|
+
"timezone": task.due.timezone,
|
|
70
|
+
}
|
|
71
|
+
return task_dict
|
|
72
|
+
|
|
73
|
+
def create_task(
|
|
74
|
+
self,
|
|
75
|
+
content: str,
|
|
76
|
+
project_id: Optional[str] = None,
|
|
77
|
+
due_string: Optional[str] = None,
|
|
78
|
+
priority: Optional[int] = None,
|
|
79
|
+
labels: Optional[List[str]] = None,
|
|
80
|
+
) -> str:
|
|
81
|
+
"""
|
|
82
|
+
Create a new task in Todoist.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
content: The task content/description
|
|
86
|
+
project_id: Optional ID of the project to add the task to
|
|
87
|
+
due_string: Optional due date in natural language (e.g., "tomorrow at 12:00")
|
|
88
|
+
priority: Optional priority level (1-4, where 4 is highest)
|
|
89
|
+
labels: Optional list of label names to apply to the task
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
str: JSON string containing the created task
|
|
93
|
+
"""
|
|
94
|
+
try:
|
|
95
|
+
task = self.api.add_task(
|
|
96
|
+
content=content, project_id=project_id, due_string=due_string, priority=priority, labels=labels or []
|
|
97
|
+
)
|
|
98
|
+
# Convert task to a dictionary and handle the Due object
|
|
99
|
+
task_dict = self._task_to_dict(task)
|
|
100
|
+
return json.dumps(task_dict, default=str)
|
|
101
|
+
except Exception as e:
|
|
102
|
+
logger.error(f"Failed to create task: {str(e)}")
|
|
103
|
+
return json.dumps({"error": str(e)})
|
|
104
|
+
|
|
105
|
+
def get_task(self, task_id: str) -> str:
|
|
106
|
+
"""Get a specific task by ID."""
|
|
107
|
+
try:
|
|
108
|
+
task = self.api.get_task(task_id)
|
|
109
|
+
task_dict = self._task_to_dict(task)
|
|
110
|
+
return json.dumps(task_dict, default=str)
|
|
111
|
+
except Exception as e:
|
|
112
|
+
logger.error(f"Failed to get task: {str(e)}")
|
|
113
|
+
return json.dumps({"error": str(e)})
|
|
114
|
+
|
|
115
|
+
def update_task(
|
|
116
|
+
self,
|
|
117
|
+
task_id: str,
|
|
118
|
+
content: Optional[str] = None,
|
|
119
|
+
description: Optional[str] = None,
|
|
120
|
+
labels: Optional[List[str]] = None,
|
|
121
|
+
priority: Optional[int] = None,
|
|
122
|
+
due_string: Optional[str] = None,
|
|
123
|
+
due_date: Optional[str] = None,
|
|
124
|
+
due_datetime: Optional[str] = None,
|
|
125
|
+
due_lang: Optional[str] = None,
|
|
126
|
+
assignee_id: Optional[str] = None,
|
|
127
|
+
section_id: Optional[str] = None,
|
|
128
|
+
) -> str:
|
|
129
|
+
"""
|
|
130
|
+
Update an existing task with the specified parameters.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
task_id: The ID of the task to update
|
|
134
|
+
content: The task content/name
|
|
135
|
+
description: The task description
|
|
136
|
+
labels: Array of label names
|
|
137
|
+
priority: Task priority from 1 (normal) to 4 (urgent)
|
|
138
|
+
due_string: Human readable date ("next Monday", "tomorrow", etc)
|
|
139
|
+
due_date: Specific date in YYYY-MM-DD format
|
|
140
|
+
due_datetime: Specific date and time in RFC3339 format
|
|
141
|
+
due_lang: 2-letter code specifying language of due_string ("en", "fr", etc)
|
|
142
|
+
assignee_id: The responsible user ID
|
|
143
|
+
section_id: ID of the section to move task to
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
str: JSON string containing success status or error message
|
|
147
|
+
"""
|
|
148
|
+
try:
|
|
149
|
+
# Build updates dictionary with only provided parameters
|
|
150
|
+
updates: Dict[str, Any] = {}
|
|
151
|
+
if content is not None:
|
|
152
|
+
updates["content"] = content
|
|
153
|
+
if description is not None:
|
|
154
|
+
updates["description"] = description
|
|
155
|
+
if labels is not None:
|
|
156
|
+
updates["labels"] = labels
|
|
157
|
+
if priority is not None:
|
|
158
|
+
updates["priority"] = priority
|
|
159
|
+
if due_string is not None:
|
|
160
|
+
updates["due_string"] = due_string
|
|
161
|
+
if due_date is not None:
|
|
162
|
+
updates["due_date"] = due_date
|
|
163
|
+
if due_datetime is not None:
|
|
164
|
+
updates["due_datetime"] = due_datetime
|
|
165
|
+
if due_lang is not None:
|
|
166
|
+
updates["due_lang"] = due_lang
|
|
167
|
+
if assignee_id is not None:
|
|
168
|
+
updates["assignee_id"] = assignee_id
|
|
169
|
+
if section_id is not None:
|
|
170
|
+
updates["section_id"] = section_id
|
|
171
|
+
|
|
172
|
+
success = self.api.update_task(task_id=task_id, **updates)
|
|
173
|
+
return json.dumps({"success": success})
|
|
174
|
+
except Exception as e:
|
|
175
|
+
error_msg = str(e)
|
|
176
|
+
logger.error(f"Failed to update task: {error_msg}")
|
|
177
|
+
return json.dumps({"error": error_msg})
|
|
178
|
+
|
|
179
|
+
def close_task(self, task_id: str) -> str:
|
|
180
|
+
"""Mark a task as completed."""
|
|
181
|
+
try:
|
|
182
|
+
success = self.api.complete_task(task_id)
|
|
183
|
+
return json.dumps({"success": success})
|
|
184
|
+
except Exception as e:
|
|
185
|
+
logger.error(f"Failed to close task: {str(e)}")
|
|
186
|
+
return json.dumps({"error": str(e)})
|
|
187
|
+
|
|
188
|
+
def delete_task(self, task_id: str) -> str:
|
|
189
|
+
"""Delete a task."""
|
|
190
|
+
try:
|
|
191
|
+
success = self.api.delete_task(task_id)
|
|
192
|
+
return json.dumps({"success": success})
|
|
193
|
+
except Exception as e:
|
|
194
|
+
logger.error(f"Failed to delete task: {str(e)}")
|
|
195
|
+
return json.dumps({"error": str(e)})
|
|
196
|
+
|
|
197
|
+
def get_active_tasks(self) -> str:
|
|
198
|
+
"""Get all active (not completed) tasks."""
|
|
199
|
+
try:
|
|
200
|
+
tasks_response = self.api.get_tasks()
|
|
201
|
+
tasks = list(tasks_response)[0]
|
|
202
|
+
tasks_list = []
|
|
203
|
+
for task in tasks:
|
|
204
|
+
task_dict = self._task_to_dict(task)
|
|
205
|
+
tasks_list.append(task_dict)
|
|
206
|
+
return json.dumps(tasks_list, default=str)
|
|
207
|
+
except Exception as e:
|
|
208
|
+
logger.error(f"Failed to get active tasks: {str(e)}")
|
|
209
|
+
return json.dumps({"error": str(e)})
|
|
210
|
+
|
|
211
|
+
def get_projects(self) -> str:
|
|
212
|
+
"""Get all projects."""
|
|
213
|
+
try:
|
|
214
|
+
projects = self.api.get_projects()
|
|
215
|
+
return json.dumps([project.__dict__ for project in projects])
|
|
216
|
+
except Exception as e:
|
|
217
|
+
logger.error(f"Failed to get projects: {str(e)}")
|
|
218
|
+
return json.dumps({"error": str(e)})
|