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
@@ -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