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
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from io import BytesIO
|
|
5
|
+
from typing import Any, List, Optional
|
|
6
|
+
from uuid import uuid4
|
|
7
|
+
|
|
8
|
+
from agno.media import Image
|
|
9
|
+
from agno.tools import Toolkit
|
|
10
|
+
from agno.tools.function import ToolResult
|
|
11
|
+
from agno.utils.log import log_debug, logger
|
|
12
|
+
|
|
13
|
+
try:
|
|
14
|
+
from google import genai
|
|
15
|
+
from google.genai import types
|
|
16
|
+
from PIL import Image as PILImage
|
|
17
|
+
|
|
18
|
+
except ImportError as exc:
|
|
19
|
+
missing = []
|
|
20
|
+
try:
|
|
21
|
+
from google.genai import types
|
|
22
|
+
except ImportError:
|
|
23
|
+
missing.append("google-genai")
|
|
24
|
+
|
|
25
|
+
try:
|
|
26
|
+
from PIL import Image as PILImage
|
|
27
|
+
except ImportError:
|
|
28
|
+
missing.append("Pillow")
|
|
29
|
+
|
|
30
|
+
raise ImportError(
|
|
31
|
+
f"Missing required package(s): {', '.join(missing)}. Install using: pip install {' '.join(missing)}"
|
|
32
|
+
) from exc
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
# Note: Expand this list as new models become supported by the Google Content Generation API.
|
|
36
|
+
ALLOWED_MODELS = ["gemini-2.5-flash-image"]
|
|
37
|
+
ALLOWED_RATIOS = ["1:1", "2:3", "3:2", "3:4", "4:3", "4:5", "5:4", "9:16", "16:9", "21:9"]
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class NanoBananaTools(Toolkit):
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
model: str = "gemini-2.5-flash-image",
|
|
44
|
+
aspect_ratio: str = "1:1",
|
|
45
|
+
api_key: Optional[str] = None,
|
|
46
|
+
enable_create_image: bool = True,
|
|
47
|
+
**kwargs,
|
|
48
|
+
):
|
|
49
|
+
self.model = model
|
|
50
|
+
self.aspect_ratio = aspect_ratio
|
|
51
|
+
self.api_key = api_key or os.getenv("GOOGLE_API_KEY")
|
|
52
|
+
|
|
53
|
+
# Validate model
|
|
54
|
+
if model not in ALLOWED_MODELS:
|
|
55
|
+
raise ValueError(f"Invalid model '{model}'. Supported: {', '.join(ALLOWED_MODELS)}")
|
|
56
|
+
|
|
57
|
+
if self.aspect_ratio not in ALLOWED_RATIOS:
|
|
58
|
+
raise ValueError(f"Invalid aspect_ratio '{self.aspect_ratio}'. Supported: {', '.join(ALLOWED_RATIOS)}")
|
|
59
|
+
|
|
60
|
+
if not self.api_key:
|
|
61
|
+
raise ValueError("GOOGLE_API_KEY not set. Export it: `export GOOGLE_API_KEY=<your-key>`")
|
|
62
|
+
|
|
63
|
+
tools: List[Any] = []
|
|
64
|
+
if enable_create_image:
|
|
65
|
+
tools.append(self.create_image)
|
|
66
|
+
|
|
67
|
+
super().__init__(name="nano_banana", tools=tools, **kwargs)
|
|
68
|
+
|
|
69
|
+
def create_image(self, prompt: str) -> ToolResult:
|
|
70
|
+
"""Generate an image from a text prompt."""
|
|
71
|
+
try:
|
|
72
|
+
client = genai.Client(api_key=self.api_key)
|
|
73
|
+
log_debug(f"NanoBanana generating image with prompt: {prompt}")
|
|
74
|
+
|
|
75
|
+
cfg = types.GenerateContentConfig(
|
|
76
|
+
response_modalities=["IMAGE"],
|
|
77
|
+
image_config=types.ImageConfig(aspect_ratio=self.aspect_ratio),
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
response = client.models.generate_content(
|
|
81
|
+
model=self.model,
|
|
82
|
+
contents=[prompt], # type: ignore
|
|
83
|
+
config=cfg,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
generated_images: List[Image] = []
|
|
87
|
+
response_str = ""
|
|
88
|
+
|
|
89
|
+
if not hasattr(response, "candidates") or not response.candidates:
|
|
90
|
+
logger.warning("No candidates in response")
|
|
91
|
+
return ToolResult(content="No images were generated in the response")
|
|
92
|
+
|
|
93
|
+
# Process each candidate
|
|
94
|
+
for candidate in response.candidates:
|
|
95
|
+
if not hasattr(candidate, "content") or not candidate.content or not candidate.content.parts:
|
|
96
|
+
continue
|
|
97
|
+
|
|
98
|
+
for part in candidate.content.parts:
|
|
99
|
+
if hasattr(part, "text") and part.text:
|
|
100
|
+
response_str += part.text + "\n"
|
|
101
|
+
|
|
102
|
+
if hasattr(part, "inline_data") and part.inline_data:
|
|
103
|
+
try:
|
|
104
|
+
# Extract image data from the blob
|
|
105
|
+
image_data = part.inline_data.data
|
|
106
|
+
mime_type = getattr(part.inline_data, "mime_type", "image/png")
|
|
107
|
+
|
|
108
|
+
if image_data:
|
|
109
|
+
pil_img = PILImage.open(BytesIO(image_data))
|
|
110
|
+
|
|
111
|
+
# Save to buffer with proper format
|
|
112
|
+
buffer = BytesIO()
|
|
113
|
+
image_format = "PNG" if "png" in mime_type.lower() else "JPEG"
|
|
114
|
+
pil_img.save(buffer, format=image_format)
|
|
115
|
+
buffer.seek(0)
|
|
116
|
+
|
|
117
|
+
agno_img = Image(
|
|
118
|
+
id=str(uuid4()),
|
|
119
|
+
content=buffer.getvalue(),
|
|
120
|
+
original_prompt=prompt,
|
|
121
|
+
)
|
|
122
|
+
generated_images.append(agno_img)
|
|
123
|
+
|
|
124
|
+
log_debug(f"Successfully processed image with ID: {agno_img.id}")
|
|
125
|
+
response_str += f"Image generated successfully (ID: {agno_img.id}).\n"
|
|
126
|
+
|
|
127
|
+
except Exception as img_exc:
|
|
128
|
+
logger.error(f"Failed to process image data: {img_exc}")
|
|
129
|
+
response_str += f"Failed to process image: {img_exc}\n"
|
|
130
|
+
|
|
131
|
+
if hasattr(response, "usage_metadata") and response.usage_metadata:
|
|
132
|
+
log_debug(
|
|
133
|
+
f"Token usage - Prompt: {response.usage_metadata.prompt_token_count}, "
|
|
134
|
+
f"Response: {response.usage_metadata.candidates_token_count}, "
|
|
135
|
+
f"Total: {response.usage_metadata.total_token_count}"
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
if generated_images:
|
|
139
|
+
return ToolResult(
|
|
140
|
+
content=response_str.strip() or "Image(s) generated successfully",
|
|
141
|
+
images=generated_images,
|
|
142
|
+
)
|
|
143
|
+
else:
|
|
144
|
+
return ToolResult(
|
|
145
|
+
content=response_str.strip() or "No images were generated",
|
|
146
|
+
images=None,
|
|
147
|
+
)
|
|
148
|
+
|
|
149
|
+
except Exception as exc:
|
|
150
|
+
logger.error(f"NanoBanana image generation failed: {exc}")
|
|
151
|
+
return ToolResult(content=f"Error generating image: {str(exc)}")
|
agno/tools/neo4j.py
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from typing import Any, List, Optional
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
from neo4j import GraphDatabase
|
|
6
|
+
except ImportError:
|
|
7
|
+
raise ImportError("`neo4j` not installed. Please install using `pip install neo4j`")
|
|
8
|
+
|
|
9
|
+
from agno.tools import Toolkit
|
|
10
|
+
from agno.utils.log import log_debug, logger
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Neo4jTools(Toolkit):
|
|
14
|
+
def __init__(
|
|
15
|
+
self,
|
|
16
|
+
uri: Optional[str] = None,
|
|
17
|
+
user: Optional[str] = None,
|
|
18
|
+
password: Optional[str] = None,
|
|
19
|
+
database: Optional[str] = None,
|
|
20
|
+
# Enable flags for <6 functions
|
|
21
|
+
enable_list_labels: bool = True,
|
|
22
|
+
enable_list_relationships: bool = True,
|
|
23
|
+
enable_get_schema: bool = True,
|
|
24
|
+
enable_run_cypher: bool = True,
|
|
25
|
+
all: bool = False,
|
|
26
|
+
**kwargs,
|
|
27
|
+
):
|
|
28
|
+
"""
|
|
29
|
+
Initialize the Neo4jTools toolkit.
|
|
30
|
+
Connection parameters (uri/user/password or host/port) can be provided.
|
|
31
|
+
If not provided, falls back to NEO4J_URI, NEO4J_USERNAME, NEO4J_PASSWORD env vars.
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
uri (Optional[str]): The Neo4j URI.
|
|
35
|
+
user (Optional[str]): The Neo4j username.
|
|
36
|
+
password (Optional[str]): The Neo4j password.
|
|
37
|
+
host (Optional[str]): The Neo4j host.
|
|
38
|
+
port (Optional[int]): The Neo4j port.
|
|
39
|
+
database (Optional[str]): The Neo4j database.
|
|
40
|
+
list_labels (bool): Whether to list node labels.
|
|
41
|
+
list_relationships (bool): Whether to list relationship types.
|
|
42
|
+
get_schema (bool): Whether to get the schema.
|
|
43
|
+
run_cypher (bool): Whether to run Cypher queries.
|
|
44
|
+
**kwargs: Additional keyword arguments.
|
|
45
|
+
"""
|
|
46
|
+
# Determine the connection URI and credentials
|
|
47
|
+
uri = uri or os.getenv("NEO4J_URI", "bolt://localhost:7687")
|
|
48
|
+
user = user or os.getenv("NEO4J_USERNAME")
|
|
49
|
+
password = password or os.getenv("NEO4J_PASSWORD")
|
|
50
|
+
|
|
51
|
+
if user is None or password is None:
|
|
52
|
+
raise ValueError("Username or password for Neo4j not provided")
|
|
53
|
+
|
|
54
|
+
# Create the Neo4j driver
|
|
55
|
+
try:
|
|
56
|
+
self.driver = GraphDatabase.driver(uri, auth=(user, password)) # type: ignore
|
|
57
|
+
self.driver.verify_connectivity()
|
|
58
|
+
log_debug("Connected to Neo4j database")
|
|
59
|
+
except Exception as e:
|
|
60
|
+
logger.error(f"Failed to connect to Neo4j: {e}")
|
|
61
|
+
raise
|
|
62
|
+
|
|
63
|
+
self.database = database or "neo4j"
|
|
64
|
+
|
|
65
|
+
# Register toolkit methods as tools
|
|
66
|
+
tools: List[Any] = []
|
|
67
|
+
if all or enable_list_labels:
|
|
68
|
+
tools.append(self.list_labels)
|
|
69
|
+
if all or enable_list_relationships:
|
|
70
|
+
tools.append(self.list_relationship_types)
|
|
71
|
+
if all or enable_get_schema:
|
|
72
|
+
tools.append(self.get_schema)
|
|
73
|
+
if all or enable_run_cypher:
|
|
74
|
+
tools.append(self.run_cypher_query)
|
|
75
|
+
super().__init__(name="neo4j_tools", tools=tools, **kwargs)
|
|
76
|
+
|
|
77
|
+
def list_labels(self) -> list:
|
|
78
|
+
"""
|
|
79
|
+
Retrieve all node labels present in the connected Neo4j database.
|
|
80
|
+
"""
|
|
81
|
+
try:
|
|
82
|
+
log_debug("Listing node labels in Neo4j database")
|
|
83
|
+
with self.driver.session(database=self.database) as session:
|
|
84
|
+
result = session.run("CALL db.labels()")
|
|
85
|
+
labels = [record["label"] for record in result]
|
|
86
|
+
return labels
|
|
87
|
+
except Exception as e:
|
|
88
|
+
logger.error(f"Error listing labels: {e}")
|
|
89
|
+
return []
|
|
90
|
+
|
|
91
|
+
def list_relationship_types(self) -> list:
|
|
92
|
+
"""
|
|
93
|
+
Retrieve all relationship types present in the connected Neo4j database.
|
|
94
|
+
"""
|
|
95
|
+
try:
|
|
96
|
+
log_debug("Listing relationship types in Neo4j database")
|
|
97
|
+
with self.driver.session(database=self.database) as session:
|
|
98
|
+
result = session.run("CALL db.relationshipTypes()")
|
|
99
|
+
types = [record["relationshipType"] for record in result]
|
|
100
|
+
return types
|
|
101
|
+
except Exception as e:
|
|
102
|
+
logger.error(f"Error listing relationship types: {e}")
|
|
103
|
+
return []
|
|
104
|
+
|
|
105
|
+
def get_schema(self) -> list:
|
|
106
|
+
"""
|
|
107
|
+
Retrieve a visualization of the database schema, including nodes and relationships.
|
|
108
|
+
"""
|
|
109
|
+
try:
|
|
110
|
+
log_debug("Retrieving Neo4j schema visualization")
|
|
111
|
+
with self.driver.session(database=self.database) as session:
|
|
112
|
+
result = session.run("CALL db.schema.visualization()")
|
|
113
|
+
schema_data = result.data()
|
|
114
|
+
return schema_data
|
|
115
|
+
except Exception as e:
|
|
116
|
+
logger.error(f"Error getting Neo4j schema: {e}")
|
|
117
|
+
return []
|
|
118
|
+
|
|
119
|
+
def run_cypher_query(self, query: str) -> list:
|
|
120
|
+
"""
|
|
121
|
+
Execute an arbitrary Cypher query against the connected Neo4j database.
|
|
122
|
+
|
|
123
|
+
Args:
|
|
124
|
+
query (str): The Cypher query string to execute.
|
|
125
|
+
"""
|
|
126
|
+
try:
|
|
127
|
+
log_debug(f"Running Cypher query: {query}")
|
|
128
|
+
with self.driver.session(database=self.database) as session:
|
|
129
|
+
result = session.run(query) # type: ignore[arg-type]
|
|
130
|
+
data = result.data()
|
|
131
|
+
return data
|
|
132
|
+
except Exception as e:
|
|
133
|
+
logger.error(f"Error running Cypher query: {e}")
|
|
134
|
+
return []
|
agno/tools/newspaper.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from agno.tools import Toolkit
|
|
2
|
+
from agno.utils.log import log_debug
|
|
2
3
|
|
|
3
4
|
try:
|
|
4
5
|
from newspaper import Article
|
|
@@ -7,14 +8,23 @@ except ImportError:
|
|
|
7
8
|
|
|
8
9
|
|
|
9
10
|
class NewspaperTools(Toolkit):
|
|
11
|
+
"""
|
|
12
|
+
Newspaper is a tool for getting the text of an article from a URL.
|
|
13
|
+
Args:
|
|
14
|
+
get_article_text (bool): Whether to get the text of an article from a URL.
|
|
15
|
+
"""
|
|
16
|
+
|
|
10
17
|
def __init__(
|
|
11
18
|
self,
|
|
12
|
-
|
|
19
|
+
enable_get_article_text: bool = True,
|
|
20
|
+
all: bool = False,
|
|
21
|
+
**kwargs,
|
|
13
22
|
):
|
|
14
|
-
|
|
23
|
+
tools = []
|
|
24
|
+
if all or enable_get_article_text:
|
|
25
|
+
tools.append(self.get_article_text)
|
|
15
26
|
|
|
16
|
-
|
|
17
|
-
self.register(self.get_article_text)
|
|
27
|
+
super().__init__(name="newspaper_toolkit", tools=tools, **kwargs)
|
|
18
28
|
|
|
19
29
|
def get_article_text(self, url: str) -> str:
|
|
20
30
|
"""Get the text of an article from a URL.
|
|
@@ -27,6 +37,7 @@ class NewspaperTools(Toolkit):
|
|
|
27
37
|
"""
|
|
28
38
|
|
|
29
39
|
try:
|
|
40
|
+
log_debug(f"Reading news: {url}")
|
|
30
41
|
article = Article(url)
|
|
31
42
|
article.download()
|
|
32
43
|
article.parse()
|
agno/tools/newspaper4k.py
CHANGED
|
@@ -2,7 +2,7 @@ import json
|
|
|
2
2
|
from typing import Any, Dict, Optional
|
|
3
3
|
|
|
4
4
|
from agno.tools import Toolkit
|
|
5
|
-
from agno.utils.log import logger
|
|
5
|
+
from agno.utils.log import log_debug, logger
|
|
6
6
|
|
|
7
7
|
try:
|
|
8
8
|
import newspaper
|
|
@@ -11,18 +11,30 @@ except ImportError:
|
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class Newspaper4kTools(Toolkit):
|
|
14
|
+
"""
|
|
15
|
+
Newspaper4kTools is a toolkit for getting the text of an article from a URL.
|
|
16
|
+
Args:
|
|
17
|
+
enable_read_article (bool): Whether to read an article from a URL.
|
|
18
|
+
include_summary (bool): Whether to include the summary of an article.
|
|
19
|
+
article_length (Optional[int]): The length of the article to read.
|
|
20
|
+
"""
|
|
21
|
+
|
|
14
22
|
def __init__(
|
|
15
23
|
self,
|
|
16
|
-
read_article: bool = True,
|
|
17
24
|
include_summary: bool = False,
|
|
18
25
|
article_length: Optional[int] = None,
|
|
26
|
+
enable_read_article: bool = True,
|
|
27
|
+
all: bool = False,
|
|
28
|
+
**kwargs,
|
|
19
29
|
):
|
|
20
|
-
super().__init__(name="newspaper_tools")
|
|
21
|
-
|
|
22
30
|
self.include_summary: bool = include_summary
|
|
23
31
|
self.article_length: Optional[int] = article_length
|
|
24
|
-
|
|
25
|
-
|
|
32
|
+
|
|
33
|
+
tools = []
|
|
34
|
+
if all or enable_read_article:
|
|
35
|
+
tools.append(self.read_article)
|
|
36
|
+
|
|
37
|
+
super().__init__(name="newspaper4k_tools", tools=tools, **kwargs)
|
|
26
38
|
|
|
27
39
|
def get_article_data(self, url: str) -> Optional[Dict[str, Any]]:
|
|
28
40
|
"""Read and get article data from a URL.
|
|
@@ -68,6 +80,7 @@ class Newspaper4kTools(Toolkit):
|
|
|
68
80
|
"""
|
|
69
81
|
|
|
70
82
|
try:
|
|
83
|
+
log_debug(f"Reading news: {url}")
|
|
71
84
|
article_data = self.get_article_data(url)
|
|
72
85
|
if not article_data:
|
|
73
86
|
return f"Error reading article from {url}: No data found."
|
agno/tools/notion.py
ADDED
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
from typing import Any, Dict, List, Optional, cast
|
|
4
|
+
|
|
5
|
+
from agno.tools import Toolkit
|
|
6
|
+
from agno.utils.log import log_debug, logger
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
from notion_client import Client
|
|
10
|
+
except ImportError:
|
|
11
|
+
raise ImportError("`notion-client` not installed. Please install using `pip install notion-client`")
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class NotionTools(Toolkit):
|
|
15
|
+
"""
|
|
16
|
+
Notion toolkit for creating and managing Notion pages.
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
api_key (Optional[str]): Notion API key (integration token). If not provided, uses NOTION_API_KEY env var.
|
|
20
|
+
database_id (Optional[str]): The ID of the database to work with. If not provided, uses NOTION_DATABASE_ID env var.
|
|
21
|
+
enable_create_page (bool): Enable creating pages. Default is True.
|
|
22
|
+
enable_update_page (bool): Enable updating pages. Default is True.
|
|
23
|
+
enable_search_pages (bool): Enable searching pages. Default is True.
|
|
24
|
+
all (bool): Enable all tools. Overrides individual flags when True. Default is False.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
def __init__(
|
|
28
|
+
self,
|
|
29
|
+
api_key: Optional[str] = None,
|
|
30
|
+
database_id: Optional[str] = None,
|
|
31
|
+
enable_create_page: bool = True,
|
|
32
|
+
enable_update_page: bool = True,
|
|
33
|
+
enable_search_pages: bool = True,
|
|
34
|
+
all: bool = False,
|
|
35
|
+
**kwargs,
|
|
36
|
+
):
|
|
37
|
+
self.api_key = api_key or os.getenv("NOTION_API_KEY")
|
|
38
|
+
self.database_id = database_id or os.getenv("NOTION_DATABASE_ID")
|
|
39
|
+
|
|
40
|
+
if not self.api_key:
|
|
41
|
+
raise ValueError(
|
|
42
|
+
"Notion API key is required. Either pass api_key parameter or set NOTION_API_KEY environment variable."
|
|
43
|
+
)
|
|
44
|
+
if not self.database_id:
|
|
45
|
+
raise ValueError(
|
|
46
|
+
"Notion database ID is required. Either pass database_id parameter or set NOTION_DATABASE_ID environment variable."
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
self.client = Client(auth=self.api_key)
|
|
50
|
+
|
|
51
|
+
tools: List[Any] = []
|
|
52
|
+
if all or enable_create_page:
|
|
53
|
+
tools.append(self.create_page)
|
|
54
|
+
if all or enable_update_page:
|
|
55
|
+
tools.append(self.update_page)
|
|
56
|
+
if all or enable_search_pages:
|
|
57
|
+
tools.append(self.search_pages)
|
|
58
|
+
|
|
59
|
+
super().__init__(name="notion_tools", tools=tools, **kwargs)
|
|
60
|
+
|
|
61
|
+
def create_page(self, title: str, tag: str, content: str) -> str:
|
|
62
|
+
"""Create a new page in the Notion database with a title, tag, and content.
|
|
63
|
+
|
|
64
|
+
Args:
|
|
65
|
+
title (str): The title of the page
|
|
66
|
+
tag (str): The tag/category for the page (e.g., travel, tech, general-blogs, fashion, documents)
|
|
67
|
+
content (str): The content to add to the page
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
str: JSON string with page creation details
|
|
71
|
+
"""
|
|
72
|
+
try:
|
|
73
|
+
log_debug(f"Creating Notion page with title: {title}, tag: {tag}")
|
|
74
|
+
|
|
75
|
+
# Create the page in the database
|
|
76
|
+
new_page = cast(
|
|
77
|
+
Dict[str, Any],
|
|
78
|
+
self.client.pages.create(
|
|
79
|
+
parent={"database_id": self.database_id},
|
|
80
|
+
properties={"Name": {"title": [{"text": {"content": title}}]}, "Tag": {"select": {"name": tag}}},
|
|
81
|
+
children=[
|
|
82
|
+
{
|
|
83
|
+
"object": "block",
|
|
84
|
+
"type": "paragraph",
|
|
85
|
+
"paragraph": {"rich_text": [{"type": "text", "text": {"content": content}}]},
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
),
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
result = {"success": True, "page_id": new_page["id"], "url": new_page["url"], "title": title, "tag": tag}
|
|
92
|
+
return json.dumps(result, indent=2)
|
|
93
|
+
|
|
94
|
+
except Exception as e:
|
|
95
|
+
logger.exception(e)
|
|
96
|
+
return json.dumps({"success": False, "error": str(e)})
|
|
97
|
+
|
|
98
|
+
def update_page(self, page_id: str, content: str) -> str:
|
|
99
|
+
"""Add content to an existing Notion page.
|
|
100
|
+
|
|
101
|
+
Args:
|
|
102
|
+
page_id (str): The ID of the page to update
|
|
103
|
+
content (str): The content to append to the page
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
str: JSON string with update status
|
|
107
|
+
"""
|
|
108
|
+
try:
|
|
109
|
+
log_debug(f"Updating Notion page: {page_id}")
|
|
110
|
+
|
|
111
|
+
# Append content to the page
|
|
112
|
+
self.client.blocks.children.append(
|
|
113
|
+
block_id=page_id,
|
|
114
|
+
children=[
|
|
115
|
+
{
|
|
116
|
+
"object": "block",
|
|
117
|
+
"type": "paragraph",
|
|
118
|
+
"paragraph": {"rich_text": [{"type": "text", "text": {"content": content}}]},
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
result = {"success": True, "page_id": page_id, "message": "Content added successfully"}
|
|
124
|
+
return json.dumps(result, indent=2)
|
|
125
|
+
|
|
126
|
+
except Exception as e:
|
|
127
|
+
logger.exception(e)
|
|
128
|
+
return json.dumps({"success": False, "error": str(e)})
|
|
129
|
+
|
|
130
|
+
def search_pages(self, tag: str) -> str:
|
|
131
|
+
"""Search for pages in the database by tag.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
tag (str): The tag to search for
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
str: JSON string with list of matching pages
|
|
138
|
+
"""
|
|
139
|
+
try:
|
|
140
|
+
log_debug(f"Searching for pages with tag: {tag}")
|
|
141
|
+
|
|
142
|
+
import httpx
|
|
143
|
+
|
|
144
|
+
headers = {
|
|
145
|
+
"Authorization": f"Bearer {self.api_key}",
|
|
146
|
+
"Notion-Version": "2022-06-28",
|
|
147
|
+
"Content-Type": "application/json",
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
payload = {"filter": {"property": "Tag", "select": {"equals": tag}}}
|
|
151
|
+
|
|
152
|
+
# The SDK client does not support the query method
|
|
153
|
+
response = httpx.post(
|
|
154
|
+
f"https://api.notion.com/v1/databases/{self.database_id}/query",
|
|
155
|
+
headers=headers,
|
|
156
|
+
json=payload,
|
|
157
|
+
timeout=30.0,
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
if response.status_code != 200:
|
|
161
|
+
return json.dumps(
|
|
162
|
+
{
|
|
163
|
+
"success": False,
|
|
164
|
+
"error": f"API request failed with status {response.status_code}",
|
|
165
|
+
"message": response.text,
|
|
166
|
+
}
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
data = response.json()
|
|
170
|
+
pages = []
|
|
171
|
+
|
|
172
|
+
for page in data.get("results", []):
|
|
173
|
+
try:
|
|
174
|
+
page_title = "Untitled"
|
|
175
|
+
if page.get("properties", {}).get("Name", {}).get("title"):
|
|
176
|
+
page_title = page["properties"]["Name"]["title"][0]["text"]["content"]
|
|
177
|
+
|
|
178
|
+
page_tag = None
|
|
179
|
+
if page.get("properties", {}).get("Tag", {}).get("select"):
|
|
180
|
+
page_tag = page["properties"]["Tag"]["select"]["name"]
|
|
181
|
+
|
|
182
|
+
page_info = {
|
|
183
|
+
"page_id": page["id"],
|
|
184
|
+
"title": page_title,
|
|
185
|
+
"tag": page_tag,
|
|
186
|
+
"url": page.get("url", ""),
|
|
187
|
+
}
|
|
188
|
+
pages.append(page_info)
|
|
189
|
+
except Exception as page_error:
|
|
190
|
+
log_debug(f"Error parsing page: {page_error}")
|
|
191
|
+
continue
|
|
192
|
+
|
|
193
|
+
result = {"success": True, "count": len(pages), "pages": pages}
|
|
194
|
+
return json.dumps(result, indent=2)
|
|
195
|
+
|
|
196
|
+
except Exception as e:
|
|
197
|
+
logger.exception(e)
|
|
198
|
+
return json.dumps(
|
|
199
|
+
{
|
|
200
|
+
"success": False,
|
|
201
|
+
"error": str(e),
|
|
202
|
+
"message": "Failed to search pages. Make sure the database is shared with the integration and has a 'Tag' property.",
|
|
203
|
+
}
|
|
204
|
+
)
|