agno 1.8.1__py3-none-any.whl → 2.0.0__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 (590) hide show
  1. agno/__init__.py +8 -0
  2. agno/agent/__init__.py +19 -27
  3. agno/agent/agent.py +3143 -4170
  4. agno/api/agent.py +11 -67
  5. agno/api/api.py +5 -46
  6. agno/api/evals.py +8 -19
  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 +11 -66
  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 +1743 -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 +1432 -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 +882 -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 +1045 -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 +1416 -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 +297 -0
  52. agno/db/postgres/__init__.py +3 -0
  53. agno/db/postgres/postgres.py +1710 -0
  54. agno/db/postgres/schemas.py +124 -0
  55. agno/db/postgres/utils.py +280 -0
  56. agno/db/redis/__init__.py +3 -0
  57. agno/db/redis/redis.py +1367 -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 +1712 -0
  67. agno/db/singlestore/utils.py +326 -0
  68. agno/db/sqlite/__init__.py +3 -0
  69. agno/db/sqlite/schemas.py +119 -0
  70. agno/db/sqlite/sqlite.py +1676 -0
  71. agno/db/sqlite/utils.py +268 -0
  72. agno/db/utils.py +88 -0
  73. agno/eval/__init__.py +14 -0
  74. agno/eval/accuracy.py +154 -48
  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 +15 -11
  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 +1551 -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 +47 -65
  115. agno/knowledge/reader/docx_reader.py +83 -0
  116. agno/{document → knowledge}/reader/firecrawl_reader.py +42 -21
  117. agno/{document → knowledge}/reader/json_reader.py +30 -9
  118. agno/{document → knowledge}/reader/markdown_reader.py +58 -9
  119. agno/{document → knowledge}/reader/pdf_reader.py +71 -126
  120. agno/knowledge/reader/reader_factory.py +268 -0
  121. agno/knowledge/reader/s3_reader.py +101 -0
  122. agno/{document → knowledge}/reader/text_reader.py +31 -10
  123. agno/knowledge/reader/url_reader.py +128 -0
  124. agno/knowledge/reader/web_search_reader.py +366 -0
  125. agno/{document → knowledge}/reader/website_reader.py +37 -10
  126. agno/knowledge/reader/wikipedia_reader.py +59 -0
  127. agno/knowledge/reader/youtube_reader.py +78 -0
  128. agno/knowledge/remote_content/remote_content.py +88 -0
  129. agno/{reranker → knowledge/reranker}/base.py +1 -1
  130. agno/{reranker → knowledge/reranker}/cohere.py +2 -2
  131. agno/{reranker → knowledge/reranker}/infinity.py +2 -2
  132. agno/{reranker → knowledge/reranker}/sentence_transformer.py +2 -2
  133. agno/knowledge/types.py +30 -0
  134. agno/knowledge/utils.py +169 -0
  135. agno/media.py +269 -268
  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 +131 -131
  141. agno/models/aws/bedrock.py +110 -182
  142. agno/models/aws/claude.py +64 -18
  143. agno/models/azure/ai_foundry.py +73 -23
  144. agno/models/base.py +346 -290
  145. agno/models/cerebras/cerebras.py +84 -27
  146. agno/models/cohere/chat.py +106 -98
  147. agno/models/google/gemini.py +105 -46
  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 +46 -151
  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 +85 -47
  158. agno/models/openai/chat.py +154 -37
  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 +15 -9
  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 +497 -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 +77 -33
  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 +32 -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 +29 -0
  184. agno/os/mcp.py +235 -0
  185. agno/os/router.py +1400 -0
  186. agno/os/routers/__init__.py +3 -0
  187. agno/os/routers/evals/__init__.py +3 -0
  188. agno/os/routers/evals/evals.py +393 -0
  189. agno/os/routers/evals/schemas.py +142 -0
  190. agno/os/routers/evals/utils.py +161 -0
  191. agno/os/routers/knowledge/__init__.py +3 -0
  192. agno/os/routers/knowledge/knowledge.py +850 -0
  193. agno/os/routers/knowledge/schemas.py +118 -0
  194. agno/os/routers/memory/__init__.py +3 -0
  195. agno/os/routers/memory/memory.py +410 -0
  196. agno/os/routers/memory/schemas.py +58 -0
  197. agno/os/routers/metrics/__init__.py +3 -0
  198. agno/os/routers/metrics/metrics.py +178 -0
  199. agno/os/routers/metrics/schemas.py +47 -0
  200. agno/os/routers/session/__init__.py +3 -0
  201. agno/os/routers/session/session.py +536 -0
  202. agno/os/schema.py +945 -0
  203. agno/{app/playground → os}/settings.py +7 -15
  204. agno/os/utils.py +270 -0
  205. agno/reasoning/azure_ai_foundry.py +4 -4
  206. agno/reasoning/deepseek.py +4 -4
  207. agno/reasoning/default.py +6 -11
  208. agno/reasoning/groq.py +4 -4
  209. agno/reasoning/helpers.py +4 -6
  210. agno/reasoning/ollama.py +4 -4
  211. agno/reasoning/openai.py +4 -4
  212. agno/run/agent.py +633 -0
  213. agno/run/base.py +53 -77
  214. agno/run/cancel.py +81 -0
  215. agno/run/team.py +243 -96
  216. agno/run/workflow.py +550 -12
  217. agno/session/__init__.py +10 -0
  218. agno/session/agent.py +244 -0
  219. agno/session/summary.py +225 -0
  220. agno/session/team.py +262 -0
  221. agno/{storage/session/v2 → session}/workflow.py +47 -24
  222. agno/team/__init__.py +15 -16
  223. agno/team/team.py +3260 -4824
  224. agno/tools/agentql.py +14 -5
  225. agno/tools/airflow.py +9 -4
  226. agno/tools/api.py +7 -3
  227. agno/tools/apify.py +2 -46
  228. agno/tools/arxiv.py +8 -3
  229. agno/tools/aws_lambda.py +7 -5
  230. agno/tools/aws_ses.py +7 -1
  231. agno/tools/baidusearch.py +4 -1
  232. agno/tools/bitbucket.py +4 -4
  233. agno/tools/brandfetch.py +14 -11
  234. agno/tools/bravesearch.py +4 -1
  235. agno/tools/brightdata.py +43 -23
  236. agno/tools/browserbase.py +13 -4
  237. agno/tools/calcom.py +12 -10
  238. agno/tools/calculator.py +10 -27
  239. agno/tools/cartesia.py +20 -17
  240. agno/tools/{clickup_tool.py → clickup.py} +12 -25
  241. agno/tools/confluence.py +8 -8
  242. agno/tools/crawl4ai.py +7 -1
  243. agno/tools/csv_toolkit.py +9 -8
  244. agno/tools/dalle.py +22 -12
  245. agno/tools/daytona.py +13 -16
  246. agno/tools/decorator.py +6 -3
  247. agno/tools/desi_vocal.py +17 -8
  248. agno/tools/discord.py +11 -8
  249. agno/tools/docker.py +30 -42
  250. agno/tools/duckdb.py +34 -53
  251. agno/tools/duckduckgo.py +8 -7
  252. agno/tools/e2b.py +62 -62
  253. agno/tools/eleven_labs.py +36 -29
  254. agno/tools/email.py +4 -1
  255. agno/tools/evm.py +7 -1
  256. agno/tools/exa.py +19 -14
  257. agno/tools/fal.py +30 -30
  258. agno/tools/file.py +9 -8
  259. agno/tools/financial_datasets.py +25 -44
  260. agno/tools/firecrawl.py +22 -22
  261. agno/tools/function.py +127 -18
  262. agno/tools/giphy.py +23 -11
  263. agno/tools/github.py +48 -126
  264. agno/tools/gmail.py +45 -61
  265. agno/tools/google_bigquery.py +7 -6
  266. agno/tools/google_maps.py +11 -26
  267. agno/tools/googlesearch.py +7 -2
  268. agno/tools/googlesheets.py +21 -17
  269. agno/tools/hackernews.py +9 -5
  270. agno/tools/jina.py +5 -4
  271. agno/tools/jira.py +18 -9
  272. agno/tools/knowledge.py +31 -32
  273. agno/tools/linear.py +19 -34
  274. agno/tools/linkup.py +5 -1
  275. agno/tools/local_file_system.py +8 -5
  276. agno/tools/lumalab.py +32 -20
  277. agno/tools/mcp.py +1 -2
  278. agno/tools/mem0.py +18 -12
  279. agno/tools/memori.py +14 -10
  280. agno/tools/mlx_transcribe.py +3 -2
  281. agno/tools/models/azure_openai.py +33 -15
  282. agno/tools/models/gemini.py +59 -32
  283. agno/tools/models/groq.py +30 -23
  284. agno/tools/models/nebius.py +28 -12
  285. agno/tools/models_labs.py +40 -16
  286. agno/tools/moviepy_video.py +7 -6
  287. agno/tools/neo4j.py +10 -8
  288. agno/tools/newspaper.py +7 -2
  289. agno/tools/newspaper4k.py +8 -3
  290. agno/tools/openai.py +58 -32
  291. agno/tools/openbb.py +12 -11
  292. agno/tools/opencv.py +63 -47
  293. agno/tools/openweather.py +14 -12
  294. agno/tools/pandas.py +11 -3
  295. agno/tools/postgres.py +4 -12
  296. agno/tools/pubmed.py +4 -1
  297. agno/tools/python.py +9 -22
  298. agno/tools/reasoning.py +35 -27
  299. agno/tools/reddit.py +11 -26
  300. agno/tools/replicate.py +55 -42
  301. agno/tools/resend.py +4 -1
  302. agno/tools/scrapegraph.py +15 -14
  303. agno/tools/searxng.py +10 -23
  304. agno/tools/serpapi.py +6 -3
  305. agno/tools/serper.py +13 -4
  306. agno/tools/shell.py +9 -2
  307. agno/tools/slack.py +12 -11
  308. agno/tools/sleep.py +3 -2
  309. agno/tools/spider.py +24 -4
  310. agno/tools/sql.py +7 -6
  311. agno/tools/tavily.py +6 -4
  312. agno/tools/telegram.py +12 -4
  313. agno/tools/todoist.py +11 -31
  314. agno/tools/toolkit.py +1 -1
  315. agno/tools/trafilatura.py +22 -6
  316. agno/tools/trello.py +9 -22
  317. agno/tools/twilio.py +10 -3
  318. agno/tools/user_control_flow.py +6 -1
  319. agno/tools/valyu.py +34 -5
  320. agno/tools/visualization.py +19 -28
  321. agno/tools/webbrowser.py +4 -3
  322. agno/tools/webex.py +11 -7
  323. agno/tools/website.py +15 -46
  324. agno/tools/webtools.py +12 -4
  325. agno/tools/whatsapp.py +5 -9
  326. agno/tools/wikipedia.py +20 -13
  327. agno/tools/x.py +14 -13
  328. agno/tools/yfinance.py +13 -40
  329. agno/tools/youtube.py +26 -20
  330. agno/tools/zendesk.py +7 -2
  331. agno/tools/zep.py +10 -7
  332. agno/tools/zoom.py +10 -9
  333. agno/utils/common.py +1 -19
  334. agno/utils/events.py +100 -123
  335. agno/utils/gemini.py +32 -2
  336. agno/utils/knowledge.py +29 -0
  337. agno/utils/log.py +54 -4
  338. agno/utils/mcp.py +68 -10
  339. agno/utils/media.py +39 -0
  340. agno/utils/message.py +12 -1
  341. agno/utils/models/aws_claude.py +1 -1
  342. agno/utils/models/claude.py +47 -4
  343. agno/utils/models/cohere.py +1 -1
  344. agno/utils/models/mistral.py +8 -7
  345. agno/utils/models/schema_utils.py +3 -3
  346. agno/utils/models/watsonx.py +1 -1
  347. agno/utils/openai.py +1 -1
  348. agno/utils/pprint.py +33 -32
  349. agno/utils/print_response/agent.py +779 -0
  350. agno/utils/print_response/team.py +1669 -0
  351. agno/utils/print_response/workflow.py +1451 -0
  352. agno/utils/prompts.py +14 -14
  353. agno/utils/reasoning.py +87 -0
  354. agno/utils/response.py +42 -42
  355. agno/utils/streamlit.py +481 -0
  356. agno/utils/string.py +8 -22
  357. agno/utils/team.py +50 -0
  358. agno/utils/timer.py +2 -2
  359. agno/vectordb/base.py +33 -21
  360. agno/vectordb/cassandra/cassandra.py +287 -23
  361. agno/vectordb/chroma/chromadb.py +482 -59
  362. agno/vectordb/clickhouse/clickhousedb.py +270 -63
  363. agno/vectordb/couchbase/couchbase.py +309 -29
  364. agno/vectordb/lancedb/lance_db.py +360 -21
  365. agno/vectordb/langchaindb/__init__.py +5 -0
  366. agno/vectordb/langchaindb/langchaindb.py +145 -0
  367. agno/vectordb/lightrag/__init__.py +5 -0
  368. agno/vectordb/lightrag/lightrag.py +374 -0
  369. agno/vectordb/llamaindex/llamaindexdb.py +127 -0
  370. agno/vectordb/milvus/milvus.py +242 -32
  371. agno/vectordb/mongodb/mongodb.py +200 -24
  372. agno/vectordb/pgvector/pgvector.py +319 -37
  373. agno/vectordb/pineconedb/pineconedb.py +221 -27
  374. agno/vectordb/qdrant/qdrant.py +334 -14
  375. agno/vectordb/singlestore/singlestore.py +286 -29
  376. agno/vectordb/surrealdb/surrealdb.py +187 -7
  377. agno/vectordb/upstashdb/upstashdb.py +342 -26
  378. agno/vectordb/weaviate/weaviate.py +227 -165
  379. agno/workflow/__init__.py +17 -13
  380. agno/workflow/{v2/condition.py → condition.py} +135 -32
  381. agno/workflow/{v2/loop.py → loop.py} +115 -28
  382. agno/workflow/{v2/parallel.py → parallel.py} +138 -108
  383. agno/workflow/{v2/router.py → router.py} +133 -32
  384. agno/workflow/{v2/step.py → step.py} +207 -49
  385. agno/workflow/{v2/steps.py → steps.py} +147 -66
  386. agno/workflow/types.py +482 -0
  387. agno/workflow/workflow.py +2410 -696
  388. agno-2.0.0.dist-info/METADATA +494 -0
  389. agno-2.0.0.dist-info/RECORD +515 -0
  390. agno-2.0.0.dist-info/licenses/LICENSE +201 -0
  391. agno/agent/metrics.py +0 -107
  392. agno/api/app.py +0 -35
  393. agno/api/playground.py +0 -92
  394. agno/api/schemas/app.py +0 -12
  395. agno/api/schemas/playground.py +0 -22
  396. agno/api/schemas/user.py +0 -35
  397. agno/api/schemas/workspace.py +0 -46
  398. agno/api/user.py +0 -160
  399. agno/api/workflows.py +0 -33
  400. agno/api/workspace.py +0 -175
  401. agno/app/agui/__init__.py +0 -3
  402. agno/app/agui/app.py +0 -17
  403. agno/app/agui/sync_router.py +0 -120
  404. agno/app/base.py +0 -186
  405. agno/app/discord/__init__.py +0 -3
  406. agno/app/fastapi/__init__.py +0 -3
  407. agno/app/fastapi/app.py +0 -107
  408. agno/app/fastapi/async_router.py +0 -457
  409. agno/app/fastapi/sync_router.py +0 -448
  410. agno/app/playground/app.py +0 -228
  411. agno/app/playground/async_router.py +0 -1050
  412. agno/app/playground/deploy.py +0 -249
  413. agno/app/playground/operator.py +0 -183
  414. agno/app/playground/schemas.py +0 -220
  415. agno/app/playground/serve.py +0 -55
  416. agno/app/playground/sync_router.py +0 -1042
  417. agno/app/playground/utils.py +0 -46
  418. agno/app/settings.py +0 -15
  419. agno/app/slack/__init__.py +0 -3
  420. agno/app/slack/app.py +0 -19
  421. agno/app/slack/sync_router.py +0 -92
  422. agno/app/utils.py +0 -54
  423. agno/app/whatsapp/__init__.py +0 -3
  424. agno/app/whatsapp/app.py +0 -15
  425. agno/app/whatsapp/sync_router.py +0 -197
  426. agno/cli/auth_server.py +0 -249
  427. agno/cli/config.py +0 -274
  428. agno/cli/console.py +0 -88
  429. agno/cli/credentials.py +0 -23
  430. agno/cli/entrypoint.py +0 -571
  431. agno/cli/operator.py +0 -357
  432. agno/cli/settings.py +0 -96
  433. agno/cli/ws/ws_cli.py +0 -817
  434. agno/constants.py +0 -13
  435. agno/document/__init__.py +0 -5
  436. agno/document/chunking/semantic.py +0 -45
  437. agno/document/chunking/strategy.py +0 -31
  438. agno/document/reader/__init__.py +0 -5
  439. agno/document/reader/base.py +0 -47
  440. agno/document/reader/docx_reader.py +0 -60
  441. agno/document/reader/gcs/pdf_reader.py +0 -44
  442. agno/document/reader/s3/pdf_reader.py +0 -59
  443. agno/document/reader/s3/text_reader.py +0 -63
  444. agno/document/reader/url_reader.py +0 -59
  445. agno/document/reader/youtube_reader.py +0 -58
  446. agno/embedder/__init__.py +0 -5
  447. agno/embedder/langdb.py +0 -80
  448. agno/embedder/mistral.py +0 -82
  449. agno/embedder/openai.py +0 -78
  450. agno/file/__init__.py +0 -5
  451. agno/file/file.py +0 -16
  452. agno/file/local/csv.py +0 -32
  453. agno/file/local/txt.py +0 -19
  454. agno/infra/app.py +0 -240
  455. agno/infra/base.py +0 -144
  456. agno/infra/context.py +0 -20
  457. agno/infra/db_app.py +0 -52
  458. agno/infra/resource.py +0 -205
  459. agno/infra/resources.py +0 -55
  460. agno/knowledge/agent.py +0 -702
  461. agno/knowledge/arxiv.py +0 -33
  462. agno/knowledge/combined.py +0 -36
  463. agno/knowledge/csv.py +0 -144
  464. agno/knowledge/csv_url.py +0 -124
  465. agno/knowledge/document.py +0 -223
  466. agno/knowledge/docx.py +0 -137
  467. agno/knowledge/firecrawl.py +0 -34
  468. agno/knowledge/gcs/__init__.py +0 -0
  469. agno/knowledge/gcs/base.py +0 -39
  470. agno/knowledge/gcs/pdf.py +0 -125
  471. agno/knowledge/json.py +0 -137
  472. agno/knowledge/langchain.py +0 -71
  473. agno/knowledge/light_rag.py +0 -273
  474. agno/knowledge/llamaindex.py +0 -66
  475. agno/knowledge/markdown.py +0 -154
  476. agno/knowledge/pdf.py +0 -164
  477. agno/knowledge/pdf_bytes.py +0 -42
  478. agno/knowledge/pdf_url.py +0 -148
  479. agno/knowledge/s3/__init__.py +0 -0
  480. agno/knowledge/s3/base.py +0 -64
  481. agno/knowledge/s3/pdf.py +0 -33
  482. agno/knowledge/s3/text.py +0 -34
  483. agno/knowledge/text.py +0 -141
  484. agno/knowledge/url.py +0 -46
  485. agno/knowledge/website.py +0 -179
  486. agno/knowledge/wikipedia.py +0 -32
  487. agno/knowledge/youtube.py +0 -35
  488. agno/memory/agent.py +0 -423
  489. agno/memory/classifier.py +0 -104
  490. agno/memory/db/__init__.py +0 -5
  491. agno/memory/db/base.py +0 -42
  492. agno/memory/db/mongodb.py +0 -189
  493. agno/memory/db/postgres.py +0 -203
  494. agno/memory/db/sqlite.py +0 -193
  495. agno/memory/memory.py +0 -22
  496. agno/memory/row.py +0 -36
  497. agno/memory/summarizer.py +0 -201
  498. agno/memory/summary.py +0 -19
  499. agno/memory/team.py +0 -415
  500. agno/memory/v2/__init__.py +0 -2
  501. agno/memory/v2/db/__init__.py +0 -1
  502. agno/memory/v2/db/base.py +0 -42
  503. agno/memory/v2/db/firestore.py +0 -339
  504. agno/memory/v2/db/mongodb.py +0 -196
  505. agno/memory/v2/db/postgres.py +0 -214
  506. agno/memory/v2/db/redis.py +0 -187
  507. agno/memory/v2/db/schema.py +0 -54
  508. agno/memory/v2/db/sqlite.py +0 -209
  509. agno/memory/v2/manager.py +0 -437
  510. agno/memory/v2/memory.py +0 -1097
  511. agno/memory/v2/schema.py +0 -55
  512. agno/memory/v2/summarizer.py +0 -215
  513. agno/memory/workflow.py +0 -38
  514. agno/models/ollama/tools.py +0 -430
  515. agno/models/qwen/__init__.py +0 -5
  516. agno/playground/__init__.py +0 -10
  517. agno/playground/deploy.py +0 -3
  518. agno/playground/playground.py +0 -3
  519. agno/playground/serve.py +0 -3
  520. agno/playground/settings.py +0 -3
  521. agno/reranker/__init__.py +0 -0
  522. agno/run/response.py +0 -467
  523. agno/run/v2/__init__.py +0 -0
  524. agno/run/v2/workflow.py +0 -567
  525. agno/storage/__init__.py +0 -0
  526. agno/storage/agent/__init__.py +0 -0
  527. agno/storage/agent/dynamodb.py +0 -1
  528. agno/storage/agent/json.py +0 -1
  529. agno/storage/agent/mongodb.py +0 -1
  530. agno/storage/agent/postgres.py +0 -1
  531. agno/storage/agent/singlestore.py +0 -1
  532. agno/storage/agent/sqlite.py +0 -1
  533. agno/storage/agent/yaml.py +0 -1
  534. agno/storage/base.py +0 -60
  535. agno/storage/dynamodb.py +0 -673
  536. agno/storage/firestore.py +0 -297
  537. agno/storage/gcs_json.py +0 -261
  538. agno/storage/in_memory.py +0 -234
  539. agno/storage/json.py +0 -237
  540. agno/storage/mongodb.py +0 -328
  541. agno/storage/mysql.py +0 -685
  542. agno/storage/postgres.py +0 -682
  543. agno/storage/redis.py +0 -336
  544. agno/storage/session/__init__.py +0 -16
  545. agno/storage/session/agent.py +0 -64
  546. agno/storage/session/team.py +0 -63
  547. agno/storage/session/v2/__init__.py +0 -5
  548. agno/storage/session/workflow.py +0 -61
  549. agno/storage/singlestore.py +0 -606
  550. agno/storage/sqlite.py +0 -646
  551. agno/storage/workflow/__init__.py +0 -0
  552. agno/storage/workflow/mongodb.py +0 -1
  553. agno/storage/workflow/postgres.py +0 -1
  554. agno/storage/workflow/sqlite.py +0 -1
  555. agno/storage/yaml.py +0 -241
  556. agno/tools/thinking.py +0 -73
  557. agno/utils/defaults.py +0 -57
  558. agno/utils/filesystem.py +0 -39
  559. agno/utils/git.py +0 -52
  560. agno/utils/json_io.py +0 -30
  561. agno/utils/load_env.py +0 -19
  562. agno/utils/py_io.py +0 -19
  563. agno/utils/pyproject.py +0 -18
  564. agno/utils/resource_filter.py +0 -31
  565. agno/workflow/v2/__init__.py +0 -21
  566. agno/workflow/v2/types.py +0 -357
  567. agno/workflow/v2/workflow.py +0 -3312
  568. agno/workspace/__init__.py +0 -0
  569. agno/workspace/config.py +0 -325
  570. agno/workspace/enums.py +0 -6
  571. agno/workspace/helpers.py +0 -52
  572. agno/workspace/operator.py +0 -757
  573. agno/workspace/settings.py +0 -158
  574. agno-1.8.1.dist-info/METADATA +0 -982
  575. agno-1.8.1.dist-info/RECORD +0 -566
  576. agno-1.8.1.dist-info/entry_points.txt +0 -3
  577. agno-1.8.1.dist-info/licenses/LICENSE +0 -375
  578. /agno/{app → db/migrations}/__init__.py +0 -0
  579. /agno/{app/playground/__init__.py → db/schemas/metrics.py} +0 -0
  580. /agno/{cli → integrations}/__init__.py +0 -0
  581. /agno/{cli/ws → knowledge/chunking}/__init__.py +0 -0
  582. /agno/{document/chunking → knowledge/remote_content}/__init__.py +0 -0
  583. /agno/{document/reader/gcs → knowledge/reranker}/__init__.py +0 -0
  584. /agno/{document/reader/s3 → os/interfaces}/__init__.py +0 -0
  585. /agno/{app → os/interfaces}/slack/security.py +0 -0
  586. /agno/{app → os/interfaces}/whatsapp/security.py +0 -0
  587. /agno/{file/local → utils/print_response}/__init__.py +0 -0
  588. /agno/{infra → vectordb/llamaindex}/__init__.py +0 -0
  589. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/WHEEL +0 -0
  590. {agno-1.8.1.dist-info → agno-2.0.0.dist-info}/top_level.txt +0 -0
@@ -9,20 +9,23 @@ from pydantic import BaseModel
9
9
 
10
10
  from agno.models.base import Model
11
11
  from agno.models.message import Message
12
+ from agno.models.metrics import Metrics
12
13
  from agno.models.response import ModelResponse
14
+ from agno.run.agent import RunOutput
13
15
  from agno.utils.log import log_debug, log_error, log_warning
14
16
 
15
17
  try:
16
18
  from cerebras.cloud.sdk import AsyncCerebras as AsyncCerebrasClient
17
19
  from cerebras.cloud.sdk import Cerebras as CerebrasClient
18
- from cerebras.cloud.sdk.types.chat import ChatCompletion
19
20
  from cerebras.cloud.sdk.types.chat.chat_completion import (
20
21
  ChatChunkResponse,
21
22
  ChatChunkResponseChoice,
22
23
  ChatChunkResponseChoiceDelta,
24
+ ChatChunkResponseUsage,
23
25
  ChatCompletionResponse,
24
26
  ChatCompletionResponseChoice,
25
27
  ChatCompletionResponseChoiceMessage,
28
+ ChatCompletionResponseUsage,
26
29
  )
27
30
  except (ImportError, ModuleNotFoundError):
28
31
  raise ImportError("`cerebras-cloud-sdk` not installed. Please install using `pip install cerebras-cloud-sdk`")
@@ -198,10 +201,12 @@ class Cerebras(Model):
198
201
  def invoke(
199
202
  self,
200
203
  messages: List[Message],
204
+ assistant_message: Message,
201
205
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
202
206
  tools: Optional[List[Dict[str, Any]]] = None,
203
207
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
204
- ) -> ChatCompletion:
208
+ run_response: Optional[RunOutput] = None,
209
+ ) -> ModelResponse:
205
210
  """
206
211
  Send a chat completion request to the Cerebras API.
207
212
 
@@ -211,19 +216,30 @@ class Cerebras(Model):
211
216
  Returns:
212
217
  CompletionResponse: The chat completion response from the API.
213
218
  """
214
- return self.get_client().chat.completions.create(
219
+ if run_response and run_response.metrics:
220
+ run_response.metrics.set_time_to_first_token()
221
+
222
+ assistant_message.metrics.start_timer()
223
+ provider_response = self.get_client().chat.completions.create(
215
224
  model=self.id,
216
225
  messages=[self._format_message(m) for m in messages], # type: ignore
217
226
  **self.get_request_params(response_format=response_format, tools=tools),
218
227
  )
228
+ assistant_message.metrics.stop_timer()
229
+
230
+ model_response = self._parse_provider_response(provider_response, response_format=response_format) # type: ignore
231
+
232
+ return model_response
219
233
 
220
234
  async def ainvoke(
221
235
  self,
222
236
  messages: List[Message],
237
+ assistant_message: Message,
223
238
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
224
239
  tools: Optional[List[Dict[str, Any]]] = None,
225
240
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
226
- ) -> ChatCompletion:
241
+ run_response: Optional[RunOutput] = None,
242
+ ) -> ModelResponse:
227
243
  """
228
244
  Sends an asynchronous chat completion request to the Cerebras API.
229
245
 
@@ -233,19 +249,30 @@ class Cerebras(Model):
233
249
  Returns:
234
250
  ChatCompletion: The chat completion response from the API.
235
251
  """
236
- return await self.get_async_client().chat.completions.create(
252
+ if run_response and run_response.metrics:
253
+ run_response.metrics.set_time_to_first_token()
254
+
255
+ assistant_message.metrics.start_timer()
256
+ provider_response = await self.get_async_client().chat.completions.create(
237
257
  model=self.id,
238
258
  messages=[self._format_message(m) for m in messages], # type: ignore
239
259
  **self.get_request_params(response_format=response_format, tools=tools),
240
260
  )
261
+ assistant_message.metrics.stop_timer()
262
+
263
+ model_response = self._parse_provider_response(provider_response, response_format=response_format) # type: ignore
264
+
265
+ return model_response
241
266
 
242
267
  def invoke_stream(
243
268
  self,
244
269
  messages: List[Message],
270
+ assistant_message: Message,
245
271
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
246
272
  tools: Optional[List[Dict[str, Any]]] = None,
247
273
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
248
- ) -> Iterator[ChatChunkResponse]:
274
+ run_response: Optional[RunOutput] = None,
275
+ ) -> Iterator[ModelResponse]:
249
276
  """
250
277
  Send a streaming chat completion request to the Cerebras API.
251
278
 
@@ -255,20 +282,30 @@ class Cerebras(Model):
255
282
  Returns:
256
283
  Iterator[ChatChunkResponse]: An iterator of chat completion chunks.
257
284
  """
258
- yield from self.get_client().chat.completions.create(
285
+ if run_response and run_response.metrics:
286
+ run_response.metrics.set_time_to_first_token()
287
+
288
+ assistant_message.metrics.start_timer()
289
+
290
+ for chunk in self.get_client().chat.completions.create(
259
291
  model=self.id,
260
292
  messages=[self._format_message(m) for m in messages], # type: ignore
261
293
  stream=True,
262
294
  **self.get_request_params(response_format=response_format, tools=tools),
263
- ) # type: ignore
295
+ ):
296
+ yield self._parse_provider_response_delta(chunk) # type: ignore
297
+
298
+ assistant_message.metrics.stop_timer()
264
299
 
265
300
  async def ainvoke_stream(
266
301
  self,
267
302
  messages: List[Message],
303
+ assistant_message: Message,
268
304
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
269
305
  tools: Optional[List[Dict[str, Any]]] = None,
270
306
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
271
- ) -> AsyncIterator[ChatChunkResponse]:
307
+ run_response: Optional[RunOutput] = None,
308
+ ) -> AsyncIterator[ModelResponse]:
272
309
  """
273
310
  Sends an asynchronous streaming chat completion request to the Cerebras API.
274
311
 
@@ -278,14 +315,22 @@ class Cerebras(Model):
278
315
  Returns:
279
316
  AsyncIterator[ChatChunkResponse]: An asynchronous iterator of chat completion chunks.
280
317
  """
318
+ if run_response and run_response.metrics:
319
+ run_response.metrics.set_time_to_first_token()
320
+
321
+ assistant_message.metrics.start_timer()
322
+
281
323
  async_stream = await self.get_async_client().chat.completions.create(
282
324
  model=self.id,
283
325
  messages=[self._format_message(m) for m in messages], # type: ignore
284
326
  stream=True,
285
327
  **self.get_request_params(response_format=response_format, tools=tools),
286
328
  )
329
+
287
330
  async for chunk in async_stream: # type: ignore
288
- yield chunk # type: ignore
331
+ yield self._parse_provider_response_delta(chunk) # type: ignore
332
+
333
+ assistant_message.metrics.stop_timer()
289
334
 
290
335
  def _format_message(self, message: Message) -> Dict[str, Any]:
291
336
  """
@@ -337,7 +382,7 @@ class Cerebras(Model):
337
382
 
338
383
  return message_dict
339
384
 
340
- def parse_provider_response(self, response: ChatCompletionResponse, **kwargs) -> ModelResponse:
385
+ def _parse_provider_response(self, response: ChatCompletionResponse, **kwargs) -> ModelResponse:
341
386
  """
342
387
  Parse the Cerebras response into a ModelResponse.
343
388
 
@@ -380,20 +425,18 @@ class Cerebras(Model):
380
425
 
381
426
  # Add usage metrics
382
427
  if response.usage:
383
- model_response.response_usage = {
384
- "input_tokens": response.usage.prompt_tokens,
385
- "output_tokens": response.usage.completion_tokens,
386
- "total_tokens": response.usage.total_tokens,
387
- }
428
+ model_response.response_usage = self._get_metrics(response.usage)
388
429
 
389
430
  return model_response
390
431
 
391
- def parse_provider_response_delta(self, response_delta: ChatChunkResponse) -> ModelResponse:
432
+ def _parse_provider_response_delta(
433
+ self, response: Union[ChatChunkResponse, ChatCompletionResponse]
434
+ ) -> ModelResponse:
392
435
  """
393
436
  Parse the streaming response from the Cerebras API into a ModelResponse.
394
437
 
395
438
  Args:
396
- response_delta (ChatChunkResponse): The streaming response chunk.
439
+ response (ChatChunkResponse): The streaming response chunk.
397
440
 
398
441
  Returns:
399
442
  ModelResponse: The parsed response.
@@ -401,9 +444,9 @@ class Cerebras(Model):
401
444
  model_response = ModelResponse()
402
445
 
403
446
  # Get the first choice (assuming single response)
404
- if response_delta.choices is not None:
405
- choice: ChatChunkResponseChoice = response_delta.choices[0]
406
- choice_delta: ChatChunkResponseChoiceDelta = choice.delta
447
+ if response.choices is not None:
448
+ choice: Union[ChatChunkResponseChoice, ChatCompletionResponseChoice] = response.choices[0]
449
+ choice_delta: ChatChunkResponseChoiceDelta = choice.delta # type: ignore
407
450
 
408
451
  if choice_delta:
409
452
  # Add content
@@ -425,11 +468,25 @@ class Cerebras(Model):
425
468
  ]
426
469
 
427
470
  # Add usage metrics
428
- if response_delta.usage:
429
- model_response.response_usage = {
430
- "input_tokens": response_delta.usage.prompt_tokens,
431
- "output_tokens": response_delta.usage.completion_tokens,
432
- "total_tokens": response_delta.usage.total_tokens,
433
- }
471
+ if response.usage:
472
+ model_response.response_usage = self._get_metrics(response.usage)
434
473
 
435
474
  return model_response
475
+
476
+ def _get_metrics(self, response_usage: Union[ChatCompletionResponseUsage, ChatChunkResponseUsage]) -> Metrics:
477
+ """
478
+ Parse the given Cerebras usage into an Agno Metrics object.
479
+
480
+ Args:
481
+ response_usage: Usage data from Cerebras
482
+
483
+ Returns:
484
+ Metrics: Parsed metrics data
485
+ """
486
+ metrics = Metrics()
487
+
488
+ metrics.input_tokens = response_usage.prompt_tokens or 0
489
+ metrics.output_tokens = response_usage.completion_tokens or 0
490
+ metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
491
+
492
+ return metrics
@@ -5,17 +5,19 @@ from typing import Any, AsyncIterator, Dict, Iterator, List, Optional, Tuple, Ty
5
5
  from pydantic import BaseModel
6
6
 
7
7
  from agno.exceptions import ModelProviderError
8
- from agno.models.base import MessageData, Model, _add_usage_metrics_to_assistant_message
8
+ from agno.models.base import Model
9
9
  from agno.models.message import Message
10
+ from agno.models.metrics import Metrics
10
11
  from agno.models.response import ModelResponse
12
+ from agno.run.agent import RunOutput
11
13
  from agno.utils.log import log_debug, log_error
12
14
  from agno.utils.models.cohere import format_messages
13
15
 
14
16
  try:
15
17
  from cohere import AsyncClientV2 as CohereAsyncClient
16
18
  from cohere import ClientV2 as CohereClient
17
- from cohere.types.chat_response import ChatResponse
18
- from cohere.types.streamed_chat_response_v2 import StreamedChatResponseV2
19
+ from cohere.v2.types.v2chat_response import V2ChatResponse
20
+ from cohere.v2.types.v2chat_stream_response import V2ChatStreamResponse
19
21
  except ImportError:
20
22
  raise ImportError("`cohere` not installed. Please install using `pip install cohere`")
21
23
 
@@ -148,18 +150,33 @@ class Cohere(Model):
148
150
  def invoke(
149
151
  self,
150
152
  messages: List[Message],
153
+ assistant_message: Message,
151
154
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
152
155
  tools: Optional[List[Dict[str, Any]]] = None,
153
156
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
154
- ) -> ChatResponse:
157
+ run_response: Optional[RunOutput] = None,
158
+ ) -> ModelResponse:
155
159
  """
156
160
  Invoke a non-streamed chat response from the Cohere API.
157
161
  """
158
-
159
162
  request_kwargs = self.get_request_params(response_format=response_format, tools=tools)
160
163
 
161
164
  try:
162
- return self.get_client().chat(model=self.id, messages=format_messages(messages), **request_kwargs) # type: ignore
165
+ if run_response and run_response.metrics:
166
+ run_response.metrics.set_time_to_first_token()
167
+
168
+ assistant_message.metrics.start_timer()
169
+ provider_response = self.get_client().chat(
170
+ model=self.id,
171
+ messages=format_messages(messages), # type: ignore
172
+ **request_kwargs,
173
+ ) # type: ignore
174
+ assistant_message.metrics.stop_timer()
175
+
176
+ model_response = self._parse_provider_response(provider_response, response_format=response_format)
177
+
178
+ return model_response
179
+
163
180
  except Exception as e:
164
181
  log_error(f"Unexpected error calling Cohere API: {str(e)}")
165
182
  raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
@@ -167,21 +184,35 @@ class Cohere(Model):
167
184
  def invoke_stream(
168
185
  self,
169
186
  messages: List[Message],
187
+ assistant_message: Message,
170
188
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
171
189
  tools: Optional[List[Dict[str, Any]]] = None,
172
190
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
173
- ) -> Iterator[StreamedChatResponseV2]:
191
+ run_response: Optional[RunOutput] = None,
192
+ ) -> Iterator[ModelResponse]:
174
193
  """
175
194
  Invoke a streamed chat response from the Cohere API.
176
195
  """
177
196
  request_kwargs = self.get_request_params(response_format=response_format, tools=tools)
178
197
 
179
198
  try:
180
- return self.get_client().chat_stream(
199
+ if run_response and run_response.metrics:
200
+ run_response.metrics.set_time_to_first_token()
201
+
202
+ tool_use: Dict[str, Any] = {}
203
+
204
+ assistant_message.metrics.start_timer()
205
+
206
+ for response in self.get_client().chat_stream(
181
207
  model=self.id,
182
208
  messages=format_messages(messages), # type: ignore
183
209
  **request_kwargs,
184
- )
210
+ ):
211
+ model_response, tool_use = self._parse_provider_response_delta(response, tool_use=tool_use)
212
+ yield model_response
213
+
214
+ assistant_message.metrics.stop_timer()
215
+
185
216
  except Exception as e:
186
217
  log_error(f"Unexpected error calling Cohere API: {str(e)}")
187
218
  raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
@@ -189,21 +220,33 @@ class Cohere(Model):
189
220
  async def ainvoke(
190
221
  self,
191
222
  messages: List[Message],
223
+ assistant_message: Message,
192
224
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
193
225
  tools: Optional[List[Dict[str, Any]]] = None,
194
226
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
195
- ) -> ChatResponse:
227
+ run_response: Optional[RunOutput] = None,
228
+ ) -> ModelResponse:
196
229
  """
197
230
  Asynchronously invoke a non-streamed chat response from the Cohere API.
198
231
  """
199
232
  request_kwargs = self.get_request_params(response_format=response_format, tools=tools)
200
233
 
201
234
  try:
202
- return await self.get_async_client().chat(
235
+ if run_response and run_response.metrics:
236
+ run_response.metrics.set_time_to_first_token()
237
+
238
+ assistant_message.metrics.start_timer()
239
+ provider_response = await self.get_async_client().chat(
203
240
  model=self.id,
204
241
  messages=format_messages(messages), # type: ignore
205
242
  **request_kwargs,
206
243
  )
244
+ assistant_message.metrics.stop_timer()
245
+
246
+ model_response = self._parse_provider_response(provider_response, response_format=response_format)
247
+
248
+ return model_response
249
+
207
250
  except Exception as e:
208
251
  log_error(f"Unexpected error calling Cohere API: {str(e)}")
209
252
  raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
@@ -211,32 +254,45 @@ class Cohere(Model):
211
254
  async def ainvoke_stream(
212
255
  self,
213
256
  messages: List[Message],
257
+ assistant_message: Message,
214
258
  response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
215
259
  tools: Optional[List[Dict[str, Any]]] = None,
216
260
  tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
217
- ) -> AsyncIterator[StreamedChatResponseV2]:
261
+ run_response: Optional[RunOutput] = None,
262
+ ) -> AsyncIterator[ModelResponse]:
218
263
  """
219
264
  Asynchronously invoke a streamed chat response from the Cohere API.
220
265
  """
221
266
  request_kwargs = self.get_request_params(response_format=response_format, tools=tools)
222
267
 
223
268
  try:
269
+ if run_response and run_response.metrics:
270
+ run_response.metrics.set_time_to_first_token()
271
+
272
+ tool_use: Dict[str, Any] = {}
273
+
274
+ assistant_message.metrics.start_timer()
275
+
224
276
  async for response in self.get_async_client().chat_stream(
225
277
  model=self.id,
226
278
  messages=format_messages(messages), # type: ignore
227
279
  **request_kwargs,
228
280
  ):
229
- yield response
281
+ model_response, tool_use = self._parse_provider_response_delta(response, tool_use=tool_use)
282
+ yield model_response
283
+
284
+ assistant_message.metrics.stop_timer()
285
+
230
286
  except Exception as e:
231
287
  log_error(f"Unexpected error calling Cohere API: {str(e)}")
232
288
  raise ModelProviderError(message=str(e), model_name=self.name, model_id=self.id) from e
233
289
 
234
- def parse_provider_response(self, response: ChatResponse, **kwargs) -> ModelResponse:
290
+ def _parse_provider_response(self, response: V2ChatResponse, **kwargs) -> ModelResponse:
235
291
  """
236
292
  Parse the model provider response.
237
293
 
238
294
  Args:
239
- response (ChatResponse): The response from the Cohere API.
295
+ response (V2ChatResponse): The response from the Cohere API.
240
296
  """
241
297
  model_response = ModelResponse()
242
298
 
@@ -246,136 +302,88 @@ class Cohere(Model):
246
302
  if response_message.content is not None:
247
303
  full_content = ""
248
304
  for item in response_message.content:
249
- full_content += item.text
305
+ if hasattr(item, "text") and item.text is not None: # type: ignore
306
+ full_content += item.text # type: ignore
250
307
  model_response.content = full_content
251
308
 
252
309
  if response_message.tool_calls is not None:
253
310
  model_response.tool_calls = [t.model_dump() for t in response_message.tool_calls]
254
311
 
255
- if response.usage is not None and response.usage.tokens is not None:
256
- model_response.response_usage = {
257
- "input_tokens": int(response.usage.tokens.input_tokens) or 0, # type: ignore
258
- "output_tokens": int(response.usage.tokens.output_tokens) or 0, # type: ignore
259
- "total_tokens": int(response.usage.tokens.input_tokens + response.usage.tokens.output_tokens) or 0, # type: ignore
260
- }
312
+ if response.usage is not None:
313
+ model_response.response_usage = self._get_metrics(response.usage)
261
314
 
262
315
  return model_response
263
316
 
264
- def _process_stream_response(
265
- self,
266
- response: StreamedChatResponseV2,
267
- assistant_message: Message,
268
- stream_data: MessageData,
269
- tool_use: Dict[str, Any],
270
- ) -> Tuple[Optional[ModelResponse], Dict[str, Any]]:
317
+ def _parse_provider_response_delta(
318
+ self, response: V2ChatStreamResponse, tool_use: Dict[str, Any]
319
+ ) -> Tuple[ModelResponse, Dict[str, Any]]: # type: ignore
271
320
  """
272
- Common handler for processing stream responses from Cohere.
321
+ Parse the streaming response from the model provider into ModelResponse objects.
273
322
 
274
323
  Args:
275
- response: The streamed response from Cohere
276
- assistant_message: The assistant message being built
277
- stream_data: Data accumulated during streaming
278
- tool_use: Current tool use data being built
324
+ response: Raw response chunk from the model provider
279
325
 
280
326
  Returns:
281
- Tuple containing the ModelResponse to yield and updated tool_use dict
327
+ ModelResponse: Parsed response delta
282
328
  """
283
- model_response = None
329
+ model_response = ModelResponse()
284
330
 
331
+ # 1. Add content
285
332
  if (
286
333
  response.type == "content-delta"
287
334
  and response.delta is not None
288
335
  and response.delta.message is not None
289
336
  and response.delta.message.content is not None
337
+ and response.delta.message.content.text is not None
290
338
  ):
291
- # Update metrics
292
- assistant_message.metrics.completion_tokens += 1
293
- if not assistant_message.metrics.time_to_first_token:
294
- assistant_message.metrics.set_time_to_first_token()
339
+ model_response.content = response.delta.message.content.text
295
340
 
296
- # Update provider response content
297
- stream_data.response_content += response.delta.message.content.text
298
- model_response = ModelResponse(content=response.delta.message.content.text)
341
+ # 2. Add tool calls information
299
342
 
343
+ # 2.1 Add starting tool call
300
344
  elif response.type == "tool-call-start" and response.delta is not None:
301
345
  if response.delta.message is not None and response.delta.message.tool_calls is not None:
302
346
  tool_use = response.delta.message.tool_calls.model_dump()
303
347
 
348
+ # 2.2 Add tool call delta
304
349
  elif response.type == "tool-call-delta" and response.delta is not None:
305
350
  if (
306
351
  response.delta.message is not None
307
352
  and response.delta.message.tool_calls is not None
308
353
  and response.delta.message.tool_calls.function is not None
354
+ and response.delta.message.tool_calls.function.arguments is not None
309
355
  ):
310
356
  tool_use["function"]["arguments"] += response.delta.message.tool_calls.function.arguments
311
357
 
358
+ # 2.3 Add ending tool call
312
359
  elif response.type == "tool-call-end":
313
- if assistant_message.tool_calls is None:
314
- assistant_message.tool_calls = []
315
- assistant_message.tool_calls.append(tool_use)
316
- tool_use = {}
360
+ model_response.tool_calls = [tool_use]
317
361
 
362
+ # 3. Add metrics
318
363
  elif (
319
364
  response.type == "message-end"
320
365
  and response.delta is not None
321
366
  and response.delta.usage is not None
322
367
  and response.delta.usage.tokens is not None
323
368
  ):
324
- _add_usage_metrics_to_assistant_message(
325
- assistant_message=assistant_message,
326
- response_usage={
327
- "input_tokens": int(response.delta.usage.tokens.input_tokens) or 0, # type: ignore
328
- "output_tokens": int(response.delta.usage.tokens.output_tokens) or 0, # type: ignore
329
- "total_tokens": int(
330
- response.delta.usage.tokens.input_tokens + response.delta.usage.tokens.output_tokens # type: ignore
331
- )
332
- or 0,
333
- },
334
- )
369
+ model_response.response_usage = self._get_metrics(response.delta.usage) # type: ignore
335
370
 
336
371
  return model_response, tool_use
337
372
 
338
- def process_response_stream(
339
- self,
340
- messages: List[Message],
341
- assistant_message: Message,
342
- stream_data: MessageData,
343
- response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
344
- tools: Optional[List[Dict[str, Any]]] = None,
345
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
346
- ) -> Iterator[ModelResponse]:
347
- """Process the synchronous response stream."""
348
- tool_use: Dict[str, Any] = {}
373
+ def _get_metrics(self, response_usage) -> Metrics:
374
+ """
375
+ Parse the given Cohere usage into an Agno Metrics object.
349
376
 
350
- for response in self.invoke_stream(
351
- messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
352
- ):
353
- model_response, tool_use = self._process_stream_response(
354
- response=response, assistant_message=assistant_message, stream_data=stream_data, tool_use=tool_use
355
- )
356
- if model_response is not None:
357
- yield model_response
377
+ Args:
378
+ response_usage: Usage data from Cohere
358
379
 
359
- async def aprocess_response_stream(
360
- self,
361
- messages: List[Message],
362
- assistant_message: Message,
363
- stream_data: MessageData,
364
- response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
365
- tools: Optional[List[Dict[str, Any]]] = None,
366
- tool_choice: Optional[Union[str, Dict[str, Any]]] = None,
367
- ) -> AsyncIterator[ModelResponse]:
368
- """Process the asynchronous response stream."""
369
- tool_use: Dict[str, Any] = {}
380
+ Returns:
381
+ Metrics: Parsed metrics data
382
+ """
383
+ metrics = Metrics()
370
384
 
371
- async for response in self.ainvoke_stream(
372
- messages=messages, response_format=response_format, tools=tools, tool_choice=tool_choice
373
- ):
374
- model_response, tool_use = self._process_stream_response(
375
- response=response, assistant_message=assistant_message, stream_data=stream_data, tool_use=tool_use
376
- )
377
- if model_response is not None:
378
- yield model_response
385
+ metrics.input_tokens = response_usage.tokens.input_tokens or 0
386
+ metrics.output_tokens = response_usage.tokens.output_tokens or 0
387
+ metrics.total_tokens = metrics.input_tokens + metrics.output_tokens
379
388
 
380
- def parse_provider_response_delta(self, response: Any) -> ModelResponse: # type: ignore
381
- pass
389
+ return metrics