agno 1.8.0__py3-none-any.whl → 2.0.0a1__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.
Files changed (583) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2781 -4126
  4. agno/api/agent.py +9 -65
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +6 -17
  7. agno/api/os.py +17 -0
  8. agno/api/routes.py +6 -41
  9. agno/api/schemas/__init__.py +9 -0
  10. agno/api/schemas/agent.py +5 -21
  11. agno/api/schemas/evals.py +7 -16
  12. agno/api/schemas/os.py +14 -0
  13. agno/api/schemas/team.py +5 -21
  14. agno/api/schemas/utils.py +21 -0
  15. agno/api/schemas/workflows.py +11 -7
  16. agno/api/settings.py +53 -0
  17. agno/api/team.py +9 -64
  18. agno/api/workflow.py +28 -0
  19. agno/cloud/aws/base.py +214 -0
  20. agno/cloud/aws/s3/__init__.py +2 -0
  21. agno/cloud/aws/s3/api_client.py +43 -0
  22. agno/cloud/aws/s3/bucket.py +195 -0
  23. agno/cloud/aws/s3/object.py +57 -0
  24. agno/db/__init__.py +24 -0
  25. agno/db/base.py +245 -0
  26. agno/db/dynamo/__init__.py +3 -0
  27. agno/db/dynamo/dynamo.py +1749 -0
  28. agno/db/dynamo/schemas.py +278 -0
  29. agno/db/dynamo/utils.py +684 -0
  30. agno/db/firestore/__init__.py +3 -0
  31. agno/db/firestore/firestore.py +1438 -0
  32. agno/db/firestore/schemas.py +130 -0
  33. agno/db/firestore/utils.py +278 -0
  34. agno/db/gcs_json/__init__.py +3 -0
  35. agno/db/gcs_json/gcs_json_db.py +1001 -0
  36. agno/db/gcs_json/utils.py +194 -0
  37. agno/db/in_memory/__init__.py +3 -0
  38. agno/db/in_memory/in_memory_db.py +888 -0
  39. agno/db/in_memory/utils.py +172 -0
  40. agno/db/json/__init__.py +3 -0
  41. agno/db/json/json_db.py +1051 -0
  42. agno/db/json/utils.py +196 -0
  43. agno/db/migrations/v1_to_v2.py +162 -0
  44. agno/db/mongo/__init__.py +3 -0
  45. agno/db/mongo/mongo.py +1417 -0
  46. agno/db/mongo/schemas.py +77 -0
  47. agno/db/mongo/utils.py +204 -0
  48. agno/db/mysql/__init__.py +3 -0
  49. agno/db/mysql/mysql.py +1719 -0
  50. agno/db/mysql/schemas.py +124 -0
  51. agno/db/mysql/utils.py +298 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1720 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +281 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1371 -0
  58. agno/db/redis/schemas.py +109 -0
  59. agno/db/redis/utils.py +288 -0
  60. agno/db/schemas/__init__.py +3 -0
  61. agno/db/schemas/evals.py +33 -0
  62. agno/db/schemas/knowledge.py +40 -0
  63. agno/db/schemas/memory.py +46 -0
  64. agno/db/singlestore/__init__.py +3 -0
  65. agno/db/singlestore/schemas.py +116 -0
  66. agno/db/singlestore/singlestore.py +1722 -0
  67. agno/db/singlestore/utils.py +327 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1680 -0
  71. agno/db/sqlite/utils.py +269 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +142 -43
  75. agno/eval/performance.py +88 -23
  76. agno/eval/reliability.py +73 -20
  77. agno/eval/utils.py +23 -13
  78. agno/integrations/discord/__init__.py +3 -0
  79. agno/{app → integrations}/discord/client.py +10 -10
  80. agno/knowledge/__init__.py +2 -2
  81. agno/{document → knowledge}/chunking/agentic.py +2 -2
  82. agno/{document → knowledge}/chunking/document.py +2 -2
  83. agno/{document → knowledge}/chunking/fixed.py +3 -3
  84. agno/{document → knowledge}/chunking/markdown.py +2 -2
  85. agno/{document → knowledge}/chunking/recursive.py +2 -2
  86. agno/{document → knowledge}/chunking/row.py +2 -2
  87. agno/knowledge/chunking/semantic.py +59 -0
  88. agno/knowledge/chunking/strategy.py +121 -0
  89. agno/knowledge/content.py +74 -0
  90. agno/knowledge/document/__init__.py +5 -0
  91. agno/{document → knowledge/document}/base.py +12 -2
  92. agno/knowledge/embedder/__init__.py +5 -0
  93. agno/{embedder → knowledge/embedder}/aws_bedrock.py +127 -1
  94. agno/{embedder → knowledge/embedder}/azure_openai.py +65 -1
  95. agno/{embedder → knowledge/embedder}/base.py +6 -0
  96. agno/{embedder → knowledge/embedder}/cohere.py +72 -1
  97. agno/{embedder → knowledge/embedder}/fastembed.py +17 -1
  98. agno/{embedder → knowledge/embedder}/fireworks.py +1 -1
  99. agno/{embedder → knowledge/embedder}/google.py +74 -1
  100. agno/{embedder → knowledge/embedder}/huggingface.py +36 -2
  101. agno/{embedder → knowledge/embedder}/jina.py +48 -2
  102. agno/knowledge/embedder/langdb.py +22 -0
  103. agno/knowledge/embedder/mistral.py +139 -0
  104. agno/{embedder → knowledge/embedder}/nebius.py +1 -1
  105. agno/{embedder → knowledge/embedder}/ollama.py +54 -3
  106. agno/knowledge/embedder/openai.py +223 -0
  107. agno/{embedder → knowledge/embedder}/sentence_transformer.py +16 -1
  108. agno/{embedder → knowledge/embedder}/together.py +1 -1
  109. agno/{embedder → knowledge/embedder}/voyageai.py +49 -1
  110. agno/knowledge/knowledge.py +1515 -0
  111. agno/knowledge/reader/__init__.py +7 -0
  112. agno/{document → knowledge}/reader/arxiv_reader.py +32 -4
  113. agno/knowledge/reader/base.py +88 -0
  114. agno/{document → knowledge}/reader/csv_reader.py +68 -15
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/knowledge/reader/gcs_reader.py +67 -0
  118. agno/{document → knowledge}/reader/json_reader.py +30 -9
  119. agno/{document → knowledge}/reader/markdown_reader.py +36 -9
  120. agno/{document → knowledge}/reader/pdf_reader.py +79 -21
  121. agno/knowledge/reader/reader_factory.py +275 -0
  122. agno/knowledge/reader/s3_reader.py +171 -0
  123. agno/{document → knowledge}/reader/text_reader.py +31 -10
  124. agno/knowledge/reader/url_reader.py +84 -0
  125. agno/knowledge/reader/web_search_reader.py +389 -0
  126. agno/{document → knowledge}/reader/website_reader.py +37 -10
  127. agno/knowledge/reader/wikipedia_reader.py +59 -0
  128. agno/knowledge/reader/youtube_reader.py +78 -0
  129. agno/knowledge/remote_content/remote_content.py +88 -0
  130. agno/{reranker → knowledge/reranker}/base.py +1 -1
  131. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  132. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  133. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  134. agno/knowledge/types.py +30 -0
  135. agno/knowledge/utils.py +169 -0
  136. agno/media.py +2 -2
  137. agno/memory/__init__.py +2 -10
  138. agno/memory/manager.py +1003 -148
  139. agno/models/aimlapi/__init__.py +2 -2
  140. agno/models/aimlapi/aimlapi.py +6 -6
  141. agno/models/anthropic/claude.py +129 -82
  142. agno/models/aws/bedrock.py +107 -175
  143. agno/models/aws/claude.py +64 -18
  144. agno/models/azure/ai_foundry.py +73 -23
  145. agno/models/base.py +347 -287
  146. agno/models/cerebras/cerebras.py +84 -27
  147. agno/models/cohere/chat.py +106 -98
  148. agno/models/dashscope/dashscope.py +14 -5
  149. agno/models/google/gemini.py +123 -53
  150. agno/models/groq/groq.py +97 -35
  151. agno/models/huggingface/huggingface.py +92 -27
  152. agno/models/ibm/watsonx.py +72 -13
  153. agno/models/litellm/chat.py +85 -13
  154. agno/models/message.py +38 -144
  155. agno/models/meta/llama.py +85 -49
  156. agno/models/metrics.py +120 -0
  157. agno/models/mistral/mistral.py +90 -21
  158. agno/models/ollama/__init__.py +0 -2
  159. agno/models/ollama/chat.py +84 -46
  160. agno/models/openai/chat.py +135 -27
  161. agno/models/openai/responses.py +233 -115
  162. agno/models/perplexity/perplexity.py +26 -2
  163. agno/models/portkey/portkey.py +0 -7
  164. agno/models/response.py +14 -8
  165. agno/models/utils.py +20 -0
  166. agno/models/vercel/__init__.py +2 -2
  167. agno/models/vercel/v0.py +1 -1
  168. agno/models/vllm/__init__.py +2 -2
  169. agno/models/vllm/vllm.py +3 -3
  170. agno/models/xai/xai.py +10 -10
  171. agno/os/__init__.py +3 -0
  172. agno/os/app.py +393 -0
  173. agno/os/auth.py +47 -0
  174. agno/os/config.py +103 -0
  175. agno/os/interfaces/agui/__init__.py +3 -0
  176. agno/os/interfaces/agui/agui.py +31 -0
  177. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  178. agno/{app → os/interfaces}/agui/utils.py +65 -28
  179. agno/os/interfaces/base.py +21 -0
  180. agno/os/interfaces/slack/__init__.py +3 -0
  181. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  182. agno/os/interfaces/slack/slack.py +33 -0
  183. agno/os/interfaces/whatsapp/__init__.py +3 -0
  184. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  185. agno/os/interfaces/whatsapp/whatsapp.py +30 -0
  186. agno/os/router.py +843 -0
  187. agno/os/routers/__init__.py +3 -0
  188. agno/os/routers/evals/__init__.py +3 -0
  189. agno/os/routers/evals/evals.py +204 -0
  190. agno/os/routers/evals/schemas.py +142 -0
  191. agno/os/routers/evals/utils.py +161 -0
  192. agno/os/routers/knowledge/__init__.py +3 -0
  193. agno/os/routers/knowledge/knowledge.py +413 -0
  194. agno/os/routers/knowledge/schemas.py +118 -0
  195. agno/os/routers/memory/__init__.py +3 -0
  196. agno/os/routers/memory/memory.py +179 -0
  197. agno/os/routers/memory/schemas.py +58 -0
  198. agno/os/routers/metrics/__init__.py +3 -0
  199. agno/os/routers/metrics/metrics.py +58 -0
  200. agno/os/routers/metrics/schemas.py +47 -0
  201. agno/os/routers/session/__init__.py +3 -0
  202. agno/os/routers/session/session.py +163 -0
  203. agno/os/schema.py +892 -0
  204. agno/{app/playground → os}/settings.py +8 -15
  205. agno/os/utils.py +270 -0
  206. agno/reasoning/azure_ai_foundry.py +4 -4
  207. agno/reasoning/deepseek.py +4 -4
  208. agno/reasoning/default.py +6 -11
  209. agno/reasoning/groq.py +4 -4
  210. agno/reasoning/helpers.py +4 -6
  211. agno/reasoning/ollama.py +4 -4
  212. agno/reasoning/openai.py +4 -4
  213. agno/run/{response.py → agent.py} +144 -72
  214. agno/run/base.py +44 -58
  215. agno/run/cancel.py +83 -0
  216. agno/run/team.py +133 -77
  217. agno/run/workflow.py +537 -12
  218. agno/session/__init__.py +10 -0
  219. agno/session/agent.py +244 -0
  220. agno/session/summary.py +225 -0
  221. agno/session/team.py +262 -0
  222. agno/{storage/session/v2 → session}/workflow.py +47 -24
  223. agno/team/__init__.py +15 -16
  224. agno/team/team.py +2967 -4243
  225. agno/tools/agentql.py +14 -5
  226. agno/tools/airflow.py +9 -4
  227. agno/tools/api.py +7 -3
  228. agno/tools/apify.py +2 -46
  229. agno/tools/arxiv.py +8 -3
  230. agno/tools/aws_lambda.py +7 -5
  231. agno/tools/aws_ses.py +7 -1
  232. agno/tools/baidusearch.py +4 -1
  233. agno/tools/bitbucket.py +4 -4
  234. agno/tools/brandfetch.py +14 -11
  235. agno/tools/bravesearch.py +4 -1
  236. agno/tools/brightdata.py +42 -22
  237. agno/tools/browserbase.py +13 -4
  238. agno/tools/calcom.py +12 -10
  239. agno/tools/calculator.py +10 -27
  240. agno/tools/cartesia.py +18 -13
  241. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  242. agno/tools/confluence.py +71 -18
  243. agno/tools/crawl4ai.py +7 -1
  244. agno/tools/csv_toolkit.py +9 -8
  245. agno/tools/dalle.py +18 -11
  246. agno/tools/daytona.py +13 -16
  247. agno/tools/decorator.py +6 -3
  248. agno/tools/desi_vocal.py +16 -7
  249. agno/tools/discord.py +11 -8
  250. agno/tools/docker.py +30 -42
  251. agno/tools/duckdb.py +34 -53
  252. agno/tools/duckduckgo.py +8 -7
  253. agno/tools/e2b.py +62 -62
  254. agno/tools/eleven_labs.py +35 -28
  255. agno/tools/email.py +4 -1
  256. agno/tools/evm.py +7 -1
  257. agno/tools/exa.py +19 -14
  258. agno/tools/fal.py +29 -29
  259. agno/tools/file.py +9 -8
  260. agno/tools/financial_datasets.py +25 -44
  261. agno/tools/firecrawl.py +22 -22
  262. agno/tools/function.py +68 -17
  263. agno/tools/giphy.py +22 -10
  264. agno/tools/github.py +48 -126
  265. agno/tools/gmail.py +46 -62
  266. agno/tools/google_bigquery.py +7 -6
  267. agno/tools/google_maps.py +11 -26
  268. agno/tools/googlesearch.py +7 -2
  269. agno/tools/googlesheets.py +21 -17
  270. agno/tools/hackernews.py +9 -5
  271. agno/tools/jina.py +5 -4
  272. agno/tools/jira.py +18 -9
  273. agno/tools/knowledge.py +31 -32
  274. agno/tools/linear.py +18 -33
  275. agno/tools/linkup.py +5 -1
  276. agno/tools/local_file_system.py +8 -5
  277. agno/tools/lumalab.py +31 -19
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +32 -14
  282. agno/tools/models/gemini.py +58 -31
  283. agno/tools/models/groq.py +29 -20
  284. agno/tools/models/nebius.py +27 -11
  285. agno/tools/models_labs.py +39 -15
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +134 -0
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +57 -26
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +62 -46
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +54 -41
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +95 -118
  335. agno/utils/knowledge.py +29 -0
  336. agno/utils/location.py +2 -2
  337. agno/utils/log.py +2 -2
  338. agno/utils/mcp.py +11 -5
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/claude.py +6 -4
  342. agno/utils/models/mistral.py +8 -7
  343. agno/utils/models/schema_utils.py +3 -3
  344. agno/utils/pprint.py +33 -32
  345. agno/utils/print_response/agent.py +779 -0
  346. agno/utils/print_response/team.py +1565 -0
  347. agno/utils/print_response/workflow.py +1451 -0
  348. agno/utils/prompts.py +14 -14
  349. agno/utils/reasoning.py +87 -0
  350. agno/utils/response.py +42 -42
  351. agno/utils/string.py +8 -22
  352. agno/utils/team.py +50 -0
  353. agno/utils/timer.py +2 -2
  354. agno/vectordb/base.py +33 -21
  355. agno/vectordb/cassandra/cassandra.py +287 -23
  356. agno/vectordb/chroma/chromadb.py +482 -59
  357. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  358. agno/vectordb/couchbase/couchbase.py +309 -29
  359. agno/vectordb/lancedb/lance_db.py +360 -21
  360. agno/vectordb/langchaindb/__init__.py +5 -0
  361. agno/vectordb/langchaindb/langchaindb.py +145 -0
  362. agno/vectordb/lightrag/__init__.py +5 -0
  363. agno/vectordb/lightrag/lightrag.py +374 -0
  364. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  365. agno/vectordb/milvus/milvus.py +242 -32
  366. agno/vectordb/mongodb/mongodb.py +200 -24
  367. agno/vectordb/pgvector/pgvector.py +319 -37
  368. agno/vectordb/pineconedb/pineconedb.py +221 -27
  369. agno/vectordb/qdrant/qdrant.py +356 -14
  370. agno/vectordb/singlestore/singlestore.py +286 -29
  371. agno/vectordb/surrealdb/surrealdb.py +187 -7
  372. agno/vectordb/upstashdb/upstashdb.py +342 -26
  373. agno/vectordb/weaviate/weaviate.py +227 -165
  374. agno/workflow/__init__.py +17 -13
  375. agno/workflow/{v2/condition.py → condition.py} +135 -32
  376. agno/workflow/{v2/loop.py → loop.py} +115 -28
  377. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  378. agno/workflow/{v2/router.py → router.py} +133 -32
  379. agno/workflow/{v2/step.py → step.py} +200 -42
  380. agno/workflow/{v2/steps.py → steps.py} +147 -66
  381. agno/workflow/types.py +482 -0
  382. agno/workflow/workflow.py +2394 -696
  383. agno-2.0.0a1.dist-info/METADATA +355 -0
  384. agno-2.0.0a1.dist-info/RECORD +514 -0
  385. agno/agent/metrics.py +0 -107
  386. agno/api/app.py +0 -35
  387. agno/api/playground.py +0 -92
  388. agno/api/schemas/app.py +0 -12
  389. agno/api/schemas/playground.py +0 -22
  390. agno/api/schemas/user.py +0 -35
  391. agno/api/schemas/workspace.py +0 -46
  392. agno/api/user.py +0 -160
  393. agno/api/workflows.py +0 -33
  394. agno/api/workspace.py +0 -175
  395. agno/app/agui/__init__.py +0 -3
  396. agno/app/agui/app.py +0 -17
  397. agno/app/agui/sync_router.py +0 -120
  398. agno/app/base.py +0 -186
  399. agno/app/discord/__init__.py +0 -3
  400. agno/app/fastapi/__init__.py +0 -3
  401. agno/app/fastapi/app.py +0 -107
  402. agno/app/fastapi/async_router.py +0 -457
  403. agno/app/fastapi/sync_router.py +0 -448
  404. agno/app/playground/app.py +0 -228
  405. agno/app/playground/async_router.py +0 -1050
  406. agno/app/playground/deploy.py +0 -249
  407. agno/app/playground/operator.py +0 -183
  408. agno/app/playground/schemas.py +0 -220
  409. agno/app/playground/serve.py +0 -55
  410. agno/app/playground/sync_router.py +0 -1042
  411. agno/app/playground/utils.py +0 -46
  412. agno/app/settings.py +0 -15
  413. agno/app/slack/__init__.py +0 -3
  414. agno/app/slack/app.py +0 -19
  415. agno/app/slack/sync_router.py +0 -92
  416. agno/app/utils.py +0 -54
  417. agno/app/whatsapp/__init__.py +0 -3
  418. agno/app/whatsapp/app.py +0 -15
  419. agno/app/whatsapp/sync_router.py +0 -197
  420. agno/cli/auth_server.py +0 -249
  421. agno/cli/config.py +0 -274
  422. agno/cli/console.py +0 -88
  423. agno/cli/credentials.py +0 -23
  424. agno/cli/entrypoint.py +0 -571
  425. agno/cli/operator.py +0 -357
  426. agno/cli/settings.py +0 -96
  427. agno/cli/ws/ws_cli.py +0 -817
  428. agno/constants.py +0 -13
  429. agno/document/__init__.py +0 -5
  430. agno/document/chunking/semantic.py +0 -45
  431. agno/document/chunking/strategy.py +0 -31
  432. agno/document/reader/__init__.py +0 -5
  433. agno/document/reader/base.py +0 -47
  434. agno/document/reader/docx_reader.py +0 -60
  435. agno/document/reader/gcs/pdf_reader.py +0 -44
  436. agno/document/reader/s3/pdf_reader.py +0 -59
  437. agno/document/reader/s3/text_reader.py +0 -63
  438. agno/document/reader/url_reader.py +0 -59
  439. agno/document/reader/youtube_reader.py +0 -58
  440. agno/embedder/__init__.py +0 -5
  441. agno/embedder/langdb.py +0 -80
  442. agno/embedder/mistral.py +0 -82
  443. agno/embedder/openai.py +0 -78
  444. agno/file/__init__.py +0 -5
  445. agno/file/file.py +0 -16
  446. agno/file/local/csv.py +0 -32
  447. agno/file/local/txt.py +0 -19
  448. agno/infra/app.py +0 -240
  449. agno/infra/base.py +0 -144
  450. agno/infra/context.py +0 -20
  451. agno/infra/db_app.py +0 -52
  452. agno/infra/resource.py +0 -205
  453. agno/infra/resources.py +0 -55
  454. agno/knowledge/agent.py +0 -698
  455. agno/knowledge/arxiv.py +0 -33
  456. agno/knowledge/combined.py +0 -36
  457. agno/knowledge/csv.py +0 -144
  458. agno/knowledge/csv_url.py +0 -124
  459. agno/knowledge/document.py +0 -223
  460. agno/knowledge/docx.py +0 -137
  461. agno/knowledge/firecrawl.py +0 -34
  462. agno/knowledge/gcs/__init__.py +0 -0
  463. agno/knowledge/gcs/base.py +0 -39
  464. agno/knowledge/gcs/pdf.py +0 -125
  465. agno/knowledge/json.py +0 -137
  466. agno/knowledge/langchain.py +0 -71
  467. agno/knowledge/light_rag.py +0 -273
  468. agno/knowledge/llamaindex.py +0 -66
  469. agno/knowledge/markdown.py +0 -154
  470. agno/knowledge/pdf.py +0 -164
  471. agno/knowledge/pdf_bytes.py +0 -42
  472. agno/knowledge/pdf_url.py +0 -148
  473. agno/knowledge/s3/__init__.py +0 -0
  474. agno/knowledge/s3/base.py +0 -64
  475. agno/knowledge/s3/pdf.py +0 -33
  476. agno/knowledge/s3/text.py +0 -34
  477. agno/knowledge/text.py +0 -141
  478. agno/knowledge/url.py +0 -46
  479. agno/knowledge/website.py +0 -179
  480. agno/knowledge/wikipedia.py +0 -32
  481. agno/knowledge/youtube.py +0 -35
  482. agno/memory/agent.py +0 -423
  483. agno/memory/classifier.py +0 -104
  484. agno/memory/db/__init__.py +0 -5
  485. agno/memory/db/base.py +0 -42
  486. agno/memory/db/mongodb.py +0 -189
  487. agno/memory/db/postgres.py +0 -203
  488. agno/memory/db/sqlite.py +0 -193
  489. agno/memory/memory.py +0 -22
  490. agno/memory/row.py +0 -36
  491. agno/memory/summarizer.py +0 -201
  492. agno/memory/summary.py +0 -19
  493. agno/memory/team.py +0 -415
  494. agno/memory/v2/__init__.py +0 -2
  495. agno/memory/v2/db/__init__.py +0 -1
  496. agno/memory/v2/db/base.py +0 -42
  497. agno/memory/v2/db/firestore.py +0 -339
  498. agno/memory/v2/db/mongodb.py +0 -196
  499. agno/memory/v2/db/postgres.py +0 -214
  500. agno/memory/v2/db/redis.py +0 -187
  501. agno/memory/v2/db/schema.py +0 -54
  502. agno/memory/v2/db/sqlite.py +0 -209
  503. agno/memory/v2/manager.py +0 -437
  504. agno/memory/v2/memory.py +0 -1097
  505. agno/memory/v2/schema.py +0 -55
  506. agno/memory/v2/summarizer.py +0 -215
  507. agno/memory/workflow.py +0 -38
  508. agno/models/ollama/tools.py +0 -430
  509. agno/models/qwen/__init__.py +0 -5
  510. agno/playground/__init__.py +0 -10
  511. agno/playground/deploy.py +0 -3
  512. agno/playground/playground.py +0 -3
  513. agno/playground/serve.py +0 -3
  514. agno/playground/settings.py +0 -3
  515. agno/reranker/__init__.py +0 -0
  516. agno/run/v2/__init__.py +0 -0
  517. agno/run/v2/workflow.py +0 -567
  518. agno/storage/__init__.py +0 -0
  519. agno/storage/agent/__init__.py +0 -0
  520. agno/storage/agent/dynamodb.py +0 -1
  521. agno/storage/agent/json.py +0 -1
  522. agno/storage/agent/mongodb.py +0 -1
  523. agno/storage/agent/postgres.py +0 -1
  524. agno/storage/agent/singlestore.py +0 -1
  525. agno/storage/agent/sqlite.py +0 -1
  526. agno/storage/agent/yaml.py +0 -1
  527. agno/storage/base.py +0 -60
  528. agno/storage/dynamodb.py +0 -673
  529. agno/storage/firestore.py +0 -297
  530. agno/storage/gcs_json.py +0 -261
  531. agno/storage/in_memory.py +0 -234
  532. agno/storage/json.py +0 -237
  533. agno/storage/mongodb.py +0 -328
  534. agno/storage/mysql.py +0 -685
  535. agno/storage/postgres.py +0 -682
  536. agno/storage/redis.py +0 -336
  537. agno/storage/session/__init__.py +0 -16
  538. agno/storage/session/agent.py +0 -64
  539. agno/storage/session/team.py +0 -63
  540. agno/storage/session/v2/__init__.py +0 -5
  541. agno/storage/session/workflow.py +0 -61
  542. agno/storage/singlestore.py +0 -606
  543. agno/storage/sqlite.py +0 -646
  544. agno/storage/workflow/__init__.py +0 -0
  545. agno/storage/workflow/mongodb.py +0 -1
  546. agno/storage/workflow/postgres.py +0 -1
  547. agno/storage/workflow/sqlite.py +0 -1
  548. agno/storage/yaml.py +0 -241
  549. agno/tools/thinking.py +0 -73
  550. agno/utils/defaults.py +0 -57
  551. agno/utils/filesystem.py +0 -39
  552. agno/utils/git.py +0 -52
  553. agno/utils/json_io.py +0 -30
  554. agno/utils/load_env.py +0 -19
  555. agno/utils/py_io.py +0 -19
  556. agno/utils/pyproject.py +0 -18
  557. agno/utils/resource_filter.py +0 -31
  558. agno/workflow/v2/__init__.py +0 -21
  559. agno/workflow/v2/types.py +0 -357
  560. agno/workflow/v2/workflow.py +0 -3312
  561. agno/workspace/__init__.py +0 -0
  562. agno/workspace/config.py +0 -325
  563. agno/workspace/enums.py +0 -6
  564. agno/workspace/helpers.py +0 -52
  565. agno/workspace/operator.py +0 -757
  566. agno/workspace/settings.py +0 -158
  567. agno-1.8.0.dist-info/METADATA +0 -979
  568. agno-1.8.0.dist-info/RECORD +0 -565
  569. agno-1.8.0.dist-info/entry_points.txt +0 -3
  570. /agno/{app → db/migrations}/__init__.py +0 -0
  571. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  572. /agno/{cli → integrations}/__init__.py +0 -0
  573. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  574. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  575. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  576. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  577. /agno/{app → os/interfaces}/slack/security.py +0 -0
  578. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  579. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  580. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  581. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  582. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  583. {agno-1.8.0.dist-info → agno-2.0.0a1.dist-info}/top_level.txt +0 -0
@@ -1,27 +1,54 @@
1
1
  import asyncio
2
2
  import uuid
3
3
  from pathlib import Path
4
- from typing import IO, Any, List, Union
4
+ from typing import IO, Any, List, Optional, Union
5
5
 
6
- from agno.document.base import Document
7
- from agno.document.reader.base import Reader
6
+ from agno.knowledge.chunking.markdown import MarkdownChunking
7
+ from agno.knowledge.chunking.strategy import ChunkingStrategy, ChunkingStrategyType
8
+ from agno.knowledge.document.base import Document
9
+ from agno.knowledge.reader.base import Reader
10
+ from agno.knowledge.types import ContentType
8
11
  from agno.utils.log import log_info, logger
9
12
 
10
13
 
11
14
  class MarkdownReader(Reader):
12
15
  """Reader for Markdown files"""
13
16
 
14
- def read(self, file: Union[Path, IO[Any]]) -> List[Document]:
17
+ @classmethod
18
+ def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
19
+ """Get the list of supported chunking strategies for Markdown readers."""
20
+ return [
21
+ ChunkingStrategyType.MARKDOWN_CHUNKING,
22
+ ChunkingStrategyType.AGENTIC_CHUNKING,
23
+ ChunkingStrategyType.DOCUMENT_CHUNKING,
24
+ ChunkingStrategyType.RECURSIVE_CHUNKING,
25
+ ChunkingStrategyType.SEMANTIC_CHUNKING,
26
+ ChunkingStrategyType.FIXED_SIZE_CHUNKING,
27
+ ]
28
+
29
+ @classmethod
30
+ def get_supported_content_types(self) -> List[ContentType]:
31
+ return [ContentType.MARKDOWN]
32
+
33
+ def __init__(
34
+ self,
35
+ chunking_strategy: Optional[ChunkingStrategy] = MarkdownChunking(),
36
+ name: Optional[str] = None,
37
+ description: Optional[str] = None,
38
+ ) -> None:
39
+ super().__init__(chunking_strategy=chunking_strategy, name=name, description=description)
40
+
41
+ def read(self, file: Union[Path, IO[Any]], name: Optional[str] = None) -> List[Document]:
15
42
  try:
16
43
  if isinstance(file, Path):
17
44
  if not file.exists():
18
45
  raise FileNotFoundError(f"Could not find file: {file}")
19
46
  log_info(f"Reading: {file}")
20
- file_name = file.stem
47
+ file_name = name or file.stem
21
48
  file_contents = file.read_text("utf-8")
22
49
  else:
23
50
  log_info(f"Reading uploaded file: {file.name}")
24
- file_name = file.name.split(".")[0]
51
+ file_name = name or file.name.split(".")[0]
25
52
  file.seek(0)
26
53
  file_contents = file.read().decode("utf-8")
27
54
 
@@ -36,14 +63,14 @@ class MarkdownReader(Reader):
36
63
  logger.error(f"Error reading: {file}: {e}")
37
64
  return []
38
65
 
39
- async def async_read(self, file: Union[Path, IO[Any]]) -> List[Document]:
66
+ async def async_read(self, file: Union[Path, IO[Any]], name: Optional[str] = None) -> List[Document]:
40
67
  try:
41
68
  if isinstance(file, Path):
42
69
  if not file.exists():
43
70
  raise FileNotFoundError(f"Could not find file: {file}")
44
71
 
45
72
  log_info(f"Reading asynchronously: {file}")
46
- file_name = file.stem
73
+ file_name = name or file.stem
47
74
 
48
75
  try:
49
76
  import aiofiles
@@ -55,7 +82,7 @@ class MarkdownReader(Reader):
55
82
  file_contents = file.read_text("utf-8")
56
83
  else:
57
84
  log_info(f"Reading uploaded file asynchronously: {file.name}")
58
- file_name = file.name.split(".")[0]
85
+ file_name = name or file.name.split(".")[0]
59
86
  file.seek(0)
60
87
  file_contents = file.read().decode("utf-8")
61
88
 
@@ -4,8 +4,10 @@ from pathlib import Path
4
4
  from typing import IO, Any, List, Optional, Tuple, Union
5
5
  from uuid import uuid4
6
6
 
7
- from agno.document.base import Document
8
- from agno.document.reader.base import Reader
7
+ from agno.knowledge.chunking.strategy import ChunkingStrategyType
8
+ from agno.knowledge.document.base import Document
9
+ from agno.knowledge.reader.base import Reader
10
+ from agno.knowledge.types import ContentType
9
11
  from agno.utils.http import async_fetch_with_retry, fetch_with_retry
10
12
  from agno.utils.log import log_error, log_info, logger
11
13
 
@@ -95,9 +97,9 @@ def _clean_page_numbers(
95
97
  Notes:
96
98
  - The function scans for page numbers using a regular expression that matches digits at the start or end of a string.
97
99
  - It evaluates several potential starting points for numbering (-2, -1, 0, 1, 2 shifts) to determine the most consistent sequence.
98
- - If at least a specified ratio of pages (defined by `PAGE_NUMBERING_CORRECTNESS_RATIO_FOR_REMOVAL`) has correct sequential numbering,
100
+ - If at least a specified ratio of pages (defined by `PAGE_NUMBERING_CORRECTNESS_RATIO_FOR_REMOVAL`) has correct sequential numbering,
99
101
  the page numbers are processed.
100
- - If page numbers are found, the function will add formatted page numbers to each page's content if `page_start_numbering_format` or
102
+ - If page numbers are found, the function will add formatted page numbers to each page's content if `page_start_numbering_format` or
101
103
  `page_end_numbering_format` is provided.
102
104
  """
103
105
  assert len(extra_content) == 0 or len(extra_content) == len(page_content_list), (
@@ -190,8 +192,23 @@ class BasePDFReader(Reader):
190
192
  self.page_end_numbering_format = page_end_numbering_format
191
193
  self.password = password
192
194
 
195
+ if self.chunking_strategy is None:
196
+ from agno.knowledge.chunking.document import DocumentChunking
197
+
198
+ self.chunking_strategy = DocumentChunking(chunk_size=5000)
193
199
  super().__init__(**kwargs)
194
200
 
201
+ @classmethod
202
+ def get_supported_chunking_strategies(self) -> List[ChunkingStrategyType]:
203
+ """Get the list of supported chunking strategies for PDF readers."""
204
+ return [
205
+ ChunkingStrategyType.DOCUMENT_CHUNKING,
206
+ ChunkingStrategyType.FIXED_SIZE_CHUNKING,
207
+ ChunkingStrategyType.AGENTIC_CHUNKING,
208
+ ChunkingStrategyType.SEMANTIC_CHUNKING,
209
+ ChunkingStrategyType.RECURSIVE_CHUNKING,
210
+ ]
211
+
195
212
  def _build_chunked_documents(self, documents: List[Document]) -> List[Document]:
196
213
  chunked_documents: List[Document] = []
197
214
  for document in documents:
@@ -306,9 +323,17 @@ class BasePDFReader(Reader):
306
323
  class PDFReader(BasePDFReader):
307
324
  """Reader for PDF files"""
308
325
 
309
- def read(self, pdf: Union[str, Path, IO[Any]], password: Optional[str] = None) -> List[Document]:
326
+ @classmethod
327
+ def get_supported_content_types(self) -> List[ContentType]:
328
+ return [ContentType.PDF]
329
+
330
+ def read(
331
+ self, pdf: Union[str, Path, IO[Any]], name: Optional[str] = None, password: Optional[str] = None
332
+ ) -> List[Document]:
310
333
  try:
311
- if isinstance(pdf, str):
334
+ if name:
335
+ doc_name = name
336
+ elif isinstance(pdf, str):
312
337
  doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
313
338
  else:
314
339
  doc_name = pdf.name.split(".")[0]
@@ -317,6 +342,22 @@ class PDFReader(BasePDFReader):
317
342
 
318
343
  log_info(f"Reading: {doc_name}")
319
344
 
345
+ try:
346
+ DocumentReader(pdf)
347
+ except PdfStreamError as e:
348
+ logger.error(f"Error reading PDF: {e}")
349
+ return []
350
+
351
+ try:
352
+ if isinstance(pdf, str):
353
+ doc_name = name or pdf.split("/")[-1].split(".")[0].replace(" ", "_")
354
+ else:
355
+ doc_name = name or pdf.name.split(".")[0]
356
+ except Exception:
357
+ doc_name = name or "pdf"
358
+
359
+ log_info(f"Reading: {doc_name}")
360
+
320
361
  try:
321
362
  pdf_reader = DocumentReader(pdf)
322
363
  except PdfStreamError as e:
@@ -330,14 +371,23 @@ class PDFReader(BasePDFReader):
330
371
  # Read and chunk.
331
372
  return self._pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=True)
332
373
 
333
- async def async_read(self, pdf: Union[str, Path, IO[Any]], password: Optional[str] = None) -> List[Document]:
374
+ async def async_read(
375
+ self,
376
+ pdf: Optional[Union[str, Path, IO[Any]]] = None,
377
+ name: Optional[str] = None,
378
+ password: Optional[str] = None,
379
+ ) -> List[Document]:
380
+ if pdf is None:
381
+ log_error("No pdf provided")
382
+ return []
383
+
334
384
  try:
335
385
  if isinstance(pdf, str):
336
- doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
386
+ doc_name = name or pdf.split("/")[-1].split(".")[0].replace(" ", "_")
337
387
  else:
338
388
  doc_name = pdf.name.split(".")[0]
339
389
  except Exception:
340
- doc_name = "pdf"
390
+ doc_name = name or "pdf"
341
391
 
342
392
  log_info(f"Reading: {doc_name}")
343
393
 
@@ -362,7 +412,11 @@ class PDFUrlReader(BasePDFReader):
362
412
  super().__init__(password=password, **kwargs)
363
413
  self.proxy = proxy
364
414
 
365
- def read(self, url: str, password: Optional[str] = None) -> List[Document]:
415
+ @classmethod
416
+ def get_supported_content_types(self) -> List[ContentType]:
417
+ return [ContentType.URL]
418
+
419
+ def read(self, url: str, name: Optional[str] = None, password: Optional[str] = None) -> List[Document]:
366
420
  if not url:
367
421
  raise ValueError("No url provided")
368
422
 
@@ -373,7 +427,7 @@ class PDFUrlReader(BasePDFReader):
373
427
  # Retry the request up to 3 times with exponential backoff
374
428
  response = fetch_with_retry(url, proxy=self.proxy)
375
429
 
376
- doc_name = url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
430
+ doc_name = name or url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
377
431
  pdf_reader = DocumentReader(BytesIO(response.content))
378
432
 
379
433
  # Handle PDF decryption
@@ -383,7 +437,7 @@ class PDFUrlReader(BasePDFReader):
383
437
  # Read and chunk.
384
438
  return self._pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=False)
385
439
 
386
- async def async_read(self, url: str, password: Optional[str] = None) -> List[Document]:
440
+ async def async_read(self, url: str, name: Optional[str] = None, password: Optional[str] = None) -> List[Document]:
387
441
  if not url:
388
442
  raise ValueError("No url provided")
389
443
 
@@ -397,7 +451,7 @@ class PDFUrlReader(BasePDFReader):
397
451
  async with httpx.AsyncClient(**client_args) as client: # type: ignore
398
452
  response = await async_fetch_with_retry(url, client=client)
399
453
 
400
- doc_name = url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
454
+ doc_name = name or url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
401
455
  pdf_reader = DocumentReader(BytesIO(response.content))
402
456
 
403
457
  # Handle PDF decryption
@@ -411,13 +465,15 @@ class PDFUrlReader(BasePDFReader):
411
465
  class PDFImageReader(BasePDFReader):
412
466
  """Reader for PDF files with text and images extraction"""
413
467
 
414
- def read(self, pdf: Union[str, Path, IO[Any]], password: Optional[str] = None) -> List[Document]:
468
+ def read(
469
+ self, pdf: Union[str, Path, IO[Any]], name: Optional[str] = None, password: Optional[str] = None
470
+ ) -> List[Document]:
415
471
  if not pdf:
416
472
  raise ValueError("No pdf provided")
417
473
 
418
474
  try:
419
475
  if isinstance(pdf, str):
420
- doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
476
+ doc_name = name or pdf.split("/")[-1].split(".")[0].replace(" ", "_")
421
477
  else:
422
478
  doc_name = pdf.name.split(".")[0]
423
479
  except Exception:
@@ -433,13 +489,15 @@ class PDFImageReader(BasePDFReader):
433
489
  # Read and chunk.
434
490
  return self._pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)
435
491
 
436
- async def async_read(self, pdf: Union[str, Path, IO[Any]], password: Optional[str] = None) -> List[Document]:
492
+ async def async_read(
493
+ self, pdf: Union[str, Path, IO[Any]], name: Optional[str] = None, password: Optional[str] = None
494
+ ) -> List[Document]:
437
495
  if not pdf:
438
496
  raise ValueError("No pdf provided")
439
497
 
440
498
  try:
441
499
  if isinstance(pdf, str):
442
- doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
500
+ doc_name = name or pdf.split("/")[-1].split(".")[0].replace(" ", "_")
443
501
  else:
444
502
  doc_name = pdf.name.split(".")[0]
445
503
  except Exception:
@@ -463,7 +521,7 @@ class PDFUrlImageReader(BasePDFReader):
463
521
  super().__init__(password=password, **kwargs)
464
522
  self.proxy = proxy
465
523
 
466
- def read(self, url: str, password: Optional[str] = None) -> List[Document]:
524
+ def read(self, url: str, name: Optional[str] = None, password: Optional[str] = None) -> List[Document]:
467
525
  if not url:
468
526
  raise ValueError("No url provided")
469
527
 
@@ -475,7 +533,7 @@ class PDFUrlImageReader(BasePDFReader):
475
533
  log_info(f"Reading: {url}")
476
534
  response = httpx.get(url, proxy=self.proxy) if self.proxy else httpx.get(url)
477
535
 
478
- doc_name = url.split("/")[-1].split(".")[0].replace(" ", "_")
536
+ doc_name = name or url.split("/")[-1].split(".")[0].replace(" ", "_")
479
537
  pdf_reader = DocumentReader(BytesIO(response.content))
480
538
 
481
539
  # Handle PDF decryption
@@ -485,7 +543,7 @@ class PDFUrlImageReader(BasePDFReader):
485
543
  # Read and chunk.
486
544
  return self._pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)
487
545
 
488
- async def async_read(self, url: str, password: Optional[str] = None) -> List[Document]:
546
+ async def async_read(self, url: str, name: Optional[str] = None, password: Optional[str] = None) -> List[Document]:
489
547
  if not url:
490
548
  raise ValueError("No url provided")
491
549
 
@@ -500,7 +558,7 @@ class PDFUrlImageReader(BasePDFReader):
500
558
  response = await client.get(url)
501
559
  response.raise_for_status()
502
560
 
503
- doc_name = url.split("/")[-1].split(".")[0].replace(" ", "_")
561
+ doc_name = name or url.split("/")[-1].split(".")[0].replace(" ", "_")
504
562
  pdf_reader = DocumentReader(BytesIO(response.content))
505
563
 
506
564
  # Handle PDF decryption
@@ -0,0 +1,275 @@
1
+ import os
2
+ from typing import Any, Callable, Dict, List, Optional
3
+
4
+ from agno.knowledge.reader.base import Reader
5
+
6
+
7
+ class ReaderFactory:
8
+ """Factory for creating and managing document readers with lazy loading."""
9
+
10
+ # Cache for instantiated readers
11
+ _reader_cache: Dict[str, Reader] = {}
12
+
13
+ @classmethod
14
+ def _get_pdf_reader(cls, **kwargs) -> Reader:
15
+ """Get PDF reader instance."""
16
+ from agno.knowledge.reader.pdf_reader import PDFReader
17
+
18
+ config: Dict[str, Any] = {"chunk": True, "chunk_size": 100}
19
+ config.update(kwargs)
20
+ return PDFReader(**config)
21
+
22
+ @classmethod
23
+ def _get_csv_reader(cls, **kwargs) -> Reader:
24
+ """Get CSV reader instance."""
25
+ from agno.knowledge.reader.csv_reader import CSVReader
26
+
27
+ config: Dict[str, Any] = {"name": "CSV Reader", "description": "Reads CSV files"}
28
+ config.update(kwargs)
29
+ return CSVReader(**config)
30
+
31
+ @classmethod
32
+ def _get_docx_reader(cls, **kwargs) -> Reader:
33
+ """Get Docx reader instance."""
34
+ from agno.knowledge.reader.docx_reader import DocxReader
35
+
36
+ config: Dict[str, Any] = {"name": "Docx Reader", "description": "Reads Docx files"}
37
+ config.update(kwargs)
38
+ return DocxReader(**config)
39
+
40
+ @classmethod
41
+ def _get_json_reader(cls, **kwargs) -> Reader:
42
+ """Get JSON reader instance."""
43
+ from agno.knowledge.reader.json_reader import JSONReader
44
+
45
+ config: Dict[str, Any] = {"name": "JSON Reader", "description": "Reads JSON files"}
46
+ config.update(kwargs)
47
+ return JSONReader(**config)
48
+
49
+ @classmethod
50
+ def _get_markdown_reader(cls, **kwargs) -> Reader:
51
+ """Get Markdown reader instance."""
52
+ from agno.knowledge.reader.markdown_reader import MarkdownReader
53
+
54
+ config: Dict[str, Any] = {"name": "Markdown Reader", "description": "Reads Markdown files"}
55
+ config.update(kwargs)
56
+ return MarkdownReader(**config)
57
+
58
+ @classmethod
59
+ def _get_text_reader(cls, **kwargs) -> Reader:
60
+ """Get Text reader instance."""
61
+ from agno.knowledge.reader.text_reader import TextReader
62
+
63
+ config: Dict[str, Any] = {"name": "Text Reader", "description": "Reads Text files"}
64
+ config.update(kwargs)
65
+ return TextReader(**config)
66
+
67
+ @classmethod
68
+ def _get_url_reader(cls, **kwargs) -> Reader:
69
+ """Get URL reader instance."""
70
+ from agno.knowledge.reader.url_reader import URLReader
71
+
72
+ config: Dict[str, Any] = {"name": "URL Reader", "description": "Reads URLs"}
73
+ config.update(kwargs)
74
+ return URLReader(**config)
75
+
76
+ @classmethod
77
+ def _get_website_reader(cls, **kwargs) -> Reader:
78
+ """Get Website reader instance."""
79
+ from agno.knowledge.reader.website_reader import WebsiteReader
80
+
81
+ config: Dict[str, Any] = {"name": "Website Reader", "description": "Reads Website files"}
82
+ config.update(kwargs)
83
+ return WebsiteReader(**config)
84
+
85
+ @classmethod
86
+ def _get_firecrawl_reader(cls, **kwargs) -> Reader:
87
+ """Get Firecrawl reader instance."""
88
+ from agno.knowledge.reader.firecrawl_reader import FirecrawlReader
89
+
90
+ config: Dict[str, Any] = {
91
+ "api_key": kwargs.get("api_key") or os.getenv("FIRECRAWL_API_KEY"),
92
+ "mode": "crawl",
93
+ "name": "Firecrawl Reader",
94
+ "description": "Crawls websites",
95
+ }
96
+ config.update(kwargs)
97
+ return FirecrawlReader(**config)
98
+
99
+ @classmethod
100
+ def _get_youtube_reader(cls, **kwargs) -> Reader:
101
+ """Get YouTube reader instance."""
102
+ from agno.knowledge.reader.youtube_reader import YouTubeReader
103
+
104
+ config: Dict[str, Any] = {"name": "YouTube Reader", "description": "Reads YouTube videos"}
105
+ config.update(kwargs)
106
+ return YouTubeReader(**config)
107
+
108
+ @classmethod
109
+ def _get_pdf_url_reader(cls, **kwargs) -> Reader:
110
+ """Get PDF URL reader instance."""
111
+ from agno.knowledge.reader.pdf_reader import PDFUrlReader
112
+
113
+ config: Dict[str, Any] = {"name": "PDF URL Reader", "description": "Reads PDF URLs"}
114
+ config.update(kwargs)
115
+ return PDFUrlReader(**config)
116
+
117
+ @classmethod
118
+ def _get_csv_url_reader(cls, **kwargs) -> Reader:
119
+ """Get CSV URL reader instance."""
120
+ from agno.knowledge.reader.csv_reader import CSVUrlReader
121
+
122
+ config: Dict[str, Any] = {"name": "CSV URL Reader", "description": "Reads CSV URLs"}
123
+ config.update(kwargs)
124
+ return CSVUrlReader(**config)
125
+
126
+ @classmethod
127
+ def _get_s3_reader(cls, **kwargs) -> Reader:
128
+ """Get S3 reader instance."""
129
+ from agno.knowledge.reader.s3_reader import S3Reader
130
+
131
+ config: Dict[str, Any] = {"name": "S3 Reader", "description": "Reads S3 files"}
132
+ config.update(kwargs)
133
+ return S3Reader(**config)
134
+
135
+ @classmethod
136
+ def _get_gcs_reader(cls, **kwargs) -> Reader:
137
+ """Get GCS reader instance."""
138
+ from agno.knowledge.reader.gcs_reader import GCSReader
139
+
140
+ config: Dict[str, Any] = {"name": "GCS Reader", "description": "Reads GCS files"}
141
+ config.update(kwargs)
142
+ return GCSReader(**config)
143
+
144
+ @classmethod
145
+ def _get_arxiv_reader(cls, **kwargs) -> Reader:
146
+ """Get Arxiv reader instance."""
147
+ from agno.knowledge.reader.arxiv_reader import ArxivReader
148
+
149
+ config: Dict[str, Any] = {"name": "Arxiv Reader", "description": "Reads Arxiv papers"}
150
+ config.update(kwargs)
151
+ return ArxivReader(**config)
152
+
153
+ @classmethod
154
+ def _get_wikipedia_reader(cls, **kwargs) -> Reader:
155
+ """Get Wikipedia reader instance."""
156
+ from agno.knowledge.reader.wikipedia_reader import WikipediaReader
157
+
158
+ config: Dict[str, Any] = {"name": "Wikipedia Reader", "description": "Reads Wikipedia articles"}
159
+ config.update(kwargs)
160
+ return WikipediaReader(**config)
161
+
162
+ @classmethod
163
+ def _get_web_search_reader(cls, **kwargs) -> Reader:
164
+ """Get Web Search reader instance."""
165
+ from agno.knowledge.reader.web_search_reader import WebSearchReader
166
+
167
+ config: Dict[str, Any] = {"name": "Web Search Reader", "description": "Performs web searches"}
168
+ config.update(kwargs)
169
+ return WebSearchReader(**config)
170
+
171
+ @classmethod
172
+ def _get_reader_method(cls, reader_key: str) -> Callable[[], Reader]:
173
+ """Get the appropriate reader method for the given key."""
174
+ method_name = f"_get_{reader_key}_reader"
175
+ if not hasattr(cls, method_name):
176
+ raise ValueError(f"Unknown reader: {reader_key}")
177
+ return getattr(cls, method_name)
178
+
179
+ @classmethod
180
+ def create_reader(cls, reader_key: str, **kwargs) -> Reader:
181
+ """Create a reader instance with the given key and optional overrides."""
182
+ if reader_key in cls._reader_cache:
183
+ return cls._reader_cache[reader_key]
184
+
185
+ # Get the reader method and create the instance
186
+ reader_method = cls._get_reader_method(reader_key)
187
+ reader = reader_method(**kwargs)
188
+
189
+ # Cache the reader
190
+ cls._reader_cache[reader_key] = reader
191
+
192
+ return reader
193
+
194
+ @classmethod
195
+ def get_reader_for_extension(cls, extension: str) -> Reader:
196
+ """Get the appropriate reader for a file extension."""
197
+ extension = extension.lower()
198
+
199
+ if extension in [".pdf", "application/pdf"]:
200
+ return cls.create_reader("pdf")
201
+ elif extension in [".csv", "text/csv"]:
202
+ return cls.create_reader("csv")
203
+ elif extension in [".docx", ".doc"]:
204
+ return cls.create_reader("docx")
205
+ elif extension == ".json":
206
+ return cls.create_reader("json")
207
+ elif extension in [".md", ".markdown"]:
208
+ return cls.create_reader("markdown")
209
+ elif extension in [".txt", ".text"]:
210
+ return cls.create_reader("text")
211
+ else:
212
+ # Default to text reader for unknown extensions
213
+ return cls.create_reader("text")
214
+
215
+ @classmethod
216
+ def get_reader_for_url(cls, url: str) -> Reader:
217
+ """Get the appropriate reader for a URL."""
218
+ url_lower = url.lower()
219
+
220
+ # Check for YouTube URLs
221
+ if any(domain in url_lower for domain in ["youtube.com", "youtu.be"]):
222
+ return cls.create_reader("youtube")
223
+
224
+ # Default to URL reader
225
+ return cls.create_reader("url")
226
+
227
+ @classmethod
228
+ def get_reader_for_url_file(cls, extension: str) -> Reader:
229
+ """Get the appropriate reader for a URL file extension."""
230
+ extension = extension.lower()
231
+
232
+ if extension == ".pdf":
233
+ return cls.create_reader("pdf_url")
234
+ elif extension == ".csv":
235
+ return cls.create_reader("csv_url")
236
+ else:
237
+ return cls.create_reader("url")
238
+
239
+ @classmethod
240
+ def get_all_reader_keys(cls) -> List[str]:
241
+ """Get all available reader keys."""
242
+ # Extract reader keys from method names
243
+ reader_keys = []
244
+ for attr_name in dir(cls):
245
+ if attr_name.startswith("_get_") and attr_name.endswith("_reader"):
246
+ reader_key = attr_name[5:-7] # Remove "_get_" prefix and "_reader" suffix
247
+ reader_keys.append(reader_key)
248
+ return reader_keys
249
+
250
+ @classmethod
251
+ def create_all_readers(cls) -> Dict[str, Reader]:
252
+ """Create all readers and return them as a dictionary."""
253
+ readers = {}
254
+ for reader_key in cls.get_all_reader_keys():
255
+ readers[reader_key] = cls.create_reader(reader_key)
256
+ return readers
257
+
258
+ @classmethod
259
+ def clear_cache(cls):
260
+ """Clear the reader cache."""
261
+ cls._reader_cache.clear()
262
+
263
+ @classmethod
264
+ def register_reader(
265
+ cls,
266
+ key: str,
267
+ reader_method,
268
+ name: str,
269
+ description: str,
270
+ extensions: Optional[List[str]] = None,
271
+ ):
272
+ """Register a new reader type."""
273
+ # Add the reader method to the class
274
+ method_name = f"_get_{key}_reader"
275
+ setattr(cls, method_name, classmethod(reader_method))