agno 1.8.1__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 (580) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +2778 -4123
  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/memory/__init__.py +2 -10
  137. agno/memory/manager.py +1003 -148
  138. agno/models/aimlapi/__init__.py +2 -2
  139. agno/models/aimlapi/aimlapi.py +6 -6
  140. agno/models/anthropic/claude.py +129 -82
  141. agno/models/aws/bedrock.py +107 -175
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +347 -287
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +100 -42
  148. agno/models/groq/groq.py +97 -35
  149. agno/models/huggingface/huggingface.py +92 -27
  150. agno/models/ibm/watsonx.py +72 -13
  151. agno/models/litellm/chat.py +85 -13
  152. agno/models/message.py +38 -144
  153. agno/models/meta/llama.py +85 -49
  154. agno/models/metrics.py +120 -0
  155. agno/models/mistral/mistral.py +90 -21
  156. agno/models/ollama/__init__.py +0 -2
  157. agno/models/ollama/chat.py +84 -46
  158. agno/models/openai/chat.py +121 -23
  159. agno/models/openai/responses.py +178 -105
  160. agno/models/perplexity/perplexity.py +26 -2
  161. agno/models/portkey/portkey.py +0 -7
  162. agno/models/response.py +14 -8
  163. agno/models/utils.py +20 -0
  164. agno/models/vercel/__init__.py +2 -2
  165. agno/models/vercel/v0.py +1 -1
  166. agno/models/vllm/__init__.py +2 -2
  167. agno/models/vllm/vllm.py +3 -3
  168. agno/models/xai/xai.py +10 -10
  169. agno/os/__init__.py +3 -0
  170. agno/os/app.py +393 -0
  171. agno/os/auth.py +47 -0
  172. agno/os/config.py +103 -0
  173. agno/os/interfaces/agui/__init__.py +3 -0
  174. agno/os/interfaces/agui/agui.py +31 -0
  175. agno/{app/agui/async_router.py → os/interfaces/agui/router.py} +16 -16
  176. agno/{app → os/interfaces}/agui/utils.py +65 -28
  177. agno/os/interfaces/base.py +21 -0
  178. agno/os/interfaces/slack/__init__.py +3 -0
  179. agno/{app/slack/async_router.py → os/interfaces/slack/router.py} +3 -5
  180. agno/os/interfaces/slack/slack.py +33 -0
  181. agno/os/interfaces/whatsapp/__init__.py +3 -0
  182. agno/{app/whatsapp/async_router.py → os/interfaces/whatsapp/router.py} +4 -7
  183. agno/os/interfaces/whatsapp/whatsapp.py +30 -0
  184. agno/os/router.py +843 -0
  185. agno/os/routers/__init__.py +3 -0
  186. agno/os/routers/evals/__init__.py +3 -0
  187. agno/os/routers/evals/evals.py +204 -0
  188. agno/os/routers/evals/schemas.py +142 -0
  189. agno/os/routers/evals/utils.py +161 -0
  190. agno/os/routers/knowledge/__init__.py +3 -0
  191. agno/os/routers/knowledge/knowledge.py +413 -0
  192. agno/os/routers/knowledge/schemas.py +118 -0
  193. agno/os/routers/memory/__init__.py +3 -0
  194. agno/os/routers/memory/memory.py +179 -0
  195. agno/os/routers/memory/schemas.py +58 -0
  196. agno/os/routers/metrics/__init__.py +3 -0
  197. agno/os/routers/metrics/metrics.py +58 -0
  198. agno/os/routers/metrics/schemas.py +47 -0
  199. agno/os/routers/session/__init__.py +3 -0
  200. agno/os/routers/session/session.py +163 -0
  201. agno/os/schema.py +892 -0
  202. agno/{app/playground → os}/settings.py +8 -15
  203. agno/os/utils.py +270 -0
  204. agno/reasoning/azure_ai_foundry.py +4 -4
  205. agno/reasoning/deepseek.py +4 -4
  206. agno/reasoning/default.py +6 -11
  207. agno/reasoning/groq.py +4 -4
  208. agno/reasoning/helpers.py +4 -6
  209. agno/reasoning/ollama.py +4 -4
  210. agno/reasoning/openai.py +4 -4
  211. agno/run/{response.py → agent.py} +144 -72
  212. agno/run/base.py +44 -58
  213. agno/run/cancel.py +83 -0
  214. agno/run/team.py +133 -77
  215. agno/run/workflow.py +537 -12
  216. agno/session/__init__.py +10 -0
  217. agno/session/agent.py +244 -0
  218. agno/session/summary.py +225 -0
  219. agno/session/team.py +262 -0
  220. agno/{storage/session/v2 → session}/workflow.py +47 -24
  221. agno/team/__init__.py +15 -16
  222. agno/team/team.py +2961 -4253
  223. agno/tools/agentql.py +14 -5
  224. agno/tools/airflow.py +9 -4
  225. agno/tools/api.py +7 -3
  226. agno/tools/apify.py +2 -46
  227. agno/tools/arxiv.py +8 -3
  228. agno/tools/aws_lambda.py +7 -5
  229. agno/tools/aws_ses.py +7 -1
  230. agno/tools/baidusearch.py +4 -1
  231. agno/tools/bitbucket.py +4 -4
  232. agno/tools/brandfetch.py +14 -11
  233. agno/tools/bravesearch.py +4 -1
  234. agno/tools/brightdata.py +42 -22
  235. agno/tools/browserbase.py +13 -4
  236. agno/tools/calcom.py +12 -10
  237. agno/tools/calculator.py +10 -27
  238. agno/tools/cartesia.py +18 -13
  239. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  240. agno/tools/confluence.py +8 -8
  241. agno/tools/crawl4ai.py +7 -1
  242. agno/tools/csv_toolkit.py +9 -8
  243. agno/tools/dalle.py +18 -11
  244. agno/tools/daytona.py +13 -16
  245. agno/tools/decorator.py +6 -3
  246. agno/tools/desi_vocal.py +16 -7
  247. agno/tools/discord.py +11 -8
  248. agno/tools/docker.py +30 -42
  249. agno/tools/duckdb.py +34 -53
  250. agno/tools/duckduckgo.py +8 -7
  251. agno/tools/e2b.py +61 -61
  252. agno/tools/eleven_labs.py +35 -28
  253. agno/tools/email.py +4 -1
  254. agno/tools/evm.py +7 -1
  255. agno/tools/exa.py +19 -14
  256. agno/tools/fal.py +29 -29
  257. agno/tools/file.py +9 -8
  258. agno/tools/financial_datasets.py +25 -44
  259. agno/tools/firecrawl.py +22 -22
  260. agno/tools/function.py +68 -17
  261. agno/tools/giphy.py +22 -10
  262. agno/tools/github.py +48 -126
  263. agno/tools/gmail.py +45 -61
  264. agno/tools/google_bigquery.py +7 -6
  265. agno/tools/google_maps.py +11 -26
  266. agno/tools/googlesearch.py +7 -2
  267. agno/tools/googlesheets.py +21 -17
  268. agno/tools/hackernews.py +9 -5
  269. agno/tools/jina.py +5 -4
  270. agno/tools/jira.py +18 -9
  271. agno/tools/knowledge.py +31 -32
  272. agno/tools/linear.py +18 -33
  273. agno/tools/linkup.py +5 -1
  274. agno/tools/local_file_system.py +8 -5
  275. agno/tools/lumalab.py +31 -19
  276. agno/tools/mem0.py +18 -12
  277. agno/tools/memori.py +14 -10
  278. agno/tools/mlx_transcribe.py +3 -2
  279. agno/tools/models/azure_openai.py +32 -14
  280. agno/tools/models/gemini.py +58 -31
  281. agno/tools/models/groq.py +29 -20
  282. agno/tools/models/nebius.py +27 -11
  283. agno/tools/models_labs.py +39 -15
  284. agno/tools/moviepy_video.py +7 -6
  285. agno/tools/neo4j.py +10 -8
  286. agno/tools/newspaper.py +7 -2
  287. agno/tools/newspaper4k.py +8 -3
  288. agno/tools/openai.py +57 -26
  289. agno/tools/openbb.py +12 -11
  290. agno/tools/opencv.py +62 -46
  291. agno/tools/openweather.py +14 -12
  292. agno/tools/pandas.py +11 -3
  293. agno/tools/postgres.py +4 -12
  294. agno/tools/pubmed.py +4 -1
  295. agno/tools/python.py +9 -22
  296. agno/tools/reasoning.py +35 -27
  297. agno/tools/reddit.py +11 -26
  298. agno/tools/replicate.py +54 -41
  299. agno/tools/resend.py +4 -1
  300. agno/tools/scrapegraph.py +15 -14
  301. agno/tools/searxng.py +10 -23
  302. agno/tools/serpapi.py +6 -3
  303. agno/tools/serper.py +13 -4
  304. agno/tools/shell.py +9 -2
  305. agno/tools/slack.py +12 -11
  306. agno/tools/sleep.py +3 -2
  307. agno/tools/spider.py +24 -4
  308. agno/tools/sql.py +7 -6
  309. agno/tools/tavily.py +6 -4
  310. agno/tools/telegram.py +12 -4
  311. agno/tools/todoist.py +11 -31
  312. agno/tools/toolkit.py +1 -1
  313. agno/tools/trafilatura.py +22 -6
  314. agno/tools/trello.py +9 -22
  315. agno/tools/twilio.py +10 -3
  316. agno/tools/user_control_flow.py +6 -1
  317. agno/tools/valyu.py +34 -5
  318. agno/tools/visualization.py +19 -28
  319. agno/tools/webbrowser.py +4 -3
  320. agno/tools/webex.py +11 -7
  321. agno/tools/website.py +15 -46
  322. agno/tools/webtools.py +12 -4
  323. agno/tools/whatsapp.py +5 -9
  324. agno/tools/wikipedia.py +20 -13
  325. agno/tools/x.py +14 -13
  326. agno/tools/yfinance.py +13 -40
  327. agno/tools/youtube.py +26 -20
  328. agno/tools/zendesk.py +7 -2
  329. agno/tools/zep.py +10 -7
  330. agno/tools/zoom.py +10 -9
  331. agno/utils/common.py +1 -19
  332. agno/utils/events.py +95 -118
  333. agno/utils/knowledge.py +29 -0
  334. agno/utils/log.py +2 -2
  335. agno/utils/mcp.py +11 -5
  336. agno/utils/media.py +39 -0
  337. agno/utils/message.py +12 -1
  338. agno/utils/models/claude.py +6 -4
  339. agno/utils/models/mistral.py +8 -7
  340. agno/utils/models/schema_utils.py +3 -3
  341. agno/utils/pprint.py +33 -32
  342. agno/utils/print_response/agent.py +779 -0
  343. agno/utils/print_response/team.py +1565 -0
  344. agno/utils/print_response/workflow.py +1451 -0
  345. agno/utils/prompts.py +14 -14
  346. agno/utils/reasoning.py +87 -0
  347. agno/utils/response.py +42 -42
  348. agno/utils/string.py +8 -22
  349. agno/utils/team.py +50 -0
  350. agno/utils/timer.py +2 -2
  351. agno/vectordb/base.py +33 -21
  352. agno/vectordb/cassandra/cassandra.py +287 -23
  353. agno/vectordb/chroma/chromadb.py +482 -59
  354. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  355. agno/vectordb/couchbase/couchbase.py +309 -29
  356. agno/vectordb/lancedb/lance_db.py +360 -21
  357. agno/vectordb/langchaindb/__init__.py +5 -0
  358. agno/vectordb/langchaindb/langchaindb.py +145 -0
  359. agno/vectordb/lightrag/__init__.py +5 -0
  360. agno/vectordb/lightrag/lightrag.py +374 -0
  361. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  362. agno/vectordb/milvus/milvus.py +242 -32
  363. agno/vectordb/mongodb/mongodb.py +200 -24
  364. agno/vectordb/pgvector/pgvector.py +319 -37
  365. agno/vectordb/pineconedb/pineconedb.py +221 -27
  366. agno/vectordb/qdrant/qdrant.py +334 -14
  367. agno/vectordb/singlestore/singlestore.py +286 -29
  368. agno/vectordb/surrealdb/surrealdb.py +187 -7
  369. agno/vectordb/upstashdb/upstashdb.py +342 -26
  370. agno/vectordb/weaviate/weaviate.py +227 -165
  371. agno/workflow/__init__.py +17 -13
  372. agno/workflow/{v2/condition.py → condition.py} +135 -32
  373. agno/workflow/{v2/loop.py → loop.py} +115 -28
  374. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  375. agno/workflow/{v2/router.py → router.py} +133 -32
  376. agno/workflow/{v2/step.py → step.py} +200 -42
  377. agno/workflow/{v2/steps.py → steps.py} +147 -66
  378. agno/workflow/types.py +482 -0
  379. agno/workflow/workflow.py +2394 -696
  380. agno-2.0.0a1.dist-info/METADATA +355 -0
  381. agno-2.0.0a1.dist-info/RECORD +514 -0
  382. agno/agent/metrics.py +0 -107
  383. agno/api/app.py +0 -35
  384. agno/api/playground.py +0 -92
  385. agno/api/schemas/app.py +0 -12
  386. agno/api/schemas/playground.py +0 -22
  387. agno/api/schemas/user.py +0 -35
  388. agno/api/schemas/workspace.py +0 -46
  389. agno/api/user.py +0 -160
  390. agno/api/workflows.py +0 -33
  391. agno/api/workspace.py +0 -175
  392. agno/app/agui/__init__.py +0 -3
  393. agno/app/agui/app.py +0 -17
  394. agno/app/agui/sync_router.py +0 -120
  395. agno/app/base.py +0 -186
  396. agno/app/discord/__init__.py +0 -3
  397. agno/app/fastapi/__init__.py +0 -3
  398. agno/app/fastapi/app.py +0 -107
  399. agno/app/fastapi/async_router.py +0 -457
  400. agno/app/fastapi/sync_router.py +0 -448
  401. agno/app/playground/app.py +0 -228
  402. agno/app/playground/async_router.py +0 -1050
  403. agno/app/playground/deploy.py +0 -249
  404. agno/app/playground/operator.py +0 -183
  405. agno/app/playground/schemas.py +0 -220
  406. agno/app/playground/serve.py +0 -55
  407. agno/app/playground/sync_router.py +0 -1042
  408. agno/app/playground/utils.py +0 -46
  409. agno/app/settings.py +0 -15
  410. agno/app/slack/__init__.py +0 -3
  411. agno/app/slack/app.py +0 -19
  412. agno/app/slack/sync_router.py +0 -92
  413. agno/app/utils.py +0 -54
  414. agno/app/whatsapp/__init__.py +0 -3
  415. agno/app/whatsapp/app.py +0 -15
  416. agno/app/whatsapp/sync_router.py +0 -197
  417. agno/cli/auth_server.py +0 -249
  418. agno/cli/config.py +0 -274
  419. agno/cli/console.py +0 -88
  420. agno/cli/credentials.py +0 -23
  421. agno/cli/entrypoint.py +0 -571
  422. agno/cli/operator.py +0 -357
  423. agno/cli/settings.py +0 -96
  424. agno/cli/ws/ws_cli.py +0 -817
  425. agno/constants.py +0 -13
  426. agno/document/__init__.py +0 -5
  427. agno/document/chunking/semantic.py +0 -45
  428. agno/document/chunking/strategy.py +0 -31
  429. agno/document/reader/__init__.py +0 -5
  430. agno/document/reader/base.py +0 -47
  431. agno/document/reader/docx_reader.py +0 -60
  432. agno/document/reader/gcs/pdf_reader.py +0 -44
  433. agno/document/reader/s3/pdf_reader.py +0 -59
  434. agno/document/reader/s3/text_reader.py +0 -63
  435. agno/document/reader/url_reader.py +0 -59
  436. agno/document/reader/youtube_reader.py +0 -58
  437. agno/embedder/__init__.py +0 -5
  438. agno/embedder/langdb.py +0 -80
  439. agno/embedder/mistral.py +0 -82
  440. agno/embedder/openai.py +0 -78
  441. agno/file/__init__.py +0 -5
  442. agno/file/file.py +0 -16
  443. agno/file/local/csv.py +0 -32
  444. agno/file/local/txt.py +0 -19
  445. agno/infra/app.py +0 -240
  446. agno/infra/base.py +0 -144
  447. agno/infra/context.py +0 -20
  448. agno/infra/db_app.py +0 -52
  449. agno/infra/resource.py +0 -205
  450. agno/infra/resources.py +0 -55
  451. agno/knowledge/agent.py +0 -702
  452. agno/knowledge/arxiv.py +0 -33
  453. agno/knowledge/combined.py +0 -36
  454. agno/knowledge/csv.py +0 -144
  455. agno/knowledge/csv_url.py +0 -124
  456. agno/knowledge/document.py +0 -223
  457. agno/knowledge/docx.py +0 -137
  458. agno/knowledge/firecrawl.py +0 -34
  459. agno/knowledge/gcs/__init__.py +0 -0
  460. agno/knowledge/gcs/base.py +0 -39
  461. agno/knowledge/gcs/pdf.py +0 -125
  462. agno/knowledge/json.py +0 -137
  463. agno/knowledge/langchain.py +0 -71
  464. agno/knowledge/light_rag.py +0 -273
  465. agno/knowledge/llamaindex.py +0 -66
  466. agno/knowledge/markdown.py +0 -154
  467. agno/knowledge/pdf.py +0 -164
  468. agno/knowledge/pdf_bytes.py +0 -42
  469. agno/knowledge/pdf_url.py +0 -148
  470. agno/knowledge/s3/__init__.py +0 -0
  471. agno/knowledge/s3/base.py +0 -64
  472. agno/knowledge/s3/pdf.py +0 -33
  473. agno/knowledge/s3/text.py +0 -34
  474. agno/knowledge/text.py +0 -141
  475. agno/knowledge/url.py +0 -46
  476. agno/knowledge/website.py +0 -179
  477. agno/knowledge/wikipedia.py +0 -32
  478. agno/knowledge/youtube.py +0 -35
  479. agno/memory/agent.py +0 -423
  480. agno/memory/classifier.py +0 -104
  481. agno/memory/db/__init__.py +0 -5
  482. agno/memory/db/base.py +0 -42
  483. agno/memory/db/mongodb.py +0 -189
  484. agno/memory/db/postgres.py +0 -203
  485. agno/memory/db/sqlite.py +0 -193
  486. agno/memory/memory.py +0 -22
  487. agno/memory/row.py +0 -36
  488. agno/memory/summarizer.py +0 -201
  489. agno/memory/summary.py +0 -19
  490. agno/memory/team.py +0 -415
  491. agno/memory/v2/__init__.py +0 -2
  492. agno/memory/v2/db/__init__.py +0 -1
  493. agno/memory/v2/db/base.py +0 -42
  494. agno/memory/v2/db/firestore.py +0 -339
  495. agno/memory/v2/db/mongodb.py +0 -196
  496. agno/memory/v2/db/postgres.py +0 -214
  497. agno/memory/v2/db/redis.py +0 -187
  498. agno/memory/v2/db/schema.py +0 -54
  499. agno/memory/v2/db/sqlite.py +0 -209
  500. agno/memory/v2/manager.py +0 -437
  501. agno/memory/v2/memory.py +0 -1097
  502. agno/memory/v2/schema.py +0 -55
  503. agno/memory/v2/summarizer.py +0 -215
  504. agno/memory/workflow.py +0 -38
  505. agno/models/ollama/tools.py +0 -430
  506. agno/models/qwen/__init__.py +0 -5
  507. agno/playground/__init__.py +0 -10
  508. agno/playground/deploy.py +0 -3
  509. agno/playground/playground.py +0 -3
  510. agno/playground/serve.py +0 -3
  511. agno/playground/settings.py +0 -3
  512. agno/reranker/__init__.py +0 -0
  513. agno/run/v2/__init__.py +0 -0
  514. agno/run/v2/workflow.py +0 -567
  515. agno/storage/__init__.py +0 -0
  516. agno/storage/agent/__init__.py +0 -0
  517. agno/storage/agent/dynamodb.py +0 -1
  518. agno/storage/agent/json.py +0 -1
  519. agno/storage/agent/mongodb.py +0 -1
  520. agno/storage/agent/postgres.py +0 -1
  521. agno/storage/agent/singlestore.py +0 -1
  522. agno/storage/agent/sqlite.py +0 -1
  523. agno/storage/agent/yaml.py +0 -1
  524. agno/storage/base.py +0 -60
  525. agno/storage/dynamodb.py +0 -673
  526. agno/storage/firestore.py +0 -297
  527. agno/storage/gcs_json.py +0 -261
  528. agno/storage/in_memory.py +0 -234
  529. agno/storage/json.py +0 -237
  530. agno/storage/mongodb.py +0 -328
  531. agno/storage/mysql.py +0 -685
  532. agno/storage/postgres.py +0 -682
  533. agno/storage/redis.py +0 -336
  534. agno/storage/session/__init__.py +0 -16
  535. agno/storage/session/agent.py +0 -64
  536. agno/storage/session/team.py +0 -63
  537. agno/storage/session/v2/__init__.py +0 -5
  538. agno/storage/session/workflow.py +0 -61
  539. agno/storage/singlestore.py +0 -606
  540. agno/storage/sqlite.py +0 -646
  541. agno/storage/workflow/__init__.py +0 -0
  542. agno/storage/workflow/mongodb.py +0 -1
  543. agno/storage/workflow/postgres.py +0 -1
  544. agno/storage/workflow/sqlite.py +0 -1
  545. agno/storage/yaml.py +0 -241
  546. agno/tools/thinking.py +0 -73
  547. agno/utils/defaults.py +0 -57
  548. agno/utils/filesystem.py +0 -39
  549. agno/utils/git.py +0 -52
  550. agno/utils/json_io.py +0 -30
  551. agno/utils/load_env.py +0 -19
  552. agno/utils/py_io.py +0 -19
  553. agno/utils/pyproject.py +0 -18
  554. agno/utils/resource_filter.py +0 -31
  555. agno/workflow/v2/__init__.py +0 -21
  556. agno/workflow/v2/types.py +0 -357
  557. agno/workflow/v2/workflow.py +0 -3312
  558. agno/workspace/__init__.py +0 -0
  559. agno/workspace/config.py +0 -325
  560. agno/workspace/enums.py +0 -6
  561. agno/workspace/helpers.py +0 -52
  562. agno/workspace/operator.py +0 -757
  563. agno/workspace/settings.py +0 -158
  564. agno-1.8.1.dist-info/METADATA +0 -982
  565. agno-1.8.1.dist-info/RECORD +0 -566
  566. agno-1.8.1.dist-info/entry_points.txt +0 -3
  567. /agno/{app → db/migrations}/__init__.py +0 -0
  568. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  569. /agno/{cli → integrations}/__init__.py +0 -0
  570. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  571. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  572. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  573. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  574. /agno/{app → os/interfaces}/slack/security.py +0 -0
  575. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  576. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  577. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  578. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/WHEEL +0 -0
  579. {agno-1.8.1.dist-info → agno-2.0.0a1.dist-info}/licenses/LICENSE +0 -0
  580. {agno-1.8.1.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))