aip-agents-binary 0.6.4__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 (612) hide show
  1. aip_agents/__init__.py +65 -0
  2. aip_agents/__init__.pyi +19 -0
  3. aip_agents/a2a/__init__.py +19 -0
  4. aip_agents/a2a/__init__.pyi +3 -0
  5. aip_agents/a2a/server/__init__.py +10 -0
  6. aip_agents/a2a/server/__init__.pyi +4 -0
  7. aip_agents/a2a/server/base_executor.py +1086 -0
  8. aip_agents/a2a/server/base_executor.pyi +73 -0
  9. aip_agents/a2a/server/google_adk_executor.py +198 -0
  10. aip_agents/a2a/server/google_adk_executor.pyi +51 -0
  11. aip_agents/a2a/server/langflow_executor.py +180 -0
  12. aip_agents/a2a/server/langflow_executor.pyi +43 -0
  13. aip_agents/a2a/server/langgraph_executor.py +270 -0
  14. aip_agents/a2a/server/langgraph_executor.pyi +47 -0
  15. aip_agents/a2a/types.py +232 -0
  16. aip_agents/a2a/types.pyi +132 -0
  17. aip_agents/agent/__init__.py +27 -0
  18. aip_agents/agent/__init__.pyi +9 -0
  19. aip_agents/agent/base_agent.py +970 -0
  20. aip_agents/agent/base_agent.pyi +221 -0
  21. aip_agents/agent/base_langgraph_agent.py +3037 -0
  22. aip_agents/agent/base_langgraph_agent.pyi +233 -0
  23. aip_agents/agent/google_adk_agent.py +926 -0
  24. aip_agents/agent/google_adk_agent.pyi +141 -0
  25. aip_agents/agent/google_adk_constants.py +6 -0
  26. aip_agents/agent/google_adk_constants.pyi +3 -0
  27. aip_agents/agent/hitl/__init__.py +24 -0
  28. aip_agents/agent/hitl/__init__.pyi +6 -0
  29. aip_agents/agent/hitl/config.py +28 -0
  30. aip_agents/agent/hitl/config.pyi +15 -0
  31. aip_agents/agent/hitl/langgraph_hitl_mixin.py +515 -0
  32. aip_agents/agent/hitl/langgraph_hitl_mixin.pyi +42 -0
  33. aip_agents/agent/hitl/manager.py +532 -0
  34. aip_agents/agent/hitl/manager.pyi +200 -0
  35. aip_agents/agent/hitl/models.py +18 -0
  36. aip_agents/agent/hitl/models.pyi +3 -0
  37. aip_agents/agent/hitl/prompt/__init__.py +9 -0
  38. aip_agents/agent/hitl/prompt/__init__.pyi +4 -0
  39. aip_agents/agent/hitl/prompt/base.py +42 -0
  40. aip_agents/agent/hitl/prompt/base.pyi +24 -0
  41. aip_agents/agent/hitl/prompt/deferred.py +73 -0
  42. aip_agents/agent/hitl/prompt/deferred.pyi +30 -0
  43. aip_agents/agent/hitl/registry.py +149 -0
  44. aip_agents/agent/hitl/registry.pyi +101 -0
  45. aip_agents/agent/interface.py +138 -0
  46. aip_agents/agent/interface.pyi +81 -0
  47. aip_agents/agent/interfaces.py +65 -0
  48. aip_agents/agent/interfaces.pyi +44 -0
  49. aip_agents/agent/langflow_agent.py +464 -0
  50. aip_agents/agent/langflow_agent.pyi +133 -0
  51. aip_agents/agent/langgraph_memory_enhancer_agent.py +767 -0
  52. aip_agents/agent/langgraph_memory_enhancer_agent.pyi +50 -0
  53. aip_agents/agent/langgraph_react_agent.py +2856 -0
  54. aip_agents/agent/langgraph_react_agent.pyi +170 -0
  55. aip_agents/agent/system_instruction_context.py +34 -0
  56. aip_agents/agent/system_instruction_context.pyi +13 -0
  57. aip_agents/clients/__init__.py +10 -0
  58. aip_agents/clients/__init__.pyi +4 -0
  59. aip_agents/clients/langflow/__init__.py +10 -0
  60. aip_agents/clients/langflow/__init__.pyi +4 -0
  61. aip_agents/clients/langflow/client.py +477 -0
  62. aip_agents/clients/langflow/client.pyi +140 -0
  63. aip_agents/clients/langflow/types.py +18 -0
  64. aip_agents/clients/langflow/types.pyi +7 -0
  65. aip_agents/constants.py +23 -0
  66. aip_agents/constants.pyi +7 -0
  67. aip_agents/credentials/manager.py +132 -0
  68. aip_agents/examples/__init__.py +5 -0
  69. aip_agents/examples/__init__.pyi +0 -0
  70. aip_agents/examples/compare_streaming_client.py +783 -0
  71. aip_agents/examples/compare_streaming_client.pyi +48 -0
  72. aip_agents/examples/compare_streaming_server.py +142 -0
  73. aip_agents/examples/compare_streaming_server.pyi +18 -0
  74. aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
  75. aip_agents/examples/hello_world_a2a_google_adk_client.pyi +9 -0
  76. aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
  77. aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +9 -0
  78. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
  79. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +9 -0
  80. aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
  81. aip_agents/examples/hello_world_a2a_google_adk_server.pyi +15 -0
  82. aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
  83. aip_agents/examples/hello_world_a2a_langchain_client.pyi +5 -0
  84. aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
  85. aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +5 -0
  86. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
  87. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +5 -0
  88. aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
  89. aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +5 -0
  90. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
  91. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +5 -0
  92. aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
  93. aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +15 -0
  94. aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
  95. aip_agents/examples/hello_world_a2a_langchain_server.pyi +15 -0
  96. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
  97. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +15 -0
  98. aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
  99. aip_agents/examples/hello_world_a2a_langflow_client.pyi +9 -0
  100. aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
  101. aip_agents/examples/hello_world_a2a_langflow_server.pyi +14 -0
  102. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
  103. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +5 -0
  104. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
  105. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +5 -0
  106. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
  107. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +16 -0
  108. aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
  109. aip_agents/examples/hello_world_a2a_langgraph_client.pyi +9 -0
  110. aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
  111. aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +9 -0
  112. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
  113. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +2 -0
  114. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
  115. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +9 -0
  116. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
  117. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +5 -0
  118. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
  119. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +5 -0
  120. aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
  121. aip_agents/examples/hello_world_a2a_langgraph_server.pyi +14 -0
  122. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
  123. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +15 -0
  124. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
  125. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +15 -0
  126. aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
  127. aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +48 -0
  128. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
  129. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +48 -0
  130. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +251 -0
  131. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +45 -0
  132. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
  133. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +5 -0
  134. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
  135. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +15 -0
  136. aip_agents/examples/hello_world_google_adk.py +41 -0
  137. aip_agents/examples/hello_world_google_adk.pyi +5 -0
  138. aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
  139. aip_agents/examples/hello_world_google_adk_mcp_http.pyi +5 -0
  140. aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
  141. aip_agents/examples/hello_world_google_adk_mcp_http_stream.pyi +5 -0
  142. aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
  143. aip_agents/examples/hello_world_google_adk_mcp_sse.pyi +5 -0
  144. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
  145. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.pyi +5 -0
  146. aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
  147. aip_agents/examples/hello_world_google_adk_mcp_stdio.pyi +5 -0
  148. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
  149. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.pyi +5 -0
  150. aip_agents/examples/hello_world_google_adk_stream.py +44 -0
  151. aip_agents/examples/hello_world_google_adk_stream.pyi +5 -0
  152. aip_agents/examples/hello_world_langchain.py +28 -0
  153. aip_agents/examples/hello_world_langchain.pyi +5 -0
  154. aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
  155. aip_agents/examples/hello_world_langchain_lm_invoker.pyi +2 -0
  156. aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
  157. aip_agents/examples/hello_world_langchain_mcp_http.pyi +5 -0
  158. aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
  159. aip_agents/examples/hello_world_langchain_mcp_http_interactive.pyi +16 -0
  160. aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
  161. aip_agents/examples/hello_world_langchain_mcp_http_stream.pyi +5 -0
  162. aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
  163. aip_agents/examples/hello_world_langchain_mcp_multi_server.pyi +18 -0
  164. aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
  165. aip_agents/examples/hello_world_langchain_mcp_sse.pyi +5 -0
  166. aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
  167. aip_agents/examples/hello_world_langchain_mcp_sse_stream.pyi +5 -0
  168. aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
  169. aip_agents/examples/hello_world_langchain_mcp_stdio.pyi +5 -0
  170. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
  171. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.pyi +5 -0
  172. aip_agents/examples/hello_world_langchain_stream.py +36 -0
  173. aip_agents/examples/hello_world_langchain_stream.pyi +5 -0
  174. aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
  175. aip_agents/examples/hello_world_langchain_stream_lm_invoker.pyi +5 -0
  176. aip_agents/examples/hello_world_langflow_agent.py +163 -0
  177. aip_agents/examples/hello_world_langflow_agent.pyi +35 -0
  178. aip_agents/examples/hello_world_langgraph.py +39 -0
  179. aip_agents/examples/hello_world_langgraph.pyi +5 -0
  180. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.py +44 -0
  181. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.pyi +5 -0
  182. aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
  183. aip_agents/examples/hello_world_langgraph_mcp_http.pyi +5 -0
  184. aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
  185. aip_agents/examples/hello_world_langgraph_mcp_http_stream.pyi +5 -0
  186. aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
  187. aip_agents/examples/hello_world_langgraph_mcp_sse.pyi +5 -0
  188. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
  189. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.pyi +5 -0
  190. aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
  191. aip_agents/examples/hello_world_langgraph_mcp_stdio.pyi +5 -0
  192. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
  193. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.pyi +5 -0
  194. aip_agents/examples/hello_world_langgraph_stream.py +43 -0
  195. aip_agents/examples/hello_world_langgraph_stream.pyi +5 -0
  196. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
  197. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.pyi +5 -0
  198. aip_agents/examples/hello_world_model_switch_cli.py +210 -0
  199. aip_agents/examples/hello_world_model_switch_cli.pyi +30 -0
  200. aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
  201. aip_agents/examples/hello_world_multi_agent_adk.pyi +6 -0
  202. aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
  203. aip_agents/examples/hello_world_multi_agent_langchain.pyi +5 -0
  204. aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
  205. aip_agents/examples/hello_world_multi_agent_langgraph.pyi +5 -0
  206. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
  207. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.pyi +5 -0
  208. aip_agents/examples/hello_world_pii_logger.py +21 -0
  209. aip_agents/examples/hello_world_pii_logger.pyi +5 -0
  210. aip_agents/examples/hello_world_ptc.py +49 -0
  211. aip_agents/examples/hello_world_ptc.pyi +5 -0
  212. aip_agents/examples/hello_world_sentry.py +133 -0
  213. aip_agents/examples/hello_world_sentry.pyi +21 -0
  214. aip_agents/examples/hello_world_step_limits.py +273 -0
  215. aip_agents/examples/hello_world_step_limits.pyi +17 -0
  216. aip_agents/examples/hello_world_stock_a2a_server.py +103 -0
  217. aip_agents/examples/hello_world_stock_a2a_server.pyi +17 -0
  218. aip_agents/examples/hello_world_tool_output_client.py +55 -0
  219. aip_agents/examples/hello_world_tool_output_client.pyi +5 -0
  220. aip_agents/examples/hello_world_tool_output_server.py +114 -0
  221. aip_agents/examples/hello_world_tool_output_server.pyi +19 -0
  222. aip_agents/examples/hitl_demo.py +724 -0
  223. aip_agents/examples/hitl_demo.pyi +67 -0
  224. aip_agents/examples/mcp_configs/configs.py +63 -0
  225. aip_agents/examples/mcp_servers/common.py +76 -0
  226. aip_agents/examples/mcp_servers/mcp_name.py +29 -0
  227. aip_agents/examples/mcp_servers/mcp_server_http.py +19 -0
  228. aip_agents/examples/mcp_servers/mcp_server_sse.py +19 -0
  229. aip_agents/examples/mcp_servers/mcp_server_stdio.py +19 -0
  230. aip_agents/examples/mcp_servers/mcp_time.py +10 -0
  231. aip_agents/examples/pii_demo_langgraph_client.py +69 -0
  232. aip_agents/examples/pii_demo_langgraph_client.pyi +5 -0
  233. aip_agents/examples/pii_demo_langgraph_server.py +126 -0
  234. aip_agents/examples/pii_demo_langgraph_server.pyi +20 -0
  235. aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
  236. aip_agents/examples/pii_demo_multi_agent_client.pyi +5 -0
  237. aip_agents/examples/pii_demo_multi_agent_server.py +247 -0
  238. aip_agents/examples/pii_demo_multi_agent_server.pyi +40 -0
  239. aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
  240. aip_agents/examples/todolist_planning_a2a_langchain_client.pyi +5 -0
  241. aip_agents/examples/todolist_planning_a2a_langgraph_server.py +88 -0
  242. aip_agents/examples/todolist_planning_a2a_langgraph_server.pyi +19 -0
  243. aip_agents/examples/tools/__init__.py +27 -0
  244. aip_agents/examples/tools/__init__.pyi +9 -0
  245. aip_agents/examples/tools/adk_arithmetic_tools.py +36 -0
  246. aip_agents/examples/tools/adk_arithmetic_tools.pyi +24 -0
  247. aip_agents/examples/tools/adk_weather_tool.py +60 -0
  248. aip_agents/examples/tools/adk_weather_tool.pyi +18 -0
  249. aip_agents/examples/tools/data_generator_tool.py +103 -0
  250. aip_agents/examples/tools/data_generator_tool.pyi +15 -0
  251. aip_agents/examples/tools/data_visualization_tool.py +312 -0
  252. aip_agents/examples/tools/data_visualization_tool.pyi +19 -0
  253. aip_agents/examples/tools/image_artifact_tool.py +136 -0
  254. aip_agents/examples/tools/image_artifact_tool.pyi +26 -0
  255. aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
  256. aip_agents/examples/tools/langchain_arithmetic_tools.pyi +17 -0
  257. aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
  258. aip_agents/examples/tools/langchain_currency_exchange_tool.pyi +20 -0
  259. aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
  260. aip_agents/examples/tools/langchain_graph_artifact_tool.pyi +25 -0
  261. aip_agents/examples/tools/langchain_weather_tool.py +48 -0
  262. aip_agents/examples/tools/langchain_weather_tool.pyi +19 -0
  263. aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
  264. aip_agents/examples/tools/langgraph_streaming_tool.pyi +43 -0
  265. aip_agents/examples/tools/mock_retrieval_tool.py +56 -0
  266. aip_agents/examples/tools/mock_retrieval_tool.pyi +13 -0
  267. aip_agents/examples/tools/pii_demo_tools.py +189 -0
  268. aip_agents/examples/tools/pii_demo_tools.pyi +54 -0
  269. aip_agents/examples/tools/random_chart_tool.py +142 -0
  270. aip_agents/examples/tools/random_chart_tool.pyi +20 -0
  271. aip_agents/examples/tools/serper_tool.py +202 -0
  272. aip_agents/examples/tools/serper_tool.pyi +16 -0
  273. aip_agents/examples/tools/stock_tools.py +82 -0
  274. aip_agents/examples/tools/stock_tools.pyi +36 -0
  275. aip_agents/examples/tools/table_generator_tool.py +167 -0
  276. aip_agents/examples/tools/table_generator_tool.pyi +22 -0
  277. aip_agents/examples/tools/time_tool.py +82 -0
  278. aip_agents/examples/tools/time_tool.pyi +15 -0
  279. aip_agents/examples/tools/weather_forecast_tool.py +38 -0
  280. aip_agents/examples/tools/weather_forecast_tool.pyi +14 -0
  281. aip_agents/executor/agent_executor.py +473 -0
  282. aip_agents/executor/base.py +48 -0
  283. aip_agents/guardrails/__init__.py +83 -0
  284. aip_agents/guardrails/__init__.pyi +6 -0
  285. aip_agents/guardrails/engines/__init__.py +69 -0
  286. aip_agents/guardrails/engines/__init__.pyi +4 -0
  287. aip_agents/guardrails/engines/base.py +90 -0
  288. aip_agents/guardrails/engines/base.pyi +61 -0
  289. aip_agents/guardrails/engines/nemo.py +101 -0
  290. aip_agents/guardrails/engines/nemo.pyi +46 -0
  291. aip_agents/guardrails/engines/phrase_matcher.py +113 -0
  292. aip_agents/guardrails/engines/phrase_matcher.pyi +48 -0
  293. aip_agents/guardrails/exceptions.py +39 -0
  294. aip_agents/guardrails/exceptions.pyi +23 -0
  295. aip_agents/guardrails/manager.py +163 -0
  296. aip_agents/guardrails/manager.pyi +42 -0
  297. aip_agents/guardrails/middleware.py +199 -0
  298. aip_agents/guardrails/middleware.pyi +87 -0
  299. aip_agents/guardrails/schemas.py +63 -0
  300. aip_agents/guardrails/schemas.pyi +43 -0
  301. aip_agents/guardrails/utils.py +45 -0
  302. aip_agents/guardrails/utils.pyi +19 -0
  303. aip_agents/mcp/__init__.py +1 -0
  304. aip_agents/mcp/__init__.pyi +0 -0
  305. aip_agents/mcp/client/__init__.py +14 -0
  306. aip_agents/mcp/client/__init__.pyi +5 -0
  307. aip_agents/mcp/client/base_mcp_client.py +369 -0
  308. aip_agents/mcp/client/base_mcp_client.pyi +148 -0
  309. aip_agents/mcp/client/connection_manager.py +228 -0
  310. aip_agents/mcp/client/connection_manager.pyi +51 -0
  311. aip_agents/mcp/client/google_adk/__init__.py +11 -0
  312. aip_agents/mcp/client/google_adk/__init__.pyi +3 -0
  313. aip_agents/mcp/client/google_adk/client.py +381 -0
  314. aip_agents/mcp/client/google_adk/client.pyi +75 -0
  315. aip_agents/mcp/client/langchain/__init__.py +11 -0
  316. aip_agents/mcp/client/langchain/__init__.pyi +3 -0
  317. aip_agents/mcp/client/langchain/client.py +265 -0
  318. aip_agents/mcp/client/langchain/client.pyi +48 -0
  319. aip_agents/mcp/client/persistent_session.py +612 -0
  320. aip_agents/mcp/client/persistent_session.pyi +122 -0
  321. aip_agents/mcp/client/session_pool.py +351 -0
  322. aip_agents/mcp/client/session_pool.pyi +101 -0
  323. aip_agents/mcp/client/transports.py +263 -0
  324. aip_agents/mcp/client/transports.pyi +132 -0
  325. aip_agents/mcp/utils/__init__.py +7 -0
  326. aip_agents/mcp/utils/__init__.pyi +0 -0
  327. aip_agents/mcp/utils/config_validator.py +139 -0
  328. aip_agents/mcp/utils/config_validator.pyi +82 -0
  329. aip_agents/memory/__init__.py +14 -0
  330. aip_agents/memory/__init__.pyi +5 -0
  331. aip_agents/memory/adapters/__init__.py +10 -0
  332. aip_agents/memory/adapters/__init__.pyi +4 -0
  333. aip_agents/memory/adapters/base_adapter.py +811 -0
  334. aip_agents/memory/adapters/base_adapter.pyi +176 -0
  335. aip_agents/memory/adapters/mem0.py +84 -0
  336. aip_agents/memory/adapters/mem0.pyi +22 -0
  337. aip_agents/memory/base.py +84 -0
  338. aip_agents/memory/base.pyi +60 -0
  339. aip_agents/memory/constants.py +49 -0
  340. aip_agents/memory/constants.pyi +25 -0
  341. aip_agents/memory/factory.py +86 -0
  342. aip_agents/memory/factory.pyi +24 -0
  343. aip_agents/memory/guidance.py +20 -0
  344. aip_agents/memory/guidance.pyi +3 -0
  345. aip_agents/memory/simple_memory.py +47 -0
  346. aip_agents/memory/simple_memory.pyi +23 -0
  347. aip_agents/middleware/__init__.py +17 -0
  348. aip_agents/middleware/__init__.pyi +5 -0
  349. aip_agents/middleware/base.py +96 -0
  350. aip_agents/middleware/base.pyi +75 -0
  351. aip_agents/middleware/manager.py +150 -0
  352. aip_agents/middleware/manager.pyi +84 -0
  353. aip_agents/middleware/todolist.py +274 -0
  354. aip_agents/middleware/todolist.pyi +125 -0
  355. aip_agents/ptc/__init__.py +48 -0
  356. aip_agents/ptc/__init__.pyi +10 -0
  357. aip_agents/ptc/doc_gen.py +122 -0
  358. aip_agents/ptc/doc_gen.pyi +40 -0
  359. aip_agents/ptc/exceptions.py +39 -0
  360. aip_agents/ptc/exceptions.pyi +22 -0
  361. aip_agents/ptc/executor.py +143 -0
  362. aip_agents/ptc/executor.pyi +73 -0
  363. aip_agents/ptc/mcp/__init__.py +45 -0
  364. aip_agents/ptc/mcp/__init__.pyi +7 -0
  365. aip_agents/ptc/mcp/sandbox_bridge.py +668 -0
  366. aip_agents/ptc/mcp/sandbox_bridge.pyi +47 -0
  367. aip_agents/ptc/mcp/templates/__init__.py +1 -0
  368. aip_agents/ptc/mcp/templates/__init__.pyi +0 -0
  369. aip_agents/ptc/mcp/templates/mcp_client.py.template +239 -0
  370. aip_agents/ptc/naming.py +184 -0
  371. aip_agents/ptc/naming.pyi +76 -0
  372. aip_agents/ptc/payload.py +26 -0
  373. aip_agents/ptc/payload.pyi +15 -0
  374. aip_agents/ptc/prompt_builder.py +571 -0
  375. aip_agents/ptc/prompt_builder.pyi +55 -0
  376. aip_agents/ptc/ptc_helper.py +16 -0
  377. aip_agents/ptc/ptc_helper.pyi +1 -0
  378. aip_agents/ptc/sandbox_bridge.py +58 -0
  379. aip_agents/ptc/sandbox_bridge.pyi +25 -0
  380. aip_agents/ptc/template_utils.py +33 -0
  381. aip_agents/ptc/template_utils.pyi +13 -0
  382. aip_agents/ptc/templates/__init__.py +1 -0
  383. aip_agents/ptc/templates/__init__.pyi +0 -0
  384. aip_agents/ptc/templates/ptc_helper.py.template +134 -0
  385. aip_agents/sandbox/__init__.py +43 -0
  386. aip_agents/sandbox/__init__.pyi +5 -0
  387. aip_agents/sandbox/defaults.py +9 -0
  388. aip_agents/sandbox/defaults.pyi +2 -0
  389. aip_agents/sandbox/e2b_runtime.py +267 -0
  390. aip_agents/sandbox/e2b_runtime.pyi +51 -0
  391. aip_agents/sandbox/template_builder.py +131 -0
  392. aip_agents/sandbox/template_builder.pyi +36 -0
  393. aip_agents/sandbox/types.py +24 -0
  394. aip_agents/sandbox/types.pyi +14 -0
  395. aip_agents/sandbox/validation.py +50 -0
  396. aip_agents/sandbox/validation.pyi +20 -0
  397. aip_agents/schema/__init__.py +69 -0
  398. aip_agents/schema/__init__.pyi +9 -0
  399. aip_agents/schema/a2a.py +56 -0
  400. aip_agents/schema/a2a.pyi +40 -0
  401. aip_agents/schema/agent.py +111 -0
  402. aip_agents/schema/agent.pyi +65 -0
  403. aip_agents/schema/hitl.py +157 -0
  404. aip_agents/schema/hitl.pyi +89 -0
  405. aip_agents/schema/langgraph.py +37 -0
  406. aip_agents/schema/langgraph.pyi +28 -0
  407. aip_agents/schema/model_id.py +97 -0
  408. aip_agents/schema/model_id.pyi +54 -0
  409. aip_agents/schema/step_limit.py +108 -0
  410. aip_agents/schema/step_limit.pyi +63 -0
  411. aip_agents/schema/storage.py +40 -0
  412. aip_agents/schema/storage.pyi +21 -0
  413. aip_agents/sentry/__init__.py +11 -0
  414. aip_agents/sentry/__init__.pyi +3 -0
  415. aip_agents/sentry/sentry.py +151 -0
  416. aip_agents/sentry/sentry.pyi +48 -0
  417. aip_agents/storage/__init__.py +41 -0
  418. aip_agents/storage/__init__.pyi +8 -0
  419. aip_agents/storage/base.py +85 -0
  420. aip_agents/storage/base.pyi +58 -0
  421. aip_agents/storage/clients/__init__.py +12 -0
  422. aip_agents/storage/clients/__init__.pyi +3 -0
  423. aip_agents/storage/clients/minio_client.py +318 -0
  424. aip_agents/storage/clients/minio_client.pyi +137 -0
  425. aip_agents/storage/config.py +62 -0
  426. aip_agents/storage/config.pyi +29 -0
  427. aip_agents/storage/providers/__init__.py +15 -0
  428. aip_agents/storage/providers/__init__.pyi +5 -0
  429. aip_agents/storage/providers/base.py +106 -0
  430. aip_agents/storage/providers/base.pyi +88 -0
  431. aip_agents/storage/providers/memory.py +114 -0
  432. aip_agents/storage/providers/memory.pyi +79 -0
  433. aip_agents/storage/providers/object_storage.py +214 -0
  434. aip_agents/storage/providers/object_storage.pyi +98 -0
  435. aip_agents/tools/__init__.py +64 -0
  436. aip_agents/tools/__init__.pyi +11 -0
  437. aip_agents/tools/browser_use/__init__.py +82 -0
  438. aip_agents/tools/browser_use/__init__.pyi +14 -0
  439. aip_agents/tools/browser_use/action_parser.py +103 -0
  440. aip_agents/tools/browser_use/action_parser.pyi +18 -0
  441. aip_agents/tools/browser_use/browser_use_tool.py +1120 -0
  442. aip_agents/tools/browser_use/browser_use_tool.pyi +50 -0
  443. aip_agents/tools/browser_use/llm_config.py +120 -0
  444. aip_agents/tools/browser_use/llm_config.pyi +52 -0
  445. aip_agents/tools/browser_use/minio_storage.py +198 -0
  446. aip_agents/tools/browser_use/minio_storage.pyi +109 -0
  447. aip_agents/tools/browser_use/schemas.py +119 -0
  448. aip_agents/tools/browser_use/schemas.pyi +32 -0
  449. aip_agents/tools/browser_use/session.py +76 -0
  450. aip_agents/tools/browser_use/session.pyi +4 -0
  451. aip_agents/tools/browser_use/session_errors.py +132 -0
  452. aip_agents/tools/browser_use/session_errors.pyi +53 -0
  453. aip_agents/tools/browser_use/steel_session_recording.py +317 -0
  454. aip_agents/tools/browser_use/steel_session_recording.pyi +63 -0
  455. aip_agents/tools/browser_use/streaming.py +815 -0
  456. aip_agents/tools/browser_use/streaming.pyi +81 -0
  457. aip_agents/tools/browser_use/structured_data_parser.py +257 -0
  458. aip_agents/tools/browser_use/structured_data_parser.pyi +86 -0
  459. aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
  460. aip_agents/tools/browser_use/structured_data_recovery.pyi +43 -0
  461. aip_agents/tools/browser_use/types.py +78 -0
  462. aip_agents/tools/browser_use/types.pyi +45 -0
  463. aip_agents/tools/code_sandbox/__init__.py +26 -0
  464. aip_agents/tools/code_sandbox/__init__.pyi +3 -0
  465. aip_agents/tools/code_sandbox/constant.py +13 -0
  466. aip_agents/tools/code_sandbox/constant.pyi +4 -0
  467. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +306 -0
  468. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +102 -0
  469. aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
  470. aip_agents/tools/code_sandbox/e2b_sandbox_tool.pyi +29 -0
  471. aip_agents/tools/constants.py +177 -0
  472. aip_agents/tools/constants.pyi +138 -0
  473. aip_agents/tools/date_range_tool.py +554 -0
  474. aip_agents/tools/date_range_tool.pyi +21 -0
  475. aip_agents/tools/document_loader/__init__.py +44 -0
  476. aip_agents/tools/document_loader/__init__.pyi +7 -0
  477. aip_agents/tools/document_loader/base_reader.py +302 -0
  478. aip_agents/tools/document_loader/base_reader.pyi +75 -0
  479. aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
  480. aip_agents/tools/document_loader/docx_reader_tool.pyi +10 -0
  481. aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
  482. aip_agents/tools/document_loader/excel_reader_tool.pyi +26 -0
  483. aip_agents/tools/document_loader/pdf_reader_tool.py +79 -0
  484. aip_agents/tools/document_loader/pdf_reader_tool.pyi +11 -0
  485. aip_agents/tools/document_loader/pdf_splitter.py +169 -0
  486. aip_agents/tools/document_loader/pdf_splitter.pyi +18 -0
  487. aip_agents/tools/execute_ptc_code.py +308 -0
  488. aip_agents/tools/execute_ptc_code.pyi +90 -0
  489. aip_agents/tools/gl_connector/__init__.py +5 -0
  490. aip_agents/tools/gl_connector/__init__.pyi +3 -0
  491. aip_agents/tools/gl_connector/tool.py +383 -0
  492. aip_agents/tools/gl_connector/tool.pyi +74 -0
  493. aip_agents/tools/gl_connector_tools.py +119 -0
  494. aip_agents/tools/gl_connector_tools.pyi +39 -0
  495. aip_agents/tools/memory_search/__init__.py +29 -0
  496. aip_agents/tools/memory_search/__init__.pyi +5 -0
  497. aip_agents/tools/memory_search/base.py +200 -0
  498. aip_agents/tools/memory_search/base.pyi +69 -0
  499. aip_agents/tools/memory_search/mem0.py +365 -0
  500. aip_agents/tools/memory_search/mem0.pyi +29 -0
  501. aip_agents/tools/memory_search/schema.py +81 -0
  502. aip_agents/tools/memory_search/schema.pyi +25 -0
  503. aip_agents/tools/memory_search_tool.py +34 -0
  504. aip_agents/tools/memory_search_tool.pyi +3 -0
  505. aip_agents/tools/time_tool.py +117 -0
  506. aip_agents/tools/time_tool.pyi +16 -0
  507. aip_agents/tools/tool_config_injector.py +300 -0
  508. aip_agents/tools/tool_config_injector.pyi +26 -0
  509. aip_agents/tools/web_search/__init__.py +15 -0
  510. aip_agents/tools/web_search/__init__.pyi +3 -0
  511. aip_agents/tools/web_search/serper_tool.py +187 -0
  512. aip_agents/tools/web_search/serper_tool.pyi +19 -0
  513. aip_agents/types/__init__.py +70 -0
  514. aip_agents/types/__init__.pyi +36 -0
  515. aip_agents/types/a2a_events.py +13 -0
  516. aip_agents/types/a2a_events.pyi +3 -0
  517. aip_agents/utils/__init__.py +79 -0
  518. aip_agents/utils/__init__.pyi +11 -0
  519. aip_agents/utils/a2a_connector.py +1757 -0
  520. aip_agents/utils/a2a_connector.pyi +146 -0
  521. aip_agents/utils/artifact_helpers.py +502 -0
  522. aip_agents/utils/artifact_helpers.pyi +203 -0
  523. aip_agents/utils/constants.py +22 -0
  524. aip_agents/utils/constants.pyi +10 -0
  525. aip_agents/utils/datetime/__init__.py +34 -0
  526. aip_agents/utils/datetime/__init__.pyi +4 -0
  527. aip_agents/utils/datetime/normalization.py +231 -0
  528. aip_agents/utils/datetime/normalization.pyi +95 -0
  529. aip_agents/utils/datetime/timezone.py +206 -0
  530. aip_agents/utils/datetime/timezone.pyi +48 -0
  531. aip_agents/utils/env_loader.py +27 -0
  532. aip_agents/utils/env_loader.pyi +10 -0
  533. aip_agents/utils/event_handler_registry.py +58 -0
  534. aip_agents/utils/event_handler_registry.pyi +23 -0
  535. aip_agents/utils/file_prompt_utils.py +176 -0
  536. aip_agents/utils/file_prompt_utils.pyi +21 -0
  537. aip_agents/utils/final_response_builder.py +211 -0
  538. aip_agents/utils/final_response_builder.pyi +34 -0
  539. aip_agents/utils/formatter_llm_client.py +231 -0
  540. aip_agents/utils/formatter_llm_client.pyi +71 -0
  541. aip_agents/utils/langgraph/__init__.py +19 -0
  542. aip_agents/utils/langgraph/__init__.pyi +3 -0
  543. aip_agents/utils/langgraph/converter.py +128 -0
  544. aip_agents/utils/langgraph/converter.pyi +49 -0
  545. aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
  546. aip_agents/utils/langgraph/tool_managers/__init__.pyi +5 -0
  547. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
  548. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +35 -0
  549. aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
  550. aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +48 -0
  551. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1096 -0
  552. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +56 -0
  553. aip_agents/utils/langgraph/tool_output_management.py +1047 -0
  554. aip_agents/utils/langgraph/tool_output_management.pyi +329 -0
  555. aip_agents/utils/logger.py +195 -0
  556. aip_agents/utils/logger.pyi +60 -0
  557. aip_agents/utils/metadata/__init__.py +27 -0
  558. aip_agents/utils/metadata/__init__.pyi +5 -0
  559. aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
  560. aip_agents/utils/metadata/activity_metadata_helper.pyi +25 -0
  561. aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
  562. aip_agents/utils/metadata/activity_narrative/__init__.pyi +7 -0
  563. aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
  564. aip_agents/utils/metadata/activity_narrative/builder.pyi +35 -0
  565. aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
  566. aip_agents/utils/metadata/activity_narrative/constants.pyi +10 -0
  567. aip_agents/utils/metadata/activity_narrative/context.py +49 -0
  568. aip_agents/utils/metadata/activity_narrative/context.pyi +32 -0
  569. aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
  570. aip_agents/utils/metadata/activity_narrative/formatters.pyi +48 -0
  571. aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
  572. aip_agents/utils/metadata/activity_narrative/utils.pyi +12 -0
  573. aip_agents/utils/metadata/schemas/__init__.py +16 -0
  574. aip_agents/utils/metadata/schemas/__init__.pyi +4 -0
  575. aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
  576. aip_agents/utils/metadata/schemas/activity_schema.pyi +18 -0
  577. aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
  578. aip_agents/utils/metadata/schemas/thinking_schema.pyi +20 -0
  579. aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
  580. aip_agents/utils/metadata/thinking_metadata_helper.pyi +4 -0
  581. aip_agents/utils/metadata_helper.py +358 -0
  582. aip_agents/utils/metadata_helper.pyi +117 -0
  583. aip_agents/utils/name_preprocessor/__init__.py +17 -0
  584. aip_agents/utils/name_preprocessor/__init__.pyi +6 -0
  585. aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
  586. aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +52 -0
  587. aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
  588. aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +38 -0
  589. aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
  590. aip_agents/utils/name_preprocessor/name_preprocessor.pyi +41 -0
  591. aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
  592. aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +34 -0
  593. aip_agents/utils/pii/__init__.py +25 -0
  594. aip_agents/utils/pii/__init__.pyi +5 -0
  595. aip_agents/utils/pii/pii_handler.py +397 -0
  596. aip_agents/utils/pii/pii_handler.pyi +96 -0
  597. aip_agents/utils/pii/pii_helper.py +207 -0
  598. aip_agents/utils/pii/pii_helper.pyi +78 -0
  599. aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
  600. aip_agents/utils/pii/uuid_deanonymizer_mapping.pyi +73 -0
  601. aip_agents/utils/reference_helper.py +273 -0
  602. aip_agents/utils/reference_helper.pyi +81 -0
  603. aip_agents/utils/sse_chunk_transformer.py +831 -0
  604. aip_agents/utils/sse_chunk_transformer.pyi +166 -0
  605. aip_agents/utils/step_limit_manager.py +265 -0
  606. aip_agents/utils/step_limit_manager.pyi +112 -0
  607. aip_agents/utils/token_usage_helper.py +156 -0
  608. aip_agents/utils/token_usage_helper.pyi +60 -0
  609. aip_agents_binary-0.6.4.dist-info/METADATA +673 -0
  610. aip_agents_binary-0.6.4.dist-info/RECORD +612 -0
  611. aip_agents_binary-0.6.4.dist-info/WHEEL +5 -0
  612. aip_agents_binary-0.6.4.dist-info/top_level.txt +1 -0
@@ -0,0 +1,166 @@
1
+ from _typeshed import Incomplete
2
+ from aip_agents.schema.a2a import A2AEvent
3
+ from collections.abc import AsyncGenerator
4
+ from enum import StrEnum
5
+ from typing import Any
6
+
7
+ __all__ = ['SSEChunkTransformer', 'TaskState', 'ChunkStatus', 'ChunkReason', 'ChunkFieldKeys']
8
+
9
+ class TaskState(StrEnum):
10
+ """Task state values for SSE chunks."""
11
+ WORKING: str
12
+ COMPLETED: str
13
+ FAILED: str
14
+
15
+ class ChunkStatus(StrEnum):
16
+ """Status values for SSE chunks."""
17
+ SUCCESS: str
18
+ ERROR: str
19
+
20
+ class ChunkReason(StrEnum):
21
+ """Reason codes for special chunk states."""
22
+ EMPTY_PAYLOAD: str
23
+
24
+ class ChunkFieldKeys(StrEnum):
25
+ """Field name constants for SSE chunk structure."""
26
+ STATUS: str
27
+ TASK_STATE: str
28
+ CONTENT: str
29
+ EVENT_TYPE: str
30
+ FINAL: str
31
+ METADATA: str
32
+ TIMESTAMP: str
33
+ TASK_ID: str
34
+ CONTEXT_ID: str
35
+ ARTIFACTS: str
36
+ REASON: str
37
+
38
+ class SSEChunkTransformer:
39
+ '''Transforms A2AEvent stream to SSE-compatible output.
40
+
41
+ This class converts events from arun_a2a_stream into the normalized dict format
42
+ matching A2AConnector.astream_to_agent output.
43
+
44
+ Lifecycle:
45
+ Single-stream instance. Must NOT be reused across concurrent streams.
46
+ Each arun_sse_stream call creates a fresh instance.
47
+
48
+ Attributes:
49
+ task_id: Optional task identifier for the stream.
50
+ context_id: Optional context identifier for the stream.
51
+
52
+ Example:
53
+ >>> transformer = SSEChunkTransformer(task_id="task-123")
54
+ >>> async for chunk in transformer.transform_stream(agent.arun_a2a_stream("query")):
55
+ ... print(chunk)
56
+ '''
57
+ task_id: Incomplete
58
+ context_id: Incomplete
59
+ def __init__(self, task_id: str | None = None, context_id: str | None = None, pii_mapping: dict[str, str] | None = None) -> None:
60
+ """Initialize the transformer with optional task and context IDs.
61
+
62
+ Args:
63
+ task_id: Optional task identifier for the stream.
64
+ context_id: Optional context identifier for the stream.
65
+ pii_mapping: Optional PII mapping to inject into each chunk's metadata.
66
+ """
67
+ @staticmethod
68
+ def normalize_metadata_enums(data: Any) -> Any:
69
+ """Recursively convert enum keys/values to their string values.
70
+
71
+ This is a pure normalization utility that converts any enum instances
72
+ (MetadataFieldKeys, Kind, Status, etc.) to their .value strings.
73
+
74
+ Args:
75
+ data: Dict, list, or value that may contain enum keys/values.
76
+
77
+ Returns:
78
+ Normalized data with all enums converted to their .value strings.
79
+ """
80
+ @staticmethod
81
+ def normalize_event_type_value(event_type: Any) -> str | None:
82
+ """Convert A2AStreamEventType enum to string.
83
+
84
+ Args:
85
+ event_type: Event type (enum, string, or None).
86
+
87
+ Returns:
88
+ String value of the event type, or None if invalid.
89
+ """
90
+ @staticmethod
91
+ def create_artifact_hash(artifact: dict[str, Any]) -> str:
92
+ """Create a stable hash for artifact deduplication.
93
+
94
+ Uses name, content_type, mime_type, and file_data for hashing,
95
+ excluding artifact_id which may be randomly generated.
96
+
97
+ Args:
98
+ artifact: Artifact dict with name, content_type, mime_type, and optionally file_data.
99
+
100
+ Returns:
101
+ SHA256 hexdigest hash string for deduplication.
102
+ """
103
+ @staticmethod
104
+ def extract_tool_outputs(tool_calls: list[dict[str, Any]]) -> list[str]:
105
+ """Extract human-readable output strings from tool calls.
106
+
107
+ Args:
108
+ tool_calls: List of tool call dictionaries.
109
+
110
+ Returns:
111
+ List of human-readable output strings.
112
+ """
113
+ @staticmethod
114
+ def format_tool_output(output: Any, tool_name: str) -> str:
115
+ """Format a single tool output for display.
116
+
117
+ Args:
118
+ output: The tool output to format.
119
+ tool_name: The name of the tool.
120
+
121
+ Returns:
122
+ The formatted output string.
123
+ """
124
+ @staticmethod
125
+ def apply_hitl_content_override(content: str | None, event_type_str: str, metadata: dict[str, Any]) -> str | None:
126
+ """Apply HITL content override when HITL is active and tool results are available.
127
+
128
+ This method overrides the content with human-readable tool output when HITL
129
+ is active, matching A2AConnector behavior.
130
+
131
+ Args:
132
+ content: The original content/status message.
133
+ event_type_str: The type of event being processed (normalized string).
134
+ metadata: The metadata dictionary containing tool_info and hitl flag.
135
+
136
+ Returns:
137
+ The original content or human-readable tool output if HITL is active.
138
+ """
139
+ def transform_event(self, event: A2AEvent) -> dict[str, Any]:
140
+ """Transform a single A2AEvent to SSE chunk format.
141
+
142
+ Converts the A2AEvent structure to the normalized SSE chunk format,
143
+ relocating fields like tool_info and thinking_and_activity_info into
144
+ metadata, and normalizing enum values to strings.
145
+
146
+ Args:
147
+ event: Single A2AEvent dict from arun_a2a_stream.
148
+
149
+ Returns:
150
+ SSEChunk dict with normalized structure.
151
+ """
152
+ async def transform_stream(self, stream: AsyncGenerator[A2AEvent, None]) -> AsyncGenerator[dict[str, Any], None]:
153
+ """Transform A2AEvent stream to SSE-compatible chunks.
154
+
155
+ Wraps the input stream and transforms each event, handling artifact
156
+ deduplication and time tracking across the stream.
157
+
158
+ Args:
159
+ stream: Async generator yielding A2AEvent dicts.
160
+
161
+ Yields:
162
+ SSEChunk dicts with normalized structure.
163
+
164
+ Raises:
165
+ Exceptions from underlying stream propagate to caller.
166
+ """
@@ -0,0 +1,265 @@
1
+ """Step limit manager for enforcing execution and delegation limits.
2
+
3
+ Authors:
4
+ Saul Sayers (saul.sayers@gdplabs.id)
5
+ """
6
+
7
+ from contextvars import ContextVar
8
+ from dataclasses import asdict, dataclass, field
9
+ from typing import Any
10
+
11
+ from aip_agents.schema.step_limit import (
12
+ MaxDelegationDepthExceededError,
13
+ MaxStepsExceededError,
14
+ StepLimitConfig,
15
+ StepLimitErrorResponse,
16
+ StepLimitErrorType,
17
+ )
18
+
19
+ # Context variables for cross-agent propagation
20
+ _DELEGATION_DEPTH_CVAR: ContextVar[int] = ContextVar("delegation_depth", default=0)
21
+ _REMAINING_STEP_BUDGET_CVAR: ContextVar[int | None] = ContextVar("remaining_step_budget", default=None)
22
+ _DELEGATION_CHAIN_CVAR: ContextVar[tuple[str, ...]] = ContextVar("delegation_chain", default=())
23
+ _STEP_LIMIT_CONFIG_CVAR: ContextVar[StepLimitConfig | None] = ContextVar("step_limit_config", default=None)
24
+
25
+
26
+ @dataclass
27
+ class StepExecutionContext:
28
+ """Runtime context for tracking step execution and delegation depth.
29
+
30
+ Attributes:
31
+ current_step: Current step number (0-indexed).
32
+ delegation_depth: Current depth in delegation chain (0 for root agent).
33
+ remaining_step_budget: Steps remaining before limit is hit.
34
+ delegation_chain: List of agent names in the delegation chain.
35
+ """
36
+
37
+ current_step: int = 0
38
+ delegation_depth: int = 0
39
+ remaining_step_budget: int | None = None
40
+ delegation_chain: list[str] = field(default_factory=list)
41
+
42
+
43
+ class StepLimitManager:
44
+ """Manages step and delegation limit enforcement during agent execution.
45
+
46
+ This manager integrates with LangGraph's existing step mechanisms and adds
47
+ delegation depth tracking and budget propagation.
48
+
49
+ Attributes:
50
+ config: Step limit configuration.
51
+ context: Current execution context.
52
+ """
53
+
54
+ def __init__(
55
+ self,
56
+ config: StepLimitConfig | None = None,
57
+ initial_delegation_depth: int = 0,
58
+ parent_step_budget: int | None = None,
59
+ ) -> None:
60
+ """Initialize step limit manager.
61
+
62
+ Args:
63
+ config: Optional step limit configuration. Uses defaults if None.
64
+ initial_delegation_depth: Starting delegation depth (from parent).
65
+ parent_step_budget: Remaining step budget inherited from parent agent.
66
+ """
67
+ self.config = config or StepLimitConfig()
68
+ self.context = StepExecutionContext(
69
+ delegation_depth=initial_delegation_depth,
70
+ remaining_step_budget=parent_step_budget if parent_step_budget is not None else self.config.max_steps,
71
+ )
72
+
73
+ def check_step_limit(self, agent_name: str = "agent", count: int = 1) -> None:
74
+ """Check if taking 'count' steps would exceed limit.
75
+
76
+ Args:
77
+ agent_name: Name of the agent to identify in error message.
78
+ count: Number of steps to check (useful for parallel tool batches).
79
+
80
+ Raises:
81
+ MaxStepsExceededError: If max_steps limit is exceeded.
82
+ """
83
+ limit_exceeded = False
84
+ limit_val = self.config.max_steps
85
+ current_val = self.context.current_step
86
+
87
+ if self.context.current_step + count > self.config.max_steps:
88
+ limit_exceeded = True
89
+ elif self.context.remaining_step_budget is not None and self.context.remaining_step_budget < count:
90
+ limit_exceeded = True
91
+ # If we hit budget, the limit was effectively what we've done so far + what's left
92
+ limit_val = self.context.current_step + self.context.remaining_step_budget
93
+
94
+ if limit_exceeded:
95
+ error_response = StepLimitErrorResponse(
96
+ error_type=StepLimitErrorType.STEP_LIMIT_EXCEEDED,
97
+ agent_name=agent_name,
98
+ current_value=current_val,
99
+ configured_limit=limit_val,
100
+ message=f"Agent exceeded maximum step limit ({current_val + count}/{limit_val} steps)",
101
+ )
102
+ raise MaxStepsExceededError(error_response)
103
+
104
+ def check_delegation_depth(self, target_agent_name: str) -> None:
105
+ """Check if delegation to target agent would exceed depth limit.
106
+
107
+ Args:
108
+ target_agent_name: Name of the agent to delegate to.
109
+
110
+ Raises:
111
+ MaxDelegationDepthExceededError: If delegation depth limit exceeded.
112
+ """
113
+ # Check for circular delegation
114
+ if target_agent_name in self.context.delegation_chain:
115
+ error_response = StepLimitErrorResponse(
116
+ error_type=StepLimitErrorType.DELEGATION_DEPTH_EXCEEDED,
117
+ agent_name=target_agent_name,
118
+ current_value=self.context.delegation_depth,
119
+ configured_limit=self.config.max_delegation_depth,
120
+ message=f"Circular delegation detected: '{target_agent_name}' already in chain {self.context.delegation_chain}",
121
+ delegation_chain=self.context.delegation_chain,
122
+ )
123
+ raise MaxDelegationDepthExceededError(error_response)
124
+
125
+ # Check depth limit
126
+ if self.context.delegation_depth >= self.config.max_delegation_depth:
127
+ error_response = StepLimitErrorResponse(
128
+ error_type=StepLimitErrorType.DELEGATION_DEPTH_EXCEEDED,
129
+ agent_name=target_agent_name,
130
+ current_value=self.context.delegation_depth,
131
+ configured_limit=self.config.max_delegation_depth,
132
+ message=f"Cannot delegate to '{target_agent_name}': Maximum delegation depth ({self.context.delegation_depth}/{self.config.max_delegation_depth}) exceeded",
133
+ delegation_chain=self.context.delegation_chain,
134
+ )
135
+ raise MaxDelegationDepthExceededError(error_response)
136
+
137
+ def increment_step(self, count: int = 1) -> None:
138
+ """Increment step counter and update remaining budget.
139
+
140
+ Args:
141
+ count: Number of steps to consume (defaults to 1).
142
+ """
143
+ if count <= 0:
144
+ return
145
+ self.context.current_step += count
146
+ if self.context.remaining_step_budget is not None:
147
+ self.context.remaining_step_budget = max(0, self.context.remaining_step_budget - count)
148
+
149
+ def get_child_budget(self, child_max_steps: int | None = None) -> int:
150
+ """Calculate step budget to allocate to child agent.
151
+
152
+ Algorithm:
153
+ 1. If remaining_step_budget is None (root with no limit), use config.max_steps - 1
154
+ 2. If remaining_step_budget <= 1, return 0 (no budget left for child)
155
+ 3. Calculate child_budget = remaining_step_budget - 1 (reserve 1 for parent)
156
+ 4. If child has own max_steps config, return min(child_budget, child.max_steps)
157
+ 5. Otherwise return child_budget
158
+
159
+ Args:
160
+ child_max_steps: Optional child agent's own max_steps limit.
161
+
162
+ Returns:
163
+ Step budget for child agent, accounting for parent's continuation.
164
+ Returns 0 if no budget available for child.
165
+
166
+ Edge Cases:
167
+ - remaining=1: Returns 0 (parent needs the last step)
168
+ - remaining=None: Uses config.max_steps - 1
169
+ - child has own limit: Returns min(calculated_budget, child_limit)
170
+ """
171
+ if self.context.remaining_step_budget is None:
172
+ child_budget = self.config.max_steps - 1
173
+ elif self.context.remaining_step_budget <= 1:
174
+ return 0
175
+ else:
176
+ child_budget = self.context.remaining_step_budget - 1
177
+
178
+ if child_max_steps is not None:
179
+ return min(child_budget, child_max_steps)
180
+ return child_budget
181
+
182
+ def add_to_delegation_chain(self, agent_name: str) -> None:
183
+ """Add agent to delegation chain for tracking.
184
+
185
+ Args:
186
+ agent_name: Name of the agent being delegated to.
187
+ """
188
+ self.context.delegation_chain.append(agent_name)
189
+
190
+ @classmethod
191
+ def from_state(
192
+ cls,
193
+ state: dict[str, Any],
194
+ config: StepLimitConfig | None = None,
195
+ ) -> "StepLimitManager":
196
+ """Create manager from LangGraph state.
197
+
198
+ Args:
199
+ state: LangGraph agent state containing remaining_steps, etc.
200
+ config: Optional step limit configuration.
201
+
202
+ Returns:
203
+ Initialized step limit manager.
204
+ """
205
+ raw_config = state.get("step_limit_config")
206
+ if isinstance(raw_config, dict):
207
+ step_limit_config = StepLimitConfig(**raw_config)
208
+ else:
209
+ step_limit_config = raw_config or config or StepLimitConfig()
210
+
211
+ delegation_depth = state.get("delegation_depth")
212
+ delegation_chain = state.get("delegation_chain")
213
+ current_step = state.get("current_step", 0)
214
+
215
+ # Restore remaining budget
216
+ remaining_step_budget = state.get("remaining_step_budget")
217
+
218
+ # Try to read from ContextVars if not in state (fallback for first step)
219
+ if remaining_step_budget is None:
220
+ try:
221
+ remaining_step_budget = _REMAINING_STEP_BUDGET_CVAR.get()
222
+ except LookupError: # pragma: no cover - unreachable with default value, defensive code
223
+ pass
224
+
225
+ if delegation_depth is None:
226
+ try:
227
+ delegation_depth = _DELEGATION_DEPTH_CVAR.get()
228
+ except LookupError: # pragma: no cover - unreachable with default value, defensive code
229
+ delegation_depth = 0
230
+
231
+ if delegation_chain is None:
232
+ try:
233
+ delegation_chain = list(_DELEGATION_CHAIN_CVAR.get())
234
+ except LookupError: # pragma: no cover - unreachable with default value, defensive code
235
+ delegation_chain = []
236
+
237
+ manager = cls(
238
+ config=step_limit_config,
239
+ initial_delegation_depth=delegation_depth,
240
+ parent_step_budget=remaining_step_budget,
241
+ )
242
+ manager.context.delegation_chain = list(delegation_chain)
243
+ manager.context.current_step = current_step
244
+ return manager
245
+
246
+ def set_context(self) -> None:
247
+ """Set context variables for downstream consumption (e.g. by delegation tools)."""
248
+ _REMAINING_STEP_BUDGET_CVAR.set(self.context.remaining_step_budget)
249
+ _DELEGATION_DEPTH_CVAR.set(self.context.delegation_depth)
250
+ _DELEGATION_CHAIN_CVAR.set(tuple(self.context.delegation_chain))
251
+ _STEP_LIMIT_CONFIG_CVAR.set(self.config)
252
+
253
+ def to_state_update(self) -> dict[str, Any]:
254
+ """Convert current context to LangGraph state update.
255
+
256
+ Returns:
257
+ Dictionary of state fields to update.
258
+ """
259
+ return {
260
+ "current_step": self.context.current_step,
261
+ "delegation_depth": self.context.delegation_depth,
262
+ "delegation_chain": self.context.delegation_chain,
263
+ "step_limit_config": asdict(self.config),
264
+ "remaining_step_budget": self.context.remaining_step_budget,
265
+ }
@@ -0,0 +1,112 @@
1
+ from _typeshed import Incomplete
2
+ from aip_agents.schema.step_limit import MaxDelegationDepthExceededError as MaxDelegationDepthExceededError, MaxStepsExceededError as MaxStepsExceededError, StepLimitConfig as StepLimitConfig, StepLimitErrorResponse as StepLimitErrorResponse, StepLimitErrorType as StepLimitErrorType
3
+ from dataclasses import dataclass, field
4
+ from typing import Any
5
+
6
+ @dataclass
7
+ class StepExecutionContext:
8
+ """Runtime context for tracking step execution and delegation depth.
9
+
10
+ Attributes:
11
+ current_step: Current step number (0-indexed).
12
+ delegation_depth: Current depth in delegation chain (0 for root agent).
13
+ remaining_step_budget: Steps remaining before limit is hit.
14
+ delegation_chain: List of agent names in the delegation chain.
15
+ """
16
+ current_step: int = ...
17
+ delegation_depth: int = ...
18
+ remaining_step_budget: int | None = ...
19
+ delegation_chain: list[str] = field(default_factory=list)
20
+
21
+ class StepLimitManager:
22
+ """Manages step and delegation limit enforcement during agent execution.
23
+
24
+ This manager integrates with LangGraph's existing step mechanisms and adds
25
+ delegation depth tracking and budget propagation.
26
+
27
+ Attributes:
28
+ config: Step limit configuration.
29
+ context: Current execution context.
30
+ """
31
+ config: Incomplete
32
+ context: Incomplete
33
+ def __init__(self, config: StepLimitConfig | None = None, initial_delegation_depth: int = 0, parent_step_budget: int | None = None) -> None:
34
+ """Initialize step limit manager.
35
+
36
+ Args:
37
+ config: Optional step limit configuration. Uses defaults if None.
38
+ initial_delegation_depth: Starting delegation depth (from parent).
39
+ parent_step_budget: Remaining step budget inherited from parent agent.
40
+ """
41
+ def check_step_limit(self, agent_name: str = 'agent', count: int = 1) -> None:
42
+ """Check if taking 'count' steps would exceed limit.
43
+
44
+ Args:
45
+ agent_name: Name of the agent to identify in error message.
46
+ count: Number of steps to check (useful for parallel tool batches).
47
+
48
+ Raises:
49
+ MaxStepsExceededError: If max_steps limit is exceeded.
50
+ """
51
+ def check_delegation_depth(self, target_agent_name: str) -> None:
52
+ """Check if delegation to target agent would exceed depth limit.
53
+
54
+ Args:
55
+ target_agent_name: Name of the agent to delegate to.
56
+
57
+ Raises:
58
+ MaxDelegationDepthExceededError: If delegation depth limit exceeded.
59
+ """
60
+ def increment_step(self, count: int = 1) -> None:
61
+ """Increment step counter and update remaining budget.
62
+
63
+ Args:
64
+ count: Number of steps to consume (defaults to 1).
65
+ """
66
+ def get_child_budget(self, child_max_steps: int | None = None) -> int:
67
+ """Calculate step budget to allocate to child agent.
68
+
69
+ Algorithm:
70
+ 1. If remaining_step_budget is None (root with no limit), use config.max_steps - 1
71
+ 2. If remaining_step_budget <= 1, return 0 (no budget left for child)
72
+ 3. Calculate child_budget = remaining_step_budget - 1 (reserve 1 for parent)
73
+ 4. If child has own max_steps config, return min(child_budget, child.max_steps)
74
+ 5. Otherwise return child_budget
75
+
76
+ Args:
77
+ child_max_steps: Optional child agent's own max_steps limit.
78
+
79
+ Returns:
80
+ Step budget for child agent, accounting for parent's continuation.
81
+ Returns 0 if no budget available for child.
82
+
83
+ Edge Cases:
84
+ - remaining=1: Returns 0 (parent needs the last step)
85
+ - remaining=None: Uses config.max_steps - 1
86
+ - child has own limit: Returns min(calculated_budget, child_limit)
87
+ """
88
+ def add_to_delegation_chain(self, agent_name: str) -> None:
89
+ """Add agent to delegation chain for tracking.
90
+
91
+ Args:
92
+ agent_name: Name of the agent being delegated to.
93
+ """
94
+ @classmethod
95
+ def from_state(cls, state: dict[str, Any], config: StepLimitConfig | None = None) -> StepLimitManager:
96
+ """Create manager from LangGraph state.
97
+
98
+ Args:
99
+ state: LangGraph agent state containing remaining_steps, etc.
100
+ config: Optional step limit configuration.
101
+
102
+ Returns:
103
+ Initialized step limit manager.
104
+ """
105
+ def set_context(self) -> None:
106
+ """Set context variables for downstream consumption (e.g. by delegation tools)."""
107
+ def to_state_update(self) -> dict[str, Any]:
108
+ """Convert current context to LangGraph state update.
109
+
110
+ Returns:
111
+ Dictionary of state fields to update.
112
+ """
@@ -0,0 +1,156 @@
1
+ """This module provides utility functions for handling token usage in LangGraph agents.
2
+
3
+ Authors:
4
+ Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
5
+ """
6
+
7
+ from typing import Any
8
+
9
+ from langchain_core.messages.ai import AIMessage, UsageMetadata
10
+ from langchain_core.messages.tool import ToolMessage
11
+ from langgraph.types import Command
12
+
13
+ # Constants for token usage field names
14
+ USAGE_METADATA_KEY = "usage_metadata"
15
+ TOTAL_USAGE_KEY = "total_usage"
16
+ STEP_USAGE_KEY = "step_usage"
17
+
18
+
19
+ def add_usage_metadata(
20
+ cur_accumulated_token_usage: UsageMetadata | None, new_token_usage: UsageMetadata | None
21
+ ) -> UsageMetadata | None:
22
+ """Reducer function to accumulate UsageMetadata across agent runs.
23
+
24
+ Args:
25
+ cur_accumulated_token_usage: The current accumulated token usage metadata.
26
+ new_token_usage: New token usage metadata to add.
27
+
28
+ Returns:
29
+ Accumulated usage metadata or None if both inputs are None.
30
+ """
31
+ # Fast path for common cases
32
+ if cur_accumulated_token_usage is None:
33
+ return new_token_usage
34
+ if new_token_usage is None:
35
+ return cur_accumulated_token_usage
36
+
37
+ # Pre-allocate result dictionary with known size
38
+ keys = {"input_tokens", "output_tokens", "total_tokens"}
39
+ result = {key: cur_accumulated_token_usage.get(key, 0) + new_token_usage.get(key, 0) for key in keys}
40
+
41
+ # Only process details if they exist
42
+ detail_keys = {"input_token_details", "output_token_details"}
43
+ for key in detail_keys:
44
+ if cur_accumulated_token_usage.get(key) or new_token_usage.get(key):
45
+ result[key] = _merge_token_details(cur_accumulated_token_usage.get(key, {}), new_token_usage.get(key, {}))
46
+
47
+ return result
48
+
49
+
50
+ def _merge_token_details(current: dict[str, int], new: dict[str, int]) -> dict[str, int]:
51
+ """Merge token details from two dictionaries.
52
+
53
+ Args:
54
+ current: Current token details.
55
+ new: New token details to add.
56
+
57
+ Returns:
58
+ Merged token details.
59
+ """
60
+ # Use dict comprehension for better performance
61
+ all_keys = current.keys() | new.keys()
62
+ return {key: current.get(key, 0) + new.get(key, 0) for key in all_keys}
63
+
64
+
65
+ def extract_and_update_token_usage_from_ai_message(ai_message: AIMessage) -> dict[str, Any]:
66
+ """Extract token usage from AI message and prepare state update.
67
+
68
+ Args:
69
+ ai_message: The AI message containing usage metadata.
70
+
71
+ Returns:
72
+ Dictionary with accumulated_usage_metadata update if usage metadata is available.
73
+ """
74
+ state_updates = {}
75
+
76
+ if hasattr(ai_message, USAGE_METADATA_KEY) and ai_message.usage_metadata:
77
+ state_updates[TOTAL_USAGE_KEY] = ai_message.usage_metadata
78
+
79
+ return state_updates
80
+
81
+
82
+ def extract_token_usage_from_tool_output(tool_output: Any) -> UsageMetadata | None:
83
+ """Extract token usage from various tool output formats.
84
+
85
+ Supports multiple tool output formats:
86
+ 1. Dictionary with 'usage_metadata' field
87
+ 2. Command with 'usage_metadata' attribute
88
+ 3. Any object with 'usage_metadata' attribute
89
+
90
+ Args:
91
+ tool_output: The output from a tool execution.
92
+
93
+ Returns:
94
+ UsageMetadata if found, None otherwise.
95
+ """
96
+ # Handle dictionary format: {"result": "...", "usage_metadata": {...}}
97
+ if isinstance(tool_output, dict) and USAGE_METADATA_KEY in tool_output:
98
+ return tool_output[USAGE_METADATA_KEY]
99
+
100
+ # Handle Command format with usage_metadata in update field
101
+ if isinstance(tool_output, Command):
102
+ return extract_token_usage_from_command(tool_output)
103
+
104
+ # Handle any object with usage_metadata attribute
105
+ if hasattr(tool_output, USAGE_METADATA_KEY):
106
+ return getattr(tool_output, USAGE_METADATA_KEY)
107
+
108
+ return None
109
+
110
+
111
+ def extract_token_usage_from_command(command: Command) -> UsageMetadata | None:
112
+ """Extract token usage from Command object.
113
+
114
+ Args:
115
+ command: The Command object to extract token usage from.
116
+
117
+ Returns:
118
+ UsageMetadata if found, None otherwise.
119
+ """
120
+ update_dict = getattr(command, "update", {}) or {}
121
+ if USAGE_METADATA_KEY in update_dict:
122
+ return update_dict[USAGE_METADATA_KEY]
123
+
124
+ # if not try to get from messages in update, and accumulate token usage
125
+ messages: list[ToolMessage] = update_dict.get("messages", [])
126
+ if not messages:
127
+ return None
128
+
129
+ accumulated_token_usage = None
130
+ for message in messages:
131
+ if USAGE_METADATA_KEY in message.response_metadata:
132
+ accumulated_token_usage = add_usage_metadata(
133
+ accumulated_token_usage, message.response_metadata[USAGE_METADATA_KEY]
134
+ )
135
+ return accumulated_token_usage
136
+
137
+
138
+ def extract_token_usage_from_agent_response(agent_response: dict[str, Any]) -> UsageMetadata | None:
139
+ """Extract accumulated token usage from agent response.
140
+
141
+ Args:
142
+ agent_response: The agent response to extract token usage from.
143
+
144
+ Returns:
145
+ UsageMetadata if found, None otherwise.
146
+ """
147
+ if not isinstance(agent_response, dict):
148
+ return None
149
+
150
+ full_state = agent_response.get("full_final_state", {})
151
+ if not isinstance(full_state, dict):
152
+ return None
153
+
154
+ if TOTAL_USAGE_KEY in full_state:
155
+ return full_state[TOTAL_USAGE_KEY]
156
+ return None