agno 1.7.8__tar.gz → 1.7.10__tar.gz

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 (564) hide show
  1. {agno-1.7.8 → agno-1.7.10}/PKG-INFO +2 -1
  2. {agno-1.7.8 → agno-1.7.10}/agno/agent/agent.py +33 -27
  3. agno-1.7.10/agno/document/reader/pdf_reader.py +511 -0
  4. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/agent.py +68 -72
  5. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/pdf.py +32 -8
  6. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/pdf_url.py +13 -5
  7. {agno-1.7.8 → agno-1.7.10}/agno/models/openai/responses.py +30 -1
  8. {agno-1.7.8 → agno-1.7.10}/agno/run/response.py +10 -0
  9. {agno-1.7.8 → agno-1.7.10}/agno/run/team.py +10 -0
  10. {agno-1.7.8 → agno-1.7.10}/agno/team/team.py +39 -20
  11. {agno-1.7.8 → agno-1.7.10}/agno/tools/aws_lambda.py +10 -0
  12. {agno-1.7.8 → agno-1.7.10}/agno/tools/github.py +54 -18
  13. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/lancedb/lance_db.py +10 -2
  14. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/pgvector/pgvector.py +3 -0
  15. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/weaviate/weaviate.py +84 -18
  16. {agno-1.7.8 → agno-1.7.10}/agno.egg-info/PKG-INFO +2 -1
  17. {agno-1.7.8 → agno-1.7.10}/agno.egg-info/requires.txt +1 -0
  18. {agno-1.7.8 → agno-1.7.10}/pyproject.toml +2 -1
  19. agno-1.7.8/agno/document/reader/pdf_reader.py +0 -352
  20. {agno-1.7.8 → agno-1.7.10}/LICENSE +0 -0
  21. {agno-1.7.8 → agno-1.7.10}/README.md +0 -0
  22. {agno-1.7.8 → agno-1.7.10}/agno/__init__.py +0 -0
  23. {agno-1.7.8 → agno-1.7.10}/agno/agent/__init__.py +0 -0
  24. {agno-1.7.8 → agno-1.7.10}/agno/agent/metrics.py +0 -0
  25. {agno-1.7.8 → agno-1.7.10}/agno/api/__init__.py +0 -0
  26. {agno-1.7.8 → agno-1.7.10}/agno/api/agent.py +0 -0
  27. {agno-1.7.8 → agno-1.7.10}/agno/api/api.py +0 -0
  28. {agno-1.7.8 → agno-1.7.10}/agno/api/app.py +0 -0
  29. {agno-1.7.8 → agno-1.7.10}/agno/api/evals.py +0 -0
  30. {agno-1.7.8 → agno-1.7.10}/agno/api/playground.py +0 -0
  31. {agno-1.7.8 → agno-1.7.10}/agno/api/routes.py +0 -0
  32. {agno-1.7.8 → agno-1.7.10}/agno/api/schemas/__init__.py +0 -0
  33. {agno-1.7.8 → agno-1.7.10}/agno/api/schemas/agent.py +0 -0
  34. {agno-1.7.8 → agno-1.7.10}/agno/api/schemas/app.py +0 -0
  35. {agno-1.7.8 → agno-1.7.10}/agno/api/schemas/evals.py +0 -0
  36. {agno-1.7.8 → agno-1.7.10}/agno/api/schemas/playground.py +0 -0
  37. {agno-1.7.8 → agno-1.7.10}/agno/api/schemas/response.py +0 -0
  38. {agno-1.7.8 → agno-1.7.10}/agno/api/schemas/team.py +0 -0
  39. {agno-1.7.8 → agno-1.7.10}/agno/api/schemas/user.py +0 -0
  40. {agno-1.7.8 → agno-1.7.10}/agno/api/schemas/workflows.py +0 -0
  41. {agno-1.7.8 → agno-1.7.10}/agno/api/schemas/workspace.py +0 -0
  42. {agno-1.7.8 → agno-1.7.10}/agno/api/team.py +0 -0
  43. {agno-1.7.8 → agno-1.7.10}/agno/api/user.py +0 -0
  44. {agno-1.7.8 → agno-1.7.10}/agno/api/workflows.py +0 -0
  45. {agno-1.7.8 → agno-1.7.10}/agno/api/workspace.py +0 -0
  46. {agno-1.7.8 → agno-1.7.10}/agno/app/__init__.py +0 -0
  47. {agno-1.7.8 → agno-1.7.10}/agno/app/agui/__init__.py +0 -0
  48. {agno-1.7.8 → agno-1.7.10}/agno/app/agui/app.py +0 -0
  49. {agno-1.7.8 → agno-1.7.10}/agno/app/agui/async_router.py +0 -0
  50. {agno-1.7.8 → agno-1.7.10}/agno/app/agui/sync_router.py +0 -0
  51. {agno-1.7.8 → agno-1.7.10}/agno/app/agui/utils.py +0 -0
  52. {agno-1.7.8 → agno-1.7.10}/agno/app/base.py +0 -0
  53. {agno-1.7.8 → agno-1.7.10}/agno/app/discord/__init__.py +0 -0
  54. {agno-1.7.8 → agno-1.7.10}/agno/app/discord/client.py +0 -0
  55. {agno-1.7.8 → agno-1.7.10}/agno/app/fastapi/__init__.py +0 -0
  56. {agno-1.7.8 → agno-1.7.10}/agno/app/fastapi/app.py +0 -0
  57. {agno-1.7.8 → agno-1.7.10}/agno/app/fastapi/async_router.py +0 -0
  58. {agno-1.7.8 → agno-1.7.10}/agno/app/fastapi/sync_router.py +0 -0
  59. {agno-1.7.8 → agno-1.7.10}/agno/app/playground/__init__.py +0 -0
  60. {agno-1.7.8 → agno-1.7.10}/agno/app/playground/app.py +0 -0
  61. {agno-1.7.8 → agno-1.7.10}/agno/app/playground/async_router.py +0 -0
  62. {agno-1.7.8 → agno-1.7.10}/agno/app/playground/deploy.py +0 -0
  63. {agno-1.7.8 → agno-1.7.10}/agno/app/playground/operator.py +0 -0
  64. {agno-1.7.8 → agno-1.7.10}/agno/app/playground/schemas.py +0 -0
  65. {agno-1.7.8 → agno-1.7.10}/agno/app/playground/serve.py +0 -0
  66. {agno-1.7.8 → agno-1.7.10}/agno/app/playground/settings.py +0 -0
  67. {agno-1.7.8 → agno-1.7.10}/agno/app/playground/sync_router.py +0 -0
  68. {agno-1.7.8 → agno-1.7.10}/agno/app/playground/utils.py +0 -0
  69. {agno-1.7.8 → agno-1.7.10}/agno/app/settings.py +0 -0
  70. {agno-1.7.8 → agno-1.7.10}/agno/app/slack/__init__.py +0 -0
  71. {agno-1.7.8 → agno-1.7.10}/agno/app/slack/app.py +0 -0
  72. {agno-1.7.8 → agno-1.7.10}/agno/app/slack/async_router.py +0 -0
  73. {agno-1.7.8 → agno-1.7.10}/agno/app/slack/security.py +0 -0
  74. {agno-1.7.8 → agno-1.7.10}/agno/app/slack/sync_router.py +0 -0
  75. {agno-1.7.8 → agno-1.7.10}/agno/app/utils.py +0 -0
  76. {agno-1.7.8 → agno-1.7.10}/agno/app/whatsapp/__init__.py +0 -0
  77. {agno-1.7.8 → agno-1.7.10}/agno/app/whatsapp/app.py +0 -0
  78. {agno-1.7.8 → agno-1.7.10}/agno/app/whatsapp/async_router.py +0 -0
  79. {agno-1.7.8 → agno-1.7.10}/agno/app/whatsapp/security.py +0 -0
  80. {agno-1.7.8 → agno-1.7.10}/agno/app/whatsapp/sync_router.py +0 -0
  81. {agno-1.7.8 → agno-1.7.10}/agno/cli/__init__.py +0 -0
  82. {agno-1.7.8 → agno-1.7.10}/agno/cli/auth_server.py +0 -0
  83. {agno-1.7.8 → agno-1.7.10}/agno/cli/config.py +0 -0
  84. {agno-1.7.8 → agno-1.7.10}/agno/cli/console.py +0 -0
  85. {agno-1.7.8 → agno-1.7.10}/agno/cli/credentials.py +0 -0
  86. {agno-1.7.8 → agno-1.7.10}/agno/cli/entrypoint.py +0 -0
  87. {agno-1.7.8 → agno-1.7.10}/agno/cli/operator.py +0 -0
  88. {agno-1.7.8 → agno-1.7.10}/agno/cli/settings.py +0 -0
  89. {agno-1.7.8 → agno-1.7.10}/agno/cli/ws/__init__.py +0 -0
  90. {agno-1.7.8 → agno-1.7.10}/agno/cli/ws/ws_cli.py +0 -0
  91. {agno-1.7.8 → agno-1.7.10}/agno/constants.py +0 -0
  92. {agno-1.7.8 → agno-1.7.10}/agno/debug.py +0 -0
  93. {agno-1.7.8 → agno-1.7.10}/agno/document/__init__.py +0 -0
  94. {agno-1.7.8 → agno-1.7.10}/agno/document/base.py +0 -0
  95. {agno-1.7.8 → agno-1.7.10}/agno/document/chunking/__init__.py +0 -0
  96. {agno-1.7.8 → agno-1.7.10}/agno/document/chunking/agentic.py +0 -0
  97. {agno-1.7.8 → agno-1.7.10}/agno/document/chunking/document.py +0 -0
  98. {agno-1.7.8 → agno-1.7.10}/agno/document/chunking/fixed.py +0 -0
  99. {agno-1.7.8 → agno-1.7.10}/agno/document/chunking/markdown.py +0 -0
  100. {agno-1.7.8 → agno-1.7.10}/agno/document/chunking/recursive.py +0 -0
  101. {agno-1.7.8 → agno-1.7.10}/agno/document/chunking/row.py +0 -0
  102. {agno-1.7.8 → agno-1.7.10}/agno/document/chunking/semantic.py +0 -0
  103. {agno-1.7.8 → agno-1.7.10}/agno/document/chunking/strategy.py +0 -0
  104. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/__init__.py +0 -0
  105. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/arxiv_reader.py +0 -0
  106. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/base.py +0 -0
  107. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/csv_reader.py +0 -0
  108. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/docx_reader.py +0 -0
  109. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/firecrawl_reader.py +0 -0
  110. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/gcs/__init__.py +0 -0
  111. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/gcs/pdf_reader.py +0 -0
  112. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/json_reader.py +0 -0
  113. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/markdown_reader.py +0 -0
  114. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/s3/__init__.py +0 -0
  115. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/s3/pdf_reader.py +0 -0
  116. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/s3/text_reader.py +0 -0
  117. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/text_reader.py +0 -0
  118. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/url_reader.py +0 -0
  119. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/website_reader.py +0 -0
  120. {agno-1.7.8 → agno-1.7.10}/agno/document/reader/youtube_reader.py +0 -0
  121. {agno-1.7.8 → agno-1.7.10}/agno/embedder/__init__.py +0 -0
  122. {agno-1.7.8 → agno-1.7.10}/agno/embedder/aws_bedrock.py +0 -0
  123. {agno-1.7.8 → agno-1.7.10}/agno/embedder/azure_openai.py +0 -0
  124. {agno-1.7.8 → agno-1.7.10}/agno/embedder/base.py +0 -0
  125. {agno-1.7.8 → agno-1.7.10}/agno/embedder/cohere.py +0 -0
  126. {agno-1.7.8 → agno-1.7.10}/agno/embedder/fastembed.py +0 -0
  127. {agno-1.7.8 → agno-1.7.10}/agno/embedder/fireworks.py +0 -0
  128. {agno-1.7.8 → agno-1.7.10}/agno/embedder/google.py +0 -0
  129. {agno-1.7.8 → agno-1.7.10}/agno/embedder/huggingface.py +0 -0
  130. {agno-1.7.8 → agno-1.7.10}/agno/embedder/jina.py +0 -0
  131. {agno-1.7.8 → agno-1.7.10}/agno/embedder/langdb.py +0 -0
  132. {agno-1.7.8 → agno-1.7.10}/agno/embedder/mistral.py +0 -0
  133. {agno-1.7.8 → agno-1.7.10}/agno/embedder/nebius.py +0 -0
  134. {agno-1.7.8 → agno-1.7.10}/agno/embedder/ollama.py +0 -0
  135. {agno-1.7.8 → agno-1.7.10}/agno/embedder/openai.py +0 -0
  136. {agno-1.7.8 → agno-1.7.10}/agno/embedder/sentence_transformer.py +0 -0
  137. {agno-1.7.8 → agno-1.7.10}/agno/embedder/together.py +0 -0
  138. {agno-1.7.8 → agno-1.7.10}/agno/embedder/voyageai.py +0 -0
  139. {agno-1.7.8 → agno-1.7.10}/agno/eval/__init__.py +0 -0
  140. {agno-1.7.8 → agno-1.7.10}/agno/eval/accuracy.py +0 -0
  141. {agno-1.7.8 → agno-1.7.10}/agno/eval/performance.py +0 -0
  142. {agno-1.7.8 → agno-1.7.10}/agno/eval/reliability.py +0 -0
  143. {agno-1.7.8 → agno-1.7.10}/agno/eval/utils.py +0 -0
  144. {agno-1.7.8 → agno-1.7.10}/agno/exceptions.py +0 -0
  145. {agno-1.7.8 → agno-1.7.10}/agno/file/__init__.py +0 -0
  146. {agno-1.7.8 → agno-1.7.10}/agno/file/file.py +0 -0
  147. {agno-1.7.8 → agno-1.7.10}/agno/file/local/__init__.py +0 -0
  148. {agno-1.7.8 → agno-1.7.10}/agno/file/local/csv.py +0 -0
  149. {agno-1.7.8 → agno-1.7.10}/agno/file/local/txt.py +0 -0
  150. {agno-1.7.8 → agno-1.7.10}/agno/infra/__init__.py +0 -0
  151. {agno-1.7.8 → agno-1.7.10}/agno/infra/app.py +0 -0
  152. {agno-1.7.8 → agno-1.7.10}/agno/infra/base.py +0 -0
  153. {agno-1.7.8 → agno-1.7.10}/agno/infra/context.py +0 -0
  154. {agno-1.7.8 → agno-1.7.10}/agno/infra/db_app.py +0 -0
  155. {agno-1.7.8 → agno-1.7.10}/agno/infra/resource.py +0 -0
  156. {agno-1.7.8 → agno-1.7.10}/agno/infra/resources.py +0 -0
  157. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/__init__.py +0 -0
  158. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/arxiv.py +0 -0
  159. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/combined.py +0 -0
  160. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/csv.py +0 -0
  161. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/csv_url.py +0 -0
  162. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/document.py +0 -0
  163. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/docx.py +0 -0
  164. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/firecrawl.py +0 -0
  165. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/gcs/__init__.py +0 -0
  166. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/gcs/base.py +0 -0
  167. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/gcs/pdf.py +0 -0
  168. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/json.py +0 -0
  169. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/langchain.py +0 -0
  170. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/light_rag.py +0 -0
  171. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/llamaindex.py +0 -0
  172. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/markdown.py +0 -0
  173. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/pdf_bytes.py +0 -0
  174. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/s3/__init__.py +0 -0
  175. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/s3/base.py +0 -0
  176. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/s3/pdf.py +0 -0
  177. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/s3/text.py +0 -0
  178. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/text.py +0 -0
  179. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/url.py +0 -0
  180. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/website.py +0 -0
  181. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/wikipedia.py +0 -0
  182. {agno-1.7.8 → agno-1.7.10}/agno/knowledge/youtube.py +0 -0
  183. {agno-1.7.8 → agno-1.7.10}/agno/media.py +0 -0
  184. {agno-1.7.8 → agno-1.7.10}/agno/memory/__init__.py +0 -0
  185. {agno-1.7.8 → agno-1.7.10}/agno/memory/agent.py +0 -0
  186. {agno-1.7.8 → agno-1.7.10}/agno/memory/classifier.py +0 -0
  187. {agno-1.7.8 → agno-1.7.10}/agno/memory/db/__init__.py +0 -0
  188. {agno-1.7.8 → agno-1.7.10}/agno/memory/db/base.py +0 -0
  189. {agno-1.7.8 → agno-1.7.10}/agno/memory/db/mongodb.py +0 -0
  190. {agno-1.7.8 → agno-1.7.10}/agno/memory/db/postgres.py +0 -0
  191. {agno-1.7.8 → agno-1.7.10}/agno/memory/db/sqlite.py +0 -0
  192. {agno-1.7.8 → agno-1.7.10}/agno/memory/manager.py +0 -0
  193. {agno-1.7.8 → agno-1.7.10}/agno/memory/memory.py +0 -0
  194. {agno-1.7.8 → agno-1.7.10}/agno/memory/row.py +0 -0
  195. {agno-1.7.8 → agno-1.7.10}/agno/memory/summarizer.py +0 -0
  196. {agno-1.7.8 → agno-1.7.10}/agno/memory/summary.py +0 -0
  197. {agno-1.7.8 → agno-1.7.10}/agno/memory/team.py +0 -0
  198. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/__init__.py +0 -0
  199. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/db/__init__.py +0 -0
  200. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/db/base.py +0 -0
  201. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/db/firestore.py +0 -0
  202. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/db/mongodb.py +0 -0
  203. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/db/postgres.py +0 -0
  204. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/db/redis.py +0 -0
  205. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/db/schema.py +0 -0
  206. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/db/sqlite.py +0 -0
  207. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/manager.py +0 -0
  208. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/memory.py +0 -0
  209. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/schema.py +0 -0
  210. {agno-1.7.8 → agno-1.7.10}/agno/memory/v2/summarizer.py +0 -0
  211. {agno-1.7.8 → agno-1.7.10}/agno/memory/workflow.py +0 -0
  212. {agno-1.7.8 → agno-1.7.10}/agno/models/__init__.py +0 -0
  213. {agno-1.7.8 → agno-1.7.10}/agno/models/aimlapi/__init__.py +0 -0
  214. {agno-1.7.8 → agno-1.7.10}/agno/models/aimlapi/aimlapi.py +0 -0
  215. {agno-1.7.8 → agno-1.7.10}/agno/models/anthropic/__init__.py +0 -0
  216. {agno-1.7.8 → agno-1.7.10}/agno/models/anthropic/claude.py +0 -0
  217. {agno-1.7.8 → agno-1.7.10}/agno/models/aws/__init__.py +0 -0
  218. {agno-1.7.8 → agno-1.7.10}/agno/models/aws/bedrock.py +0 -0
  219. {agno-1.7.8 → agno-1.7.10}/agno/models/aws/claude.py +0 -0
  220. {agno-1.7.8 → agno-1.7.10}/agno/models/azure/__init__.py +0 -0
  221. {agno-1.7.8 → agno-1.7.10}/agno/models/azure/ai_foundry.py +0 -0
  222. {agno-1.7.8 → agno-1.7.10}/agno/models/azure/openai_chat.py +0 -0
  223. {agno-1.7.8 → agno-1.7.10}/agno/models/base.py +0 -0
  224. {agno-1.7.8 → agno-1.7.10}/agno/models/cerebras/__init__.py +0 -0
  225. {agno-1.7.8 → agno-1.7.10}/agno/models/cerebras/cerebras.py +0 -0
  226. {agno-1.7.8 → agno-1.7.10}/agno/models/cerebras/cerebras_openai.py +0 -0
  227. {agno-1.7.8 → agno-1.7.10}/agno/models/cohere/__init__.py +0 -0
  228. {agno-1.7.8 → agno-1.7.10}/agno/models/cohere/chat.py +0 -0
  229. {agno-1.7.8 → agno-1.7.10}/agno/models/deepinfra/__init__.py +0 -0
  230. {agno-1.7.8 → agno-1.7.10}/agno/models/deepinfra/deepinfra.py +0 -0
  231. {agno-1.7.8 → agno-1.7.10}/agno/models/deepseek/__init__.py +0 -0
  232. {agno-1.7.8 → agno-1.7.10}/agno/models/deepseek/deepseek.py +0 -0
  233. {agno-1.7.8 → agno-1.7.10}/agno/models/defaults.py +0 -0
  234. {agno-1.7.8 → agno-1.7.10}/agno/models/fireworks/__init__.py +0 -0
  235. {agno-1.7.8 → agno-1.7.10}/agno/models/fireworks/fireworks.py +0 -0
  236. {agno-1.7.8 → agno-1.7.10}/agno/models/google/__init__.py +0 -0
  237. {agno-1.7.8 → agno-1.7.10}/agno/models/google/gemini.py +0 -0
  238. {agno-1.7.8 → agno-1.7.10}/agno/models/groq/__init__.py +0 -0
  239. {agno-1.7.8 → agno-1.7.10}/agno/models/groq/groq.py +0 -0
  240. {agno-1.7.8 → agno-1.7.10}/agno/models/huggingface/__init__.py +0 -0
  241. {agno-1.7.8 → agno-1.7.10}/agno/models/huggingface/huggingface.py +0 -0
  242. {agno-1.7.8 → agno-1.7.10}/agno/models/ibm/__init__.py +0 -0
  243. {agno-1.7.8 → agno-1.7.10}/agno/models/ibm/watsonx.py +0 -0
  244. {agno-1.7.8 → agno-1.7.10}/agno/models/internlm/__init__.py +0 -0
  245. {agno-1.7.8 → agno-1.7.10}/agno/models/internlm/internlm.py +0 -0
  246. {agno-1.7.8 → agno-1.7.10}/agno/models/langdb/__init__.py +0 -0
  247. {agno-1.7.8 → agno-1.7.10}/agno/models/langdb/langdb.py +0 -0
  248. {agno-1.7.8 → agno-1.7.10}/agno/models/litellm/__init__.py +0 -0
  249. {agno-1.7.8 → agno-1.7.10}/agno/models/litellm/chat.py +0 -0
  250. {agno-1.7.8 → agno-1.7.10}/agno/models/litellm/litellm_openai.py +0 -0
  251. {agno-1.7.8 → agno-1.7.10}/agno/models/lmstudio/__init__.py +0 -0
  252. {agno-1.7.8 → agno-1.7.10}/agno/models/lmstudio/lmstudio.py +0 -0
  253. {agno-1.7.8 → agno-1.7.10}/agno/models/message.py +0 -0
  254. {agno-1.7.8 → agno-1.7.10}/agno/models/meta/__init__.py +0 -0
  255. {agno-1.7.8 → agno-1.7.10}/agno/models/meta/llama.py +0 -0
  256. {agno-1.7.8 → agno-1.7.10}/agno/models/meta/llama_openai.py +0 -0
  257. {agno-1.7.8 → agno-1.7.10}/agno/models/mistral/__init__.py +0 -0
  258. {agno-1.7.8 → agno-1.7.10}/agno/models/mistral/mistral.py +0 -0
  259. {agno-1.7.8 → agno-1.7.10}/agno/models/nebius/__init__.py +0 -0
  260. {agno-1.7.8 → agno-1.7.10}/agno/models/nebius/nebius.py +0 -0
  261. {agno-1.7.8 → agno-1.7.10}/agno/models/nvidia/__init__.py +0 -0
  262. {agno-1.7.8 → agno-1.7.10}/agno/models/nvidia/nvidia.py +0 -0
  263. {agno-1.7.8 → agno-1.7.10}/agno/models/ollama/__init__.py +0 -0
  264. {agno-1.7.8 → agno-1.7.10}/agno/models/ollama/chat.py +0 -0
  265. {agno-1.7.8 → agno-1.7.10}/agno/models/ollama/tools.py +0 -0
  266. {agno-1.7.8 → agno-1.7.10}/agno/models/openai/__init__.py +0 -0
  267. {agno-1.7.8 → agno-1.7.10}/agno/models/openai/chat.py +0 -0
  268. {agno-1.7.8 → agno-1.7.10}/agno/models/openai/like.py +0 -0
  269. {agno-1.7.8 → agno-1.7.10}/agno/models/openrouter/__init__.py +0 -0
  270. {agno-1.7.8 → agno-1.7.10}/agno/models/openrouter/openrouter.py +0 -0
  271. {agno-1.7.8 → agno-1.7.10}/agno/models/perplexity/__init__.py +0 -0
  272. {agno-1.7.8 → agno-1.7.10}/agno/models/perplexity/perplexity.py +0 -0
  273. {agno-1.7.8 → agno-1.7.10}/agno/models/portkey/__init__.py +0 -0
  274. {agno-1.7.8 → agno-1.7.10}/agno/models/portkey/portkey.py +0 -0
  275. {agno-1.7.8 → agno-1.7.10}/agno/models/response.py +0 -0
  276. {agno-1.7.8 → agno-1.7.10}/agno/models/sambanova/__init__.py +0 -0
  277. {agno-1.7.8 → agno-1.7.10}/agno/models/sambanova/sambanova.py +0 -0
  278. {agno-1.7.8 → agno-1.7.10}/agno/models/together/__init__.py +0 -0
  279. {agno-1.7.8 → agno-1.7.10}/agno/models/together/together.py +0 -0
  280. {agno-1.7.8 → agno-1.7.10}/agno/models/vercel/__init__.py +0 -0
  281. {agno-1.7.8 → agno-1.7.10}/agno/models/vercel/v0.py +0 -0
  282. {agno-1.7.8 → agno-1.7.10}/agno/models/vllm/__init__.py +0 -0
  283. {agno-1.7.8 → agno-1.7.10}/agno/models/vllm/vllm.py +0 -0
  284. {agno-1.7.8 → agno-1.7.10}/agno/models/xai/__init__.py +0 -0
  285. {agno-1.7.8 → agno-1.7.10}/agno/models/xai/xai.py +0 -0
  286. {agno-1.7.8 → agno-1.7.10}/agno/playground/__init__.py +0 -0
  287. {agno-1.7.8 → agno-1.7.10}/agno/playground/deploy.py +0 -0
  288. {agno-1.7.8 → agno-1.7.10}/agno/playground/playground.py +0 -0
  289. {agno-1.7.8 → agno-1.7.10}/agno/playground/serve.py +0 -0
  290. {agno-1.7.8 → agno-1.7.10}/agno/playground/settings.py +0 -0
  291. {agno-1.7.8 → agno-1.7.10}/agno/py.typed +0 -0
  292. {agno-1.7.8 → agno-1.7.10}/agno/reasoning/__init__.py +0 -0
  293. {agno-1.7.8 → agno-1.7.10}/agno/reasoning/azure_ai_foundry.py +0 -0
  294. {agno-1.7.8 → agno-1.7.10}/agno/reasoning/deepseek.py +0 -0
  295. {agno-1.7.8 → agno-1.7.10}/agno/reasoning/default.py +0 -0
  296. {agno-1.7.8 → agno-1.7.10}/agno/reasoning/groq.py +0 -0
  297. {agno-1.7.8 → agno-1.7.10}/agno/reasoning/helpers.py +0 -0
  298. {agno-1.7.8 → agno-1.7.10}/agno/reasoning/ollama.py +0 -0
  299. {agno-1.7.8 → agno-1.7.10}/agno/reasoning/openai.py +0 -0
  300. {agno-1.7.8 → agno-1.7.10}/agno/reasoning/step.py +0 -0
  301. {agno-1.7.8 → agno-1.7.10}/agno/reranker/__init__.py +0 -0
  302. {agno-1.7.8 → agno-1.7.10}/agno/reranker/base.py +0 -0
  303. {agno-1.7.8 → agno-1.7.10}/agno/reranker/cohere.py +0 -0
  304. {agno-1.7.8 → agno-1.7.10}/agno/reranker/infinity.py +0 -0
  305. {agno-1.7.8 → agno-1.7.10}/agno/reranker/sentence_transformer.py +0 -0
  306. {agno-1.7.8 → agno-1.7.10}/agno/run/__init__.py +0 -0
  307. {agno-1.7.8 → agno-1.7.10}/agno/run/base.py +0 -0
  308. {agno-1.7.8 → agno-1.7.10}/agno/run/messages.py +0 -0
  309. {agno-1.7.8 → agno-1.7.10}/agno/run/v2/__init__.py +0 -0
  310. {agno-1.7.8 → agno-1.7.10}/agno/run/v2/workflow.py +0 -0
  311. {agno-1.7.8 → agno-1.7.10}/agno/run/workflow.py +0 -0
  312. {agno-1.7.8 → agno-1.7.10}/agno/storage/__init__.py +0 -0
  313. {agno-1.7.8 → agno-1.7.10}/agno/storage/agent/__init__.py +0 -0
  314. {agno-1.7.8 → agno-1.7.10}/agno/storage/agent/dynamodb.py +0 -0
  315. {agno-1.7.8 → agno-1.7.10}/agno/storage/agent/json.py +0 -0
  316. {agno-1.7.8 → agno-1.7.10}/agno/storage/agent/mongodb.py +0 -0
  317. {agno-1.7.8 → agno-1.7.10}/agno/storage/agent/postgres.py +0 -0
  318. {agno-1.7.8 → agno-1.7.10}/agno/storage/agent/singlestore.py +0 -0
  319. {agno-1.7.8 → agno-1.7.10}/agno/storage/agent/sqlite.py +0 -0
  320. {agno-1.7.8 → agno-1.7.10}/agno/storage/agent/yaml.py +0 -0
  321. {agno-1.7.8 → agno-1.7.10}/agno/storage/base.py +0 -0
  322. {agno-1.7.8 → agno-1.7.10}/agno/storage/dynamodb.py +0 -0
  323. {agno-1.7.8 → agno-1.7.10}/agno/storage/firestore.py +0 -0
  324. {agno-1.7.8 → agno-1.7.10}/agno/storage/gcs_json.py +0 -0
  325. {agno-1.7.8 → agno-1.7.10}/agno/storage/json.py +0 -0
  326. {agno-1.7.8 → agno-1.7.10}/agno/storage/mongodb.py +0 -0
  327. {agno-1.7.8 → agno-1.7.10}/agno/storage/mysql.py +0 -0
  328. {agno-1.7.8 → agno-1.7.10}/agno/storage/postgres.py +0 -0
  329. {agno-1.7.8 → agno-1.7.10}/agno/storage/redis.py +0 -0
  330. {agno-1.7.8 → agno-1.7.10}/agno/storage/session/__init__.py +0 -0
  331. {agno-1.7.8 → agno-1.7.10}/agno/storage/session/agent.py +0 -0
  332. {agno-1.7.8 → agno-1.7.10}/agno/storage/session/team.py +0 -0
  333. {agno-1.7.8 → agno-1.7.10}/agno/storage/session/v2/__init__.py +0 -0
  334. {agno-1.7.8 → agno-1.7.10}/agno/storage/session/v2/workflow.py +0 -0
  335. {agno-1.7.8 → agno-1.7.10}/agno/storage/session/workflow.py +0 -0
  336. {agno-1.7.8 → agno-1.7.10}/agno/storage/singlestore.py +0 -0
  337. {agno-1.7.8 → agno-1.7.10}/agno/storage/sqlite.py +0 -0
  338. {agno-1.7.8 → agno-1.7.10}/agno/storage/workflow/__init__.py +0 -0
  339. {agno-1.7.8 → agno-1.7.10}/agno/storage/workflow/mongodb.py +0 -0
  340. {agno-1.7.8 → agno-1.7.10}/agno/storage/workflow/postgres.py +0 -0
  341. {agno-1.7.8 → agno-1.7.10}/agno/storage/workflow/sqlite.py +0 -0
  342. {agno-1.7.8 → agno-1.7.10}/agno/storage/yaml.py +0 -0
  343. {agno-1.7.8 → agno-1.7.10}/agno/team/__init__.py +0 -0
  344. {agno-1.7.8 → agno-1.7.10}/agno/tools/__init__.py +0 -0
  345. {agno-1.7.8 → agno-1.7.10}/agno/tools/agentql.py +0 -0
  346. {agno-1.7.8 → agno-1.7.10}/agno/tools/airflow.py +0 -0
  347. {agno-1.7.8 → agno-1.7.10}/agno/tools/api.py +0 -0
  348. {agno-1.7.8 → agno-1.7.10}/agno/tools/apify.py +0 -0
  349. {agno-1.7.8 → agno-1.7.10}/agno/tools/arxiv.py +0 -0
  350. {agno-1.7.8 → agno-1.7.10}/agno/tools/aws_ses.py +0 -0
  351. {agno-1.7.8 → agno-1.7.10}/agno/tools/baidusearch.py +0 -0
  352. {agno-1.7.8 → agno-1.7.10}/agno/tools/bitbucket.py +0 -0
  353. {agno-1.7.8 → agno-1.7.10}/agno/tools/bravesearch.py +0 -0
  354. {agno-1.7.8 → agno-1.7.10}/agno/tools/brightdata.py +0 -0
  355. {agno-1.7.8 → agno-1.7.10}/agno/tools/browserbase.py +0 -0
  356. {agno-1.7.8 → agno-1.7.10}/agno/tools/calcom.py +0 -0
  357. {agno-1.7.8 → agno-1.7.10}/agno/tools/calculator.py +0 -0
  358. {agno-1.7.8 → agno-1.7.10}/agno/tools/cartesia.py +0 -0
  359. {agno-1.7.8 → agno-1.7.10}/agno/tools/clickup_tool.py +0 -0
  360. {agno-1.7.8 → agno-1.7.10}/agno/tools/confluence.py +0 -0
  361. {agno-1.7.8 → agno-1.7.10}/agno/tools/crawl4ai.py +0 -0
  362. {agno-1.7.8 → agno-1.7.10}/agno/tools/csv_toolkit.py +0 -0
  363. {agno-1.7.8 → agno-1.7.10}/agno/tools/dalle.py +0 -0
  364. {agno-1.7.8 → agno-1.7.10}/agno/tools/daytona.py +0 -0
  365. {agno-1.7.8 → agno-1.7.10}/agno/tools/decorator.py +0 -0
  366. {agno-1.7.8 → agno-1.7.10}/agno/tools/desi_vocal.py +0 -0
  367. {agno-1.7.8 → agno-1.7.10}/agno/tools/discord.py +0 -0
  368. {agno-1.7.8 → agno-1.7.10}/agno/tools/docker.py +0 -0
  369. {agno-1.7.8 → agno-1.7.10}/agno/tools/duckdb.py +0 -0
  370. {agno-1.7.8 → agno-1.7.10}/agno/tools/duckduckgo.py +0 -0
  371. {agno-1.7.8 → agno-1.7.10}/agno/tools/e2b.py +0 -0
  372. {agno-1.7.8 → agno-1.7.10}/agno/tools/eleven_labs.py +0 -0
  373. {agno-1.7.8 → agno-1.7.10}/agno/tools/email.py +0 -0
  374. {agno-1.7.8 → agno-1.7.10}/agno/tools/evm.py +0 -0
  375. {agno-1.7.8 → agno-1.7.10}/agno/tools/exa.py +0 -0
  376. {agno-1.7.8 → agno-1.7.10}/agno/tools/fal.py +0 -0
  377. {agno-1.7.8 → agno-1.7.10}/agno/tools/file.py +0 -0
  378. {agno-1.7.8 → agno-1.7.10}/agno/tools/financial_datasets.py +0 -0
  379. {agno-1.7.8 → agno-1.7.10}/agno/tools/firecrawl.py +0 -0
  380. {agno-1.7.8 → agno-1.7.10}/agno/tools/function.py +0 -0
  381. {agno-1.7.8 → agno-1.7.10}/agno/tools/giphy.py +0 -0
  382. {agno-1.7.8 → agno-1.7.10}/agno/tools/gmail.py +0 -0
  383. {agno-1.7.8 → agno-1.7.10}/agno/tools/google_bigquery.py +0 -0
  384. {agno-1.7.8 → agno-1.7.10}/agno/tools/google_maps.py +0 -0
  385. {agno-1.7.8 → agno-1.7.10}/agno/tools/googlecalendar.py +0 -0
  386. {agno-1.7.8 → agno-1.7.10}/agno/tools/googlesearch.py +0 -0
  387. {agno-1.7.8 → agno-1.7.10}/agno/tools/googlesheets.py +0 -0
  388. {agno-1.7.8 → agno-1.7.10}/agno/tools/hackernews.py +0 -0
  389. {agno-1.7.8 → agno-1.7.10}/agno/tools/jina.py +0 -0
  390. {agno-1.7.8 → agno-1.7.10}/agno/tools/jira.py +0 -0
  391. {agno-1.7.8 → agno-1.7.10}/agno/tools/knowledge.py +0 -0
  392. {agno-1.7.8 → agno-1.7.10}/agno/tools/linear.py +0 -0
  393. {agno-1.7.8 → agno-1.7.10}/agno/tools/linkup.py +0 -0
  394. {agno-1.7.8 → agno-1.7.10}/agno/tools/local_file_system.py +0 -0
  395. {agno-1.7.8 → agno-1.7.10}/agno/tools/lumalab.py +0 -0
  396. {agno-1.7.8 → agno-1.7.10}/agno/tools/mcp.py +0 -0
  397. {agno-1.7.8 → agno-1.7.10}/agno/tools/mem0.py +0 -0
  398. {agno-1.7.8 → agno-1.7.10}/agno/tools/mlx_transcribe.py +0 -0
  399. {agno-1.7.8 → agno-1.7.10}/agno/tools/models/__init__.py +0 -0
  400. {agno-1.7.8 → agno-1.7.10}/agno/tools/models/azure_openai.py +0 -0
  401. {agno-1.7.8 → agno-1.7.10}/agno/tools/models/gemini.py +0 -0
  402. {agno-1.7.8 → agno-1.7.10}/agno/tools/models/groq.py +0 -0
  403. {agno-1.7.8 → agno-1.7.10}/agno/tools/models/morph.py +0 -0
  404. {agno-1.7.8 → agno-1.7.10}/agno/tools/models/nebius.py +0 -0
  405. {agno-1.7.8 → agno-1.7.10}/agno/tools/models_labs.py +0 -0
  406. {agno-1.7.8 → agno-1.7.10}/agno/tools/moviepy_video.py +0 -0
  407. {agno-1.7.8 → agno-1.7.10}/agno/tools/newspaper.py +0 -0
  408. {agno-1.7.8 → agno-1.7.10}/agno/tools/newspaper4k.py +0 -0
  409. {agno-1.7.8 → agno-1.7.10}/agno/tools/openai.py +0 -0
  410. {agno-1.7.8 → agno-1.7.10}/agno/tools/openbb.py +0 -0
  411. {agno-1.7.8 → agno-1.7.10}/agno/tools/opencv.py +0 -0
  412. {agno-1.7.8 → agno-1.7.10}/agno/tools/openweather.py +0 -0
  413. {agno-1.7.8 → agno-1.7.10}/agno/tools/oxylabs.py +0 -0
  414. {agno-1.7.8 → agno-1.7.10}/agno/tools/pandas.py +0 -0
  415. {agno-1.7.8 → agno-1.7.10}/agno/tools/postgres.py +0 -0
  416. {agno-1.7.8 → agno-1.7.10}/agno/tools/pubmed.py +0 -0
  417. {agno-1.7.8 → agno-1.7.10}/agno/tools/python.py +0 -0
  418. {agno-1.7.8 → agno-1.7.10}/agno/tools/reasoning.py +0 -0
  419. {agno-1.7.8 → agno-1.7.10}/agno/tools/reddit.py +0 -0
  420. {agno-1.7.8 → agno-1.7.10}/agno/tools/replicate.py +0 -0
  421. {agno-1.7.8 → agno-1.7.10}/agno/tools/resend.py +0 -0
  422. {agno-1.7.8 → agno-1.7.10}/agno/tools/scrapegraph.py +0 -0
  423. {agno-1.7.8 → agno-1.7.10}/agno/tools/searxng.py +0 -0
  424. {agno-1.7.8 → agno-1.7.10}/agno/tools/serpapi.py +0 -0
  425. {agno-1.7.8 → agno-1.7.10}/agno/tools/serper.py +0 -0
  426. {agno-1.7.8 → agno-1.7.10}/agno/tools/shell.py +0 -0
  427. {agno-1.7.8 → agno-1.7.10}/agno/tools/slack.py +0 -0
  428. {agno-1.7.8 → agno-1.7.10}/agno/tools/sleep.py +0 -0
  429. {agno-1.7.8 → agno-1.7.10}/agno/tools/spider.py +0 -0
  430. {agno-1.7.8 → agno-1.7.10}/agno/tools/sql.py +0 -0
  431. {agno-1.7.8 → agno-1.7.10}/agno/tools/streamlit/__init__.py +0 -0
  432. {agno-1.7.8 → agno-1.7.10}/agno/tools/streamlit/components.py +0 -0
  433. {agno-1.7.8 → agno-1.7.10}/agno/tools/tavily.py +0 -0
  434. {agno-1.7.8 → agno-1.7.10}/agno/tools/telegram.py +0 -0
  435. {agno-1.7.8 → agno-1.7.10}/agno/tools/thinking.py +0 -0
  436. {agno-1.7.8 → agno-1.7.10}/agno/tools/todoist.py +0 -0
  437. {agno-1.7.8 → agno-1.7.10}/agno/tools/tool_registry.py +0 -0
  438. {agno-1.7.8 → agno-1.7.10}/agno/tools/toolkit.py +0 -0
  439. {agno-1.7.8 → agno-1.7.10}/agno/tools/trello.py +0 -0
  440. {agno-1.7.8 → agno-1.7.10}/agno/tools/twilio.py +0 -0
  441. {agno-1.7.8 → agno-1.7.10}/agno/tools/user_control_flow.py +0 -0
  442. {agno-1.7.8 → agno-1.7.10}/agno/tools/valyu.py +0 -0
  443. {agno-1.7.8 → agno-1.7.10}/agno/tools/visualization.py +0 -0
  444. {agno-1.7.8 → agno-1.7.10}/agno/tools/webbrowser.py +0 -0
  445. {agno-1.7.8 → agno-1.7.10}/agno/tools/webex.py +0 -0
  446. {agno-1.7.8 → agno-1.7.10}/agno/tools/website.py +0 -0
  447. {agno-1.7.8 → agno-1.7.10}/agno/tools/webtools.py +0 -0
  448. {agno-1.7.8 → agno-1.7.10}/agno/tools/whatsapp.py +0 -0
  449. {agno-1.7.8 → agno-1.7.10}/agno/tools/wikipedia.py +0 -0
  450. {agno-1.7.8 → agno-1.7.10}/agno/tools/x.py +0 -0
  451. {agno-1.7.8 → agno-1.7.10}/agno/tools/yfinance.py +0 -0
  452. {agno-1.7.8 → agno-1.7.10}/agno/tools/youtube.py +0 -0
  453. {agno-1.7.8 → agno-1.7.10}/agno/tools/zendesk.py +0 -0
  454. {agno-1.7.8 → agno-1.7.10}/agno/tools/zep.py +0 -0
  455. {agno-1.7.8 → agno-1.7.10}/agno/tools/zoom.py +0 -0
  456. {agno-1.7.8 → agno-1.7.10}/agno/utils/__init__.py +0 -0
  457. {agno-1.7.8 → agno-1.7.10}/agno/utils/audio.py +0 -0
  458. {agno-1.7.8 → agno-1.7.10}/agno/utils/certs.py +0 -0
  459. {agno-1.7.8 → agno-1.7.10}/agno/utils/code_execution.py +0 -0
  460. {agno-1.7.8 → agno-1.7.10}/agno/utils/common.py +0 -0
  461. {agno-1.7.8 → agno-1.7.10}/agno/utils/defaults.py +0 -0
  462. {agno-1.7.8 → agno-1.7.10}/agno/utils/dttm.py +0 -0
  463. {agno-1.7.8 → agno-1.7.10}/agno/utils/enum.py +0 -0
  464. {agno-1.7.8 → agno-1.7.10}/agno/utils/env.py +0 -0
  465. {agno-1.7.8 → agno-1.7.10}/agno/utils/events.py +0 -0
  466. {agno-1.7.8 → agno-1.7.10}/agno/utils/filesystem.py +0 -0
  467. {agno-1.7.8 → agno-1.7.10}/agno/utils/format_str.py +0 -0
  468. {agno-1.7.8 → agno-1.7.10}/agno/utils/functions.py +0 -0
  469. {agno-1.7.8 → agno-1.7.10}/agno/utils/gemini.py +0 -0
  470. {agno-1.7.8 → agno-1.7.10}/agno/utils/git.py +0 -0
  471. {agno-1.7.8 → agno-1.7.10}/agno/utils/http.py +0 -0
  472. {agno-1.7.8 → agno-1.7.10}/agno/utils/json_io.py +0 -0
  473. {agno-1.7.8 → agno-1.7.10}/agno/utils/json_schema.py +0 -0
  474. {agno-1.7.8 → agno-1.7.10}/agno/utils/load_env.py +0 -0
  475. {agno-1.7.8 → agno-1.7.10}/agno/utils/location.py +0 -0
  476. {agno-1.7.8 → agno-1.7.10}/agno/utils/log.py +0 -0
  477. {agno-1.7.8 → agno-1.7.10}/agno/utils/mcp.py +0 -0
  478. {agno-1.7.8 → agno-1.7.10}/agno/utils/media.py +0 -0
  479. {agno-1.7.8 → agno-1.7.10}/agno/utils/merge_dict.py +0 -0
  480. {agno-1.7.8 → agno-1.7.10}/agno/utils/message.py +0 -0
  481. {agno-1.7.8 → agno-1.7.10}/agno/utils/models/__init__.py +0 -0
  482. {agno-1.7.8 → agno-1.7.10}/agno/utils/models/ai_foundry.py +0 -0
  483. {agno-1.7.8 → agno-1.7.10}/agno/utils/models/aws_claude.py +0 -0
  484. {agno-1.7.8 → agno-1.7.10}/agno/utils/models/claude.py +0 -0
  485. {agno-1.7.8 → agno-1.7.10}/agno/utils/models/cohere.py +0 -0
  486. {agno-1.7.8 → agno-1.7.10}/agno/utils/models/llama.py +0 -0
  487. {agno-1.7.8 → agno-1.7.10}/agno/utils/models/mistral.py +0 -0
  488. {agno-1.7.8 → agno-1.7.10}/agno/utils/models/openai_responses.py +0 -0
  489. {agno-1.7.8 → agno-1.7.10}/agno/utils/models/schema_utils.py +0 -0
  490. {agno-1.7.8 → agno-1.7.10}/agno/utils/models/watsonx.py +0 -0
  491. {agno-1.7.8 → agno-1.7.10}/agno/utils/openai.py +0 -0
  492. {agno-1.7.8 → agno-1.7.10}/agno/utils/pickle.py +0 -0
  493. {agno-1.7.8 → agno-1.7.10}/agno/utils/pprint.py +0 -0
  494. {agno-1.7.8 → agno-1.7.10}/agno/utils/prompts.py +0 -0
  495. {agno-1.7.8 → agno-1.7.10}/agno/utils/py_io.py +0 -0
  496. {agno-1.7.8 → agno-1.7.10}/agno/utils/pyproject.py +0 -0
  497. {agno-1.7.8 → agno-1.7.10}/agno/utils/resource_filter.py +0 -0
  498. {agno-1.7.8 → agno-1.7.10}/agno/utils/response.py +0 -0
  499. {agno-1.7.8 → agno-1.7.10}/agno/utils/response_iterator.py +0 -0
  500. {agno-1.7.8 → agno-1.7.10}/agno/utils/safe_formatter.py +0 -0
  501. {agno-1.7.8 → agno-1.7.10}/agno/utils/shell.py +0 -0
  502. {agno-1.7.8 → agno-1.7.10}/agno/utils/string.py +0 -0
  503. {agno-1.7.8 → agno-1.7.10}/agno/utils/timer.py +0 -0
  504. {agno-1.7.8 → agno-1.7.10}/agno/utils/tools.py +0 -0
  505. {agno-1.7.8 → agno-1.7.10}/agno/utils/web.py +0 -0
  506. {agno-1.7.8 → agno-1.7.10}/agno/utils/whatsapp.py +0 -0
  507. {agno-1.7.8 → agno-1.7.10}/agno/utils/yaml_io.py +0 -0
  508. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/__init__.py +0 -0
  509. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/base.py +0 -0
  510. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/cassandra/__init__.py +0 -0
  511. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/cassandra/cassandra.py +0 -0
  512. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/cassandra/extra_param_mixin.py +0 -0
  513. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/cassandra/index.py +0 -0
  514. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/chroma/__init__.py +0 -0
  515. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/chroma/chromadb.py +0 -0
  516. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/clickhouse/__init__.py +0 -0
  517. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/clickhouse/clickhousedb.py +0 -0
  518. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/clickhouse/index.py +0 -0
  519. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/couchbase/__init__.py +0 -0
  520. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/couchbase/couchbase.py +0 -0
  521. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/distance.py +0 -0
  522. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/lancedb/__init__.py +0 -0
  523. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/milvus/__init__.py +0 -0
  524. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/milvus/milvus.py +0 -0
  525. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/mongodb/__init__.py +0 -0
  526. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/mongodb/mongodb.py +0 -0
  527. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/pgvector/__init__.py +0 -0
  528. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/pgvector/index.py +0 -0
  529. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/pineconedb/__init__.py +0 -0
  530. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/pineconedb/pineconedb.py +0 -0
  531. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/qdrant/__init__.py +0 -0
  532. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/qdrant/qdrant.py +0 -0
  533. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/search.py +0 -0
  534. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/singlestore/__init__.py +0 -0
  535. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/singlestore/index.py +0 -0
  536. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/singlestore/singlestore.py +0 -0
  537. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/surrealdb/__init__.py +0 -0
  538. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/surrealdb/surrealdb.py +0 -0
  539. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/upstashdb/__init__.py +0 -0
  540. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/upstashdb/upstashdb.py +0 -0
  541. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/weaviate/__init__.py +0 -0
  542. {agno-1.7.8 → agno-1.7.10}/agno/vectordb/weaviate/index.py +0 -0
  543. {agno-1.7.8 → agno-1.7.10}/agno/workflow/__init__.py +0 -0
  544. {agno-1.7.8 → agno-1.7.10}/agno/workflow/v2/__init__.py +0 -0
  545. {agno-1.7.8 → agno-1.7.10}/agno/workflow/v2/condition.py +0 -0
  546. {agno-1.7.8 → agno-1.7.10}/agno/workflow/v2/loop.py +0 -0
  547. {agno-1.7.8 → agno-1.7.10}/agno/workflow/v2/parallel.py +0 -0
  548. {agno-1.7.8 → agno-1.7.10}/agno/workflow/v2/router.py +0 -0
  549. {agno-1.7.8 → agno-1.7.10}/agno/workflow/v2/step.py +0 -0
  550. {agno-1.7.8 → agno-1.7.10}/agno/workflow/v2/steps.py +0 -0
  551. {agno-1.7.8 → agno-1.7.10}/agno/workflow/v2/types.py +0 -0
  552. {agno-1.7.8 → agno-1.7.10}/agno/workflow/v2/workflow.py +0 -0
  553. {agno-1.7.8 → agno-1.7.10}/agno/workflow/workflow.py +0 -0
  554. {agno-1.7.8 → agno-1.7.10}/agno/workspace/__init__.py +0 -0
  555. {agno-1.7.8 → agno-1.7.10}/agno/workspace/config.py +0 -0
  556. {agno-1.7.8 → agno-1.7.10}/agno/workspace/enums.py +0 -0
  557. {agno-1.7.8 → agno-1.7.10}/agno/workspace/helpers.py +0 -0
  558. {agno-1.7.8 → agno-1.7.10}/agno/workspace/operator.py +0 -0
  559. {agno-1.7.8 → agno-1.7.10}/agno/workspace/settings.py +0 -0
  560. {agno-1.7.8 → agno-1.7.10}/agno.egg-info/SOURCES.txt +0 -0
  561. {agno-1.7.8 → agno-1.7.10}/agno.egg-info/dependency_links.txt +0 -0
  562. {agno-1.7.8 → agno-1.7.10}/agno.egg-info/entry_points.txt +0 -0
  563. {agno-1.7.8 → agno-1.7.10}/agno.egg-info/top_level.txt +0 -0
  564. {agno-1.7.8 → agno-1.7.10}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agno
3
- Version: 1.7.8
3
+ Version: 1.7.10
4
4
  Summary: Agno: a lightweight library for building Multi-Agent Systems
5
5
  Author-email: Ashpreet Bedi <ashpreet@agno.com>
6
6
  License: Copyright (c) Agno, Inc.
@@ -400,6 +400,7 @@ License-File: LICENSE
400
400
  Requires-Dist: docstring-parser
401
401
  Requires-Dist: gitpython
402
402
  Requires-Dist: httpx
403
+ Requires-Dist: packaging
403
404
  Requires-Dist: pydantic-settings
404
405
  Requires-Dist: pydantic
405
406
  Requires-Dist: python-dotenv
@@ -893,7 +893,7 @@ class Agent:
893
893
  ):
894
894
  yield event
895
895
  else:
896
- from agno.utils.events import RunResponseContentEvent
896
+ from agno.run.response import IntermediateRunResponseContentEvent, RunResponseContentEvent
897
897
 
898
898
  for event in self._handle_model_response_stream(
899
899
  run_response=run_response,
@@ -903,7 +903,10 @@ class Agent:
903
903
  ):
904
904
  if isinstance(event, RunResponseContentEvent):
905
905
  if stream_intermediate_steps:
906
- yield event
906
+ yield IntermediateRunResponseContentEvent(
907
+ content=event.content,
908
+ content_type=event.content_type,
909
+ )
907
910
  else:
908
911
  yield event
909
912
 
@@ -1331,7 +1334,7 @@ class Agent:
1331
1334
  ):
1332
1335
  yield event
1333
1336
  else:
1334
- from agno.utils.events import RunResponseContentEvent
1337
+ from agno.run.response import IntermediateRunResponseContentEvent, RunResponseContentEvent
1335
1338
 
1336
1339
  async for event in self._ahandle_model_response_stream(
1337
1340
  run_response=run_response,
@@ -1341,7 +1344,10 @@ class Agent:
1341
1344
  ):
1342
1345
  if isinstance(event, RunResponseContentEvent):
1343
1346
  if stream_intermediate_steps:
1344
- yield event
1347
+ yield IntermediateRunResponseContentEvent(
1348
+ content=event.content,
1349
+ content_type=event.content_type,
1350
+ )
1345
1351
  else:
1346
1352
  yield event
1347
1353
 
@@ -4973,9 +4979,26 @@ class Agent:
4973
4979
 
4974
4980
  run_messages.messages += history_copy
4975
4981
 
4976
- # 4.Add user message to run_messages
4982
+ # 4. Add messages to run_messages if provided
4983
+ if messages is not None and len(messages) > 0:
4984
+ for _m in messages:
4985
+ if isinstance(_m, Message):
4986
+ run_messages.messages.append(_m)
4987
+ if run_messages.extra_messages is None:
4988
+ run_messages.extra_messages = []
4989
+ run_messages.extra_messages.append(_m)
4990
+ elif isinstance(_m, dict):
4991
+ try:
4992
+ run_messages.messages.append(Message.model_validate(_m))
4993
+ if run_messages.extra_messages is None:
4994
+ run_messages.extra_messages = []
4995
+ run_messages.extra_messages.append(Message.model_validate(_m))
4996
+ except Exception as e:
4997
+ log_warning(f"Failed to validate message: {e}")
4998
+
4999
+ # 5. Add user message to run_messages
4977
5000
  user_message: Optional[Message] = None
4978
- # 4.1 Build user message if message is None, str or list
5001
+ # 5.1 Build user message if message is None, str or list
4979
5002
  if message is None or isinstance(message, str) or isinstance(message, list):
4980
5003
  user_message = self.get_user_message(
4981
5004
  message=message,
@@ -4986,16 +5009,16 @@ class Agent:
4986
5009
  knowledge_filters=knowledge_filters,
4987
5010
  **kwargs,
4988
5011
  )
4989
- # 4.2 If message is provided as a Message, use it directly
5012
+ # 5.2 If message is provided as a Message, use it directly
4990
5013
  elif isinstance(message, Message):
4991
5014
  user_message = message
4992
- # 4.3 If message is provided as a dict, try to validate it as a Message
5015
+ # 5.3 If message is provided as a dict, try to validate it as a Message
4993
5016
  elif isinstance(message, dict):
4994
5017
  try:
4995
5018
  user_message = Message.model_validate(message)
4996
5019
  except Exception as e:
4997
5020
  log_warning(f"Failed to validate message: {e}")
4998
- # 4.4 If message is provided as a BaseModel, convert it to a Message
5021
+ # 5.4 If message is provided as a BaseModel, convert it to a Message
4999
5022
  elif isinstance(message, BaseModel):
5000
5023
  try:
5001
5024
  # Create a user message with the BaseModel content
@@ -5008,23 +5031,6 @@ class Agent:
5008
5031
  run_messages.user_message = user_message
5009
5032
  run_messages.messages.append(user_message)
5010
5033
 
5011
- # 5. Add messages to run_messages if provided
5012
- if messages is not None and len(messages) > 0:
5013
- for _m in messages:
5014
- if isinstance(_m, Message):
5015
- run_messages.messages.append(_m)
5016
- if run_messages.extra_messages is None:
5017
- run_messages.extra_messages = []
5018
- run_messages.extra_messages.append(_m)
5019
- elif isinstance(_m, dict):
5020
- try:
5021
- run_messages.messages.append(Message.model_validate(_m))
5022
- if run_messages.extra_messages is None:
5023
- run_messages.extra_messages = []
5024
- run_messages.extra_messages.append(Message.model_validate(_m))
5025
- except Exception as e:
5026
- log_warning(f"Failed to validate message: {e}")
5027
-
5028
5034
  return run_messages
5029
5035
 
5030
5036
  def get_continue_run_messages(
@@ -6866,7 +6872,7 @@ class Agent:
6866
6872
  document_name = query.replace(" ", "_").replace("?", "").replace("!", "").replace(".", "")
6867
6873
  document_content = json.dumps({"query": query, "result": result})
6868
6874
  log_info(f"Adding document to knowledge base: {document_name}: {document_content}")
6869
- self.knowledge.add_document_to_knowledge_base(
6875
+ self.knowledge.load_document(
6870
6876
  document=Document(
6871
6877
  name=document_name,
6872
6878
  content=document_content,
@@ -0,0 +1,511 @@
1
+ import asyncio
2
+ import re
3
+ from pathlib import Path
4
+ from typing import IO, Any, List, Optional, Tuple, Union
5
+ from uuid import uuid4
6
+
7
+ from agno.document.base import Document
8
+ from agno.document.reader.base import Reader
9
+ from agno.utils.http import async_fetch_with_retry, fetch_with_retry
10
+ from agno.utils.log import log_error, log_info, logger
11
+
12
+ try:
13
+ from pypdf import PdfReader as DocumentReader # noqa: F401
14
+ from pypdf.errors import PdfStreamError
15
+ except ImportError:
16
+ raise ImportError("`pypdf` not installed. Please install it via `pip install pypdf`.")
17
+
18
+
19
+ PAGE_START_NUMBERING_FORMAT_DEFAULT = "<start page {page_nr}>"
20
+ PAGE_END_NUMBERING_FORMAT_DEFAULT = "<end page {page_nr}>"
21
+ PAGE_NUMBERING_CORRECTNESS_RATIO_FOR_REMOVAL = 0.4
22
+
23
+
24
+ def _ocr_reader(page: Any) -> str:
25
+ """A single PDF page object."""
26
+ try:
27
+ import rapidocr_onnxruntime as rapidocr
28
+ except ImportError:
29
+ raise ImportError(
30
+ "`rapidocr_onnxruntime` not installed. Please install it via `pip install rapidocr_onnxruntime`."
31
+ )
32
+ ocr = rapidocr.RapidOCR()
33
+ images_text_list = []
34
+
35
+ # Extract and process images
36
+ for image_object in page.images:
37
+ image_data = image_object.data
38
+
39
+ # Perform OCR on the image
40
+ ocr_result, elapse = ocr(image_data)
41
+
42
+ # Extract text from OCR result
43
+ images_text_list += [item[1] for item in ocr_result] if ocr_result else []
44
+
45
+ return "\n".join(images_text_list)
46
+
47
+
48
+ async def _async_ocr_reader(page: Any) -> str:
49
+ """page: A single PDF page object."""
50
+ try:
51
+ import rapidocr_onnxruntime as rapidocr
52
+ except ImportError:
53
+ raise ImportError(
54
+ "`rapidocr_onnxruntime` not installed. Please install it via `pip install rapidocr_onnxruntime`."
55
+ )
56
+ ocr = rapidocr.RapidOCR()
57
+
58
+ # Process images in parallel
59
+ async def process_image(image_data: bytes) -> List[str]:
60
+ ocr_result, _ = ocr(image_data)
61
+ return [item[1] for item in ocr_result] if ocr_result else []
62
+
63
+ image_tasks = [process_image(image.data) for image in page.images]
64
+ images_results = await asyncio.gather(*image_tasks)
65
+
66
+ images_text_list: List = []
67
+ for result in images_results:
68
+ images_text_list.extend(result)
69
+
70
+ images_text = "\n".join(images_text_list)
71
+ return images_text
72
+
73
+
74
+ def _clean_page_numbers(
75
+ page_content_list: List[str],
76
+ extra_content: List[str] = [],
77
+ page_start_numbering_format: str = PAGE_START_NUMBERING_FORMAT_DEFAULT,
78
+ page_end_numbering_format: str = PAGE_END_NUMBERING_FORMAT_DEFAULT,
79
+ ) -> Tuple[List[str], Optional[int]]:
80
+ f"""
81
+ Identifies and removes or reformats page numbers from a list of PDF page contents, based on the most consistent sequential numbering.
82
+
83
+ Args:
84
+ page_content_list (List[str]): A list of strings where each string represents the content of a PDF page.
85
+ extra_content (List[str]): A list of strings where each string will be appended after the main content. Can be used for appending image information.
86
+ page_start_numbering_format (str): A format string to prepend to the page content, with `{{page_nr}}` as a placeholder for the page number.
87
+ Defaults to {PAGE_START_NUMBERING_FORMAT_DEFAULT}. Make it an empty string to remove the page number.
88
+ page_end_numbering_format (str): A format string to append to the page content, with `{{page_nr}}` as a placeholder for the page number.
89
+ Defaults to {PAGE_END_NUMBERING_FORMAT_DEFAULT}. Make it an empty string to remove the page number.
90
+
91
+ Returns:
92
+ List[str]: The list of page contents with page numbers removed or reformatted based on the detected sequence.
93
+ Optional[Int]: The shift for the page numbering. Can be (-2, -1, 0, 1, 2).
94
+
95
+ Notes:
96
+ - The function scans for page numbers using a regular expression that matches digits at the start or end of a string.
97
+ - 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,
99
+ 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
101
+ `page_end_numbering_format` is provided.
102
+ """
103
+ assert len(extra_content) == 0 or len(extra_content) == len(page_content_list), (
104
+ "Please provide an equally sized list of extra content if provided."
105
+ )
106
+
107
+ # Regex to match potential page numbers at the start or end of a string
108
+ page_number_regex = re.compile(r"^\s*(\d+)\s*|\s*(\d+)\s*$")
109
+
110
+ def find_page_number(content):
111
+ match = page_number_regex.search(content)
112
+ if match:
113
+ return int(match.group(1) or match.group(2))
114
+ return None
115
+
116
+ page_numbers = [find_page_number(content) for content in page_content_list]
117
+ if all(x is None or x > 5 for x in page_numbers):
118
+ # This approach won't work reliably for higher page numbers.
119
+ return page_content_list, None
120
+
121
+ # Possible range shifts to detect page numbering
122
+ range_shifts = [-2, -1, 0, 1, 2]
123
+ best_match, best_correct_count, best_shift = _identify_best_page_sequence(page_numbers, range_shifts)
124
+
125
+ # Check if at least ..% of the pages have correct sequential numbering
126
+ if best_match and best_correct_count / len(page_numbers) >= PAGE_NUMBERING_CORRECTNESS_RATIO_FOR_REMOVAL:
127
+ # Remove the page numbers from the content
128
+ for i, expected_number in enumerate(best_match):
129
+ page_content_list[i] = re.sub(
130
+ rf"^\s*{expected_number}\s*|\s*{expected_number}\s*$", "", page_content_list[i]
131
+ )
132
+
133
+ page_start = (
134
+ page_start_numbering_format.format(page_nr=expected_number) + "\n"
135
+ if page_start_numbering_format
136
+ else ""
137
+ )
138
+ page_end = (
139
+ "\n" + page_end_numbering_format.format(page_nr=expected_number) if page_end_numbering_format else ""
140
+ )
141
+ extra_info = "\n" + extra_content[i] if extra_content else ""
142
+
143
+ # Add formatted page numbering if configured.
144
+ page_content_list[i] = page_start + page_content_list[i] + extra_info + page_end
145
+ else:
146
+ best_shift = None
147
+
148
+ return page_content_list, best_shift
149
+
150
+
151
+ def _identify_best_page_sequence(page_numbers, range_shifts):
152
+ best_match = None
153
+ best_shift: Optional[int] = None
154
+ best_correct_count = 0
155
+
156
+ for shift in range_shifts:
157
+ expected_numbers = [i + shift for i in range(len(page_numbers))]
158
+ # Check if expected number occurs (or that the expected "2" occurs in an incorrectly merged number like 25,
159
+ # where 2 is the page number and 5 is part of the PDF content).
160
+ correct_count = sum(
161
+ 1
162
+ for actual, expected in zip(page_numbers, expected_numbers)
163
+ if actual == expected or str(actual).startswith(str(expected)) or str(actual).endswith(str(expected))
164
+ )
165
+
166
+ if correct_count > best_correct_count:
167
+ best_correct_count = correct_count
168
+ best_match = expected_numbers
169
+ best_shift = shift
170
+
171
+ return best_match, best_correct_count, best_shift
172
+
173
+
174
+ class BasePDFReader(Reader):
175
+ def __init__(
176
+ self,
177
+ split_on_pages: bool = True,
178
+ page_start_numbering_format: Optional[str] = None,
179
+ page_end_numbering_format: Optional[str] = None,
180
+ password: Optional[str] = None,
181
+ **kwargs,
182
+ ):
183
+ if page_start_numbering_format is None:
184
+ page_start_numbering_format = PAGE_START_NUMBERING_FORMAT_DEFAULT
185
+ if page_end_numbering_format is None:
186
+ page_end_numbering_format = PAGE_END_NUMBERING_FORMAT_DEFAULT
187
+
188
+ self.split_on_pages = split_on_pages
189
+ self.page_start_numbering_format = page_start_numbering_format
190
+ self.page_end_numbering_format = page_end_numbering_format
191
+ self.password = password
192
+
193
+ super().__init__(**kwargs)
194
+
195
+ def _build_chunked_documents(self, documents: List[Document]) -> List[Document]:
196
+ chunked_documents: List[Document] = []
197
+ for document in documents:
198
+ chunked_documents.extend(self.chunk_document(document))
199
+ return chunked_documents
200
+
201
+ def _decrypt_pdf(self, doc_reader: DocumentReader, doc_name: str, password: Optional[str] = None) -> bool:
202
+ if not doc_reader.is_encrypted:
203
+ return True
204
+
205
+ # Use provided password or fall back to instance password
206
+ pdf_password = password or self.password
207
+ if not pdf_password:
208
+ logger.error(f"PDF {doc_name} is password protected but no password provided")
209
+ return False
210
+
211
+ try:
212
+ decrypted_pdf = doc_reader.decrypt(pdf_password)
213
+ if decrypted_pdf:
214
+ log_info(f"Successfully decrypted PDF {doc_name} with user password")
215
+ return True
216
+ else:
217
+ log_error(f"Failed to decrypt PDF {doc_name}: incorrect password")
218
+ return False
219
+ except Exception as e:
220
+ log_error(f"Error decrypting PDF {doc_name}: {e}")
221
+ return False
222
+
223
+ def _create_documents(self, pdf_content: List[str], doc_name: str, use_uuid_for_id: bool, page_number_shift):
224
+ if self.split_on_pages:
225
+ shift = page_number_shift if page_number_shift is not None else 1
226
+ documents: List[Document] = []
227
+ for page_number, page_content in enumerate(pdf_content, start=shift):
228
+ documents.append(
229
+ Document(
230
+ name=doc_name,
231
+ id=(str(uuid4()) if use_uuid_for_id else f"{doc_name}_{page_number}"),
232
+ meta_data={"page": page_number},
233
+ content=page_content,
234
+ )
235
+ )
236
+ else:
237
+ pdf_content_str = "\n".join(pdf_content)
238
+ document = Document(
239
+ name=doc_name,
240
+ id=str(uuid4()) if use_uuid_for_id else doc_name,
241
+ meta_data={},
242
+ content=pdf_content_str,
243
+ )
244
+ documents = [document]
245
+
246
+ if self.chunk:
247
+ return self._build_chunked_documents(documents)
248
+
249
+ return documents
250
+
251
+ def _pdf_reader_to_documents(
252
+ self,
253
+ doc_reader: DocumentReader,
254
+ doc_name,
255
+ read_images=False,
256
+ use_uuid_for_id=False,
257
+ ):
258
+ pdf_content = []
259
+ pdf_images_text = []
260
+ for page in doc_reader.pages:
261
+ pdf_content.append(page.extract_text())
262
+ if read_images:
263
+ pdf_images_text.append(_ocr_reader(page))
264
+
265
+ pdf_content, shift = _clean_page_numbers(
266
+ page_content_list=pdf_content,
267
+ extra_content=pdf_images_text,
268
+ page_start_numbering_format=self.page_start_numbering_format,
269
+ page_end_numbering_format=self.page_end_numbering_format,
270
+ )
271
+ return self._create_documents(pdf_content, doc_name, use_uuid_for_id, shift)
272
+
273
+ async def _async_pdf_reader_to_documents(
274
+ self,
275
+ doc_reader: DocumentReader,
276
+ doc_name: str,
277
+ read_images=False,
278
+ use_uuid_for_id=False,
279
+ ):
280
+ async def _read_pdf_page(page, read_images) -> Tuple[str, str]:
281
+ # We tried "asyncio.to_thread(page.extract_text)", but it maintains state internally, which leads to issues.
282
+ page_text = page.extract_text()
283
+
284
+ if read_images:
285
+ pdf_images_text = await _async_ocr_reader(page)
286
+ else:
287
+ pdf_images_text = ""
288
+
289
+ return page_text, pdf_images_text
290
+
291
+ # Process pages in parallel using asyncio.gather
292
+ pdf_content: List[Tuple[str, str]] = await asyncio.gather(
293
+ *[_read_pdf_page(page, read_images) for page in doc_reader.pages]
294
+ )
295
+
296
+ pdf_content_clean, shift = _clean_page_numbers(
297
+ page_content_list=[x[0] for x in pdf_content],
298
+ extra_content=[x[1] for x in pdf_content],
299
+ page_start_numbering_format=self.page_start_numbering_format,
300
+ page_end_numbering_format=self.page_end_numbering_format,
301
+ )
302
+
303
+ return self._create_documents(pdf_content_clean, doc_name, use_uuid_for_id, shift)
304
+
305
+
306
+ class PDFReader(BasePDFReader):
307
+ """Reader for PDF files"""
308
+
309
+ def read(self, pdf: Union[str, Path, IO[Any]], password: Optional[str] = None) -> List[Document]:
310
+ try:
311
+ if isinstance(pdf, str):
312
+ doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
313
+ else:
314
+ doc_name = pdf.name.split(".")[0]
315
+ except Exception:
316
+ doc_name = "pdf"
317
+
318
+ log_info(f"Reading: {doc_name}")
319
+
320
+ try:
321
+ pdf_reader = DocumentReader(pdf)
322
+ except PdfStreamError as e:
323
+ logger.error(f"Error reading PDF: {e}")
324
+ return []
325
+
326
+ # Handle PDF decryption
327
+ if not self._decrypt_pdf(pdf_reader, doc_name, password):
328
+ return []
329
+
330
+ # Read and chunk.
331
+ return self._pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=True)
332
+
333
+ async def async_read(self, pdf: Union[str, Path, IO[Any]], password: Optional[str] = None) -> List[Document]:
334
+ try:
335
+ if isinstance(pdf, str):
336
+ doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
337
+ else:
338
+ doc_name = pdf.name.split(".")[0]
339
+ except Exception:
340
+ doc_name = "pdf"
341
+
342
+ log_info(f"Reading: {doc_name}")
343
+
344
+ try:
345
+ pdf_reader = DocumentReader(pdf)
346
+ except PdfStreamError as e:
347
+ logger.error(f"Error reading PDF: {e}")
348
+ return []
349
+
350
+ # Handle PDF decryption
351
+ if not self._decrypt_pdf(pdf_reader, doc_name, password):
352
+ return []
353
+
354
+ # Read and chunk.
355
+ return await self._async_pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=True)
356
+
357
+
358
+ class PDFUrlReader(BasePDFReader):
359
+ """Reader for PDF files from URL"""
360
+
361
+ def __init__(self, proxy: Optional[str] = None, password: Optional[str] = None, **kwargs):
362
+ super().__init__(password=password, **kwargs)
363
+ self.proxy = proxy
364
+
365
+ def read(self, url: str, password: Optional[str] = None) -> List[Document]:
366
+ if not url:
367
+ raise ValueError("No url provided")
368
+
369
+ from io import BytesIO
370
+
371
+ log_info(f"Reading: {url}")
372
+
373
+ # Retry the request up to 3 times with exponential backoff
374
+ response = fetch_with_retry(url, proxy=self.proxy)
375
+
376
+ doc_name = url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
377
+ pdf_reader = DocumentReader(BytesIO(response.content))
378
+
379
+ # Handle PDF decryption
380
+ if not self._decrypt_pdf(pdf_reader, doc_name, password):
381
+ return []
382
+
383
+ # Read and chunk.
384
+ return self._pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=False)
385
+
386
+ async def async_read(self, url: str, password: Optional[str] = None) -> List[Document]:
387
+ if not url:
388
+ raise ValueError("No url provided")
389
+
390
+ from io import BytesIO
391
+
392
+ import httpx
393
+
394
+ log_info(f"Reading: {url}")
395
+
396
+ client_args = {"proxy": self.proxy} if self.proxy else {}
397
+ async with httpx.AsyncClient(**client_args) as client: # type: ignore
398
+ response = await async_fetch_with_retry(url, client=client)
399
+
400
+ doc_name = url.split("/")[-1].split(".")[0].replace("/", "_").replace(" ", "_")
401
+ pdf_reader = DocumentReader(BytesIO(response.content))
402
+
403
+ # Handle PDF decryption
404
+ if not self._decrypt_pdf(pdf_reader, doc_name, password):
405
+ return []
406
+
407
+ # Read and chunk.
408
+ return await self._async_pdf_reader_to_documents(pdf_reader, doc_name, use_uuid_for_id=False)
409
+
410
+
411
+ class PDFImageReader(BasePDFReader):
412
+ """Reader for PDF files with text and images extraction"""
413
+
414
+ def read(self, pdf: Union[str, Path, IO[Any]], password: Optional[str] = None) -> List[Document]:
415
+ if not pdf:
416
+ raise ValueError("No pdf provided")
417
+
418
+ try:
419
+ if isinstance(pdf, str):
420
+ doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
421
+ else:
422
+ doc_name = pdf.name.split(".")[0]
423
+ except Exception:
424
+ doc_name = "pdf"
425
+
426
+ log_info(f"Reading: {doc_name}")
427
+ pdf_reader = DocumentReader(pdf)
428
+
429
+ # Handle PDF decryption
430
+ if not self._decrypt_pdf(pdf_reader, doc_name, password):
431
+ return []
432
+
433
+ # Read and chunk.
434
+ return self._pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)
435
+
436
+ async def async_read(self, pdf: Union[str, Path, IO[Any]], password: Optional[str] = None) -> List[Document]:
437
+ if not pdf:
438
+ raise ValueError("No pdf provided")
439
+
440
+ try:
441
+ if isinstance(pdf, str):
442
+ doc_name = pdf.split("/")[-1].split(".")[0].replace(" ", "_")
443
+ else:
444
+ doc_name = pdf.name.split(".")[0]
445
+ except Exception:
446
+ doc_name = "pdf"
447
+
448
+ log_info(f"Reading: {doc_name}")
449
+ pdf_reader = DocumentReader(pdf)
450
+
451
+ # Handle PDF decryption
452
+ if not self._decrypt_pdf(pdf_reader, doc_name, password):
453
+ return []
454
+
455
+ # Read and chunk.
456
+ return await self._async_pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)
457
+
458
+
459
+ class PDFUrlImageReader(BasePDFReader):
460
+ """Reader for PDF files from URL with text and images extraction"""
461
+
462
+ def __init__(self, proxy: Optional[str] = None, password: Optional[str] = None, **kwargs):
463
+ super().__init__(password=password, **kwargs)
464
+ self.proxy = proxy
465
+
466
+ def read(self, url: str, password: Optional[str] = None) -> List[Document]:
467
+ if not url:
468
+ raise ValueError("No url provided")
469
+
470
+ from io import BytesIO
471
+
472
+ import httpx
473
+
474
+ # Read the PDF from the URL
475
+ log_info(f"Reading: {url}")
476
+ response = httpx.get(url, proxy=self.proxy) if self.proxy else httpx.get(url)
477
+
478
+ doc_name = url.split("/")[-1].split(".")[0].replace(" ", "_")
479
+ pdf_reader = DocumentReader(BytesIO(response.content))
480
+
481
+ # Handle PDF decryption
482
+ if not self._decrypt_pdf(pdf_reader, doc_name, password):
483
+ return []
484
+
485
+ # Read and chunk.
486
+ return self._pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)
487
+
488
+ async def async_read(self, url: str, password: Optional[str] = None) -> List[Document]:
489
+ if not url:
490
+ raise ValueError("No url provided")
491
+
492
+ from io import BytesIO
493
+
494
+ import httpx
495
+
496
+ log_info(f"Reading: {url}")
497
+
498
+ client_args = {"proxy": self.proxy} if self.proxy else {}
499
+ async with httpx.AsyncClient(**client_args) as client: # type: ignore
500
+ response = await client.get(url)
501
+ response.raise_for_status()
502
+
503
+ doc_name = url.split("/")[-1].split(".")[0].replace(" ", "_")
504
+ pdf_reader = DocumentReader(BytesIO(response.content))
505
+
506
+ # Handle PDF decryption
507
+ if not self._decrypt_pdf(pdf_reader, doc_name, password):
508
+ return []
509
+
510
+ # Read and chunk.
511
+ return await self._async_pdf_reader_to_documents(pdf_reader, doc_name, read_images=True, use_uuid_for_id=False)