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/{twitter.py → x.py}
RENAMED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import json
|
|
2
|
-
import
|
|
3
|
-
from typing import Optional
|
|
2
|
+
from os import getenv
|
|
3
|
+
from typing import Any, List, Optional
|
|
4
4
|
|
|
5
5
|
from agno.tools import Toolkit
|
|
6
|
-
from agno.utils.log import logger
|
|
6
|
+
from agno.utils.log import log_debug, log_info, logger
|
|
7
7
|
|
|
8
8
|
try:
|
|
9
9
|
import tweepy
|
|
@@ -11,7 +11,7 @@ except ImportError:
|
|
|
11
11
|
raise ImportError("`tweepy` not installed. Please install using `pip install tweepy`.")
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
class
|
|
14
|
+
class XTools(Toolkit):
|
|
15
15
|
def __init__(
|
|
16
16
|
self,
|
|
17
17
|
bearer_token: Optional[str] = None,
|
|
@@ -19,9 +19,12 @@ class TwitterTools(Toolkit):
|
|
|
19
19
|
consumer_secret: Optional[str] = None,
|
|
20
20
|
access_token: Optional[str] = None,
|
|
21
21
|
access_token_secret: Optional[str] = None,
|
|
22
|
+
include_post_metrics: bool = False,
|
|
23
|
+
wait_on_rate_limit: bool = False,
|
|
24
|
+
**kwargs,
|
|
22
25
|
):
|
|
23
26
|
"""
|
|
24
|
-
Initialize the
|
|
27
|
+
Initialize the XTools.
|
|
25
28
|
|
|
26
29
|
Args:
|
|
27
30
|
bearer_token Optional[str]: The bearer token for Twitter API.
|
|
@@ -29,76 +32,82 @@ class TwitterTools(Toolkit):
|
|
|
29
32
|
consumer_secret Optional[str]: The consumer secret for Twitter API.
|
|
30
33
|
access_token Optional[str]: The access token for Twitter API.
|
|
31
34
|
access_token_secret Optional[str]: The access token secret for Twitter API.
|
|
35
|
+
include_post_metrics Optional[bool]: Whether to include post metrics in the search results.
|
|
36
|
+
wait_on_rate_limit Optional[bool]: Whether to wait on rate limit.
|
|
32
37
|
"""
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
self.
|
|
36
|
-
self.
|
|
37
|
-
self.
|
|
38
|
-
self.
|
|
39
|
-
self.access_token_secret = access_token_secret or os.getenv("TWITTER_ACCESS_TOKEN_SECRET")
|
|
40
|
-
|
|
38
|
+
self.bearer_token = bearer_token or getenv("X_BEARER_TOKEN")
|
|
39
|
+
self.consumer_key = consumer_key or getenv("X_CONSUMER_KEY")
|
|
40
|
+
self.consumer_secret = consumer_secret or getenv("X_CONSUMER_SECRET")
|
|
41
|
+
self.access_token = access_token or getenv("X_ACCESS_TOKEN")
|
|
42
|
+
self.access_token_secret = access_token_secret or getenv("X_ACCESS_TOKEN_SECRET")
|
|
43
|
+
self.wait_on_rate_limit = wait_on_rate_limit
|
|
41
44
|
self.client = tweepy.Client(
|
|
42
45
|
bearer_token=self.bearer_token,
|
|
43
46
|
consumer_key=self.consumer_key,
|
|
44
47
|
consumer_secret=self.consumer_secret,
|
|
45
48
|
access_token=self.access_token,
|
|
46
49
|
access_token_secret=self.access_token_secret,
|
|
50
|
+
wait_on_rate_limit=self.wait_on_rate_limit,
|
|
47
51
|
)
|
|
48
|
-
self.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
self.include_post_metrics = include_post_metrics
|
|
53
|
+
|
|
54
|
+
tools: List[Any] = [
|
|
55
|
+
self.create_post,
|
|
56
|
+
self.reply_to_post,
|
|
57
|
+
self.send_dm,
|
|
58
|
+
self.get_user_info,
|
|
59
|
+
self.get_home_timeline,
|
|
60
|
+
self.search_posts,
|
|
61
|
+
]
|
|
62
|
+
|
|
63
|
+
super().__init__(name="x", tools=tools, **kwargs)
|
|
55
64
|
|
|
56
|
-
def
|
|
65
|
+
def create_post(self, text: str) -> str:
|
|
57
66
|
"""
|
|
58
|
-
Create a new
|
|
67
|
+
Create a new X post.
|
|
59
68
|
|
|
60
69
|
Args:
|
|
61
|
-
text (str): The content of the
|
|
70
|
+
text (str): The content of the post to create.
|
|
62
71
|
|
|
63
72
|
Returns:
|
|
64
|
-
A JSON-formatted string containing the response from Twitter API with the created
|
|
65
|
-
or an error message if the
|
|
73
|
+
A JSON-formatted string containing the response from X API (Twitter API) with the created post details,
|
|
74
|
+
or an error message if the post creation fails.
|
|
66
75
|
"""
|
|
67
|
-
|
|
76
|
+
log_debug(f"Attempting to create post with text: {text}")
|
|
68
77
|
try:
|
|
69
78
|
response = self.client.create_tweet(text=text)
|
|
70
|
-
|
|
79
|
+
post_id = response.data["id"]
|
|
71
80
|
user = self.client.get_me().data
|
|
72
|
-
|
|
81
|
+
post_url = f"https://x.com/{user.username}/status/{post_id}"
|
|
73
82
|
|
|
74
|
-
result = {"message": "
|
|
83
|
+
result = {"message": "Post successfully created!", "url": post_url}
|
|
75
84
|
return json.dumps(result, indent=2)
|
|
76
85
|
except tweepy.TweepyException as e:
|
|
77
|
-
logger.error(f"Error creating
|
|
86
|
+
logger.error(f"Error creating post: {e}")
|
|
78
87
|
return json.dumps({"error": str(e)})
|
|
79
88
|
|
|
80
|
-
def
|
|
89
|
+
def reply_to_post(self, post_id: str, text: str) -> str:
|
|
81
90
|
"""
|
|
82
|
-
Reply to an existing
|
|
91
|
+
Reply to an existing post.
|
|
83
92
|
|
|
84
93
|
Args:
|
|
85
|
-
|
|
86
|
-
text (str): The content of the reply
|
|
94
|
+
post_id (str): The ID of the post to reply to.
|
|
95
|
+
text (str): The content of the reply post.
|
|
87
96
|
|
|
88
97
|
Returns:
|
|
89
|
-
A JSON-formatted string containing the response from Twitter API with the reply
|
|
98
|
+
A JSON-formatted string containing the response from Twitter API with the reply post details,
|
|
90
99
|
or an error message if the reply fails.
|
|
91
100
|
"""
|
|
92
|
-
|
|
101
|
+
log_debug(f"Attempting to reply to {post_id} with text {text}")
|
|
93
102
|
try:
|
|
94
|
-
response = self.client.create_tweet(text=text, in_reply_to_tweet_id=
|
|
103
|
+
response = self.client.create_tweet(text=text, in_reply_to_tweet_id=post_id)
|
|
95
104
|
reply_id = response.data["id"]
|
|
96
105
|
user = self.client.get_me().data
|
|
97
106
|
reply_url = f"https://twitter.com/{user.username}/status/{reply_id}"
|
|
98
107
|
result = {"message": "Reply successfully posted!", "url": reply_url}
|
|
99
108
|
return json.dumps(result, indent=2)
|
|
100
109
|
except tweepy.TweepyException as e:
|
|
101
|
-
logger.error(f"Error replying to
|
|
110
|
+
logger.error(f"Error replying to post: {e}")
|
|
102
111
|
return json.dumps({"error": str(e)})
|
|
103
112
|
|
|
104
113
|
def send_dm(self, recipient: str, text: str) -> str:
|
|
@@ -113,18 +122,18 @@ class TwitterTools(Toolkit):
|
|
|
113
122
|
A JSON-formatted string containing the response from Twitter API with the sent message details,
|
|
114
123
|
or an error message if sending the DM fails.
|
|
115
124
|
"""
|
|
116
|
-
|
|
125
|
+
log_debug(f"Attempting to send DM to user {recipient}")
|
|
117
126
|
try:
|
|
118
127
|
# Check if recipient is a user ID (numeric) or username
|
|
119
128
|
if not recipient.isdigit():
|
|
120
129
|
# If it's not numeric, assume it's a username and get the user ID
|
|
121
130
|
user = self.client.get_user(username=recipient)
|
|
122
|
-
|
|
131
|
+
log_debug(f"Attempting to send DM to user's id {user}")
|
|
123
132
|
recipient_id = user.data.id
|
|
124
133
|
else:
|
|
125
134
|
recipient_id = recipient
|
|
126
135
|
|
|
127
|
-
|
|
136
|
+
log_debug(f"Attempting to send DM to user's id {recipient_id}")
|
|
128
137
|
response = self.client.create_direct_message(participant_id=recipient_id, text=text)
|
|
129
138
|
result = {
|
|
130
139
|
"message": "Direct message sent successfully!",
|
|
@@ -134,7 +143,7 @@ class TwitterTools(Toolkit):
|
|
|
134
143
|
}
|
|
135
144
|
return json.dumps(result, indent=2)
|
|
136
145
|
except tweepy.TweepyException as e:
|
|
137
|
-
logger.error(f"Error sending DM: {e}")
|
|
146
|
+
logger.error(f"Error from X while sending DM: {e}")
|
|
138
147
|
error_message = str(e)
|
|
139
148
|
if "User not found" in error_message:
|
|
140
149
|
error_message = f"User '{recipient}' not found. Please check the username or user ID."
|
|
@@ -156,7 +165,7 @@ class TwitterTools(Toolkit):
|
|
|
156
165
|
including id, name, username, description, and follower/following counts,
|
|
157
166
|
or an error message if fetching the information fails.
|
|
158
167
|
"""
|
|
159
|
-
|
|
168
|
+
log_debug("Fetching information about myself")
|
|
160
169
|
try:
|
|
161
170
|
me = self.client.get_me(user_fields=["description", "public_metrics"])
|
|
162
171
|
user_info = me.data.data
|
|
@@ -186,7 +195,7 @@ class TwitterTools(Toolkit):
|
|
|
186
195
|
including id, name, username, description, and follower/following counts,
|
|
187
196
|
or an error message if fetching the information fails.
|
|
188
197
|
"""
|
|
189
|
-
|
|
198
|
+
log_debug(f"Fetching information about user {username}")
|
|
190
199
|
try:
|
|
191
200
|
user = self.client.get_user(username=username, user_fields=["description", "public_metrics"])
|
|
192
201
|
user_info = user.data.data
|
|
@@ -216,7 +225,7 @@ class TwitterTools(Toolkit):
|
|
|
216
225
|
including tweet id, text, creation time, and author id,
|
|
217
226
|
or an error message if fetching the timeline fails.
|
|
218
227
|
"""
|
|
219
|
-
|
|
228
|
+
log_debug(f"Fetching home timeline, max results: {max_results}")
|
|
220
229
|
try:
|
|
221
230
|
tweets = self.client.get_home_timeline(
|
|
222
231
|
max_results=max_results, tweet_fields=["created_at", "public_metrics"]
|
|
@@ -231,9 +240,96 @@ class TwitterTools(Toolkit):
|
|
|
231
240
|
"author_id": tweet.author_id,
|
|
232
241
|
}
|
|
233
242
|
)
|
|
234
|
-
|
|
243
|
+
log_info(f"Successfully fetched {len(timeline)} tweets")
|
|
235
244
|
result = {"home_timeline": timeline}
|
|
236
245
|
return json.dumps(result, indent=2)
|
|
237
246
|
except tweepy.TweepyException as e:
|
|
238
247
|
logger.error(f"Error fetching home timeline: {e}")
|
|
239
248
|
return json.dumps({"error": str(e)})
|
|
249
|
+
|
|
250
|
+
def search_posts(self, query: str, max_results: int = 10) -> str:
|
|
251
|
+
"""
|
|
252
|
+
Search for tweets based on a search query.
|
|
253
|
+
|
|
254
|
+
Args:
|
|
255
|
+
query (str): The search query.
|
|
256
|
+
max_results (int): The maximum number of posts to retrieve.
|
|
257
|
+
|
|
258
|
+
Returns:
|
|
259
|
+
A list of posts matching the search query
|
|
260
|
+
"""
|
|
261
|
+
try:
|
|
262
|
+
max_results = max(10, min(max_results, 100)) # range 10 - 100
|
|
263
|
+
|
|
264
|
+
log_debug(f"Searching for posts with query: {query}, bounded max results: {max_results}")
|
|
265
|
+
results = self.client.search_recent_tweets(
|
|
266
|
+
query=query,
|
|
267
|
+
max_results=max_results,
|
|
268
|
+
tweet_fields=[
|
|
269
|
+
"author_id",
|
|
270
|
+
"created_at",
|
|
271
|
+
"id",
|
|
272
|
+
"public_metrics",
|
|
273
|
+
"text",
|
|
274
|
+
],
|
|
275
|
+
user_fields=["name", "username", "verified"],
|
|
276
|
+
)
|
|
277
|
+
|
|
278
|
+
users_data = {}
|
|
279
|
+
if hasattr(results, "includes") and "users" in results.includes:
|
|
280
|
+
for user in results.includes["users"]:
|
|
281
|
+
users_data[user.id] = {
|
|
282
|
+
"id": user.id,
|
|
283
|
+
"name": user.name,
|
|
284
|
+
"username": user.username,
|
|
285
|
+
"verified": getattr(user, "verified", False),
|
|
286
|
+
}
|
|
287
|
+
tweets = []
|
|
288
|
+
|
|
289
|
+
if results.data:
|
|
290
|
+
for tweet in results.data:
|
|
291
|
+
author_info = users_data.get(
|
|
292
|
+
tweet.author_id, {"id": tweet.author_id, "name": "Unknown", "username": "unknown"}
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
post_url = f"https://x.com/{author_info.get('username', 'unknown')}/status/{tweet.id}"
|
|
296
|
+
|
|
297
|
+
post_data = {
|
|
298
|
+
"id": tweet.id,
|
|
299
|
+
"text": tweet.text,
|
|
300
|
+
"created_at": tweet.created_at.strftime("%Y-%m-%d %H:%M:%S")
|
|
301
|
+
if hasattr(tweet, "created_at")
|
|
302
|
+
else None,
|
|
303
|
+
"author": author_info,
|
|
304
|
+
"url": post_url,
|
|
305
|
+
}
|
|
306
|
+
if self.include_post_metrics:
|
|
307
|
+
post_data["metrics"] = {
|
|
308
|
+
"retweet_count": tweet.public_metrics.get("retweet_count", 0)
|
|
309
|
+
if hasattr(tweet, "public_metrics")
|
|
310
|
+
else 0,
|
|
311
|
+
"reply_count": tweet.public_metrics.get("reply_count", 0)
|
|
312
|
+
if hasattr(tweet, "public_metrics")
|
|
313
|
+
else 0,
|
|
314
|
+
"like_count": tweet.public_metrics.get("like_count", 0)
|
|
315
|
+
if hasattr(tweet, "public_metrics")
|
|
316
|
+
else 0,
|
|
317
|
+
"quote_count": tweet.public_metrics.get("quote_count", 0)
|
|
318
|
+
if hasattr(tweet, "public_metrics")
|
|
319
|
+
else 0,
|
|
320
|
+
}
|
|
321
|
+
tweets.append(post_data)
|
|
322
|
+
|
|
323
|
+
log_info(f"Successfully found {len(tweets)} posts for query: {query}")
|
|
324
|
+
result = {"query": query, "count": len(tweets), "posts": tweets}
|
|
325
|
+
else:
|
|
326
|
+
log_info(f"No posts found for query: {query}")
|
|
327
|
+
result = {}
|
|
328
|
+
return json.dumps(result, indent=2)
|
|
329
|
+
|
|
330
|
+
except tweepy.TweepyException as e:
|
|
331
|
+
logger.error(f"Error searching posts: {e}")
|
|
332
|
+
return json.dumps({"error": str(e), "query": query})
|
|
333
|
+
except Exception as e:
|
|
334
|
+
logger.error(f"Unexpected error searching posts: {e}")
|
|
335
|
+
return json.dumps({"error": f"An unexpected error occurred: {str(e)}", "query": query})
|
agno/tools/yfinance.py
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import json
|
|
2
|
+
from typing import Any, List, Optional
|
|
2
3
|
|
|
3
4
|
from agno.tools import Toolkit
|
|
5
|
+
from agno.utils.log import log_debug
|
|
4
6
|
|
|
5
7
|
try:
|
|
6
8
|
import yfinance as yf
|
|
@@ -9,39 +11,29 @@ except ImportError:
|
|
|
9
11
|
|
|
10
12
|
|
|
11
13
|
class YFinanceTools(Toolkit):
|
|
14
|
+
"""
|
|
15
|
+
YFinanceTools is a toolkit for getting financial data from Yahoo Finance.
|
|
16
|
+
Includes all available financial data tools.
|
|
17
|
+
"""
|
|
18
|
+
|
|
12
19
|
def __init__(
|
|
13
20
|
self,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
stock_fundamentals: bool = False,
|
|
17
|
-
income_statements: bool = False,
|
|
18
|
-
key_financial_ratios: bool = False,
|
|
19
|
-
analyst_recommendations: bool = False,
|
|
20
|
-
company_news: bool = False,
|
|
21
|
-
technical_indicators: bool = False,
|
|
22
|
-
historical_prices: bool = False,
|
|
23
|
-
enable_all: bool = False,
|
|
21
|
+
session: Optional[Any] = None,
|
|
22
|
+
**kwargs,
|
|
24
23
|
):
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
self.
|
|
29
|
-
|
|
30
|
-
self.
|
|
31
|
-
|
|
32
|
-
self.
|
|
33
|
-
|
|
34
|
-
self.
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
self.register(self.get_analyst_recommendations)
|
|
39
|
-
if company_news or enable_all:
|
|
40
|
-
self.register(self.get_company_news)
|
|
41
|
-
if technical_indicators or enable_all:
|
|
42
|
-
self.register(self.get_technical_indicators)
|
|
43
|
-
if historical_prices or enable_all:
|
|
44
|
-
self.register(self.get_historical_stock_prices)
|
|
24
|
+
tools: List[Any] = [
|
|
25
|
+
self.get_current_stock_price,
|
|
26
|
+
self.get_company_info,
|
|
27
|
+
self.get_stock_fundamentals,
|
|
28
|
+
self.get_income_statements,
|
|
29
|
+
self.get_key_financial_ratios,
|
|
30
|
+
self.get_analyst_recommendations,
|
|
31
|
+
self.get_company_news,
|
|
32
|
+
self.get_technical_indicators,
|
|
33
|
+
self.get_historical_stock_prices,
|
|
34
|
+
]
|
|
35
|
+
self.session = session
|
|
36
|
+
super().__init__(name="yfinance_tools", tools=tools, **kwargs)
|
|
45
37
|
|
|
46
38
|
def get_current_stock_price(self, symbol: str) -> str:
|
|
47
39
|
"""
|
|
@@ -54,7 +46,8 @@ class YFinanceTools(Toolkit):
|
|
|
54
46
|
str: The current stock price or error message.
|
|
55
47
|
"""
|
|
56
48
|
try:
|
|
57
|
-
|
|
49
|
+
log_debug(f"Fetching current price for {symbol}")
|
|
50
|
+
stock = yf.Ticker(symbol, session=self.session)
|
|
58
51
|
# Use "regularMarketPrice" for regular market hours, or "currentPrice" for pre/post market
|
|
59
52
|
current_price = stock.info.get("regularMarketPrice", stock.info.get("currentPrice"))
|
|
60
53
|
return f"{current_price:.4f}" if current_price else f"Could not fetch current price for {symbol}"
|
|
@@ -71,10 +64,12 @@ class YFinanceTools(Toolkit):
|
|
|
71
64
|
str: JSON containing company profile and overview.
|
|
72
65
|
"""
|
|
73
66
|
try:
|
|
74
|
-
company_info_full = yf.Ticker(symbol).info
|
|
67
|
+
company_info_full = yf.Ticker(symbol, session=self.session).info
|
|
75
68
|
if company_info_full is None:
|
|
76
69
|
return f"Could not fetch company info for {symbol}"
|
|
77
70
|
|
|
71
|
+
log_debug(f"Fetching company info for {symbol}")
|
|
72
|
+
|
|
78
73
|
company_info_cleaned = {
|
|
79
74
|
"Name": company_info_full.get("shortName"),
|
|
80
75
|
"Symbol": company_info_full.get("symbol"),
|
|
@@ -125,7 +120,8 @@ class YFinanceTools(Toolkit):
|
|
|
125
120
|
str: The current stock price or error message.
|
|
126
121
|
"""
|
|
127
122
|
try:
|
|
128
|
-
|
|
123
|
+
log_debug(f"Fetching historical prices for {symbol}")
|
|
124
|
+
stock = yf.Ticker(symbol, session=self.session)
|
|
129
125
|
historical_price = stock.history(period=period, interval=interval)
|
|
130
126
|
return historical_price.to_json(orient="index")
|
|
131
127
|
except Exception as e:
|
|
@@ -154,7 +150,8 @@ class YFinanceTools(Toolkit):
|
|
|
154
150
|
- '52_week_low': The 52-week low price of the stock.
|
|
155
151
|
"""
|
|
156
152
|
try:
|
|
157
|
-
|
|
153
|
+
log_debug(f"Fetching fundamentals for {symbol}")
|
|
154
|
+
stock = yf.Ticker(symbol, session=self.session)
|
|
158
155
|
info = stock.info
|
|
159
156
|
fundamentals = {
|
|
160
157
|
"symbol": symbol,
|
|
@@ -184,7 +181,8 @@ class YFinanceTools(Toolkit):
|
|
|
184
181
|
dict: JSON containing income statements or an empty dictionary.
|
|
185
182
|
"""
|
|
186
183
|
try:
|
|
187
|
-
|
|
184
|
+
log_debug(f"Fetching income statements for {symbol}")
|
|
185
|
+
stock = yf.Ticker(symbol, session=self.session)
|
|
188
186
|
financials = stock.financials
|
|
189
187
|
return financials.to_json(orient="index")
|
|
190
188
|
except Exception as e:
|
|
@@ -200,7 +198,8 @@ class YFinanceTools(Toolkit):
|
|
|
200
198
|
dict: JSON containing key financial ratios.
|
|
201
199
|
"""
|
|
202
200
|
try:
|
|
203
|
-
|
|
201
|
+
log_debug(f"Fetching key financial ratios for {symbol}")
|
|
202
|
+
stock = yf.Ticker(symbol, session=self.session)
|
|
204
203
|
key_ratios = stock.info
|
|
205
204
|
return json.dumps(key_ratios, indent=2)
|
|
206
205
|
except Exception as e:
|
|
@@ -216,7 +215,8 @@ class YFinanceTools(Toolkit):
|
|
|
216
215
|
str: JSON containing analyst recommendations.
|
|
217
216
|
"""
|
|
218
217
|
try:
|
|
219
|
-
|
|
218
|
+
log_debug(f"Fetching analyst recommendations for {symbol}")
|
|
219
|
+
stock = yf.Ticker(symbol, session=self.session)
|
|
220
220
|
recommendations = stock.recommendations
|
|
221
221
|
return recommendations.to_json(orient="index")
|
|
222
222
|
except Exception as e:
|
|
@@ -233,7 +233,8 @@ class YFinanceTools(Toolkit):
|
|
|
233
233
|
str: JSON containing company news and press releases.
|
|
234
234
|
"""
|
|
235
235
|
try:
|
|
236
|
-
news
|
|
236
|
+
log_debug(f"Fetching company news for {symbol}")
|
|
237
|
+
news = yf.Ticker(symbol, session=self.session).news
|
|
237
238
|
return json.dumps(news[:num_stories], indent=2)
|
|
238
239
|
except Exception as e:
|
|
239
240
|
return f"Error fetching company news for {symbol}: {e}"
|
|
@@ -250,7 +251,8 @@ class YFinanceTools(Toolkit):
|
|
|
250
251
|
str: JSON containing technical indicators.
|
|
251
252
|
"""
|
|
252
253
|
try:
|
|
253
|
-
indicators
|
|
254
|
+
log_debug(f"Fetching technical indicators for {symbol}")
|
|
255
|
+
indicators = yf.Ticker(symbol, session=self.session).history(period=period)
|
|
254
256
|
return indicators.to_json(orient="index")
|
|
255
257
|
except Exception as e:
|
|
256
258
|
return f"Error fetching technical indicators for {symbol}: {e}"
|
agno/tools/youtube.py
CHANGED
|
@@ -4,6 +4,7 @@ from urllib.parse import parse_qs, urlencode, urlparse
|
|
|
4
4
|
from urllib.request import urlopen
|
|
5
5
|
|
|
6
6
|
from agno.tools import Toolkit
|
|
7
|
+
from agno.utils.log import log_debug
|
|
7
8
|
|
|
8
9
|
try:
|
|
9
10
|
from youtube_transcript_api import YouTubeTranscriptApi
|
|
@@ -16,22 +17,26 @@ except ImportError:
|
|
|
16
17
|
class YouTubeTools(Toolkit):
|
|
17
18
|
def __init__(
|
|
18
19
|
self,
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
enable_get_video_captions: bool = True,
|
|
21
|
+
enable_get_video_data: bool = True,
|
|
22
|
+
enable_get_video_timestamps: bool = True,
|
|
23
|
+
all: bool = False,
|
|
22
24
|
languages: Optional[List[str]] = None,
|
|
23
25
|
proxies: Optional[Dict[str, Any]] = None,
|
|
26
|
+
**kwargs,
|
|
24
27
|
):
|
|
25
|
-
super().__init__(name="youtube_tools")
|
|
26
|
-
|
|
27
28
|
self.languages: Optional[List[str]] = languages
|
|
28
29
|
self.proxies: Optional[Dict[str, Any]] = proxies
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if
|
|
32
|
-
|
|
33
|
-
if
|
|
34
|
-
|
|
30
|
+
|
|
31
|
+
tools: List[Any] = []
|
|
32
|
+
if all or enable_get_video_captions:
|
|
33
|
+
tools.append(self.get_youtube_video_captions)
|
|
34
|
+
if all or enable_get_video_data:
|
|
35
|
+
tools.append(self.get_youtube_video_data)
|
|
36
|
+
if all or enable_get_video_timestamps:
|
|
37
|
+
tools.append(self.get_video_timestamps)
|
|
38
|
+
|
|
39
|
+
super().__init__(name="youtube_tools", tools=tools, **kwargs)
|
|
35
40
|
|
|
36
41
|
def get_youtube_video_id(self, url: str) -> Optional[str]:
|
|
37
42
|
"""Function to get the video ID from a YouTube URL.
|
|
@@ -70,6 +75,8 @@ class YouTubeTools(Toolkit):
|
|
|
70
75
|
if not url:
|
|
71
76
|
return "No URL provided"
|
|
72
77
|
|
|
78
|
+
log_debug(f"Getting video data for youtube video: {url}")
|
|
79
|
+
|
|
73
80
|
try:
|
|
74
81
|
video_id = self.get_youtube_video_id(url)
|
|
75
82
|
except Exception:
|
|
@@ -112,6 +119,8 @@ class YouTubeTools(Toolkit):
|
|
|
112
119
|
if not url:
|
|
113
120
|
return "No URL provided"
|
|
114
121
|
|
|
122
|
+
log_debug(f"Getting captions for youtube video: {url}")
|
|
123
|
+
|
|
115
124
|
try:
|
|
116
125
|
video_id = self.get_youtube_video_id(url)
|
|
117
126
|
except Exception:
|
|
@@ -124,12 +133,15 @@ class YouTubeTools(Toolkit):
|
|
|
124
133
|
kwargs["languages"] = self.languages or ["en"]
|
|
125
134
|
if self.proxies:
|
|
126
135
|
kwargs["proxies"] = self.proxies
|
|
127
|
-
|
|
128
|
-
|
|
136
|
+
if video_id is not None:
|
|
137
|
+
captions = YouTubeTranscriptApi().fetch(video_id, **kwargs)
|
|
138
|
+
else:
|
|
139
|
+
return "No video ID found"
|
|
129
140
|
if captions:
|
|
130
|
-
return " ".join(line
|
|
141
|
+
return " ".join(line.text for line in captions)
|
|
131
142
|
return "No captions found for video"
|
|
132
143
|
except Exception as e:
|
|
144
|
+
# log_info(f"Error getting captions for video {video_id}: {e}")
|
|
133
145
|
return f"Error getting captions for video: {e}"
|
|
134
146
|
|
|
135
147
|
def get_video_timestamps(self, url: str) -> str:
|
|
@@ -144,11 +156,16 @@ class YouTubeTools(Toolkit):
|
|
|
144
156
|
if not url:
|
|
145
157
|
return "No URL provided"
|
|
146
158
|
|
|
159
|
+
log_debug(f"Getting timestamps for youtube video: {url}")
|
|
160
|
+
|
|
147
161
|
try:
|
|
148
162
|
video_id = self.get_youtube_video_id(url)
|
|
149
163
|
except Exception:
|
|
150
164
|
return "Error getting video ID from URL, please provide a valid YouTube url"
|
|
151
165
|
|
|
166
|
+
if video_id is None:
|
|
167
|
+
return "No video ID found"
|
|
168
|
+
|
|
152
169
|
try:
|
|
153
170
|
kwargs: Dict = {}
|
|
154
171
|
if self.languages:
|
|
@@ -156,12 +173,12 @@ class YouTubeTools(Toolkit):
|
|
|
156
173
|
if self.proxies:
|
|
157
174
|
kwargs["proxies"] = self.proxies
|
|
158
175
|
|
|
159
|
-
captions = YouTubeTranscriptApi.
|
|
176
|
+
captions = YouTubeTranscriptApi().fetch(video_id, **kwargs)
|
|
160
177
|
timestamps = []
|
|
161
178
|
for line in captions:
|
|
162
|
-
start = int(line
|
|
179
|
+
start = int(line.start)
|
|
163
180
|
minutes, seconds = divmod(start, 60)
|
|
164
|
-
timestamps.append(f"{minutes}:{seconds:02d} - {line
|
|
181
|
+
timestamps.append(f"{minutes}:{seconds:02d} - {line.text}")
|
|
165
182
|
return "\n".join(timestamps)
|
|
166
183
|
except Exception as e:
|
|
167
184
|
return f"Error generating timestamps: {e}"
|
agno/tools/zendesk.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import re
|
|
3
3
|
from os import getenv
|
|
4
|
-
from typing import Optional
|
|
4
|
+
from typing import Any, List, Optional
|
|
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
|
try:
|
|
10
10
|
import requests
|
|
@@ -23,6 +23,9 @@ class ZendeskTools(Toolkit):
|
|
|
23
23
|
username: Optional[str] = None,
|
|
24
24
|
password: Optional[str] = None,
|
|
25
25
|
company_name: Optional[str] = None,
|
|
26
|
+
enable_search_zendesk: bool = True,
|
|
27
|
+
all: bool = False,
|
|
28
|
+
**kwargs,
|
|
26
29
|
):
|
|
27
30
|
"""
|
|
28
31
|
Initializes the ZendeskTools class with necessary authentication details
|
|
@@ -32,16 +35,21 @@ class ZendeskTools(Toolkit):
|
|
|
32
35
|
username (str): The username for Zendesk API authentication.
|
|
33
36
|
password (str): The password for Zendesk API authentication.
|
|
34
37
|
company_name (str): The company name to form the base URL for API requests.
|
|
38
|
+
enable_search_zendesk (bool): Whether to enable the search functionality.
|
|
39
|
+
all (bool): Enable all functions.
|
|
35
40
|
"""
|
|
36
|
-
super().__init__(name="zendesk_tools")
|
|
37
41
|
self.username = username or getenv("ZENDESK_USERNAME")
|
|
38
|
-
self.password = password or getenv("
|
|
42
|
+
self.password = password or getenv("ZENDESK_PASSWORD")
|
|
39
43
|
self.company_name = company_name or getenv("ZENDESK_COMPANY_NAME")
|
|
40
44
|
|
|
41
45
|
if not self.username or not self.password or not self.company_name:
|
|
42
46
|
logger.error("Username, password, or company name not provided.")
|
|
43
47
|
|
|
44
|
-
|
|
48
|
+
tools: List[Any] = []
|
|
49
|
+
if all or enable_search_zendesk:
|
|
50
|
+
tools.append(self.search_zendesk)
|
|
51
|
+
|
|
52
|
+
super().__init__(name="zendesk_tools", tools=tools, **kwargs)
|
|
45
53
|
|
|
46
54
|
def search_zendesk(self, search_string: str) -> str:
|
|
47
55
|
"""
|
|
@@ -60,6 +68,8 @@ class ZendeskTools(Toolkit):
|
|
|
60
68
|
if not self.username or not self.password or not self.company_name:
|
|
61
69
|
return "Username, password, or company name not provided."
|
|
62
70
|
|
|
71
|
+
log_debug(f"Searching Zendesk for: {search_string}")
|
|
72
|
+
|
|
63
73
|
auth = (self.username, self.password)
|
|
64
74
|
url = f"https://{self.company_name}.zendesk.com/api/v2/help_center/articles/search.json?query={search_string}"
|
|
65
75
|
try:
|