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,3 +1,4 @@
1
+ import asyncio
1
2
  from hashlib import md5
2
3
  from typing import Any, Dict, List, Optional
3
4
 
@@ -10,8 +11,8 @@ try:
10
11
  except ImportError:
11
12
  raise ImportError("`clickhouse-connect` not installed. Use `pip install clickhouse-connect` to install it")
12
13
 
13
- from agno.document import Document
14
- from agno.embedder import Embedder
14
+ from agno.knowledge.document import Document
15
+ from agno.knowledge.embedder import Embedder
15
16
  from agno.utils.log import log_debug, log_info, logger
16
17
  from agno.vectordb.base import VectorDb
17
18
  from agno.vectordb.distance import Distance
@@ -62,7 +63,7 @@ class Clickhouse(VectorDb):
62
63
  # Embedder for embedding the document contents
63
64
  _embedder = embedder
64
65
  if _embedder is None:
65
- from agno.embedder.openai import OpenAIEmbedder
66
+ from agno.knowledge.embedder.openai import OpenAIEmbedder
66
67
 
67
68
  _embedder = OpenAIEmbedder()
68
69
  log_info("Embedder not provided, using OpenAIEmbedder as default.")
@@ -157,6 +158,7 @@ class Clickhouse(VectorDb):
157
158
  meta_data JSON DEFAULT '{{}}',
158
159
  filters JSON DEFAULT '{{}}',
159
160
  content String,
161
+ content_id String,
160
162
  embedding Array(Float32),
161
163
  usage JSON,
162
164
  created_at DateTime('UTC') DEFAULT now(),
@@ -201,6 +203,7 @@ class Clickhouse(VectorDb):
201
203
  meta_data JSON DEFAULT '{{}}',
202
204
  filters JSON DEFAULT '{{}}',
203
205
  content String,
206
+ content_id String,
204
207
  embedding Array(Float32),
205
208
  usage JSON,
206
209
  created_at DateTime('UTC') DEFAULT now(),
@@ -211,37 +214,6 @@ class Clickhouse(VectorDb):
211
214
  parameters=parameters,
212
215
  )
213
216
 
214
- def doc_exists(self, document: Document) -> bool:
215
- """
216
- Validating if the document exists or not
217
-
218
- Args:
219
- document (Document): Document to validate
220
- """
221
- cleaned_content = document.content.replace("\x00", "\ufffd")
222
- parameters = self._get_base_parameters()
223
- parameters["content_hash"] = md5(cleaned_content.encode()).hexdigest()
224
-
225
- result = self.client.query(
226
- "SELECT content_hash FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_hash = {content_hash:String}",
227
- parameters=parameters,
228
- )
229
- return bool(result.result_rows)
230
-
231
- async def async_doc_exists(self, document: Document) -> bool:
232
- """Check if a document exists asynchronously."""
233
- cleaned_content = document.content.replace("\x00", "\ufffd")
234
- async_client = await self._ensure_async_client()
235
-
236
- parameters = self._get_base_parameters()
237
- parameters["content_hash"] = md5(cleaned_content.encode()).hexdigest()
238
-
239
- result = await async_client.query(
240
- "SELECT content_hash FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_hash = {content_hash:String}",
241
- parameters=parameters,
242
- )
243
- return bool(result.result_rows)
244
-
245
217
  def name_exists(self, name: str) -> bool:
246
218
  """
247
219
  Validate if a row with this name exists or not
@@ -289,6 +261,7 @@ class Clickhouse(VectorDb):
289
261
 
290
262
  def insert(
291
263
  self,
264
+ content_hash: str,
292
265
  documents: List[Document],
293
266
  filters: Optional[Dict[str, Any]] = None,
294
267
  ) -> None:
@@ -296,8 +269,7 @@ class Clickhouse(VectorDb):
296
269
  for document in documents:
297
270
  document.embed(embedder=self.embedder)
298
271
  cleaned_content = document.content.replace("\x00", "\ufffd")
299
- content_hash = md5(cleaned_content.encode()).hexdigest()
300
- _id = document.id or content_hash
272
+ _id = md5(cleaned_content.encode()).hexdigest()
301
273
 
302
274
  row: List[Any] = [
303
275
  _id,
@@ -305,6 +277,7 @@ class Clickhouse(VectorDb):
305
277
  document.meta_data,
306
278
  filters,
307
279
  cleaned_content,
280
+ document.content_id,
308
281
  document.embedding,
309
282
  document.usage,
310
283
  content_hash,
@@ -320,6 +293,7 @@ class Clickhouse(VectorDb):
320
293
  "meta_data",
321
294
  "filters",
322
295
  "content",
296
+ "content_id",
323
297
  "embedding",
324
298
  "usage",
325
299
  "content_hash",
@@ -327,16 +301,19 @@ class Clickhouse(VectorDb):
327
301
  )
328
302
  log_debug(f"Inserted {len(documents)} documents")
329
303
 
330
- async def async_insert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
304
+ async def async_insert(
305
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
306
+ ) -> None:
331
307
  """Insert documents asynchronously."""
332
308
  rows: List[List[Any]] = []
333
309
  async_client = await self._ensure_async_client()
334
310
 
311
+ embed_tasks = [document.async_embed(embedder=self.embedder) for document in documents]
312
+ await asyncio.gather(*embed_tasks, return_exceptions=True)
313
+
335
314
  for document in documents:
336
- document.embed(embedder=self.embedder)
337
315
  cleaned_content = document.content.replace("\x00", "\ufffd")
338
- content_hash = md5(cleaned_content.encode()).hexdigest()
339
- _id = document.id or content_hash
316
+ _id = md5(cleaned_content.encode()).hexdigest()
340
317
 
341
318
  row: List[Any] = [
342
319
  _id,
@@ -344,6 +321,7 @@ class Clickhouse(VectorDb):
344
321
  document.meta_data,
345
322
  filters,
346
323
  cleaned_content,
324
+ document.content_id,
347
325
  document.embedding,
348
326
  document.usage,
349
327
  content_hash,
@@ -359,6 +337,7 @@ class Clickhouse(VectorDb):
359
337
  "meta_data",
360
338
  "filters",
361
339
  "content",
340
+ "content_id",
362
341
  "embedding",
363
342
  "usage",
364
343
  "content_hash",
@@ -371,6 +350,20 @@ class Clickhouse(VectorDb):
371
350
 
372
351
  def upsert(
373
352
  self,
353
+ content_hash: str,
354
+ documents: List[Document],
355
+ filters: Optional[Dict[str, Any]] = None,
356
+ ) -> None:
357
+ """
358
+ Upsert documents into the database.
359
+ """
360
+ if self.content_hash_exists(content_hash):
361
+ self._delete_by_content_hash(content_hash)
362
+ self.insert(content_hash=content_hash, documents=documents, filters=filters)
363
+
364
+ def _upsert(
365
+ self,
366
+ content_hash: str,
374
367
  documents: List[Document],
375
368
  filters: Optional[Dict[str, Any]] = None,
376
369
  ) -> None:
@@ -384,7 +377,7 @@ class Clickhouse(VectorDb):
384
377
  """
385
378
  # We are using ReplacingMergeTree engine in our table, so we need to insert the documents,
386
379
  # then call SELECT with FINAL
387
- self.insert(documents=documents, filters=filters)
380
+ self.insert(content_hash=content_hash, documents=documents, filters=filters)
388
381
 
389
382
  parameters = self._get_base_parameters()
390
383
  self.client.query(
@@ -392,11 +385,21 @@ class Clickhouse(VectorDb):
392
385
  parameters=parameters,
393
386
  )
394
387
 
395
- async def async_upsert(self, documents: List[Document], filters: Optional[Dict[str, Any]] = None) -> None:
388
+ async def async_upsert(
389
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
390
+ ) -> None:
391
+ """Upsert documents asynchronously."""
392
+ if self.content_hash_exists(content_hash):
393
+ self._delete_by_content_hash(content_hash)
394
+ await self._async_upsert(content_hash=content_hash, documents=documents, filters=filters)
395
+
396
+ async def _async_upsert(
397
+ self, content_hash: str, documents: List[Document], filters: Optional[Dict[str, Any]] = None
398
+ ) -> None:
396
399
  """Upsert documents asynchronously."""
397
400
  # We are using ReplacingMergeTree engine in our table, so we need to insert the documents,
398
401
  # then call SELECT with FINAL
399
- await self.async_insert(documents=documents, filters=filters)
402
+ await self.async_insert(content_hash=content_hash, documents=documents, filters=filters)
400
403
 
401
404
  parameters = self._get_base_parameters()
402
405
  await self.async_client.query( # type: ignore
@@ -412,13 +415,6 @@ class Clickhouse(VectorDb):
412
415
 
413
416
  parameters = self._get_base_parameters()
414
417
  where_query = ""
415
- # if filters:
416
- # query_filters: List[str] = []
417
- # for key, value in filters.values():
418
- # query_filters.append(f"{{{key}_key:String}} = {{{key}_value:String}}")
419
- # parameters[f"{key}_key"] = key
420
- # parameters[f"{key}_value"] = value
421
- # where_query = f"WHERE {' AND '.join(query_filters)}"
422
418
 
423
419
  order_by_query = ""
424
420
  if self.distance == Distance.l2 or self.distance == Distance.max_inner_product:
@@ -429,7 +425,7 @@ class Clickhouse(VectorDb):
429
425
  parameters["query_embedding"] = query_embedding
430
426
 
431
427
  clickhouse_query = (
432
- "SELECT name, meta_data, content, embedding, usage FROM "
428
+ "SELECT name, meta_data, content, content_id, embedding, usage FROM "
433
429
  "{database_name:Identifier}.{table_name:Identifier} "
434
430
  f"{where_query} {order_by_query} LIMIT {limit}"
435
431
  )
@@ -455,9 +451,10 @@ class Clickhouse(VectorDb):
455
451
  name=result[0],
456
452
  meta_data=result[1],
457
453
  content=result[2],
454
+ content_id=result[3],
458
455
  embedder=self.embedder,
459
- embedding=result[3],
460
- usage=result[4],
456
+ embedding=result[4],
457
+ usage=result[5],
461
458
  )
462
459
  )
463
460
 
@@ -476,13 +473,6 @@ class Clickhouse(VectorDb):
476
473
 
477
474
  parameters = self._get_base_parameters()
478
475
  where_query = ""
479
- # if filters:
480
- # query_filters: List[str] = []
481
- # for key, value in filters.values():
482
- # query_filters.append(f"{{{key}_key:String}} = {{{key}_value:String}}")
483
- # parameters[f"{key}_key"] = key
484
- # parameters[f"{key}_value"] = value
485
- # where_query = f"WHERE {' AND '.join(query_filters)}"
486
476
 
487
477
  order_by_query = ""
488
478
  if self.distance == Distance.l2 or self.distance == Distance.max_inner_product:
@@ -493,7 +483,7 @@ class Clickhouse(VectorDb):
493
483
  parameters["query_embedding"] = query_embedding
494
484
 
495
485
  clickhouse_query = (
496
- "SELECT name, meta_data, content, embedding, usage FROM "
486
+ "SELECT name, meta_data, content, content_id, embedding, usage FROM "
497
487
  "{database_name:Identifier}.{table_name:Identifier} "
498
488
  f"{where_query} {order_by_query} LIMIT {limit}"
499
489
  )
@@ -519,9 +509,10 @@ class Clickhouse(VectorDb):
519
509
  name=result[0],
520
510
  meta_data=result[1],
521
511
  content=result[2],
512
+ content_id=result[3],
522
513
  embedder=self.embedder,
523
- embedding=result[3],
524
- usage=result[4],
514
+ embedding=result[4],
515
+ usage=result[5],
525
516
  )
526
517
  )
527
518
 
@@ -573,3 +564,219 @@ class Clickhouse(VectorDb):
573
564
  parameters=parameters,
574
565
  )
575
566
  return True
567
+
568
+ def delete_by_id(self, id: str) -> bool:
569
+ """
570
+
571
+ Delete a document by its ID.
572
+
573
+ Args:
574
+ id (str): The document ID to delete
575
+
576
+ Returns:
577
+ bool: True if document was deleted, False otherwise
578
+ """
579
+ try:
580
+ log_debug(f"ClickHouse VectorDB : Deleting document with ID {id}")
581
+ if not self.id_exists(id):
582
+ return False
583
+
584
+ parameters = self._get_base_parameters()
585
+ parameters["id"] = id
586
+
587
+ self.client.command(
588
+ "DELETE FROM {database_name:Identifier}.{table_name:Identifier} WHERE id = {id:String}",
589
+ parameters=parameters,
590
+ )
591
+ return True
592
+ except Exception as e:
593
+ log_info(f"Error deleting document with ID {id}: {e}")
594
+ return False
595
+
596
+ def delete_by_name(self, name: str) -> bool:
597
+ """
598
+ Delete documents by name.
599
+
600
+ Args:
601
+ name (str): The document name to delete
602
+
603
+ Returns:
604
+ bool: True if documents were deleted, False otherwise
605
+ """
606
+ try:
607
+ log_debug(f"ClickHouse VectorDB : Deleting documents with name {name}")
608
+ if not self.name_exists(name):
609
+ return False
610
+
611
+ parameters = self._get_base_parameters()
612
+ parameters["name"] = name
613
+
614
+ self.client.command(
615
+ "DELETE FROM {database_name:Identifier}.{table_name:Identifier} WHERE name = {name:String}",
616
+ parameters=parameters,
617
+ )
618
+ return True
619
+ except Exception as e:
620
+ log_info(f"Error deleting documents with name {name}: {e}")
621
+ return False
622
+
623
+ def delete_by_metadata(self, metadata: Dict[str, Any]) -> bool:
624
+ """
625
+ Delete documents by metadata.
626
+
627
+ Args:
628
+ metadata (Dict[str, Any]): The metadata to match for deletion
629
+
630
+ Returns:
631
+ bool: True if documents were deleted, False otherwise
632
+ """
633
+ try:
634
+ log_debug(f"ClickHouse VectorDB : Deleting documents with metadata {metadata}")
635
+ parameters = self._get_base_parameters()
636
+
637
+ # Build WHERE clause for metadata matching using proper ClickHouse JSON syntax
638
+ where_conditions = []
639
+ for key, value in metadata.items():
640
+ if isinstance(value, bool):
641
+ where_conditions.append(f"JSONExtractBool(toString(filters), '{key}') = {str(value).lower()}")
642
+ elif isinstance(value, (int, float)):
643
+ where_conditions.append(f"JSONExtractFloat(toString(filters), '{key}') = {value}")
644
+ else:
645
+ where_conditions.append(f"JSONExtractString(toString(filters), '{key}') = '{value}'")
646
+
647
+ if not where_conditions:
648
+ return False
649
+
650
+ where_clause = " AND ".join(where_conditions)
651
+
652
+ self.client.command(
653
+ f"DELETE FROM {{database_name:Identifier}}.{{table_name:Identifier}} WHERE {where_clause}",
654
+ parameters=parameters,
655
+ )
656
+ return True
657
+ except Exception as e:
658
+ log_info(f"Error deleting documents with metadata {metadata}: {e}")
659
+ return False
660
+
661
+ def delete_by_content_id(self, content_id: str) -> bool:
662
+ """
663
+ Delete documents by content ID.
664
+
665
+ Args:
666
+ content_id (str): The content ID to delete
667
+
668
+ Returns:
669
+ bool: True if documents were deleted, False otherwise
670
+ """
671
+ try:
672
+ log_debug(f"ClickHouse VectorDB : Deleting documents with content_id {content_id}")
673
+ parameters = self._get_base_parameters()
674
+ parameters["content_id"] = content_id
675
+
676
+ self.client.command(
677
+ "DELETE FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_id = {content_id:String}",
678
+ parameters=parameters,
679
+ )
680
+ return True
681
+ except Exception as e:
682
+ log_info(f"Error deleting documents with content_id {content_id}: {e}")
683
+ return False
684
+
685
+ def content_hash_exists(self, content_hash: str) -> bool:
686
+ """
687
+ Validate if a row with this content_hash exists or not
688
+
689
+ Args:
690
+ content_hash (str): Content hash to check
691
+ """
692
+ parameters = self._get_base_parameters()
693
+ parameters["content_hash"] = content_hash
694
+
695
+ result = self.client.query(
696
+ "SELECT content_hash FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_hash = {content_hash:String}",
697
+ parameters=parameters,
698
+ )
699
+ return bool(result)
700
+
701
+ def _delete_by_content_hash(self, content_hash: str) -> bool:
702
+ """
703
+ Delete documents by content hash.
704
+ """
705
+ try:
706
+ parameters = self._get_base_parameters()
707
+ parameters["content_hash"] = content_hash
708
+
709
+ self.client.command(
710
+ "DELETE FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_hash = {content_hash:String}",
711
+ parameters=parameters,
712
+ )
713
+ return True
714
+ except Exception:
715
+ return False
716
+
717
+ def update_metadata(self, content_id: str, metadata: Dict[str, Any]) -> None:
718
+ """
719
+ Update the metadata for documents with the given content_id.
720
+
721
+ Args:
722
+ content_id (str): The content ID to update
723
+ metadata (Dict[str, Any]): The metadata to update
724
+ """
725
+ import json
726
+
727
+ try:
728
+ parameters = self._get_base_parameters()
729
+ parameters["content_id"] = content_id
730
+
731
+ # First, get existing documents with their current metadata and filters
732
+ result = self.client.query(
733
+ "SELECT id, meta_data, filters FROM {database_name:Identifier}.{table_name:Identifier} WHERE content_id = {content_id:String}",
734
+ parameters=parameters,
735
+ )
736
+
737
+ if not result.result_rows:
738
+ logger.debug(f"No documents found with content_id: {content_id}")
739
+ return
740
+
741
+ # Update each document
742
+ updated_count = 0
743
+ for row in result.result_rows:
744
+ doc_id, current_meta_json, current_filters_json = row
745
+
746
+ # Parse existing metadata
747
+ try:
748
+ current_metadata = json.loads(current_meta_json) if current_meta_json else {}
749
+ except (json.JSONDecodeError, TypeError):
750
+ current_metadata = {}
751
+
752
+ # Parse existing filters
753
+ try:
754
+ current_filters = json.loads(current_filters_json) if current_filters_json else {}
755
+ except (json.JSONDecodeError, TypeError):
756
+ current_filters = {}
757
+
758
+ # Merge existing metadata with new metadata
759
+ updated_metadata = current_metadata.copy()
760
+ updated_metadata.update(metadata)
761
+
762
+ # Merge existing filters with new metadata
763
+ updated_filters = current_filters.copy()
764
+ updated_filters.update(metadata)
765
+
766
+ # Update the document
767
+ update_params = parameters.copy()
768
+ update_params["doc_id"] = doc_id
769
+ update_params["metadata_json"] = json.dumps(updated_metadata)
770
+ update_params["filters_json"] = json.dumps(updated_filters)
771
+
772
+ self.client.command(
773
+ "ALTER TABLE {database_name:Identifier}.{table_name:Identifier} UPDATE meta_data = {metadata_json:String}, filters = {filters_json:String} WHERE id = {doc_id:String}",
774
+ parameters=update_params,
775
+ )
776
+ updated_count += 1
777
+
778
+ logger.debug(f"Updated metadata for {updated_count} documents with content_id: {content_id}")
779
+
780
+ except Exception as e:
781
+ logger.error(f"Error updating metadata for content_id '{content_id}': {e}")
782
+ raise