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/apify.py
CHANGED
|
@@ -1,121 +1,314 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import string
|
|
1
3
|
from os import getenv
|
|
2
|
-
from typing import List, Optional
|
|
4
|
+
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
5
|
+
|
|
6
|
+
import requests
|
|
3
7
|
|
|
4
8
|
from agno.tools import Toolkit
|
|
5
|
-
from agno.utils.log import logger
|
|
9
|
+
from agno.utils.log import log_info, logger
|
|
6
10
|
|
|
7
11
|
try:
|
|
8
12
|
from apify_client import ApifyClient
|
|
9
13
|
except ImportError:
|
|
10
|
-
raise ImportError("`
|
|
14
|
+
raise ImportError("`apify-client` not installed. Please install using `pip install apify-client`")
|
|
11
15
|
|
|
12
16
|
|
|
13
17
|
class ApifyTools(Toolkit):
|
|
14
|
-
def __init__(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
super().__init__(name="apify_tools")
|
|
21
|
-
|
|
22
|
-
self.api_key = api_key or getenv("MY_APIFY_TOKEN")
|
|
23
|
-
if not self.api_key:
|
|
24
|
-
logger.error("No Apify API key provided")
|
|
25
|
-
|
|
26
|
-
if website_content_crawler:
|
|
27
|
-
self.register(self.website_content_crawler)
|
|
28
|
-
if web_scraper:
|
|
29
|
-
self.register(self.web_scrapper)
|
|
30
|
-
|
|
31
|
-
def website_content_crawler(self, urls: List[str], timeout: Optional[int] = 60) -> str:
|
|
18
|
+
def __init__(self, actors: Optional[Union[str, List[str]]] = None, apify_api_token: Optional[str] = None):
|
|
19
|
+
"""Initialize ApifyTools with specific Actors.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
actors (Optional[Union[str, List[str]]]): Single Actor ID as string or list of Actor IDs to register as individual tools
|
|
23
|
+
apify_api_token (Optional[str]): Apify API token (defaults to APIFY_API_TOKEN env variable)
|
|
32
24
|
"""
|
|
33
|
-
|
|
25
|
+
# Get API token from args or environment
|
|
26
|
+
self.apify_api_token = apify_api_token or getenv("APIFY_API_TOKEN")
|
|
27
|
+
if not self.apify_api_token:
|
|
28
|
+
raise ValueError("APIFY_API_TOKEN environment variable or apify_api_token parameter must be set")
|
|
29
|
+
|
|
30
|
+
self.client = create_apify_client(self.apify_api_token)
|
|
31
|
+
|
|
32
|
+
tools: List[Any] = []
|
|
33
|
+
if actors:
|
|
34
|
+
actor_list = [actors] if isinstance(actors, str) else actors
|
|
35
|
+
for actor_id in actor_list:
|
|
36
|
+
tools.append(actor_id)
|
|
37
|
+
|
|
38
|
+
super().__init__(name="ApifyTools", tools=[], auto_register=False)
|
|
39
|
+
|
|
40
|
+
for actor_id in tools:
|
|
41
|
+
self.register_actor(actor_id)
|
|
34
42
|
|
|
35
|
-
|
|
36
|
-
|
|
43
|
+
def register_actor(self, actor_id: str) -> None:
|
|
44
|
+
"""Register an Apify Actor as a function in the toolkit.
|
|
37
45
|
|
|
38
|
-
:
|
|
46
|
+
Args:
|
|
47
|
+
actor_id (str): ID of the Apify Actor to register (e.g., 'apify/web-scraper')
|
|
39
48
|
"""
|
|
40
|
-
|
|
41
|
-
|
|
49
|
+
try:
|
|
50
|
+
# Get actor metadata
|
|
51
|
+
build = get_actor_latest_build(self.client, actor_id)
|
|
52
|
+
tool_name = actor_id_to_tool_name(actor_id)
|
|
53
|
+
|
|
54
|
+
# Get actor description
|
|
55
|
+
actor_description = build.get("actorDefinition", {}).get("description", "")
|
|
56
|
+
if len(actor_description) > MAX_DESCRIPTION_LEN:
|
|
57
|
+
actor_description = actor_description[:MAX_DESCRIPTION_LEN] + "...(TRUNCATED, TOO LONG)"
|
|
58
|
+
|
|
59
|
+
# Get input schema
|
|
60
|
+
actor_input = build.get("actorDefinition", {}).get("input")
|
|
61
|
+
if not actor_input:
|
|
62
|
+
raise ValueError(f"Input schema not found in the Actor build for Actor: {actor_id}")
|
|
63
|
+
|
|
64
|
+
properties, required = prune_actor_input_schema(actor_input)
|
|
65
|
+
|
|
66
|
+
# Create a wrapper function that calls the Actor
|
|
67
|
+
def actor_function(**kwargs) -> str:
|
|
68
|
+
"""Actor function wrapper."""
|
|
69
|
+
try:
|
|
70
|
+
# Params are nested under 'kwargs' key
|
|
71
|
+
if len(kwargs) == 1 and "kwargs" in kwargs:
|
|
72
|
+
kwargs = kwargs["kwargs"]
|
|
73
|
+
|
|
74
|
+
log_info(f"Running Apify Actor {actor_id} with parameters: {kwargs}")
|
|
75
|
+
|
|
76
|
+
# Run the Actor directly with the client
|
|
77
|
+
details = self.client.actor(actor_id=actor_id).call(run_input=kwargs)
|
|
78
|
+
if details is None:
|
|
79
|
+
error_msg = (
|
|
80
|
+
f"Actor: {actor_id} was not started properly and details about the run were not returned"
|
|
81
|
+
)
|
|
82
|
+
raise ValueError(error_msg)
|
|
83
|
+
|
|
84
|
+
run_id = details.get("id")
|
|
85
|
+
if run_id is None:
|
|
86
|
+
error_msg = f"Run ID not found in the run details for Actor: {actor_id}"
|
|
87
|
+
raise ValueError(error_msg)
|
|
88
|
+
|
|
89
|
+
# Get the results
|
|
90
|
+
run = self.client.run(run_id=run_id)
|
|
91
|
+
results = run.dataset().list_items(clean=True).items
|
|
92
|
+
|
|
93
|
+
return json.dumps(results)
|
|
94
|
+
|
|
95
|
+
except Exception as e:
|
|
96
|
+
error_msg = f"Error running Apify Actor {actor_id}: {str(e)}"
|
|
97
|
+
logger.error(error_msg)
|
|
98
|
+
return json.dumps([{"error": error_msg}])
|
|
99
|
+
|
|
100
|
+
docstring = f"{actor_description}\n\nArgs:\n"
|
|
101
|
+
|
|
102
|
+
for param_name, param_info in properties.items():
|
|
103
|
+
param_type = param_info.get("type", "any")
|
|
104
|
+
param_desc = param_info.get("description", "No description available")
|
|
105
|
+
required_marker = "(required)" if param_name in required else "(optional)"
|
|
106
|
+
docstring += f" {param_name} ({param_type}): {required_marker} {param_desc}\n"
|
|
107
|
+
|
|
108
|
+
docstring += """
|
|
109
|
+
Returns:
|
|
110
|
+
str: JSON string containing the Actor's output dataset
|
|
111
|
+
"""
|
|
112
|
+
|
|
113
|
+
# Update function metadata
|
|
114
|
+
actor_function.__name__ = tool_name
|
|
115
|
+
actor_function.__doc__ = docstring
|
|
116
|
+
|
|
117
|
+
# Register the function with the toolkit
|
|
118
|
+
self.register(actor_function)
|
|
119
|
+
# Fix params schema
|
|
120
|
+
self.functions[tool_name].parameters = props_to_json_schema(properties, required)
|
|
121
|
+
log_info(f"Registered Apify Actor '{actor_id}' as function '{tool_name}'")
|
|
122
|
+
|
|
123
|
+
except Exception as e:
|
|
124
|
+
logger.error(f"Failed to register Apify Actor '{actor_id}': {str(e)}")
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
# Constants
|
|
128
|
+
MAX_DESCRIPTION_LEN = 350
|
|
129
|
+
REQUESTS_TIMEOUT_SECS = 300
|
|
130
|
+
APIFY_API_ENDPOINT_GET_DEFAULT_BUILD = "https://api.apify.com/v2/acts/{actor_id}/builds/default"
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
# Utility functions
|
|
134
|
+
def props_to_json_schema(input_dict, required_fields=None):
|
|
135
|
+
schema: Dict[str, Any] = {"type": "object", "properties": {}, "required": required_fields or []}
|
|
136
|
+
|
|
137
|
+
def infer_array_item_type(prop):
|
|
138
|
+
type_map = {
|
|
139
|
+
"string": "string",
|
|
140
|
+
"int": "number",
|
|
141
|
+
"float": "number",
|
|
142
|
+
"dict": "object",
|
|
143
|
+
"list": "array",
|
|
144
|
+
"bool": "boolean",
|
|
145
|
+
"none": "null",
|
|
146
|
+
}
|
|
147
|
+
if prop.get("items", {}).get("type"):
|
|
148
|
+
return prop["items"]["type"]
|
|
149
|
+
if "prefill" in prop and prop["prefill"] and len(prop["prefill"]) > 0:
|
|
150
|
+
return type_map.get(type(prop["prefill"][0]).__name__.lower(), "string")
|
|
151
|
+
if "default" in prop and prop["default"] and len(prop["default"]) > 0:
|
|
152
|
+
return type_map.get(type(prop["default"][0]).__name__.lower(), "string")
|
|
153
|
+
return "string" # Fallback for arrays like searchStringsArray
|
|
154
|
+
|
|
155
|
+
for key, value in input_dict.items():
|
|
156
|
+
prop_schema: Dict[str, Any] = {}
|
|
157
|
+
prop_type = value.get("type")
|
|
158
|
+
|
|
159
|
+
if "enum" in value:
|
|
160
|
+
prop_schema["enum"] = value["enum"]
|
|
161
|
+
|
|
162
|
+
if "default" in value:
|
|
163
|
+
prop_schema["default"] = value["default"]
|
|
164
|
+
elif "prefill" in value:
|
|
165
|
+
prop_schema["default"] = value["prefill"]
|
|
166
|
+
|
|
167
|
+
if "description" in value:
|
|
168
|
+
prop_schema["description"] = value["description"]
|
|
169
|
+
|
|
170
|
+
# Handle Apify special types first
|
|
171
|
+
if prop_type == "object" and value.get("editor") == "proxy":
|
|
172
|
+
prop_schema["type"] = "object"
|
|
173
|
+
prop_schema["properties"] = {
|
|
174
|
+
"useApifyProxy": {
|
|
175
|
+
"title": "Use Apify Proxy",
|
|
176
|
+
"type": "boolean",
|
|
177
|
+
"description": "Whether to use Apify Proxy - ALWAYS SET TO TRUE.",
|
|
178
|
+
"default": True,
|
|
179
|
+
"examples": [True],
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
prop_schema["required"] = ["useApifyProxy"]
|
|
183
|
+
if "default" in value:
|
|
184
|
+
prop_schema["default"] = value["default"]
|
|
185
|
+
|
|
186
|
+
elif prop_type == "array" and value.get("editor") == "requestListSources":
|
|
187
|
+
prop_schema["type"] = "array"
|
|
188
|
+
prop_schema["items"] = {
|
|
189
|
+
"type": "object",
|
|
190
|
+
"title": "Request list source",
|
|
191
|
+
"description": "Request list source",
|
|
192
|
+
"properties": {
|
|
193
|
+
"url": {"title": "URL", "type": "string", "description": "URL of the request list source"}
|
|
194
|
+
},
|
|
195
|
+
}
|
|
42
196
|
|
|
43
|
-
|
|
44
|
-
|
|
197
|
+
elif prop_type == "array":
|
|
198
|
+
prop_schema["type"] = "array"
|
|
199
|
+
prop_schema["items"] = {
|
|
200
|
+
"type": infer_array_item_type(value),
|
|
201
|
+
"title": value.get("title", "Item"),
|
|
202
|
+
"description": "Item",
|
|
203
|
+
}
|
|
45
204
|
|
|
46
|
-
|
|
205
|
+
elif prop_type == "object":
|
|
206
|
+
prop_schema["type"] = "object"
|
|
207
|
+
if "default" in value:
|
|
208
|
+
prop_schema["default"] = value["default"]
|
|
209
|
+
prop_schema["properties"] = {}
|
|
210
|
+
for k, v in value.get("properties", value["default"]).items():
|
|
211
|
+
prop_type = v["type"] if isinstance(v, dict) else type(v).__name__.lower()
|
|
212
|
+
if prop_type == "bool":
|
|
213
|
+
prop_type = "boolean"
|
|
214
|
+
prop_schema["properties"][k] = {"type": prop_type}
|
|
47
215
|
|
|
48
|
-
|
|
216
|
+
else:
|
|
217
|
+
prop_schema["type"] = prop_type
|
|
49
218
|
|
|
50
|
-
|
|
219
|
+
schema["properties"][key] = prop_schema
|
|
51
220
|
|
|
52
|
-
|
|
221
|
+
return schema
|
|
53
222
|
|
|
54
|
-
run = client.actor("apify/website-content-crawler").call(run_input=run_input, timeout_secs=timeout)
|
|
55
223
|
|
|
56
|
-
|
|
224
|
+
def create_apify_client(token: str) -> ApifyClient:
|
|
225
|
+
"""Create an Apify client instance with a custom user-agent.
|
|
57
226
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
results += item.get("text") + "\n"
|
|
227
|
+
Args:
|
|
228
|
+
token (str): API token
|
|
61
229
|
|
|
62
|
-
|
|
230
|
+
Returns:
|
|
231
|
+
ApifyClient: Apify client instance
|
|
63
232
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
233
|
+
Raises:
|
|
234
|
+
ValueError: If the API token is not provided
|
|
235
|
+
"""
|
|
236
|
+
if not token:
|
|
237
|
+
raise ValueError("API token is required to create an Apify client.")
|
|
67
238
|
|
|
68
|
-
|
|
69
|
-
|
|
239
|
+
client = ApifyClient(token)
|
|
240
|
+
if http_client := getattr(client.http_client, "httpx_client", None):
|
|
241
|
+
http_client.headers["user-agent"] += "; Origin/agno"
|
|
242
|
+
return client
|
|
70
243
|
|
|
71
|
-
:return: The results of the scraping.
|
|
72
|
-
"""
|
|
73
|
-
if self.api_key is None:
|
|
74
|
-
return "No API key provided"
|
|
75
244
|
|
|
76
|
-
|
|
77
|
-
|
|
245
|
+
def actor_id_to_tool_name(actor_id: str) -> str:
|
|
246
|
+
"""Turn actor_id into a valid tool name.
|
|
78
247
|
|
|
79
|
-
|
|
248
|
+
Args:
|
|
249
|
+
actor_id (str): Actor ID from Apify store
|
|
80
250
|
|
|
81
|
-
|
|
251
|
+
Returns:
|
|
252
|
+
str: A valid tool name
|
|
253
|
+
"""
|
|
254
|
+
valid_chars = string.ascii_letters + string.digits + "_-"
|
|
255
|
+
return "apify_actor_" + "".join(char if char in valid_chars else "_" for char in actor_id)
|
|
82
256
|
|
|
83
|
-
formatted_urls = [{"url": url} for url in urls]
|
|
84
257
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const $ = context.jQuery;
|
|
88
|
-
const pageTitle = $('title').first().text();
|
|
89
|
-
const h1 = $('h1').first().text();
|
|
90
|
-
const first_h2 = $('h2').first().text();
|
|
91
|
-
const random_text_from_the_page = $('p').first().text();
|
|
258
|
+
def get_actor_latest_build(apify_client: ApifyClient, actor_id: str) -> Dict[str, Any]:
|
|
259
|
+
"""Get the latest build of an Actor from the default build tag.
|
|
92
260
|
|
|
93
|
-
|
|
261
|
+
Args:
|
|
262
|
+
apify_client (ApifyClient): An instance of the ApifyClient class
|
|
263
|
+
actor_id (str): Actor name from Apify store to run
|
|
94
264
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
pageTitle,
|
|
98
|
-
h1,
|
|
99
|
-
first_h2,
|
|
100
|
-
random_text_from_the_page
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
"""
|
|
265
|
+
Returns:
|
|
266
|
+
Dict[str, Any]: The latest build of the Actor
|
|
104
267
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
268
|
+
Raises:
|
|
269
|
+
ValueError: If the Actor is not found or the build data is not found
|
|
270
|
+
TypeError: If the build is not a dictionary
|
|
271
|
+
"""
|
|
272
|
+
if not (actor := apify_client.actor(actor_id).get()):
|
|
273
|
+
raise ValueError(f"Actor {actor_id} not found.")
|
|
274
|
+
|
|
275
|
+
if not (actor_obj_id := actor.get("id")):
|
|
276
|
+
raise ValueError(f"Failed to get the Actor object ID for {actor_id}.")
|
|
277
|
+
|
|
278
|
+
url = APIFY_API_ENDPOINT_GET_DEFAULT_BUILD.format(actor_id=actor_obj_id)
|
|
279
|
+
response = requests.request("GET", url, timeout=REQUESTS_TIMEOUT_SECS)
|
|
280
|
+
|
|
281
|
+
build = response.json()
|
|
282
|
+
if not isinstance(build, dict):
|
|
283
|
+
raise TypeError(f"Failed to get the latest build of the Actor {actor_id}.")
|
|
284
|
+
|
|
285
|
+
if (data := build.get("data")) is None:
|
|
286
|
+
raise ValueError(f"Failed to get the latest build data of the Actor {actor_id}.")
|
|
287
|
+
|
|
288
|
+
return data
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
def prune_actor_input_schema(input_schema: Dict[str, Any]) -> Tuple[Dict[str, Any], List[str]]:
|
|
292
|
+
"""Get the input schema from the Actor build and trim descriptions.
|
|
109
293
|
|
|
110
|
-
|
|
294
|
+
Args:
|
|
295
|
+
input_schema (Dict[str, Any]): The input schema from the Actor build
|
|
111
296
|
|
|
112
|
-
|
|
297
|
+
Returns:
|
|
298
|
+
Tuple[Dict[str, Any], List[str]]: A tuple containing the pruned properties and required fields
|
|
299
|
+
"""
|
|
300
|
+
properties = input_schema.get("properties", {})
|
|
301
|
+
required = input_schema.get("required", [])
|
|
113
302
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
303
|
+
properties_out: Dict[str, Any] = {}
|
|
304
|
+
for item, meta in properties.items():
|
|
305
|
+
properties_out[item] = {}
|
|
306
|
+
if desc := meta.get("description"):
|
|
307
|
+
properties_out[item]["description"] = (
|
|
308
|
+
desc[:MAX_DESCRIPTION_LEN] + "..." if len(desc) > MAX_DESCRIPTION_LEN else desc
|
|
309
|
+
)
|
|
310
|
+
for key_name in ("type", "default", "prefill", "enum"):
|
|
311
|
+
if value := meta.get(key_name):
|
|
312
|
+
properties_out[item][key_name] = value
|
|
120
313
|
|
|
121
|
-
|
|
314
|
+
return properties_out, required
|
|
@@ -3,7 +3,7 @@ from pathlib import Path
|
|
|
3
3
|
from typing import Any, Dict, 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, logger
|
|
7
7
|
|
|
8
8
|
try:
|
|
9
9
|
import arxiv
|
|
@@ -17,16 +17,24 @@ except ImportError:
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class ArxivTools(Toolkit):
|
|
20
|
-
def __init__(
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
enable_search_arxiv: bool = True,
|
|
23
|
+
enable_read_arxiv_papers: bool = True,
|
|
24
|
+
all: bool = False,
|
|
25
|
+
download_dir: Optional[Path] = None,
|
|
26
|
+
**kwargs,
|
|
27
|
+
):
|
|
23
28
|
self.client: arxiv.Client = arxiv.Client()
|
|
24
29
|
self.download_dir: Path = download_dir or Path(__file__).parent.joinpath("arxiv_pdfs")
|
|
25
30
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
31
|
+
tools: List[Any] = []
|
|
32
|
+
if all or enable_search_arxiv:
|
|
33
|
+
tools.append(self.search_arxiv_and_return_articles)
|
|
34
|
+
if all or enable_read_arxiv_papers:
|
|
35
|
+
tools.append(self.read_arxiv_papers)
|
|
36
|
+
|
|
37
|
+
super().__init__(name="arxiv_tools", tools=tools, **kwargs)
|
|
30
38
|
|
|
31
39
|
def search_arxiv_and_return_articles(self, query: str, num_articles: int = 10) -> str:
|
|
32
40
|
"""Use this function to search arXiv for a query and return the top articles.
|
|
@@ -39,7 +47,7 @@ class ArxivTools(Toolkit):
|
|
|
39
47
|
"""
|
|
40
48
|
|
|
41
49
|
articles = []
|
|
42
|
-
|
|
50
|
+
log_debug(f"Searching arxiv for: {query}")
|
|
43
51
|
for result in self.client.results(
|
|
44
52
|
search=arxiv.Search(
|
|
45
53
|
query=query,
|
|
@@ -83,7 +91,7 @@ class ArxivTools(Toolkit):
|
|
|
83
91
|
download_dir.mkdir(parents=True, exist_ok=True)
|
|
84
92
|
|
|
85
93
|
articles = []
|
|
86
|
-
|
|
94
|
+
log_debug(f"Searching arxiv for: {id_list}")
|
|
87
95
|
for result in self.client.results(search=arxiv.Search(id_list=id_list)):
|
|
88
96
|
try:
|
|
89
97
|
article: Dict[str, Any] = {
|
|
@@ -100,9 +108,9 @@ class ArxivTools(Toolkit):
|
|
|
100
108
|
"comment": result.comment,
|
|
101
109
|
}
|
|
102
110
|
if result.pdf_url:
|
|
103
|
-
|
|
111
|
+
log_debug(f"Downloading: {result.pdf_url}")
|
|
104
112
|
pdf_path = result.download_pdf(dirpath=str(download_dir))
|
|
105
|
-
|
|
113
|
+
log_debug(f"To: {pdf_path}")
|
|
106
114
|
pdf_reader = PdfReader(pdf_path)
|
|
107
115
|
article["content"] = []
|
|
108
116
|
for page_number, page in enumerate(pdf_reader.pages, start=1):
|
agno/tools/aws_lambda.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from typing import Any, List
|
|
2
|
+
|
|
1
3
|
from agno.tools import Toolkit
|
|
2
4
|
|
|
3
5
|
try:
|
|
@@ -7,16 +9,28 @@ except ImportError:
|
|
|
7
9
|
|
|
8
10
|
|
|
9
11
|
class AWSLambdaTools(Toolkit):
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
def __init__(
|
|
13
|
+
self,
|
|
14
|
+
region_name: str = "us-east-1",
|
|
15
|
+
enable_list_functions: bool = True,
|
|
16
|
+
enable_invoke_function: bool = True,
|
|
17
|
+
all: bool = False,
|
|
18
|
+
**kwargs,
|
|
19
|
+
):
|
|
15
20
|
self.client = boto3.client("lambda", region_name=region_name)
|
|
16
|
-
|
|
17
|
-
|
|
21
|
+
|
|
22
|
+
tools: List[Any] = []
|
|
23
|
+
if all or enable_list_functions:
|
|
24
|
+
tools.append(self.list_functions)
|
|
25
|
+
if all or enable_invoke_function:
|
|
26
|
+
tools.append(self.invoke_function)
|
|
27
|
+
|
|
28
|
+
super().__init__(name="aws-lambda", tools=tools, **kwargs)
|
|
18
29
|
|
|
19
30
|
def list_functions(self) -> str:
|
|
31
|
+
"""
|
|
32
|
+
List all AWS Lambda functions in the configured AWS account.
|
|
33
|
+
"""
|
|
20
34
|
try:
|
|
21
35
|
response = self.client.list_functions()
|
|
22
36
|
functions = [func["FunctionName"] for func in response["Functions"]]
|
|
@@ -25,6 +39,13 @@ class AWSLambdaTools(Toolkit):
|
|
|
25
39
|
return f"Error listing functions: {str(e)}"
|
|
26
40
|
|
|
27
41
|
def invoke_function(self, function_name: str, payload: str = "{}") -> str:
|
|
42
|
+
"""
|
|
43
|
+
Invoke a specific AWS Lambda function with an optional JSON payload.
|
|
44
|
+
|
|
45
|
+
Args:
|
|
46
|
+
function_name (str): The name of the Lambda function to invoke.
|
|
47
|
+
payload (str): The JSON payload to send to the function. Defaults to "{}".
|
|
48
|
+
"""
|
|
28
49
|
try:
|
|
29
50
|
response = self.client.invoke(FunctionName=function_name, Payload=payload)
|
|
30
51
|
return f"Function invoked successfully. Status code: {response['StatusCode']}, Payload: {response['Payload'].read().decode('utf-8')}"
|
agno/tools/aws_ses.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from typing import Optional
|
|
2
|
+
|
|
3
|
+
from agno.tools import Toolkit
|
|
4
|
+
from agno.utils.log import log_debug
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
import boto3
|
|
8
|
+
except ImportError:
|
|
9
|
+
raise ImportError("boto3 is required for AWSSESTool. Please install it using `pip install boto3`.")
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class AWSSESTool(Toolkit):
|
|
13
|
+
def __init__(
|
|
14
|
+
self,
|
|
15
|
+
sender_email: Optional[str] = None,
|
|
16
|
+
sender_name: Optional[str] = None,
|
|
17
|
+
region_name: str = "us-east-1",
|
|
18
|
+
enable_send_email: bool = True,
|
|
19
|
+
all: bool = False,
|
|
20
|
+
**kwargs,
|
|
21
|
+
):
|
|
22
|
+
tools = []
|
|
23
|
+
if all or enable_send_email:
|
|
24
|
+
tools.append(self.send_email)
|
|
25
|
+
super().__init__(name="aws_ses_tool", tools=tools, **kwargs)
|
|
26
|
+
self.client = boto3.client("ses", region_name=region_name)
|
|
27
|
+
self.sender_email = sender_email
|
|
28
|
+
self.sender_name = sender_name
|
|
29
|
+
|
|
30
|
+
def send_email(self, subject: str, body: str, receiver_email: str) -> str:
|
|
31
|
+
"""
|
|
32
|
+
Use this tool to send an email using AWS SES.
|
|
33
|
+
|
|
34
|
+
Args: subject: The subject of the email
|
|
35
|
+
body: The body of the email
|
|
36
|
+
receiver_email: The email address of the receiver
|
|
37
|
+
"""
|
|
38
|
+
if not self.client:
|
|
39
|
+
raise Exception("AWS SES client not initialized. Please check the configuration.")
|
|
40
|
+
if not subject:
|
|
41
|
+
return "Email subject cannot be empty."
|
|
42
|
+
if not body:
|
|
43
|
+
return "Email body cannot be empty."
|
|
44
|
+
try:
|
|
45
|
+
response = self.client.send_email(
|
|
46
|
+
Source=f"{self.sender_name} <{self.sender_email}>",
|
|
47
|
+
Destination={
|
|
48
|
+
"ToAddresses": [receiver_email],
|
|
49
|
+
},
|
|
50
|
+
Message={
|
|
51
|
+
"Body": {
|
|
52
|
+
"Text": {
|
|
53
|
+
"Charset": "UTF-8",
|
|
54
|
+
"Data": body,
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
"Subject": {
|
|
58
|
+
"Charset": "UTF-8",
|
|
59
|
+
"Data": subject,
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
)
|
|
63
|
+
log_debug(f"Email sent with message ID: {response['MessageId']}")
|
|
64
|
+
return "Email sent successfully!"
|
|
65
|
+
except Exception as e:
|
|
66
|
+
raise Exception(f"Failed to send email: {e}")
|
agno/tools/baidusearch.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
|
|
5
|
+
from agno.utils.log import log_debug
|
|
6
6
|
|
|
7
7
|
try:
|
|
8
8
|
from baidusearch.baidusearch import search # type: ignore
|
|
@@ -35,15 +35,22 @@ class BaiduSearchTools(Toolkit):
|
|
|
35
35
|
proxy: Optional[str] = None,
|
|
36
36
|
timeout: Optional[int] = 10,
|
|
37
37
|
debug: Optional[bool] = False,
|
|
38
|
+
enable_baidu_search: bool = True,
|
|
39
|
+
all: bool = False,
|
|
40
|
+
**kwargs,
|
|
38
41
|
):
|
|
39
|
-
super().__init__(name="baidusearch")
|
|
40
42
|
self.fixed_max_results = fixed_max_results
|
|
41
43
|
self.fixed_language = fixed_language
|
|
42
44
|
self.headers = headers
|
|
43
45
|
self.proxy = proxy
|
|
44
46
|
self.timeout = timeout
|
|
45
47
|
self.debug = debug
|
|
46
|
-
|
|
48
|
+
|
|
49
|
+
tools = []
|
|
50
|
+
if all or enable_baidu_search:
|
|
51
|
+
tools.append(self.baidu_search)
|
|
52
|
+
|
|
53
|
+
super().__init__(name="baidusearch", tools=tools, **kwargs)
|
|
47
54
|
|
|
48
55
|
def baidu_search(self, query: str, max_results: int = 5, language: str = "zh") -> str:
|
|
49
56
|
"""Execute Baidu search and return results
|
|
@@ -65,7 +72,7 @@ class BaiduSearchTools(Toolkit):
|
|
|
65
72
|
except LookupError:
|
|
66
73
|
language = "zh"
|
|
67
74
|
|
|
68
|
-
|
|
75
|
+
log_debug(f"Searching Baidu [{language}] for: {query}")
|
|
69
76
|
|
|
70
77
|
results = search(keyword=query, num_results=max_results)
|
|
71
78
|
|