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/eleven_labs.py
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
from base64 import b64encode
|
|
2
1
|
from io import BytesIO
|
|
3
2
|
from os import getenv, path
|
|
4
3
|
from pathlib import Path
|
|
5
|
-
from typing import Iterator, Literal, Optional
|
|
4
|
+
from typing import Any, Iterator, List, Literal, Optional, Union
|
|
6
5
|
from uuid import uuid4
|
|
7
6
|
|
|
8
7
|
from agno.agent import Agent
|
|
9
|
-
from agno.media import
|
|
8
|
+
from agno.media import Audio
|
|
9
|
+
from agno.team.team import Team
|
|
10
10
|
from agno.tools import Toolkit
|
|
11
|
-
from agno.
|
|
11
|
+
from agno.tools.function import ToolResult
|
|
12
|
+
from agno.utils.log import log_error, log_info
|
|
12
13
|
|
|
13
14
|
try:
|
|
14
15
|
from elevenlabs import ElevenLabs # type: ignore
|
|
@@ -38,12 +39,15 @@ class ElevenLabsTools(Toolkit):
|
|
|
38
39
|
target_directory: Optional[str] = None,
|
|
39
40
|
model_id: str = "eleven_multilingual_v2",
|
|
40
41
|
output_format: ElevenLabsAudioOutputFormat = "mp3_44100_64",
|
|
42
|
+
enable_get_voices: bool = True,
|
|
43
|
+
enable_generate_sound_effect: bool = True,
|
|
44
|
+
enable_text_to_speech: bool = True,
|
|
45
|
+
all: bool = False,
|
|
46
|
+
**kwargs,
|
|
41
47
|
):
|
|
42
|
-
super().__init__(name="elevenlabs_tools")
|
|
43
|
-
|
|
44
48
|
self.api_key = api_key or getenv("ELEVEN_LABS_API_KEY")
|
|
45
49
|
if not self.api_key:
|
|
46
|
-
|
|
50
|
+
log_error("ELEVEN_LABS_API_KEY not set. Please set the ELEVEN_LABS_API_KEY environment variable.")
|
|
47
51
|
|
|
48
52
|
self.target_directory = target_directory
|
|
49
53
|
self.voice_id = voice_id
|
|
@@ -55,13 +59,20 @@ class ElevenLabsTools(Toolkit):
|
|
|
55
59
|
target_path.mkdir(parents=True, exist_ok=True)
|
|
56
60
|
|
|
57
61
|
self.eleven_labs_client = ElevenLabs(api_key=self.api_key)
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
|
|
63
|
+
tools: List[Any] = []
|
|
64
|
+
if all or enable_get_voices:
|
|
65
|
+
tools.append(self.get_voices)
|
|
66
|
+
if all or enable_generate_sound_effect:
|
|
67
|
+
tools.append(self.generate_sound_effect)
|
|
68
|
+
if all or enable_text_to_speech:
|
|
69
|
+
tools.append(self.text_to_speech)
|
|
70
|
+
|
|
71
|
+
super().__init__(name="elevenlabs_tools", tools=tools, **kwargs)
|
|
61
72
|
|
|
62
73
|
def get_voices(self) -> str:
|
|
63
74
|
"""
|
|
64
|
-
|
|
75
|
+
Get all the voices available.
|
|
65
76
|
|
|
66
77
|
Returns:
|
|
67
78
|
result (list): A list of voices that have an ID, name and description.
|
|
@@ -82,20 +93,19 @@ class ElevenLabsTools(Toolkit):
|
|
|
82
93
|
return str(response)
|
|
83
94
|
|
|
84
95
|
except Exception as e:
|
|
85
|
-
|
|
96
|
+
log_error(f"Failed to fetch voices: {e}")
|
|
86
97
|
return f"Error: {e}"
|
|
87
98
|
|
|
88
|
-
def _process_audio(self, audio_generator: Iterator[bytes]) ->
|
|
89
|
-
# Step 1: Write audio data to BytesIO
|
|
99
|
+
def _process_audio(self, audio_generator: Iterator[bytes]) -> bytes:
|
|
90
100
|
audio_bytes = BytesIO()
|
|
91
101
|
for chunk in audio_generator:
|
|
92
102
|
audio_bytes.write(chunk)
|
|
93
|
-
audio_bytes.seek(0) # Rewind the stream
|
|
94
103
|
|
|
95
|
-
#
|
|
96
|
-
|
|
104
|
+
# Read bytes
|
|
105
|
+
audio_bytes.seek(0)
|
|
106
|
+
audio_data = audio_bytes.read()
|
|
97
107
|
|
|
98
|
-
#
|
|
108
|
+
# Save to disk if target_directory exists
|
|
99
109
|
if self.target_directory:
|
|
100
110
|
# Determine file extension based on output format
|
|
101
111
|
if self.output_format.startswith("mp3"):
|
|
@@ -110,76 +120,77 @@ class ElevenLabsTools(Toolkit):
|
|
|
110
120
|
output_filename = f"{uuid4()}.{extension}"
|
|
111
121
|
output_path = path.join(self.target_directory, output_filename)
|
|
112
122
|
|
|
113
|
-
# Write from BytesIO to disk
|
|
114
|
-
audio_bytes.seek(0) # Reset the BytesIO stream again
|
|
115
123
|
with open(output_path, "wb") as f:
|
|
116
|
-
f.write(
|
|
124
|
+
f.write(audio_data)
|
|
117
125
|
|
|
118
|
-
|
|
126
|
+
log_info(f"Audio saved to: {output_path}")
|
|
119
127
|
|
|
120
|
-
|
|
128
|
+
return audio_data
|
|
129
|
+
|
|
130
|
+
def generate_sound_effect(self, prompt: str, duration_seconds: Optional[float] = None) -> ToolResult:
|
|
121
131
|
"""
|
|
122
|
-
|
|
132
|
+
Generate a sound effect from a text description.
|
|
123
133
|
|
|
124
134
|
Args:
|
|
125
|
-
prompt (str):
|
|
126
|
-
duration_seconds (Optional[float]): Duration in seconds to generate audio from.
|
|
135
|
+
prompt (str): Description of the sound effect
|
|
136
|
+
duration_seconds (Optional[float]): Duration in seconds to generate audio from. Has to be between 0.5 and 22.
|
|
127
137
|
Returns:
|
|
128
|
-
|
|
138
|
+
ToolResult: A ToolResult containing the generated audio or error message.
|
|
129
139
|
"""
|
|
130
140
|
try:
|
|
131
141
|
audio_generator = self.eleven_labs_client.text_to_sound_effects.convert(
|
|
132
142
|
text=prompt, duration_seconds=duration_seconds
|
|
133
143
|
)
|
|
134
144
|
|
|
135
|
-
|
|
145
|
+
audio_data = self._process_audio(audio_generator)
|
|
136
146
|
|
|
137
|
-
#
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
mime_type="audio/mpeg",
|
|
143
|
-
)
|
|
147
|
+
# Create AudioArtifact
|
|
148
|
+
audio_artifact = Audio(
|
|
149
|
+
id=str(uuid4()),
|
|
150
|
+
content=audio_data,
|
|
151
|
+
mime_type="audio/mpeg",
|
|
144
152
|
)
|
|
145
153
|
|
|
146
|
-
return
|
|
154
|
+
return ToolResult(
|
|
155
|
+
content="Sound effect generated successfully",
|
|
156
|
+
audios=[audio_artifact],
|
|
157
|
+
)
|
|
147
158
|
|
|
148
159
|
except Exception as e:
|
|
149
|
-
|
|
150
|
-
return f"Error: {e}"
|
|
160
|
+
log_error(f"Failed to generate sound effect: {e}")
|
|
161
|
+
return ToolResult(content=f"Error: {e}")
|
|
151
162
|
|
|
152
|
-
def text_to_speech(self, agent: Agent,
|
|
163
|
+
def text_to_speech(self, agent: Union[Agent, Team], prompt: str) -> ToolResult:
|
|
153
164
|
"""
|
|
154
|
-
|
|
165
|
+
Convert text to speech.
|
|
155
166
|
|
|
156
167
|
Args:
|
|
157
168
|
prompt (str): Text to generate audio from.
|
|
158
|
-
voice_id (Optional[str]): The ID of the voice to use for audio generation. Uses default if none is specified.
|
|
159
169
|
Returns:
|
|
160
|
-
|
|
170
|
+
ToolResult: A ToolResult containing the generated audio or error message.
|
|
161
171
|
"""
|
|
162
172
|
try:
|
|
163
173
|
audio_generator = self.eleven_labs_client.text_to_speech.convert(
|
|
164
174
|
text=prompt,
|
|
165
|
-
voice_id=
|
|
175
|
+
voice_id=self.voice_id,
|
|
166
176
|
model_id=self.model_id,
|
|
167
177
|
output_format=self.output_format,
|
|
168
178
|
)
|
|
169
179
|
|
|
170
|
-
|
|
180
|
+
audio_data = self._process_audio(audio_generator)
|
|
171
181
|
|
|
172
|
-
#
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
mime_type="audio/mpeg",
|
|
178
|
-
)
|
|
182
|
+
# Create AudioArtifact
|
|
183
|
+
audio_artifact = Audio(
|
|
184
|
+
id=str(uuid4()),
|
|
185
|
+
content=audio_data,
|
|
186
|
+
mime_type="audio/mpeg",
|
|
179
187
|
)
|
|
180
188
|
|
|
181
|
-
return
|
|
189
|
+
return ToolResult(
|
|
190
|
+
content="Audio generated successfully",
|
|
191
|
+
audios=[audio_artifact],
|
|
192
|
+
)
|
|
182
193
|
|
|
183
194
|
except Exception as e:
|
|
184
|
-
|
|
185
|
-
return f"Error: {e}"
|
|
195
|
+
log_error(f"Failed to generate audio: {e}")
|
|
196
|
+
return ToolResult(content=f"Error: {e}")
|
agno/tools/email.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
from typing import Optional
|
|
2
2
|
|
|
3
3
|
from agno.tools import Toolkit
|
|
4
|
-
from agno.utils.log import logger
|
|
4
|
+
from agno.utils.log import log_info, logger
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class EmailTools(Toolkit):
|
|
@@ -11,15 +11,23 @@ class EmailTools(Toolkit):
|
|
|
11
11
|
sender_name: Optional[str] = None,
|
|
12
12
|
sender_email: Optional[str] = None,
|
|
13
13
|
sender_passkey: Optional[str] = None,
|
|
14
|
+
enable_email_user: bool = True,
|
|
15
|
+
all: bool = False,
|
|
16
|
+
**kwargs,
|
|
14
17
|
):
|
|
15
|
-
super().__init__(name="email_tools")
|
|
16
18
|
self.receiver_email: Optional[str] = receiver_email
|
|
17
19
|
self.sender_name: Optional[str] = sender_name
|
|
18
20
|
self.sender_email: Optional[str] = sender_email
|
|
19
21
|
self.sender_passkey: Optional[str] = sender_passkey
|
|
20
|
-
self.register(self.email_user)
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
tools = []
|
|
24
|
+
if all or enable_email_user:
|
|
25
|
+
tools.append(self.email_user)
|
|
26
|
+
|
|
27
|
+
# Call superclass with tools list
|
|
28
|
+
super().__init__(name="email_tools", tools=tools, **kwargs)
|
|
29
|
+
|
|
30
|
+
def email_user(self, subject: str, body: str, **kwargs) -> str:
|
|
23
31
|
"""Emails the user with the given subject and body.
|
|
24
32
|
|
|
25
33
|
:param subject: The subject of the email.
|
|
@@ -48,7 +56,7 @@ class EmailTools(Toolkit):
|
|
|
48
56
|
msg["To"] = self.receiver_email
|
|
49
57
|
msg.set_content(body)
|
|
50
58
|
|
|
51
|
-
|
|
59
|
+
log_info(f"Sending Email to {self.receiver_email}")
|
|
52
60
|
try:
|
|
53
61
|
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as smtp:
|
|
54
62
|
smtp.login(self.sender_email, self.sender_passkey)
|
agno/tools/evm.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
from os import getenv
|
|
2
|
+
from typing import Optional
|
|
3
|
+
|
|
4
|
+
from agno.tools import Toolkit
|
|
5
|
+
from agno.utils.log import log_debug, log_error
|
|
6
|
+
|
|
7
|
+
try:
|
|
8
|
+
from eth_account.account import LocalAccount
|
|
9
|
+
from eth_account.datastructures import SignedTransaction
|
|
10
|
+
from hexbytes import HexBytes
|
|
11
|
+
from web3 import Web3
|
|
12
|
+
from web3.main import Web3 as Web3Type
|
|
13
|
+
from web3.providers.rpc import HTTPProvider
|
|
14
|
+
from web3.types import TxParams, TxReceipt
|
|
15
|
+
except ImportError:
|
|
16
|
+
raise ImportError("`web3` not installed. Please install using `pip install web3`")
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class EvmTools(Toolkit):
|
|
20
|
+
def __init__(
|
|
21
|
+
self,
|
|
22
|
+
private_key: Optional[str] = None,
|
|
23
|
+
rpc_url: Optional[str] = None,
|
|
24
|
+
enable_send_transaction: bool = True,
|
|
25
|
+
all: bool = False,
|
|
26
|
+
**kwargs,
|
|
27
|
+
):
|
|
28
|
+
"""Initialize EVM tools for blockchain interactions.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
private_key: Private key for signing transactions (defaults to EVM_PRIVATE_KEY env var)
|
|
32
|
+
rpc_url: RPC URL for blockchain connection (defaults to EVM_RPC_URL env var)
|
|
33
|
+
**kwargs: Additional arguments passed to parent Toolkit class
|
|
34
|
+
"""
|
|
35
|
+
|
|
36
|
+
self.private_key = private_key or getenv("EVM_PRIVATE_KEY")
|
|
37
|
+
self.rpc_url = rpc_url or getenv("EVM_RPC_URL")
|
|
38
|
+
|
|
39
|
+
if not self.private_key:
|
|
40
|
+
log_error("Private Key is required")
|
|
41
|
+
raise ValueError("Private Key is required")
|
|
42
|
+
if not self.rpc_url:
|
|
43
|
+
log_error("RPC Url is needed to interact with EVM blockchain")
|
|
44
|
+
raise ValueError("RPC Url is needed to interact with EVM blockchain")
|
|
45
|
+
|
|
46
|
+
# Ensure private key has 0x prefix
|
|
47
|
+
if not self.private_key.startswith("0x"):
|
|
48
|
+
self.private_key = f"0x{self.private_key}"
|
|
49
|
+
|
|
50
|
+
# Initialize Web3 client and account
|
|
51
|
+
self.web3_client: "Web3Type" = Web3(HTTPProvider(self.rpc_url))
|
|
52
|
+
self.account: "LocalAccount" = self.web3_client.eth.account.from_key(self.private_key)
|
|
53
|
+
log_debug(f"Your wallet address is: {self.account.address}")
|
|
54
|
+
|
|
55
|
+
tools = []
|
|
56
|
+
if all or enable_send_transaction:
|
|
57
|
+
tools.append(self.send_transaction)
|
|
58
|
+
|
|
59
|
+
super().__init__(name="evm_tools", tools=tools, **kwargs)
|
|
60
|
+
|
|
61
|
+
def get_max_priority_fee_per_gas(self) -> int:
|
|
62
|
+
"""Get the max priority fee per gas for the transaction.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
int: The max priority fee per gas for the transaction (1 gwei)
|
|
66
|
+
"""
|
|
67
|
+
max_priority_fee_per_gas = self.web3_client.to_wei(1, "gwei")
|
|
68
|
+
return max_priority_fee_per_gas
|
|
69
|
+
|
|
70
|
+
def get_max_fee_per_gas(self, max_priority_fee_per_gas: int) -> int:
|
|
71
|
+
"""Get the max fee per gas for the transaction.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
max_priority_fee_per_gas: The max priority fee per gas
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
int: The max fee per gas for the transaction
|
|
78
|
+
"""
|
|
79
|
+
latest_block = self.web3_client.eth.get_block("latest")
|
|
80
|
+
base_fee_per_gas = latest_block.get("baseFeePerGas")
|
|
81
|
+
if base_fee_per_gas is None:
|
|
82
|
+
log_error("Base fee per gas not found in the latest block.")
|
|
83
|
+
raise ValueError("Base fee per gas not found in the latest block.")
|
|
84
|
+
max_fee_per_gas = (2 * base_fee_per_gas) + max_priority_fee_per_gas
|
|
85
|
+
return max_fee_per_gas
|
|
86
|
+
|
|
87
|
+
def send_transaction(self, to_address: str, amount_in_wei: int) -> str:
|
|
88
|
+
"""Sends a transaction to the address provided.
|
|
89
|
+
|
|
90
|
+
Args:
|
|
91
|
+
to_address: The address to which you want to send ETH
|
|
92
|
+
amount_in_wei: The amount of ETH to send in wei
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
str: The transaction hash of the transaction or error message
|
|
96
|
+
"""
|
|
97
|
+
try:
|
|
98
|
+
max_priority_fee_per_gas = self.get_max_priority_fee_per_gas()
|
|
99
|
+
max_fee_per_gas = self.get_max_fee_per_gas(max_priority_fee_per_gas)
|
|
100
|
+
|
|
101
|
+
transaction_params: "TxParams" = {
|
|
102
|
+
"from": self.account.address,
|
|
103
|
+
"to": to_address,
|
|
104
|
+
"value": amount_in_wei, # type: ignore[typeddict-item]
|
|
105
|
+
"nonce": self.web3_client.eth.get_transaction_count(self.account.address),
|
|
106
|
+
"gas": 21000,
|
|
107
|
+
"maxFeePerGas": max_fee_per_gas, # type: ignore[typeddict-item]
|
|
108
|
+
"maxPriorityFeePerGas": max_priority_fee_per_gas, # type: ignore[typeddict-item]
|
|
109
|
+
"chainId": self.web3_client.eth.chain_id,
|
|
110
|
+
"type": 2, # EIP-1559 dynamic fee transaction
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
signed_transaction: "SignedTransaction" = self.web3_client.eth.account.sign_transaction(
|
|
114
|
+
transaction_params, self.private_key
|
|
115
|
+
)
|
|
116
|
+
transaction_hash: "HexBytes" = self.web3_client.eth.send_raw_transaction(signed_transaction.raw_transaction)
|
|
117
|
+
log_debug(f"Ongoing Transaction hash: 0x{transaction_hash.hex()}")
|
|
118
|
+
|
|
119
|
+
transaction_receipt: "TxReceipt" = self.web3_client.eth.wait_for_transaction_receipt(transaction_hash)
|
|
120
|
+
if transaction_receipt.get("status") == 1:
|
|
121
|
+
log_debug(f"Transaction successful! Transaction hash: 0x{transaction_hash.hex()}")
|
|
122
|
+
return f"0x{transaction_hash.hex()}"
|
|
123
|
+
else:
|
|
124
|
+
log_error("Transaction failed!")
|
|
125
|
+
raise Exception("Transaction failed!")
|
|
126
|
+
|
|
127
|
+
except Exception as e:
|
|
128
|
+
log_error(f"Error sending transaction: {e}")
|
|
129
|
+
return f"error: {e}"
|