aip-agents-binary 0.5.25b1__py3-none-macosx_13_0_arm64.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 (566) 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 +2948 -0
  22. aip_agents/agent/base_langgraph_agent.pyi +232 -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 +433 -0
  52. aip_agents/agent/langgraph_memory_enhancer_agent.pyi +49 -0
  53. aip_agents/agent/langgraph_react_agent.py +2596 -0
  54. aip_agents/agent/langgraph_react_agent.pyi +131 -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/demo_memory_recall.py +401 -0
  75. aip_agents/examples/demo_memory_recall.pyi +58 -0
  76. aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
  77. aip_agents/examples/hello_world_a2a_google_adk_client.pyi +9 -0
  78. aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
  79. aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +9 -0
  80. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
  81. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +9 -0
  82. aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
  83. aip_agents/examples/hello_world_a2a_google_adk_server.pyi +15 -0
  84. aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
  85. aip_agents/examples/hello_world_a2a_langchain_client.pyi +5 -0
  86. aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
  87. aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +5 -0
  88. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
  89. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +5 -0
  90. aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
  91. aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +5 -0
  92. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
  93. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +5 -0
  94. aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
  95. aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +15 -0
  96. aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
  97. aip_agents/examples/hello_world_a2a_langchain_server.pyi +15 -0
  98. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
  99. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +15 -0
  100. aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
  101. aip_agents/examples/hello_world_a2a_langflow_client.pyi +9 -0
  102. aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
  103. aip_agents/examples/hello_world_a2a_langflow_server.pyi +14 -0
  104. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
  105. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +5 -0
  106. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
  107. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +5 -0
  108. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
  109. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +16 -0
  110. aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
  111. aip_agents/examples/hello_world_a2a_langgraph_client.pyi +9 -0
  112. aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
  113. aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +9 -0
  114. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
  115. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +2 -0
  116. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
  117. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +9 -0
  118. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
  119. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +5 -0
  120. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
  121. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +5 -0
  122. aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
  123. aip_agents/examples/hello_world_a2a_langgraph_server.pyi +14 -0
  124. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
  125. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +15 -0
  126. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
  127. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +15 -0
  128. aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
  129. aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +48 -0
  130. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
  131. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +48 -0
  132. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +251 -0
  133. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +45 -0
  134. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
  135. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +5 -0
  136. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
  137. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +15 -0
  138. aip_agents/examples/hello_world_google_adk.py +41 -0
  139. aip_agents/examples/hello_world_google_adk.pyi +5 -0
  140. aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
  141. aip_agents/examples/hello_world_google_adk_mcp_http.pyi +5 -0
  142. aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
  143. aip_agents/examples/hello_world_google_adk_mcp_http_stream.pyi +5 -0
  144. aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
  145. aip_agents/examples/hello_world_google_adk_mcp_sse.pyi +5 -0
  146. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
  147. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.pyi +5 -0
  148. aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
  149. aip_agents/examples/hello_world_google_adk_mcp_stdio.pyi +5 -0
  150. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
  151. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.pyi +5 -0
  152. aip_agents/examples/hello_world_google_adk_stream.py +44 -0
  153. aip_agents/examples/hello_world_google_adk_stream.pyi +5 -0
  154. aip_agents/examples/hello_world_langchain.py +28 -0
  155. aip_agents/examples/hello_world_langchain.pyi +5 -0
  156. aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
  157. aip_agents/examples/hello_world_langchain_lm_invoker.pyi +2 -0
  158. aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
  159. aip_agents/examples/hello_world_langchain_mcp_http.pyi +5 -0
  160. aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
  161. aip_agents/examples/hello_world_langchain_mcp_http_interactive.pyi +16 -0
  162. aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
  163. aip_agents/examples/hello_world_langchain_mcp_http_stream.pyi +5 -0
  164. aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
  165. aip_agents/examples/hello_world_langchain_mcp_multi_server.pyi +18 -0
  166. aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
  167. aip_agents/examples/hello_world_langchain_mcp_sse.pyi +5 -0
  168. aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
  169. aip_agents/examples/hello_world_langchain_mcp_sse_stream.pyi +5 -0
  170. aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
  171. aip_agents/examples/hello_world_langchain_mcp_stdio.pyi +5 -0
  172. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
  173. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.pyi +5 -0
  174. aip_agents/examples/hello_world_langchain_stream.py +36 -0
  175. aip_agents/examples/hello_world_langchain_stream.pyi +5 -0
  176. aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
  177. aip_agents/examples/hello_world_langchain_stream_lm_invoker.pyi +5 -0
  178. aip_agents/examples/hello_world_langflow_agent.py +163 -0
  179. aip_agents/examples/hello_world_langflow_agent.pyi +35 -0
  180. aip_agents/examples/hello_world_langgraph.py +39 -0
  181. aip_agents/examples/hello_world_langgraph.pyi +5 -0
  182. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.py +44 -0
  183. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.pyi +5 -0
  184. aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
  185. aip_agents/examples/hello_world_langgraph_mcp_http.pyi +5 -0
  186. aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
  187. aip_agents/examples/hello_world_langgraph_mcp_http_stream.pyi +5 -0
  188. aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
  189. aip_agents/examples/hello_world_langgraph_mcp_sse.pyi +5 -0
  190. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
  191. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.pyi +5 -0
  192. aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
  193. aip_agents/examples/hello_world_langgraph_mcp_stdio.pyi +5 -0
  194. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
  195. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.pyi +5 -0
  196. aip_agents/examples/hello_world_langgraph_stream.py +43 -0
  197. aip_agents/examples/hello_world_langgraph_stream.pyi +5 -0
  198. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
  199. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.pyi +5 -0
  200. aip_agents/examples/hello_world_model_switch_cli.py +210 -0
  201. aip_agents/examples/hello_world_model_switch_cli.pyi +30 -0
  202. aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
  203. aip_agents/examples/hello_world_multi_agent_adk.pyi +6 -0
  204. aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
  205. aip_agents/examples/hello_world_multi_agent_langchain.pyi +5 -0
  206. aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
  207. aip_agents/examples/hello_world_multi_agent_langgraph.pyi +5 -0
  208. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
  209. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.pyi +5 -0
  210. aip_agents/examples/hello_world_pii_logger.py +21 -0
  211. aip_agents/examples/hello_world_pii_logger.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 +46 -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 +193 -0
  310. aip_agents/mcp/client/connection_manager.pyi +48 -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 +362 -0
  320. aip_agents/mcp/client/persistent_session.pyi +113 -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 +228 -0
  324. aip_agents/mcp/client/transports.pyi +123 -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 +717 -0
  334. aip_agents/memory/adapters/base_adapter.pyi +150 -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/schema/__init__.py +69 -0
  356. aip_agents/schema/__init__.pyi +9 -0
  357. aip_agents/schema/a2a.py +56 -0
  358. aip_agents/schema/a2a.pyi +40 -0
  359. aip_agents/schema/agent.py +111 -0
  360. aip_agents/schema/agent.pyi +65 -0
  361. aip_agents/schema/hitl.py +157 -0
  362. aip_agents/schema/hitl.pyi +89 -0
  363. aip_agents/schema/langgraph.py +37 -0
  364. aip_agents/schema/langgraph.pyi +28 -0
  365. aip_agents/schema/model_id.py +97 -0
  366. aip_agents/schema/model_id.pyi +54 -0
  367. aip_agents/schema/step_limit.py +108 -0
  368. aip_agents/schema/step_limit.pyi +63 -0
  369. aip_agents/schema/storage.py +40 -0
  370. aip_agents/schema/storage.pyi +21 -0
  371. aip_agents/sentry/__init__.py +11 -0
  372. aip_agents/sentry/__init__.pyi +3 -0
  373. aip_agents/sentry/sentry.py +151 -0
  374. aip_agents/sentry/sentry.pyi +48 -0
  375. aip_agents/storage/__init__.py +41 -0
  376. aip_agents/storage/__init__.pyi +8 -0
  377. aip_agents/storage/base.py +85 -0
  378. aip_agents/storage/base.pyi +58 -0
  379. aip_agents/storage/clients/__init__.py +12 -0
  380. aip_agents/storage/clients/__init__.pyi +3 -0
  381. aip_agents/storage/clients/minio_client.py +318 -0
  382. aip_agents/storage/clients/minio_client.pyi +137 -0
  383. aip_agents/storage/config.py +62 -0
  384. aip_agents/storage/config.pyi +29 -0
  385. aip_agents/storage/providers/__init__.py +15 -0
  386. aip_agents/storage/providers/__init__.pyi +5 -0
  387. aip_agents/storage/providers/base.py +106 -0
  388. aip_agents/storage/providers/base.pyi +88 -0
  389. aip_agents/storage/providers/memory.py +114 -0
  390. aip_agents/storage/providers/memory.pyi +79 -0
  391. aip_agents/storage/providers/object_storage.py +214 -0
  392. aip_agents/storage/providers/object_storage.pyi +98 -0
  393. aip_agents/tools/__init__.py +53 -0
  394. aip_agents/tools/__init__.pyi +9 -0
  395. aip_agents/tools/browser_use/__init__.py +82 -0
  396. aip_agents/tools/browser_use/__init__.pyi +14 -0
  397. aip_agents/tools/browser_use/action_parser.py +103 -0
  398. aip_agents/tools/browser_use/action_parser.pyi +18 -0
  399. aip_agents/tools/browser_use/browser_use_tool.py +1112 -0
  400. aip_agents/tools/browser_use/browser_use_tool.pyi +50 -0
  401. aip_agents/tools/browser_use/llm_config.py +120 -0
  402. aip_agents/tools/browser_use/llm_config.pyi +52 -0
  403. aip_agents/tools/browser_use/minio_storage.py +198 -0
  404. aip_agents/tools/browser_use/minio_storage.pyi +109 -0
  405. aip_agents/tools/browser_use/schemas.py +119 -0
  406. aip_agents/tools/browser_use/schemas.pyi +32 -0
  407. aip_agents/tools/browser_use/session.py +76 -0
  408. aip_agents/tools/browser_use/session.pyi +4 -0
  409. aip_agents/tools/browser_use/session_errors.py +132 -0
  410. aip_agents/tools/browser_use/session_errors.pyi +53 -0
  411. aip_agents/tools/browser_use/steel_session_recording.py +317 -0
  412. aip_agents/tools/browser_use/steel_session_recording.pyi +63 -0
  413. aip_agents/tools/browser_use/streaming.py +813 -0
  414. aip_agents/tools/browser_use/streaming.pyi +81 -0
  415. aip_agents/tools/browser_use/structured_data_parser.py +257 -0
  416. aip_agents/tools/browser_use/structured_data_parser.pyi +86 -0
  417. aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
  418. aip_agents/tools/browser_use/structured_data_recovery.pyi +43 -0
  419. aip_agents/tools/browser_use/types.py +78 -0
  420. aip_agents/tools/browser_use/types.pyi +45 -0
  421. aip_agents/tools/code_sandbox/__init__.py +26 -0
  422. aip_agents/tools/code_sandbox/__init__.pyi +3 -0
  423. aip_agents/tools/code_sandbox/constant.py +13 -0
  424. aip_agents/tools/code_sandbox/constant.pyi +4 -0
  425. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +306 -0
  426. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +102 -0
  427. aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
  428. aip_agents/tools/code_sandbox/e2b_sandbox_tool.pyi +29 -0
  429. aip_agents/tools/constants.py +177 -0
  430. aip_agents/tools/constants.pyi +138 -0
  431. aip_agents/tools/document_loader/__init__.py +44 -0
  432. aip_agents/tools/document_loader/__init__.pyi +7 -0
  433. aip_agents/tools/document_loader/base_reader.py +302 -0
  434. aip_agents/tools/document_loader/base_reader.pyi +75 -0
  435. aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
  436. aip_agents/tools/document_loader/docx_reader_tool.pyi +10 -0
  437. aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
  438. aip_agents/tools/document_loader/excel_reader_tool.pyi +26 -0
  439. aip_agents/tools/document_loader/pdf_reader_tool.py +79 -0
  440. aip_agents/tools/document_loader/pdf_reader_tool.pyi +11 -0
  441. aip_agents/tools/document_loader/pdf_splitter.py +169 -0
  442. aip_agents/tools/document_loader/pdf_splitter.pyi +18 -0
  443. aip_agents/tools/gl_connector/__init__.py +5 -0
  444. aip_agents/tools/gl_connector/__init__.pyi +3 -0
  445. aip_agents/tools/gl_connector/tool.py +383 -0
  446. aip_agents/tools/gl_connector/tool.pyi +74 -0
  447. aip_agents/tools/gl_connector_tools.py +119 -0
  448. aip_agents/tools/gl_connector_tools.pyi +39 -0
  449. aip_agents/tools/memory_search/__init__.py +22 -0
  450. aip_agents/tools/memory_search/__init__.pyi +5 -0
  451. aip_agents/tools/memory_search/base.py +200 -0
  452. aip_agents/tools/memory_search/base.pyi +69 -0
  453. aip_agents/tools/memory_search/mem0.py +258 -0
  454. aip_agents/tools/memory_search/mem0.pyi +19 -0
  455. aip_agents/tools/memory_search/schema.py +48 -0
  456. aip_agents/tools/memory_search/schema.pyi +15 -0
  457. aip_agents/tools/memory_search_tool.py +26 -0
  458. aip_agents/tools/memory_search_tool.pyi +3 -0
  459. aip_agents/tools/time_tool.py +117 -0
  460. aip_agents/tools/time_tool.pyi +16 -0
  461. aip_agents/tools/tool_config_injector.py +300 -0
  462. aip_agents/tools/tool_config_injector.pyi +26 -0
  463. aip_agents/tools/web_search/__init__.py +15 -0
  464. aip_agents/tools/web_search/__init__.pyi +3 -0
  465. aip_agents/tools/web_search/serper_tool.py +187 -0
  466. aip_agents/tools/web_search/serper_tool.pyi +19 -0
  467. aip_agents/types/__init__.py +70 -0
  468. aip_agents/types/__init__.pyi +36 -0
  469. aip_agents/types/a2a_events.py +13 -0
  470. aip_agents/types/a2a_events.pyi +3 -0
  471. aip_agents/utils/__init__.py +79 -0
  472. aip_agents/utils/__init__.pyi +11 -0
  473. aip_agents/utils/a2a_connector.py +1757 -0
  474. aip_agents/utils/a2a_connector.pyi +146 -0
  475. aip_agents/utils/artifact_helpers.py +502 -0
  476. aip_agents/utils/artifact_helpers.pyi +203 -0
  477. aip_agents/utils/constants.py +22 -0
  478. aip_agents/utils/constants.pyi +10 -0
  479. aip_agents/utils/datetime/__init__.py +34 -0
  480. aip_agents/utils/datetime/__init__.pyi +4 -0
  481. aip_agents/utils/datetime/normalization.py +231 -0
  482. aip_agents/utils/datetime/normalization.pyi +95 -0
  483. aip_agents/utils/datetime/timezone.py +206 -0
  484. aip_agents/utils/datetime/timezone.pyi +48 -0
  485. aip_agents/utils/env_loader.py +27 -0
  486. aip_agents/utils/env_loader.pyi +10 -0
  487. aip_agents/utils/event_handler_registry.py +58 -0
  488. aip_agents/utils/event_handler_registry.pyi +23 -0
  489. aip_agents/utils/file_prompt_utils.py +176 -0
  490. aip_agents/utils/file_prompt_utils.pyi +21 -0
  491. aip_agents/utils/final_response_builder.py +211 -0
  492. aip_agents/utils/final_response_builder.pyi +34 -0
  493. aip_agents/utils/formatter_llm_client.py +231 -0
  494. aip_agents/utils/formatter_llm_client.pyi +71 -0
  495. aip_agents/utils/langgraph/__init__.py +19 -0
  496. aip_agents/utils/langgraph/__init__.pyi +3 -0
  497. aip_agents/utils/langgraph/converter.py +128 -0
  498. aip_agents/utils/langgraph/converter.pyi +49 -0
  499. aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
  500. aip_agents/utils/langgraph/tool_managers/__init__.pyi +5 -0
  501. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
  502. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +35 -0
  503. aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
  504. aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +48 -0
  505. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1071 -0
  506. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +56 -0
  507. aip_agents/utils/langgraph/tool_output_management.py +967 -0
  508. aip_agents/utils/langgraph/tool_output_management.pyi +292 -0
  509. aip_agents/utils/logger.py +195 -0
  510. aip_agents/utils/logger.pyi +60 -0
  511. aip_agents/utils/metadata/__init__.py +27 -0
  512. aip_agents/utils/metadata/__init__.pyi +5 -0
  513. aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
  514. aip_agents/utils/metadata/activity_metadata_helper.pyi +25 -0
  515. aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
  516. aip_agents/utils/metadata/activity_narrative/__init__.pyi +7 -0
  517. aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
  518. aip_agents/utils/metadata/activity_narrative/builder.pyi +35 -0
  519. aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
  520. aip_agents/utils/metadata/activity_narrative/constants.pyi +10 -0
  521. aip_agents/utils/metadata/activity_narrative/context.py +49 -0
  522. aip_agents/utils/metadata/activity_narrative/context.pyi +32 -0
  523. aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
  524. aip_agents/utils/metadata/activity_narrative/formatters.pyi +48 -0
  525. aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
  526. aip_agents/utils/metadata/activity_narrative/utils.pyi +12 -0
  527. aip_agents/utils/metadata/schemas/__init__.py +16 -0
  528. aip_agents/utils/metadata/schemas/__init__.pyi +4 -0
  529. aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
  530. aip_agents/utils/metadata/schemas/activity_schema.pyi +18 -0
  531. aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
  532. aip_agents/utils/metadata/schemas/thinking_schema.pyi +20 -0
  533. aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
  534. aip_agents/utils/metadata/thinking_metadata_helper.pyi +4 -0
  535. aip_agents/utils/metadata_helper.py +358 -0
  536. aip_agents/utils/metadata_helper.pyi +117 -0
  537. aip_agents/utils/name_preprocessor/__init__.py +17 -0
  538. aip_agents/utils/name_preprocessor/__init__.pyi +6 -0
  539. aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
  540. aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +52 -0
  541. aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
  542. aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +38 -0
  543. aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
  544. aip_agents/utils/name_preprocessor/name_preprocessor.pyi +41 -0
  545. aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
  546. aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +34 -0
  547. aip_agents/utils/pii/__init__.py +25 -0
  548. aip_agents/utils/pii/__init__.pyi +5 -0
  549. aip_agents/utils/pii/pii_handler.py +397 -0
  550. aip_agents/utils/pii/pii_handler.pyi +96 -0
  551. aip_agents/utils/pii/pii_helper.py +207 -0
  552. aip_agents/utils/pii/pii_helper.pyi +78 -0
  553. aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
  554. aip_agents/utils/pii/uuid_deanonymizer_mapping.pyi +73 -0
  555. aip_agents/utils/reference_helper.py +273 -0
  556. aip_agents/utils/reference_helper.pyi +81 -0
  557. aip_agents/utils/sse_chunk_transformer.py +831 -0
  558. aip_agents/utils/sse_chunk_transformer.pyi +166 -0
  559. aip_agents/utils/step_limit_manager.py +265 -0
  560. aip_agents/utils/step_limit_manager.pyi +112 -0
  561. aip_agents/utils/token_usage_helper.py +156 -0
  562. aip_agents/utils/token_usage_helper.pyi +60 -0
  563. aip_agents_binary-0.5.25b1.dist-info/METADATA +681 -0
  564. aip_agents_binary-0.5.25b1.dist-info/RECORD +566 -0
  565. aip_agents_binary-0.5.25b1.dist-info/WHEEL +5 -0
  566. aip_agents_binary-0.5.25b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,76 @@
1
+ """Session management for browser-use framework.
2
+
3
+ Authors:
4
+ Reinhart Linanda (reinhart.linanda@gdplabs.id)
5
+
6
+ References:
7
+ https://github.com/browser-use/browser-use/blob/0.5.9/browser_use/browser/session.py
8
+ """
9
+
10
+ import asyncio
11
+
12
+ from browser_use.agent.views import DOMElementNode
13
+ from browser_use.browser.session import BrowserSession as BrowserUseSession
14
+ from browser_use.browser.session import require_healthy_browser
15
+ from browser_use.browser.views import BrowserError
16
+ from browser_use.observability import observe_debug
17
+ from browser_use.utils import _log_pretty_url, time_execution_async
18
+
19
+
20
+ class BrowserSession(BrowserUseSession):
21
+ """Represents an active browser session with a running browser process somewhere."""
22
+
23
+ @require_healthy_browser(usable_page=True, reopen_page=True)
24
+ @time_execution_async("--input_text_element_node")
25
+ @observe_debug(ignore_input=True, name="input_text_element_node")
26
+ async def _input_text_element_node(self, element_node: DOMElementNode, text: str):
27
+ """Input text into an element with proper error handling and state management.
28
+
29
+ Args:
30
+ element_node (DOMElementNode): The element node to input text into.
31
+ text (str): The text to input into the element.
32
+ """
33
+ try:
34
+ element_handle = await self.get_locate_element(element_node)
35
+
36
+ if element_handle is None:
37
+ raise BrowserError(f"Element: {repr(element_node)} not found")
38
+
39
+ # Ensure element is ready for input
40
+ try:
41
+ await element_handle.wait_for_element_state("stable", timeout=1_000)
42
+ is_visible = await self._is_visible(element_handle)
43
+ if is_visible:
44
+ await element_handle.scroll_into_view_if_needed(timeout=1_000)
45
+ except Exception as state_error:
46
+ self.logger.debug(
47
+ "Skipping pre-input visibility preparation for %s due to %s",
48
+ repr(element_node),
49
+ state_error,
50
+ )
51
+
52
+ # let's first try to click and type
53
+ try:
54
+ await element_handle.evaluate('el => {el.textContent = ""; el.value = "";}')
55
+ await element_handle.click()
56
+ await asyncio.sleep(0.1) # Increased sleep time
57
+ page = await self.get_current_page()
58
+ await page.keyboard.insert_text(text)
59
+ return
60
+ except Exception as e:
61
+ self.logger.debug(f"Input text with click and type failed, trying element handle method: {e}")
62
+ # fall through to BrowserUseSession fallback below
63
+
64
+ except Exception as e:
65
+ # Get current page URL safely for error message
66
+ try:
67
+ page = await self.get_current_page()
68
+ page_url = _log_pretty_url(page.url)
69
+ except Exception:
70
+ page_url = "unknown page"
71
+
72
+ self.logger.debug(
73
+ f"❌ Failed to input text into element: {repr(element_node)} "
74
+ f"on page {page_url}: {type(e).__name__}: {e}"
75
+ )
76
+ raise BrowserError(f"Failed to input text into index {element_node.highlight_index}") from e
@@ -0,0 +1,4 @@
1
+ from browser_use.browser.session import BrowserSession as BrowserUseSession
2
+
3
+ class BrowserSession(BrowserUseSession):
4
+ """Represents an active browser session with a running browser process somewhere."""
@@ -0,0 +1,132 @@
1
+ """Centralized Steel/browser session error policies used by BrowserUseTool.
2
+
3
+ Authors:
4
+ Raymond Christopher (raymond.christopher@gdplabs.id)
5
+ """
6
+
7
+ from collections.abc import Iterable
8
+ from dataclasses import dataclass
9
+
10
+
11
+ @dataclass(frozen=True)
12
+ class SessionErrorCategory:
13
+ """Represents a fatal Steel/browser disconnect classification."""
14
+
15
+ name: str
16
+ markers: tuple[str, ...]
17
+ fatal: bool
18
+ retryable: bool
19
+
20
+
21
+ _FATAL_SESSION_ERROR_CATEGORIES: tuple[SessionErrorCategory, ...] = (
22
+ SessionErrorCategory(
23
+ name="browser_closed",
24
+ markers=(
25
+ "browser has been closed",
26
+ "target page, context or browser has been closed",
27
+ ),
28
+ fatal=True,
29
+ retryable=True,
30
+ ),
31
+ SessionErrorCategory(
32
+ name="websocket_disconnect",
33
+ markers=(
34
+ "code=1006",
35
+ "websocket was closed before the connection was established",
36
+ "websocket error",
37
+ ),
38
+ fatal=True,
39
+ retryable=True,
40
+ ),
41
+ )
42
+
43
+ _WARNING_MARKERS: dict[str, str] = {
44
+ "502 bad gateway": "page_load_warning",
45
+ "page link: about:blank": "blank_page_warning",
46
+ "no webpage content": "blank_page_warning",
47
+ "scroll_into_view_if_needed": "element_interaction_warning",
48
+ }
49
+
50
+ _FATAL_LOOKUP: dict[str, SessionErrorCategory] = {
51
+ marker.lower(): category for category in _FATAL_SESSION_ERROR_CATEGORIES for marker in category.markers
52
+ }
53
+
54
+
55
+ def categorize_fatal_message(message: str) -> SessionErrorCategory | None:
56
+ """Return the fatal session category associated with the given message, if any.
57
+
58
+ Args:
59
+ message: The error message to categorize.
60
+
61
+ Returns:
62
+ The SessionErrorCategory if the message matches a fatal error pattern,
63
+ None otherwise.
64
+ """
65
+ if not message:
66
+ return None
67
+
68
+ lowered = message.lower()
69
+ for marker, category in _FATAL_LOOKUP.items():
70
+ if marker in lowered:
71
+ return category
72
+ return None
73
+
74
+
75
+ def categorize_warning_message(message: str) -> str | None:
76
+ """Return the name of a known non-fatal warning when present in the message.
77
+
78
+ Args:
79
+ message: The error message to check for warning patterns.
80
+
81
+ Returns:
82
+ The warning name if the message matches a known warning pattern,
83
+ None otherwise.
84
+ """
85
+ if not message:
86
+ return None
87
+
88
+ lowered = message.lower()
89
+ for marker, warning_name in _WARNING_MARKERS.items():
90
+ if marker in lowered:
91
+ return warning_name
92
+ return None
93
+
94
+
95
+ def find_fatal_message(messages: Iterable[str]) -> tuple[str, SessionErrorCategory] | None:
96
+ """Return the first fatal message detected in the iterable.
97
+
98
+ Args:
99
+ messages: An iterable of error messages to search through.
100
+
101
+ Returns:
102
+ A tuple of (message, category) for the first fatal message found,
103
+ None if no fatal messages are detected.
104
+ """
105
+ for message in messages:
106
+ category = categorize_fatal_message(message)
107
+ if category:
108
+ return message, category
109
+ return None
110
+
111
+
112
+ def is_recoverable_message(message: str) -> bool:
113
+ """Return True when the message maps to a retryable session disconnect.
114
+
115
+ Args:
116
+ message: The error message to check for recoverability.
117
+
118
+ Returns:
119
+ True if the message corresponds to a retryable fatal error,
120
+ False otherwise.
121
+ """
122
+ category = categorize_fatal_message(message)
123
+ return bool(category and category.retryable)
124
+
125
+
126
+ __all__ = [
127
+ "SessionErrorCategory",
128
+ "categorize_fatal_message",
129
+ "categorize_warning_message",
130
+ "find_fatal_message",
131
+ "is_recoverable_message",
132
+ ]
@@ -0,0 +1,53 @@
1
+ from collections.abc import Iterable
2
+ from dataclasses import dataclass
3
+
4
+ __all__ = ['SessionErrorCategory', 'categorize_fatal_message', 'categorize_warning_message', 'find_fatal_message', 'is_recoverable_message']
5
+
6
+ @dataclass(frozen=True)
7
+ class SessionErrorCategory:
8
+ """Represents a fatal Steel/browser disconnect classification."""
9
+ name: str
10
+ markers: tuple[str, ...]
11
+ fatal: bool
12
+ retryable: bool
13
+
14
+ def categorize_fatal_message(message: str) -> SessionErrorCategory | None:
15
+ """Return the fatal session category associated with the given message, if any.
16
+
17
+ Args:
18
+ message: The error message to categorize.
19
+
20
+ Returns:
21
+ The SessionErrorCategory if the message matches a fatal error pattern,
22
+ None otherwise.
23
+ """
24
+ def categorize_warning_message(message: str) -> str | None:
25
+ """Return the name of a known non-fatal warning when present in the message.
26
+
27
+ Args:
28
+ message: The error message to check for warning patterns.
29
+
30
+ Returns:
31
+ The warning name if the message matches a known warning pattern,
32
+ None otherwise.
33
+ """
34
+ def find_fatal_message(messages: Iterable[str]) -> tuple[str, SessionErrorCategory] | None:
35
+ """Return the first fatal message detected in the iterable.
36
+
37
+ Args:
38
+ messages: An iterable of error messages to search through.
39
+
40
+ Returns:
41
+ A tuple of (message, category) for the first fatal message found,
42
+ None if no fatal messages are detected.
43
+ """
44
+ def is_recoverable_message(message: str) -> bool:
45
+ """Return True when the message maps to a retryable session disconnect.
46
+
47
+ Args:
48
+ message: The error message to check for recoverability.
49
+
50
+ Returns:
51
+ True if the message corresponds to a retryable fatal error,
52
+ False otherwise.
53
+ """
@@ -0,0 +1,317 @@
1
+ """Steel session recording helper built on Steel's HLS exports.
2
+
3
+ This module downloads Steel session HLS manifests, merges the associated
4
+ segments into a single MP4 file, and uploads the result to MinIO storage.
5
+ It replaces the earlier rrweb + Playwright conversion pipeline.
6
+
7
+ Authors:
8
+ Reinhart Linanda (reinhart.linanda@gdplabs.id)
9
+ """
10
+
11
+ import asyncio
12
+ import re
13
+ import shutil
14
+ import tempfile
15
+ import time
16
+ from io import BufferedWriter
17
+ from pathlib import Path
18
+ from urllib.parse import urljoin
19
+
20
+ import requests
21
+ from dotenv import load_dotenv
22
+
23
+ from aip_agents.tools.browser_use.minio_storage import MinIOStorage
24
+ from aip_agents.utils.logger import get_logger
25
+
26
+ load_dotenv()
27
+
28
+ logger = get_logger(__name__)
29
+
30
+ VIDEO_FILE_NAME_PREFIX = "session_"
31
+ MANIFEST_TEMP_SUFFIX = ".m3u8"
32
+
33
+
34
+ class SteelSessionRecorder:
35
+ """High-level helper to export Steel sessions via their HLS manifests.
36
+
37
+ This class provides a high-level interface for exporting Steel sessions via their HLS manifests.
38
+ It provides methods for sanitizing session IDs, building safe filenames, and generating video filenames.
39
+ It also provides methods for downloading and merging HLS manifests, and uploading videos to MinIO.
40
+ """
41
+
42
+ @staticmethod
43
+ def safe_session_id(session_id: str) -> str:
44
+ """Sanitize a session ID for filename usage.
45
+
46
+ Args:
47
+ session_id: The session ID to sanitize.
48
+
49
+ Returns:
50
+ str: The sanitized session ID.
51
+ """
52
+ return "".join(c for c in session_id if c.isalnum() or c in ("-", "_"))
53
+
54
+ @staticmethod
55
+ def safe_session_filename(session_id: str, extension: str) -> str:
56
+ """Build a safe filename for a session recording.
57
+
58
+ Args:
59
+ session_id: The session ID to build a filename for.
60
+ extension: The extension of the filename.
61
+
62
+ Returns:
63
+ str: The safe filename.
64
+ """
65
+ safe_id = SteelSessionRecorder.safe_session_id(session_id)
66
+ return f"{VIDEO_FILE_NAME_PREFIX}{safe_id}{extension}"
67
+
68
+ @staticmethod
69
+ def generate_video_filename(session_id: str, extension: str = ".mp4") -> str:
70
+ """Generate a filename for a session recording.
71
+
72
+ Args:
73
+ session_id: The session ID to generate a filename for.
74
+ extension: The extension of the filename.
75
+
76
+ Returns:
77
+ str: The generated filename.
78
+ """
79
+ normalized_extension = extension if extension.startswith(".") else f".{extension}"
80
+ return SteelSessionRecorder.safe_session_filename(session_id, normalized_extension)
81
+
82
+ @staticmethod
83
+ def _parse_manifest_entries(manifest_text: str, manifest_url: str) -> tuple[str | None, list[str]]:
84
+ """Parse manifest lines into init segment and media segment URLs.
85
+
86
+ Args:
87
+ manifest_text: The text of the manifest.
88
+ manifest_url: The URL of the manifest.
89
+
90
+ Returns:
91
+ tuple[str | None, list[str]]: The init segment URL and the list of media segment URLs.
92
+ """
93
+ init_url = None
94
+ segments: list[str] = []
95
+
96
+ for line in manifest_text.splitlines():
97
+ line = line.strip()
98
+ if not line:
99
+ continue
100
+
101
+ if not line.startswith("#"):
102
+ segments.append(urljoin(manifest_url, line))
103
+ continue
104
+
105
+ if line.startswith("#EXT-X-MAP"):
106
+ match = re.search(r'URI="([^"]+)"', line)
107
+ if match:
108
+ init_url = match.group(1)
109
+
110
+ if init_url:
111
+ init_url = urljoin(manifest_url, init_url)
112
+
113
+ return init_url, segments
114
+
115
+ @staticmethod
116
+ def _stream_url(session: requests.Session, url: str, headers: dict[str, str], output_file: BufferedWriter) -> None:
117
+ """Stream data from a URL into a buffered writer.
118
+
119
+ Args:
120
+ session: The requests session to use.
121
+ url: The URL to stream from.
122
+ headers: The headers to use.
123
+ output_file: The buffered writer to write the data to.
124
+ """
125
+ with session.get(url, headers=headers, stream=True, timeout=120) as resp:
126
+ resp.raise_for_status()
127
+
128
+ # Validate content type
129
+ content_type = resp.headers.get("content-type", "")
130
+ if not content_type.startswith(("video/", "application/octet-stream")):
131
+ logger.warning("Unexpected content type: %s", content_type)
132
+ return
133
+
134
+ for chunk in resp.iter_content(chunk_size=64 * 1024):
135
+ if chunk:
136
+ output_file.write(chunk)
137
+
138
+ @staticmethod
139
+ def _cleanup_temp_directory(video_dir: str) -> None:
140
+ """Clean up the temporary directory.
141
+
142
+ Args:
143
+ video_dir: The directory to clean up.
144
+ """
145
+ try:
146
+ shutil.rmtree(video_dir)
147
+ except OSError:
148
+ pass
149
+
150
+ def __init__(self, base_url: str, api_key: str):
151
+ """Initialize the recorder.
152
+
153
+ Args:
154
+ base_url: Steel API base URL.
155
+ api_key: Steel API key for authentication.
156
+ """
157
+ self.base_url = base_url
158
+ self.api_key = api_key
159
+
160
+ self._manifest_poll_timeout_minutes = 1
161
+ self._manifest_poll_interval_seconds = 2
162
+
163
+ try:
164
+ self.minio_storage = MinIOStorage()
165
+ except Exception as exc:
166
+ logger.warning("Failed to initialize MinIO storage: %s", exc)
167
+ self.minio_storage = None
168
+
169
+ def _download_manifest(self, session_id: str, dest: Path) -> str | None:
170
+ """Download the Steel HLS manifest for a session.
171
+
172
+ Args:
173
+ session_id: The session ID to download the manifest for.
174
+ dest: The destination path to save the manifest to.
175
+
176
+ Returns:
177
+ str | None: The URL of the manifest, or None if the base URL or API key is not set.
178
+
179
+ Raises:
180
+ requests.exceptions.RequestException: If the manifest is not ready after the timeout.
181
+ """
182
+ if not self.base_url or not self.api_key:
183
+ logger.warning("Base URL or API key not set, skipping download for session %s", session_id)
184
+ return None
185
+
186
+ url = f"{self.base_url.rstrip('/')}/v1/sessions/{session_id}/hls"
187
+ headers = {"steel-api-key": self.api_key}
188
+
189
+ deadline = time.monotonic() + (self._manifest_poll_timeout_minutes * 60)
190
+ attempt = 0
191
+ while True:
192
+ response = requests.get(url, headers=headers, timeout=60)
193
+ if response.ok:
194
+ dest.write_text(response.text)
195
+ return response.url
196
+
197
+ pollable = response.status_code in {404, 408, 429, 503}
198
+ attempt += 1
199
+ if not pollable or time.monotonic() >= deadline:
200
+ logger.warning(
201
+ "Manifest not ready for session %s after %.1f minutes, last status %d",
202
+ session_id,
203
+ self._manifest_poll_timeout_minutes,
204
+ response.status_code,
205
+ )
206
+ response.raise_for_status()
207
+
208
+ logger.debug(
209
+ "Manifest not ready for session %s (attempt %d, status %d); waiting %.1f seconds",
210
+ session_id,
211
+ attempt,
212
+ response.status_code,
213
+ self._manifest_poll_interval_seconds,
214
+ )
215
+ time.sleep(self._manifest_poll_interval_seconds)
216
+
217
+ def _merge_segments(self, manifest_path: Path, manifest_url: str, output_path: Path) -> bool:
218
+ """Merge HLS segments defined in a manifest into a single video file.
219
+
220
+ Args:
221
+ manifest_path: The path to the manifest.
222
+ manifest_url: The URL of the manifest.
223
+ output_path: The path to save the merged video to.
224
+
225
+ Returns:
226
+ bool: True if the segments were merged successfully, False otherwise.
227
+ """
228
+ if not self.api_key:
229
+ logger.warning("API key not set, skipping merge for session %s", manifest_url)
230
+ return False
231
+
232
+ headers = {"steel-api-key": self.api_key}
233
+ manifest_text = manifest_path.read_text()
234
+ init_url, segments = SteelSessionRecorder._parse_manifest_entries(manifest_text, manifest_url)
235
+
236
+ if not init_url or not segments:
237
+ logger.warning("No media segments found in manifest.")
238
+ return False
239
+
240
+ output_path.parent.mkdir(parents=True, exist_ok=True)
241
+
242
+ with requests.Session() as session, open(output_path, "wb") as output_file:
243
+ if init_url:
244
+ SteelSessionRecorder._stream_url(session, init_url, headers, output_file)
245
+
246
+ for segment_url in segments:
247
+ SteelSessionRecorder._stream_url(session, segment_url, headers, output_file)
248
+
249
+ return True
250
+
251
+ async def _download_and_merge_manifest(self, session_id: str, output_path: Path) -> bool:
252
+ """Download and merge the Steel HLS manifest into a single file.
253
+
254
+ Args:
255
+ session_id: The session ID to download the manifest for.
256
+ output_path: The path to save the merged video to.
257
+
258
+ Returns:
259
+ bool: True if the manifest was downloaded and merged successfully, False otherwise.
260
+ """
261
+ manifest_path = Path(tempfile.NamedTemporaryFile(suffix=MANIFEST_TEMP_SUFFIX, delete=False).name)
262
+
263
+ try:
264
+ manifest_url = await asyncio.to_thread(self._download_manifest, session_id, manifest_path)
265
+ if not manifest_url:
266
+ logger.warning("Failed to download manifest for session %s", session_id)
267
+ return False
268
+
269
+ merged = await asyncio.to_thread(self._merge_segments, manifest_path, manifest_url, output_path)
270
+ if not merged:
271
+ logger.warning("Failed to merge segments for session %s", session_id)
272
+ return False
273
+
274
+ return True
275
+ except Exception as exc:
276
+ logger.warning(
277
+ "Failed to generate video from HLS manifest for session %s: %s", session_id, exc, exc_info=True
278
+ )
279
+ return False
280
+ finally:
281
+ manifest_path.unlink(missing_ok=True)
282
+
283
+ async def _upload_video_to_minio(self, video_path: Path, video_filename: str) -> None:
284
+ """Upload a video file to MinIO storage.
285
+
286
+ Args:
287
+ video_path: The path to the video file to upload.
288
+ video_filename: The filename of the video to upload.
289
+ """
290
+ if not video_path.exists():
291
+ logger.warning("Video file not found: %s", video_path)
292
+ return
293
+
294
+ await asyncio.to_thread(self.minio_storage.upload_file, str(video_path), video_filename)
295
+
296
+ async def record_session_to_video(self, session_id: str) -> None:
297
+ """Download the HLS manifest and upload the merged video to MinIO.
298
+
299
+ Args:
300
+ session_id: The session ID to record.
301
+ """
302
+ if not self.minio_storage:
303
+ logger.warning("MinIO storage not available, skipping recording for %s", session_id)
304
+ return
305
+
306
+ video_dir = tempfile.mkdtemp()
307
+ try:
308
+ video_filename = SteelSessionRecorder.generate_video_filename(session_id, extension=".mp4")
309
+ output_path = Path(video_dir) / video_filename
310
+ merged = await self._download_and_merge_manifest(session_id, output_path)
311
+ if not merged:
312
+ logger.warning("Skipping upload because manifest merge failed for session %s", session_id)
313
+ return
314
+
315
+ await self._upload_video_to_minio(output_path, video_filename)
316
+ finally:
317
+ SteelSessionRecorder._cleanup_temp_directory(video_dir)
@@ -0,0 +1,63 @@
1
+ from _typeshed import Incomplete
2
+ from aip_agents.tools.browser_use.minio_storage import MinIOStorage as MinIOStorage
3
+ from aip_agents.utils.logger import get_logger as get_logger
4
+
5
+ logger: Incomplete
6
+ VIDEO_FILE_NAME_PREFIX: str
7
+ MANIFEST_TEMP_SUFFIX: str
8
+
9
+ class SteelSessionRecorder:
10
+ """High-level helper to export Steel sessions via their HLS manifests.
11
+
12
+ This class provides a high-level interface for exporting Steel sessions via their HLS manifests.
13
+ It provides methods for sanitizing session IDs, building safe filenames, and generating video filenames.
14
+ It also provides methods for downloading and merging HLS manifests, and uploading videos to MinIO.
15
+ """
16
+ @staticmethod
17
+ def safe_session_id(session_id: str) -> str:
18
+ """Sanitize a session ID for filename usage.
19
+
20
+ Args:
21
+ session_id: The session ID to sanitize.
22
+
23
+ Returns:
24
+ str: The sanitized session ID.
25
+ """
26
+ @staticmethod
27
+ def safe_session_filename(session_id: str, extension: str) -> str:
28
+ """Build a safe filename for a session recording.
29
+
30
+ Args:
31
+ session_id: The session ID to build a filename for.
32
+ extension: The extension of the filename.
33
+
34
+ Returns:
35
+ str: The safe filename.
36
+ """
37
+ @staticmethod
38
+ def generate_video_filename(session_id: str, extension: str = '.mp4') -> str:
39
+ """Generate a filename for a session recording.
40
+
41
+ Args:
42
+ session_id: The session ID to generate a filename for.
43
+ extension: The extension of the filename.
44
+
45
+ Returns:
46
+ str: The generated filename.
47
+ """
48
+ base_url: Incomplete
49
+ api_key: Incomplete
50
+ minio_storage: Incomplete
51
+ def __init__(self, base_url: str, api_key: str) -> None:
52
+ """Initialize the recorder.
53
+
54
+ Args:
55
+ base_url: Steel API base URL.
56
+ api_key: Steel API key for authentication.
57
+ """
58
+ async def record_session_to_video(self, session_id: str) -> None:
59
+ """Download the HLS manifest and upload the merged video to MinIO.
60
+
61
+ Args:
62
+ session_id: The session ID to record.
63
+ """