aip-agents-binary 0.0.0b2__py3-none-any.whl → 0.5.11__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 (506) 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 +1 -1
  5. aip_agents/a2a/server/__init__.py +10 -0
  6. aip_agents/a2a/server/base_executor.py +1086 -0
  7. aip_agents/a2a/server/base_executor.pyi +16 -6
  8. aip_agents/a2a/server/google_adk_executor.py +198 -0
  9. aip_agents/a2a/server/google_adk_executor.pyi +11 -11
  10. aip_agents/a2a/server/langflow_executor.py +180 -0
  11. aip_agents/a2a/server/langflow_executor.pyi +43 -0
  12. aip_agents/a2a/server/langgraph_executor.py +267 -0
  13. aip_agents/a2a/server/langgraph_executor.pyi +11 -12
  14. aip_agents/a2a/types.py +232 -0
  15. aip_agents/a2a/types.pyi +54 -47
  16. aip_agents/agent/__init__.py +27 -0
  17. aip_agents/agent/__init__.pyi +3 -1
  18. aip_agents/agent/base_agent.py +970 -0
  19. aip_agents/agent/base_agent.pyi +24 -8
  20. aip_agents/agent/base_langgraph_agent.py +2942 -0
  21. aip_agents/agent/base_langgraph_agent.pyi +93 -25
  22. aip_agents/agent/google_adk_agent.py +926 -0
  23. aip_agents/agent/google_adk_agent.pyi +34 -21
  24. aip_agents/agent/google_adk_constants.py +6 -0
  25. aip_agents/agent/google_adk_constants.pyi +3 -0
  26. aip_agents/agent/hitl/__init__.py +24 -0
  27. aip_agents/agent/hitl/__init__.pyi +6 -0
  28. aip_agents/agent/hitl/config.py +28 -0
  29. aip_agents/agent/hitl/config.pyi +15 -0
  30. aip_agents/agent/hitl/langgraph_hitl_mixin.py +515 -0
  31. aip_agents/agent/hitl/langgraph_hitl_mixin.pyi +42 -0
  32. aip_agents/agent/hitl/manager.py +522 -0
  33. aip_agents/agent/hitl/manager.pyi +199 -0
  34. aip_agents/agent/hitl/models.py +18 -0
  35. aip_agents/agent/hitl/models.pyi +3 -0
  36. aip_agents/agent/hitl/prompt/__init__.py +9 -0
  37. aip_agents/agent/hitl/prompt/__init__.pyi +4 -0
  38. aip_agents/agent/hitl/prompt/base.py +42 -0
  39. aip_agents/agent/hitl/prompt/base.pyi +24 -0
  40. aip_agents/agent/hitl/prompt/deferred.py +73 -0
  41. aip_agents/agent/hitl/prompt/deferred.pyi +30 -0
  42. aip_agents/agent/interface.py +138 -0
  43. aip_agents/agent/interface.pyi +5 -5
  44. aip_agents/agent/interfaces.py +65 -0
  45. aip_agents/agent/interfaces.pyi +44 -0
  46. aip_agents/agent/langflow_agent.py +464 -0
  47. aip_agents/agent/langflow_agent.pyi +133 -0
  48. aip_agents/agent/langgraph_memory_enhancer_agent.py +433 -0
  49. aip_agents/agent/langgraph_memory_enhancer_agent.pyi +49 -0
  50. aip_agents/agent/langgraph_react_agent.py +2514 -0
  51. aip_agents/agent/langgraph_react_agent.pyi +51 -56
  52. aip_agents/agent/system_instruction_context.py +34 -0
  53. aip_agents/agent/system_instruction_context.pyi +13 -0
  54. aip_agents/clients/__init__.py +10 -0
  55. aip_agents/clients/__init__.pyi +4 -0
  56. aip_agents/clients/langflow/__init__.py +10 -0
  57. aip_agents/clients/langflow/__init__.pyi +4 -0
  58. aip_agents/clients/langflow/client.py +477 -0
  59. aip_agents/clients/langflow/client.pyi +140 -0
  60. aip_agents/clients/langflow/types.py +18 -0
  61. aip_agents/clients/langflow/types.pyi +7 -0
  62. aip_agents/constants.py +23 -0
  63. aip_agents/constants.pyi +1 -0
  64. aip_agents/credentials/manager.py +132 -0
  65. aip_agents/examples/__init__.py +5 -0
  66. aip_agents/examples/compare_streaming_client.py +783 -0
  67. aip_agents/examples/compare_streaming_client.pyi +48 -0
  68. aip_agents/examples/compare_streaming_server.py +142 -0
  69. aip_agents/examples/compare_streaming_server.pyi +18 -0
  70. aip_agents/examples/demo_memory_recall.py +401 -0
  71. aip_agents/examples/demo_memory_recall.pyi +58 -0
  72. aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
  73. aip_agents/examples/hello_world_a2a_google_adk_client.pyi +2 -2
  74. aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
  75. aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +2 -2
  76. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
  77. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +2 -2
  78. aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
  79. aip_agents/examples/hello_world_a2a_google_adk_server.pyi +7 -2
  80. aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
  81. aip_agents/examples/hello_world_a2a_langchain_client.pyi +1 -1
  82. aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
  83. aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +1 -1
  84. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
  85. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +1 -1
  86. aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
  87. aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +1 -1
  88. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
  89. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +1 -1
  90. aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
  91. aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +8 -3
  92. aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
  93. aip_agents/examples/hello_world_a2a_langchain_server.pyi +7 -2
  94. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
  95. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +7 -2
  96. aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
  97. aip_agents/examples/hello_world_a2a_langflow_client.pyi +9 -0
  98. aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
  99. aip_agents/examples/hello_world_a2a_langflow_server.pyi +14 -0
  100. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
  101. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +1 -1
  102. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
  103. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +1 -1
  104. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
  105. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +7 -2
  106. aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
  107. aip_agents/examples/hello_world_a2a_langgraph_client.pyi +2 -2
  108. aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
  109. aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +2 -2
  110. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
  111. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +1 -1
  112. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
  113. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +3 -3
  114. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
  115. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +1 -1
  116. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
  117. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +1 -1
  118. aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
  119. aip_agents/examples/hello_world_a2a_langgraph_server.pyi +7 -2
  120. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
  121. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +7 -2
  122. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
  123. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +7 -2
  124. aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
  125. aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +1 -1
  126. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
  127. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +31 -6
  128. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +251 -0
  129. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +33 -5
  130. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
  131. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +1 -1
  132. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
  133. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +7 -2
  134. aip_agents/examples/hello_world_google_adk.py +41 -0
  135. aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
  136. aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
  137. aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
  138. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
  139. aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
  140. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
  141. aip_agents/examples/hello_world_google_adk_stream.py +44 -0
  142. aip_agents/examples/hello_world_langchain.py +28 -0
  143. aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
  144. aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
  145. aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
  146. aip_agents/examples/hello_world_langchain_mcp_http_interactive.pyi +16 -0
  147. aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
  148. aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
  149. aip_agents/examples/hello_world_langchain_mcp_multi_server.pyi +18 -0
  150. aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
  151. aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
  152. aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
  153. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
  154. aip_agents/examples/hello_world_langchain_stream.py +36 -0
  155. aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
  156. aip_agents/examples/hello_world_langflow_agent.py +163 -0
  157. aip_agents/examples/hello_world_langflow_agent.pyi +35 -0
  158. aip_agents/examples/hello_world_langgraph.py +39 -0
  159. aip_agents/examples/hello_world_langgraph_bosa_twitter.py +41 -0
  160. aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
  161. aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
  162. aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
  163. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
  164. aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
  165. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
  166. aip_agents/examples/hello_world_langgraph_stream.py +43 -0
  167. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
  168. aip_agents/examples/hello_world_model_switch_cli.py +210 -0
  169. aip_agents/examples/hello_world_model_switch_cli.pyi +18 -3
  170. aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
  171. aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
  172. aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
  173. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
  174. aip_agents/examples/hello_world_pii_logger.py +21 -0
  175. aip_agents/examples/hello_world_pii_logger.pyi +1 -1
  176. aip_agents/examples/hello_world_sentry.py +133 -0
  177. aip_agents/examples/hello_world_sentry.pyi +1 -1
  178. aip_agents/examples/hello_world_step_limits.py +273 -0
  179. aip_agents/examples/hello_world_step_limits.pyi +17 -0
  180. aip_agents/examples/hello_world_stock_a2a_server.py +103 -0
  181. aip_agents/examples/hello_world_stock_a2a_server.pyi +7 -2
  182. aip_agents/examples/hello_world_tool_output_client.py +46 -0
  183. aip_agents/examples/hello_world_tool_output_client.pyi +1 -1
  184. aip_agents/examples/hello_world_tool_output_server.py +114 -0
  185. aip_agents/examples/hello_world_tool_output_server.pyi +7 -2
  186. aip_agents/examples/hitl_demo.py +724 -0
  187. aip_agents/examples/hitl_demo.pyi +67 -0
  188. aip_agents/examples/mcp_configs/configs.py +63 -0
  189. aip_agents/examples/mcp_servers/common.py +76 -0
  190. aip_agents/examples/mcp_servers/mcp_name.py +29 -0
  191. aip_agents/examples/mcp_servers/mcp_server_http.py +19 -0
  192. aip_agents/examples/mcp_servers/mcp_server_sse.py +19 -0
  193. aip_agents/examples/mcp_servers/mcp_server_stdio.py +19 -0
  194. aip_agents/examples/mcp_servers/mcp_time.py +10 -0
  195. aip_agents/examples/pii_demo_langgraph_client.py +69 -0
  196. aip_agents/examples/pii_demo_langgraph_client.pyi +5 -0
  197. aip_agents/examples/pii_demo_langgraph_server.py +126 -0
  198. aip_agents/examples/pii_demo_langgraph_server.pyi +20 -0
  199. aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
  200. aip_agents/examples/pii_demo_multi_agent_client.pyi +5 -0
  201. aip_agents/examples/pii_demo_multi_agent_server.py +247 -0
  202. aip_agents/examples/pii_demo_multi_agent_server.pyi +40 -0
  203. aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
  204. aip_agents/examples/todolist_planning_a2a_langchain_client.pyi +5 -0
  205. aip_agents/examples/todolist_planning_a2a_langgraph_server.py +88 -0
  206. aip_agents/examples/todolist_planning_a2a_langgraph_server.pyi +19 -0
  207. aip_agents/examples/tools/__init__.py +27 -0
  208. aip_agents/examples/tools/__init__.pyi +3 -1
  209. aip_agents/examples/tools/adk_arithmetic_tools.py +36 -0
  210. aip_agents/examples/tools/adk_weather_tool.py +60 -0
  211. aip_agents/examples/tools/adk_weather_tool.pyi +1 -1
  212. aip_agents/examples/tools/data_generator_tool.py +103 -0
  213. aip_agents/examples/tools/data_visualization_tool.py +312 -0
  214. aip_agents/examples/tools/data_visualization_tool.pyi +2 -0
  215. aip_agents/examples/tools/image_artifact_tool.py +136 -0
  216. aip_agents/examples/tools/image_artifact_tool.pyi +2 -0
  217. aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
  218. aip_agents/examples/tools/langchain_arithmetic_tools.pyi +7 -0
  219. aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
  220. aip_agents/examples/tools/langchain_currency_exchange_tool.pyi +0 -1
  221. aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
  222. aip_agents/examples/tools/langchain_graph_artifact_tool.pyi +2 -0
  223. aip_agents/examples/tools/langchain_weather_tool.py +48 -0
  224. aip_agents/examples/tools/langchain_weather_tool.pyi +1 -1
  225. aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
  226. aip_agents/examples/tools/langgraph_streaming_tool.pyi +1 -1
  227. aip_agents/examples/tools/mock_retrieval_tool.py +56 -0
  228. aip_agents/examples/tools/mock_retrieval_tool.pyi +13 -0
  229. aip_agents/examples/tools/pii_demo_tools.py +189 -0
  230. aip_agents/examples/tools/pii_demo_tools.pyi +54 -0
  231. aip_agents/examples/tools/random_chart_tool.py +142 -0
  232. aip_agents/examples/tools/random_chart_tool.pyi +20 -0
  233. aip_agents/examples/tools/serper_tool.py +202 -0
  234. aip_agents/examples/tools/stock_tools.py +82 -0
  235. aip_agents/examples/tools/stock_tools.pyi +18 -3
  236. aip_agents/examples/tools/table_generator_tool.py +167 -0
  237. aip_agents/examples/tools/time_tool.py +82 -0
  238. aip_agents/examples/tools/weather_forecast_tool.py +38 -0
  239. aip_agents/executor/agent_executor.py +473 -0
  240. aip_agents/executor/base.py +48 -0
  241. aip_agents/mcp/__init__.py +1 -0
  242. aip_agents/mcp/client/__init__.py +14 -0
  243. aip_agents/mcp/client/__init__.pyi +4 -3
  244. aip_agents/mcp/client/base_mcp_client.py +369 -0
  245. aip_agents/mcp/client/base_mcp_client.pyi +148 -0
  246. aip_agents/mcp/client/connection_manager.py +193 -0
  247. aip_agents/mcp/client/connection_manager.pyi +48 -0
  248. aip_agents/mcp/client/google_adk/__init__.py +11 -0
  249. aip_agents/mcp/client/google_adk/__init__.pyi +1 -1
  250. aip_agents/mcp/client/google_adk/client.py +381 -0
  251. aip_agents/mcp/client/google_adk/client.pyi +50 -13
  252. aip_agents/mcp/client/langchain/__init__.py +11 -0
  253. aip_agents/mcp/client/langchain/__init__.pyi +1 -1
  254. aip_agents/mcp/client/langchain/client.py +265 -0
  255. aip_agents/mcp/client/langchain/client.pyi +47 -2
  256. aip_agents/mcp/client/persistent_session.py +359 -0
  257. aip_agents/mcp/client/persistent_session.pyi +113 -0
  258. aip_agents/mcp/client/session_pool.py +351 -0
  259. aip_agents/mcp/client/session_pool.pyi +101 -0
  260. aip_agents/mcp/client/transports.py +215 -0
  261. aip_agents/mcp/client/transports.pyi +123 -0
  262. aip_agents/mcp/utils/__init__.py +7 -0
  263. aip_agents/mcp/utils/__init__.pyi +0 -0
  264. aip_agents/mcp/utils/config_validator.py +139 -0
  265. aip_agents/mcp/utils/config_validator.pyi +82 -0
  266. aip_agents/memory/__init__.py +14 -0
  267. aip_agents/memory/__init__.pyi +5 -0
  268. aip_agents/memory/adapters/__init__.py +10 -0
  269. aip_agents/memory/adapters/__init__.pyi +4 -0
  270. aip_agents/memory/adapters/base_adapter.py +717 -0
  271. aip_agents/memory/adapters/base_adapter.pyi +150 -0
  272. aip_agents/memory/adapters/mem0.py +84 -0
  273. aip_agents/memory/adapters/mem0.pyi +22 -0
  274. aip_agents/memory/base.py +84 -0
  275. aip_agents/memory/base.pyi +15 -4
  276. aip_agents/memory/constants.py +49 -0
  277. aip_agents/memory/constants.pyi +25 -0
  278. aip_agents/memory/factory.py +86 -0
  279. aip_agents/memory/factory.pyi +24 -0
  280. aip_agents/memory/guidance.py +20 -0
  281. aip_agents/memory/guidance.pyi +3 -0
  282. aip_agents/memory/simple_memory.py +47 -0
  283. aip_agents/memory/simple_memory.pyi +6 -5
  284. aip_agents/middleware/__init__.py +17 -0
  285. aip_agents/middleware/__init__.pyi +5 -0
  286. aip_agents/middleware/base.py +88 -0
  287. aip_agents/middleware/base.pyi +71 -0
  288. aip_agents/middleware/manager.py +128 -0
  289. aip_agents/middleware/manager.pyi +80 -0
  290. aip_agents/middleware/todolist.py +274 -0
  291. aip_agents/middleware/todolist.pyi +125 -0
  292. aip_agents/schema/__init__.py +69 -0
  293. aip_agents/schema/__init__.pyi +9 -0
  294. aip_agents/schema/a2a.py +56 -0
  295. aip_agents/schema/a2a.pyi +40 -0
  296. aip_agents/schema/agent.py +111 -0
  297. aip_agents/schema/agent.pyi +65 -0
  298. aip_agents/schema/hitl.py +157 -0
  299. aip_agents/schema/hitl.pyi +89 -0
  300. aip_agents/schema/langgraph.py +37 -0
  301. aip_agents/schema/langgraph.pyi +28 -0
  302. aip_agents/schema/model_id.py +97 -0
  303. aip_agents/schema/model_id.pyi +54 -0
  304. aip_agents/schema/step_limit.py +108 -0
  305. aip_agents/schema/step_limit.pyi +63 -0
  306. aip_agents/schema/storage.py +40 -0
  307. aip_agents/schema/storage.pyi +21 -0
  308. aip_agents/sentry/__init__.py +11 -0
  309. aip_agents/sentry/__init__.pyi +1 -1
  310. aip_agents/sentry/sentry.py +151 -0
  311. aip_agents/sentry/sentry.pyi +2 -2
  312. aip_agents/storage/__init__.py +41 -0
  313. aip_agents/storage/base.py +85 -0
  314. aip_agents/storage/base.pyi +1 -2
  315. aip_agents/storage/clients/__init__.py +12 -0
  316. aip_agents/storage/clients/minio_client.py +318 -0
  317. aip_agents/storage/config.py +62 -0
  318. aip_agents/storage/config.pyi +9 -46
  319. aip_agents/storage/providers/__init__.py +15 -0
  320. aip_agents/storage/providers/base.py +106 -0
  321. aip_agents/storage/providers/base.pyi +2 -3
  322. aip_agents/storage/providers/memory.py +114 -0
  323. aip_agents/storage/providers/object_storage.py +214 -0
  324. aip_agents/storage/providers/object_storage.pyi +1 -1
  325. aip_agents/tools/__init__.py +6 -0
  326. aip_agents/tools/__init__.pyi +3 -2
  327. aip_agents/tools/bosa_tools.py +105 -0
  328. aip_agents/tools/bosa_tools.pyi +2 -2
  329. aip_agents/tools/browser_use/__init__.py +82 -0
  330. aip_agents/tools/browser_use/__init__.pyi +14 -0
  331. aip_agents/tools/browser_use/action_parser.py +103 -0
  332. aip_agents/tools/browser_use/action_parser.pyi +18 -0
  333. aip_agents/tools/browser_use/browser_use_tool.py +1112 -0
  334. aip_agents/tools/browser_use/browser_use_tool.pyi +50 -0
  335. aip_agents/tools/browser_use/llm_config.py +120 -0
  336. aip_agents/tools/browser_use/llm_config.pyi +52 -0
  337. aip_agents/tools/browser_use/minio_storage.py +198 -0
  338. aip_agents/tools/browser_use/minio_storage.pyi +109 -0
  339. aip_agents/tools/browser_use/schemas.py +119 -0
  340. aip_agents/tools/browser_use/schemas.pyi +32 -0
  341. aip_agents/tools/browser_use/session.py +76 -0
  342. aip_agents/tools/browser_use/session.pyi +4 -0
  343. aip_agents/tools/browser_use/session_errors.py +132 -0
  344. aip_agents/tools/browser_use/session_errors.pyi +53 -0
  345. aip_agents/tools/browser_use/steel_session_recording.py +317 -0
  346. aip_agents/tools/browser_use/steel_session_recording.pyi +63 -0
  347. aip_agents/tools/browser_use/streaming.py +813 -0
  348. aip_agents/tools/browser_use/streaming.pyi +81 -0
  349. aip_agents/tools/browser_use/structured_data_parser.py +257 -0
  350. aip_agents/tools/browser_use/structured_data_parser.pyi +86 -0
  351. aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
  352. aip_agents/tools/browser_use/structured_data_recovery.pyi +43 -0
  353. aip_agents/tools/browser_use/types.py +78 -0
  354. aip_agents/tools/browser_use/types.pyi +45 -0
  355. aip_agents/tools/code_sandbox/__init__.py +26 -0
  356. aip_agents/tools/code_sandbox/__init__.pyi +3 -0
  357. aip_agents/tools/code_sandbox/constant.py +13 -0
  358. aip_agents/tools/code_sandbox/constant.pyi +4 -0
  359. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +257 -0
  360. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +86 -0
  361. aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
  362. aip_agents/tools/code_sandbox/e2b_sandbox_tool.pyi +29 -0
  363. aip_agents/tools/constants.py +165 -0
  364. aip_agents/tools/constants.pyi +105 -100
  365. aip_agents/tools/document_loader/__init__.py +37 -0
  366. aip_agents/tools/document_loader/__init__.pyi +7 -0
  367. aip_agents/tools/document_loader/base_reader.py +262 -0
  368. aip_agents/tools/document_loader/base_reader.pyi +62 -0
  369. aip_agents/tools/document_loader/docx_reader_tool.py +53 -0
  370. aip_agents/tools/document_loader/docx_reader_tool.pyi +6 -0
  371. aip_agents/tools/document_loader/excel_reader_tool.py +160 -0
  372. aip_agents/tools/document_loader/excel_reader_tool.pyi +26 -0
  373. aip_agents/tools/document_loader/pdf_reader_tool.py +67 -0
  374. aip_agents/tools/document_loader/pdf_reader_tool.pyi +11 -0
  375. aip_agents/tools/document_loader/pdf_splitter.py +169 -0
  376. aip_agents/tools/document_loader/pdf_splitter.pyi +18 -0
  377. aip_agents/tools/gl_connector/__init__.py +5 -0
  378. aip_agents/tools/gl_connector/__init__.pyi +3 -0
  379. aip_agents/tools/gl_connector/tool.py +351 -0
  380. aip_agents/tools/gl_connector/tool.pyi +74 -0
  381. aip_agents/tools/memory_search/__init__.py +22 -0
  382. aip_agents/tools/memory_search/__init__.pyi +5 -0
  383. aip_agents/tools/memory_search/base.py +200 -0
  384. aip_agents/tools/memory_search/base.pyi +69 -0
  385. aip_agents/tools/memory_search/mem0.py +258 -0
  386. aip_agents/tools/memory_search/mem0.pyi +19 -0
  387. aip_agents/tools/memory_search/schema.py +48 -0
  388. aip_agents/tools/memory_search/schema.pyi +15 -0
  389. aip_agents/tools/memory_search_tool.py +26 -0
  390. aip_agents/tools/memory_search_tool.pyi +3 -0
  391. aip_agents/tools/tool_config_injector.py +300 -0
  392. aip_agents/tools/web_search/__init__.py +15 -0
  393. aip_agents/tools/web_search/__init__.pyi +3 -0
  394. aip_agents/tools/web_search/serper_tool.py +187 -0
  395. aip_agents/tools/web_search/serper_tool.pyi +19 -0
  396. aip_agents/types/__init__.py +70 -0
  397. aip_agents/types/__init__.pyi +35 -2
  398. aip_agents/types/a2a_events.py +13 -0
  399. aip_agents/types/a2a_events.pyi +2 -73
  400. aip_agents/utils/__init__.py +79 -0
  401. aip_agents/utils/__init__.pyi +8 -2
  402. aip_agents/utils/a2a_connector.py +1757 -0
  403. aip_agents/utils/a2a_connector.pyi +15 -4
  404. aip_agents/utils/artifact_helpers.py +502 -0
  405. aip_agents/utils/artifact_helpers.pyi +26 -2
  406. aip_agents/utils/constants.py +22 -0
  407. aip_agents/utils/constants.pyi +10 -0
  408. aip_agents/utils/datetime/__init__.py +34 -0
  409. aip_agents/utils/datetime/__init__.pyi +4 -0
  410. aip_agents/utils/datetime/normalization.py +231 -0
  411. aip_agents/utils/datetime/normalization.pyi +95 -0
  412. aip_agents/utils/datetime/timezone.py +206 -0
  413. aip_agents/utils/datetime/timezone.pyi +48 -0
  414. aip_agents/utils/env_loader.py +27 -0
  415. aip_agents/utils/env_loader.pyi +10 -0
  416. aip_agents/utils/event_handler_registry.py +58 -0
  417. aip_agents/utils/event_handler_registry.pyi +23 -0
  418. aip_agents/utils/file_prompt_utils.py +176 -0
  419. aip_agents/utils/file_prompt_utils.pyi +21 -0
  420. aip_agents/utils/final_response_builder.py +211 -0
  421. aip_agents/utils/final_response_builder.pyi +34 -0
  422. aip_agents/utils/formatter_llm_client.py +231 -0
  423. aip_agents/utils/formatter_llm_client.pyi +71 -0
  424. aip_agents/utils/langgraph/__init__.py +19 -0
  425. aip_agents/utils/langgraph/converter.py +128 -0
  426. aip_agents/utils/langgraph/converter.pyi +1 -1
  427. aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
  428. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
  429. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +2 -2
  430. aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
  431. aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +2 -3
  432. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1071 -0
  433. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +17 -11
  434. aip_agents/utils/langgraph/tool_output_management.py +967 -0
  435. aip_agents/utils/langgraph/tool_output_management.pyi +15 -33
  436. aip_agents/utils/logger.py +195 -0
  437. aip_agents/utils/logger.pyi +60 -0
  438. aip_agents/utils/metadata/__init__.py +27 -0
  439. aip_agents/utils/metadata/__init__.pyi +5 -0
  440. aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
  441. aip_agents/utils/metadata/activity_metadata_helper.pyi +25 -0
  442. aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
  443. aip_agents/utils/metadata/activity_narrative/__init__.pyi +7 -0
  444. aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
  445. aip_agents/utils/metadata/activity_narrative/builder.pyi +35 -0
  446. aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
  447. aip_agents/utils/metadata/activity_narrative/constants.pyi +10 -0
  448. aip_agents/utils/metadata/activity_narrative/context.py +49 -0
  449. aip_agents/utils/metadata/activity_narrative/context.pyi +32 -0
  450. aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
  451. aip_agents/utils/metadata/activity_narrative/formatters.pyi +48 -0
  452. aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
  453. aip_agents/utils/metadata/activity_narrative/utils.pyi +12 -0
  454. aip_agents/utils/metadata/schemas/__init__.py +16 -0
  455. aip_agents/utils/metadata/schemas/__init__.pyi +4 -0
  456. aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
  457. aip_agents/utils/metadata/schemas/activity_schema.pyi +18 -0
  458. aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
  459. aip_agents/utils/metadata/schemas/thinking_schema.pyi +20 -0
  460. aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
  461. aip_agents/utils/metadata/thinking_metadata_helper.pyi +4 -0
  462. aip_agents/utils/metadata_helper.py +358 -0
  463. aip_agents/utils/metadata_helper.pyi +55 -48
  464. aip_agents/utils/name_preprocessor/__init__.py +17 -0
  465. aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
  466. aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +1 -2
  467. aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
  468. aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +1 -1
  469. aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
  470. aip_agents/utils/name_preprocessor/name_preprocessor.pyi +4 -4
  471. aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
  472. aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +1 -1
  473. aip_agents/utils/pii/__init__.py +25 -0
  474. aip_agents/utils/pii/__init__.pyi +5 -0
  475. aip_agents/utils/pii/pii_handler.py +397 -0
  476. aip_agents/utils/pii/pii_handler.pyi +96 -0
  477. aip_agents/utils/pii/pii_helper.py +207 -0
  478. aip_agents/utils/pii/pii_helper.pyi +78 -0
  479. aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
  480. aip_agents/utils/pii/uuid_deanonymizer_mapping.pyi +73 -0
  481. aip_agents/utils/reference_helper.py +273 -0
  482. aip_agents/utils/reference_helper.pyi +38 -6
  483. aip_agents/utils/sse_chunk_transformer.py +831 -0
  484. aip_agents/utils/sse_chunk_transformer.pyi +166 -0
  485. aip_agents/utils/step_limit_manager.py +265 -0
  486. aip_agents/utils/step_limit_manager.pyi +112 -0
  487. aip_agents/utils/token_usage_helper.py +156 -0
  488. aip_agents/utils/token_usage_helper.pyi +1 -1
  489. aip_agents_binary-0.5.11.dist-info/METADATA +689 -0
  490. aip_agents_binary-0.5.11.dist-info/RECORD +542 -0
  491. {aip_agents_binary-0.0.0b2.dist-info → aip_agents_binary-0.5.11.dist-info}/WHEEL +2 -1
  492. aip_agents_binary-0.5.11.dist-info/top_level.txt +1 -0
  493. aip_agents/agent/types.pyi +0 -106
  494. aip_agents/examples/hello_world_a2a_multi_agent_coordinator_client.pyi +0 -15
  495. aip_agents/examples/hello_world_a2a_multi_agent_coordinator_client_streaming.pyi +0 -5
  496. aip_agents/examples/hello_world_a2a_multi_agent_coordinator_server.pyi +0 -11
  497. aip_agents/examples/hello_world_langgraph_bosa.pyi +0 -5
  498. aip_agents/examples/tools/pr_details_bosa_tool.pyi +0 -26
  499. aip_agents/tools/base.pyi +0 -44
  500. aip_agents/tools/base_bosa_tools.pyi +0 -12
  501. aip_agents/tools/bosa_connector.pyi +0 -30
  502. aip_agents/tools/bosa_tools_interface.pyi +0 -26
  503. aip_agents/tools/nested_agent_tool.pyi +0 -45
  504. aip_agents/utils/logger_manager.pyi +0 -151
  505. aip_agents_binary-0.0.0b2.dist-info/METADATA +0 -277
  506. aip_agents_binary-0.0.0b2.dist-info/RECORD +0 -157
@@ -0,0 +1,151 @@
1
+ """This file contains the Sentry and OpenTelemetry configuration for BOSA SDK.
2
+
3
+ Authors:
4
+ Saul Sayers (saul.sayers@gdplabs.id)
5
+ """
6
+
7
+ import inspect
8
+ import os
9
+
10
+ from bosa_core.telemetry import (
11
+ FastAPIConfig,
12
+ OpenTelemetryConfig,
13
+ SentryConfig,
14
+ TelemetryConfig,
15
+ init_telemetry,
16
+ )
17
+ from bosa_core.telemetry.opentelemetry.instrument.functions import (
18
+ BOSAFunctionsInstrumentor,
19
+ )
20
+ from dotenv import load_dotenv
21
+ from fastapi import FastAPI
22
+
23
+ from aip_agents.agent import BaseAgent, GoogleADKAgent, LangChainAgent, LangGraphAgent
24
+ from aip_agents.utils.logger import get_logger
25
+
26
+ load_dotenv()
27
+
28
+
29
+ logger = get_logger(__name__)
30
+
31
+ SENTRY_DSN = os.getenv("SENTRY_DSN")
32
+ SENTRY_ENVIRONMENT = os.getenv("SENTRY_ENVIRONMENT", "development")
33
+ SENTRY_PROJECT = os.getenv("SENTRY_PROJECT")
34
+ VERSION_NUMBER = os.getenv("VERSION_NUMBER", "0.0.0")
35
+ BUILD_NUMBER = os.getenv("BUILD_NUMBER", "0")
36
+ USE_OPENTELEMETRY = os.getenv("USE_OPENTELEMETRY", "true").lower() == "true"
37
+
38
+ CLASSES_TO_INSTRUMENT = [
39
+ BaseAgent,
40
+ LangGraphAgent,
41
+ LangChainAgent,
42
+ GoogleADKAgent,
43
+ ]
44
+
45
+
46
+ def get_all_methods(cls: type) -> list:
47
+ """Get all methods from a class.
48
+
49
+ Args:
50
+ cls: The class to get methods from.
51
+
52
+ Returns:
53
+ list: A list of methods.
54
+ """
55
+ methods = []
56
+ for name, member in inspect.getmembers(cls):
57
+ if name.startswith("_"):
58
+ continue # skip dunder and private
59
+ if inspect.isfunction(member) or inspect.ismethod(member) or inspect.iscoroutinefunction(member):
60
+ methods.append(member)
61
+ return methods
62
+
63
+
64
+ def instrument_bosa_functions() -> None:
65
+ """Instrument BOSA functions."""
66
+ if BOSAFunctionsInstrumentor is None:
67
+ return
68
+ agent_methods = []
69
+ for cls in CLASSES_TO_INSTRUMENT:
70
+ agent_methods.extend(get_all_methods(cls))
71
+ BOSAFunctionsInstrumentor().instrument(methods=agent_methods)
72
+
73
+
74
+ def traces_sampler(*args) -> float:
75
+ """Determine appropriate sampling rate for Sentry transactions.
76
+
77
+ Args:
78
+ *args: Additional positional arguments
79
+
80
+ Returns:
81
+ float: Sampling rate between 0 and 1
82
+ """
83
+ # TODO: Dont sample healthcheck endpoints (return 0.0)
84
+ return 1.0
85
+
86
+
87
+ def setup_sentry_with_open_telemetry(app: FastAPI) -> None:
88
+ """Configure telemetry with both Sentry and OpenTelemetry.
89
+
90
+ Args:
91
+ app: FastAPI application instance
92
+ """
93
+ try:
94
+ fastapi_config = FastAPIConfig(app)
95
+
96
+ # Create OpenTelemetry configuration
97
+ opentelemetry_init = OpenTelemetryConfig(
98
+ use_langchain=True,
99
+ fastapi_config=fastapi_config,
100
+ )
101
+
102
+ # Sentry configuration with OpenTelemetry
103
+ sentry_config = SentryConfig(
104
+ dsn=SENTRY_DSN,
105
+ traces_sampler=traces_sampler,
106
+ environment=SENTRY_ENVIRONMENT,
107
+ release=f"{SENTRY_PROJECT}@{VERSION_NUMBER}+{BUILD_NUMBER}",
108
+ send_default_pii=True,
109
+ open_telemetry_config=opentelemetry_init,
110
+ )
111
+
112
+ telemetry_config = TelemetryConfig(sentry_config=sentry_config)
113
+ init_telemetry(telemetry_config)
114
+ logger.info(f"Telemetry initialized with OpenTelemetry for environment: {SENTRY_ENVIRONMENT}")
115
+ except Exception as e:
116
+ logger.error(f"Failed to initialize telemetry with OpenTelemetry: {e}")
117
+
118
+
119
+ def setup_sentry_only() -> None:
120
+ """Configure telemetry with Sentry only (no OpenTelemetry)."""
121
+ try:
122
+ # Sentry configuration without OpenTelemetry
123
+ sentry_config = SentryConfig(
124
+ dsn=SENTRY_DSN,
125
+ traces_sampler=traces_sampler,
126
+ environment=SENTRY_ENVIRONMENT,
127
+ release=f"{SENTRY_PROJECT}@{VERSION_NUMBER}+{BUILD_NUMBER}",
128
+ send_default_pii=True,
129
+ )
130
+
131
+ telemetry_config = TelemetryConfig(sentry_config=sentry_config)
132
+ init_telemetry(telemetry_config)
133
+ logger.info(f"Telemetry initialized with Sentry only for environment: {SENTRY_ENVIRONMENT}")
134
+ except Exception as e:
135
+ logger.error(f"Failed to initialize telemetry with Sentry only: {e}")
136
+
137
+
138
+ def setup_telemetry(app: FastAPI) -> None:
139
+ """Configure and initialize telemetry based on configuration.
140
+
141
+ Args:
142
+ app: FastAPI application instance
143
+ """
144
+ if not SENTRY_DSN:
145
+ logger.warning("Warning: SENTRY_DSN not set. Sentry will not be enabled.")
146
+ return
147
+ if USE_OPENTELEMETRY:
148
+ setup_sentry_with_open_telemetry(app)
149
+ else:
150
+ setup_sentry_only()
151
+ instrument_bosa_functions()
@@ -1,7 +1,7 @@
1
1
  from _typeshed import Incomplete
2
2
  from aip_agents.agent import BaseAgent as BaseAgent, GoogleADKAgent as GoogleADKAgent, LangChainAgent as LangChainAgent, LangGraphAgent as LangGraphAgent
3
- from aip_agents.utils.logger_manager import LoggerManager as LoggerManager
4
- from fastapi import FastAPI as FastAPI
3
+ from aip_agents.utils.logger import get_logger as get_logger
4
+ from fastapi import FastAPI
5
5
 
6
6
  logger: Incomplete
7
7
  SENTRY_DSN: Incomplete
@@ -0,0 +1,41 @@
1
+ """Storage module for aip_agents.
2
+
3
+ This module provides comprehensive storage functionality including object storage
4
+ clients, storage providers for tool outputs, and configuration management.
5
+
6
+ Authors:
7
+ Fachriza Adhiatma (fachriza.d.adhiatma@gdplabs.id)
8
+ Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
9
+ """
10
+
11
+ # Object storage clients
12
+ from aip_agents.storage.base import BaseObjectStorageClient
13
+ from aip_agents.storage.clients.minio_client import MinioConfig, MinioObjectStorage
14
+
15
+ # Configuration and factory
16
+ from aip_agents.storage.config import (
17
+ StorageConfig,
18
+ StorageProviderFactory,
19
+ StorageType,
20
+ )
21
+
22
+ # Storage providers
23
+ from aip_agents.storage.providers.base import BaseStorageProvider, StorageError
24
+ from aip_agents.storage.providers.memory import InMemoryStorageProvider
25
+ from aip_agents.storage.providers.object_storage import ObjectStorageProvider
26
+
27
+ __all__ = [
28
+ # Object storage
29
+ "BaseObjectStorageClient",
30
+ "MinioConfig",
31
+ "MinioObjectStorage",
32
+ # Storage providers
33
+ "BaseStorageProvider",
34
+ "StorageError",
35
+ "InMemoryStorageProvider",
36
+ "ObjectStorageProvider",
37
+ # Configuration
38
+ "StorageConfig",
39
+ "StorageType",
40
+ "StorageProviderFactory",
41
+ ]
@@ -0,0 +1,85 @@
1
+ """Base class for object storage clients.
2
+
3
+ Authors:
4
+ Fachriza Adhiatma (fachriza.d.adhiatma@gdplabs.id)
5
+ Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
6
+ """
7
+
8
+ from abc import ABC, abstractmethod
9
+ from typing import BinaryIO
10
+
11
+
12
+ class BaseObjectStorageClient(ABC):
13
+ """Abstract base class for object storage clients."""
14
+
15
+ @abstractmethod
16
+ def object_exists(self, object_key: str) -> bool:
17
+ """Check if an object exists in the storage.
18
+
19
+ Args:
20
+ object_key: The key of the object to check.
21
+
22
+ Returns:
23
+ True if the object exists, False otherwise.
24
+ """
25
+ raise NotImplementedError
26
+
27
+ @abstractmethod
28
+ def upload(
29
+ self,
30
+ object_key: str,
31
+ file_stream: bytes | BinaryIO,
32
+ filename: str | None = None,
33
+ content_type: str | None = None,
34
+ metadata: dict[str, str] | None = None,
35
+ ) -> str:
36
+ """Upload data to object storage.
37
+
38
+ Args:
39
+ object_key: The key of the object in the storage
40
+ file_stream: The binary data to upload
41
+ filename: The name of the file
42
+ content_type: The content type of the file
43
+ metadata: Additional metadata to store with the object
44
+
45
+ Returns:
46
+ The key of the uploaded object
47
+ """
48
+ raise NotImplementedError
49
+
50
+ @abstractmethod
51
+ def get(self, object_key: str) -> bytes:
52
+ """Get data from object storage.
53
+
54
+ Args:
55
+ object_key: The key of the object in the storage
56
+
57
+ Returns:
58
+ The binary data of the object
59
+ """
60
+ raise NotImplementedError
61
+
62
+ @abstractmethod
63
+ def delete(self, object_key: str) -> None:
64
+ """Delete data from object storage.
65
+
66
+ Args:
67
+ object_key: The key of the object in the storage
68
+ """
69
+ raise NotImplementedError
70
+
71
+ @abstractmethod
72
+ def generate_presigned_url(
73
+ self, object_key: str, expires: int = 24, response_headers: dict[str, str] | None = None
74
+ ) -> str:
75
+ """Generate a presigned URL for accessing the object.
76
+
77
+ Args:
78
+ object_key: The key of the object in the storage
79
+ expires: The number of hours the URL is valid for
80
+ response_headers: Additional headers to include in the response
81
+
82
+ Returns:
83
+ The presigned URL
84
+ """
85
+ raise NotImplementedError
@@ -1,8 +1,7 @@
1
- import abc
2
1
  from abc import ABC, abstractmethod
3
2
  from typing import BinaryIO
4
3
 
5
- class BaseObjectStorageClient(ABC, metaclass=abc.ABCMeta):
4
+ class BaseObjectStorageClient(ABC):
6
5
  """Abstract base class for object storage clients."""
7
6
  @abstractmethod
8
7
  def object_exists(self, object_key: str) -> bool:
@@ -0,0 +1,12 @@
1
+ """Storage client implementations.
2
+
3
+ This module contains concrete implementations of object storage clients
4
+ for various backends like MinIO, AWS S3, etc.
5
+
6
+ Authors:
7
+ Fachriza Adhiatma (fachriza.d.adhiatma@gdplabs.id)
8
+ """
9
+
10
+ from aip_agents.storage.clients.minio_client import MinioConfig, MinioObjectStorage
11
+
12
+ __all__ = ["MinioConfig", "MinioObjectStorage"]
@@ -0,0 +1,318 @@
1
+ """Minio object storage implementation.
2
+
3
+ Authors:
4
+ Fachriza Adhiatma (fachriza.d.adhiatma@gdplabs.id)
5
+ """
6
+
7
+ import datetime
8
+ import io
9
+ import os
10
+ from dataclasses import dataclass
11
+ from typing import BinaryIO
12
+
13
+ from minio import Minio, S3Error
14
+ from urllib3.exceptions import HTTPError
15
+
16
+ from aip_agents.storage.base import BaseObjectStorageClient
17
+
18
+ S3_ERR_NO_SUCH_KEY = "NoSuchKey"
19
+ S3_ERR_NO_SUCH_BUCKET = "NoSuchBucket"
20
+ S3_ERR_ACCESS_DENIED = "AccessDenied"
21
+
22
+
23
+ @dataclass
24
+ class MinioConfig:
25
+ """Configuration for MinIO object storage client.
26
+
27
+ Attributes:
28
+ endpoint: MinIO server endpoint URL
29
+ access_key: Access key for authentication
30
+ secret_key: Secret key for authentication
31
+ bucket: Bucket name to use for storage
32
+ secure: Whether to use HTTPS (defaults to True)
33
+ """
34
+
35
+ endpoint: str
36
+ access_key: str
37
+ secret_key: str
38
+ bucket: str
39
+ secure: bool = True
40
+
41
+ @classmethod
42
+ def from_env(cls) -> "MinioConfig":
43
+ """Create MinioConfig from environment variables.
44
+
45
+ Expected environment variables:
46
+ - OBJECT_STORAGE_URL
47
+ - OBJECT_STORAGE_USER
48
+ - OBJECT_STORAGE_PASSWORD
49
+ - OBJECT_STORAGE_BUCKET
50
+ - OBJECT_STORAGE_SECURE (optional, defaults to True)
51
+
52
+ Returns:
53
+ MinioConfig instance
54
+
55
+ Raises:
56
+ ValueError: If required environment variables are not set
57
+ """
58
+ endpoint = os.getenv("OBJECT_STORAGE_URL")
59
+ access_key = os.getenv("OBJECT_STORAGE_USER")
60
+ secret_key = os.getenv("OBJECT_STORAGE_PASSWORD")
61
+ bucket = os.getenv("OBJECT_STORAGE_BUCKET")
62
+ secure_str = os.getenv("OBJECT_STORAGE_SECURE")
63
+
64
+ if not all([endpoint, access_key, secret_key, bucket]):
65
+ raise ValueError(
66
+ "MinIO configuration incomplete. Required environment variables: "
67
+ "OBJECT_STORAGE_URL, OBJECT_STORAGE_USER, "
68
+ "OBJECT_STORAGE_PASSWORD, OBJECT_STORAGE_BUCKET"
69
+ )
70
+
71
+ secure = secure_str.lower() in ("true", "1", "yes", "on")
72
+
73
+ return cls(endpoint=endpoint, access_key=access_key, secret_key=secret_key, bucket=bucket, secure=secure)
74
+
75
+
76
+ class MinioObjectStorage(BaseObjectStorageClient):
77
+ """Implementation of ObjectStorageInterface using Minio."""
78
+
79
+ def __init__(self, config: MinioConfig | None = None, ensure_bucket: bool = True):
80
+ """Initialize MinioObjectStorage with configuration.
81
+
82
+ Args:
83
+ config: MinioConfig instance. If None, will attempt to load from environment variables.
84
+ ensure_bucket: Whether to ensure bucket exists during initialization (optional). Defaults to True.
85
+
86
+ Raises:
87
+ ValueError: If configuration is invalid or incomplete
88
+ """
89
+ if config is None:
90
+ config = MinioConfig.from_env()
91
+
92
+ self.config = config
93
+ self.client = Minio(
94
+ endpoint=config.endpoint,
95
+ access_key=config.access_key,
96
+ secret_key=config.secret_key,
97
+ secure=config.secure,
98
+ )
99
+ self.bucket = config.bucket
100
+ self._bucket_exists = None
101
+
102
+ if ensure_bucket:
103
+ self._ensure_bucket_exists()
104
+
105
+ def _ensure_bucket_exists(self) -> None:
106
+ """Ensure the bucket exists, creating it if necessary.
107
+
108
+ Uses caching to avoid repeated bucket existence checks.
109
+
110
+ Raises:
111
+ PermissionError: If user lacks permission to create the bucket
112
+ ConnectionError: If there's a network/connection issue creating the bucket
113
+ """
114
+ if self._bucket_exists is None:
115
+ try:
116
+ self._bucket_exists = self.client.bucket_exists(self.bucket)
117
+ if not self._bucket_exists:
118
+ self.client.make_bucket(self.bucket)
119
+ self._bucket_exists = True
120
+ except S3Error as e:
121
+ if e.code == S3_ERR_ACCESS_DENIED: # pragma: no cover - difficult to test with mocks
122
+ raise PermissionError(
123
+ f"Access denied: Insufficient permissions to create bucket '{self.bucket}'. "
124
+ f"Please check your AWS/MinIO user permissions."
125
+ ) from e
126
+ else:
127
+ raise ConnectionError(f"Failed to create bucket '{self.bucket}': {str(e)}") from e
128
+
129
+ def _prepare_file_stream(self, file_stream: bytes | BinaryIO) -> tuple[BinaryIO, int]:
130
+ """Prepare file stream for upload and validate its content.
131
+
132
+ Args:
133
+ file_stream: The file stream to prepare (bytes or file-like object)
134
+
135
+ Returns:
136
+ Tuple containing:
137
+ - Prepared file stream
138
+ - Length of the file content
139
+
140
+ Raises:
141
+ ValueError: If the file stream is empty or invalid
142
+ """
143
+ if isinstance(file_stream, bytes):
144
+ file_stream = io.BytesIO(file_stream)
145
+ file_length = len(file_stream.getvalue())
146
+ else:
147
+ # For file-like objects, seek to end to get size, then reset
148
+ try:
149
+ current_pos = file_stream.tell()
150
+ file_stream.seek(0, 2) # Seek to end
151
+ file_length = file_stream.tell()
152
+ file_stream.seek(current_pos)
153
+ except (OSError, AttributeError) as e:
154
+ raise ValueError(f"Invalid file stream: {str(e)}") from e
155
+
156
+ if file_length == 0:
157
+ raise ValueError("File stream is empty.")
158
+
159
+ return file_stream, file_length
160
+
161
+ def upload(
162
+ self,
163
+ object_key: str,
164
+ file_stream: bytes | BinaryIO,
165
+ filename: str | None = None,
166
+ content_type: str | None = None,
167
+ metadata: dict[str, str] | None = None,
168
+ ) -> str:
169
+ """Upload data to Minio object storage.
170
+
171
+ Args:
172
+ object_key: The key to store the object under
173
+ file_stream: The data to upload (bytes or file-like object)
174
+ filename: The filename of the data (optional)
175
+ content_type: The content type of the data (optional)
176
+ metadata: Additional metadata to store with the object (optional)
177
+
178
+ Returns:
179
+ The object key of the uploaded data
180
+
181
+ Raises:
182
+ ValueError: If the file stream is empty or invalid
183
+ ConnectionError: If there's an issue connecting to Minio
184
+ Exception: For other unexpected errors during upload
185
+ """
186
+ if self._bucket_exists is None:
187
+ self._ensure_bucket_exists()
188
+ prepared_stream, file_length = self._prepare_file_stream(file_stream)
189
+
190
+ try:
191
+ self.client.put_object(
192
+ bucket_name=self.bucket,
193
+ object_name=object_key,
194
+ data=prepared_stream,
195
+ length=file_length,
196
+ content_type=content_type,
197
+ metadata=metadata,
198
+ )
199
+ except S3Error as e:
200
+ raise ConnectionError(f"Failed to upload object '{object_key}' to Minio: {str(e)}") from e
201
+ except HTTPError as e:
202
+ raise ConnectionError(f"A network error occurred during object upload: {str(e)}") from e
203
+
204
+ return object_key
205
+
206
+ def get(self, object_key: str) -> bytes:
207
+ """Get data from Minio object storage.
208
+
209
+ Args:
210
+ object_key: The key of the object to retrieve
211
+
212
+ Returns:
213
+ The object data as bytes
214
+
215
+ Raises:
216
+ KeyError: If the object is not found
217
+ ConnectionError: If there's a network or connection issue
218
+ """
219
+ try:
220
+ with self.client.get_object(bucket_name=self.bucket, object_name=object_key) as response:
221
+ return response.read()
222
+ except S3Error as e:
223
+ if e.code == S3_ERR_NO_SUCH_KEY:
224
+ raise KeyError(f"Object with key '{object_key}' not found") from e
225
+ raise ConnectionError(f"Failed to get object '{object_key}': {str(e)}") from e
226
+ except HTTPError as e:
227
+ raise ConnectionError(f"A network error occurred during object retrieval: {str(e)}") from e
228
+
229
+ def delete(self, object_key: str) -> None:
230
+ """Delete data from Minio object storage.
231
+
232
+ Args:
233
+ object_key: The key of the object to delete
234
+
235
+ Raises:
236
+ ConnectionError: If there's a network or connection issue
237
+ """
238
+ try:
239
+ self.client.remove_object(bucket_name=self.bucket, object_name=object_key)
240
+ except S3Error as e:
241
+ if e.code != S3_ERR_NO_SUCH_KEY: # Don't raise error if object doesn't exist
242
+ raise ConnectionError(f"Failed to delete object '{object_key}': {str(e)}") from e
243
+ except HTTPError as e:
244
+ raise ConnectionError(f"A network error occurred during file deletion: {str(e)}") from e
245
+
246
+ def object_exists(self, object_key: str) -> bool:
247
+ """Check if an object exists in the MinIO bucket.
248
+
249
+ Args:
250
+ object_key: The key of the object to check.
251
+
252
+ Returns:
253
+ True if the object exists, False otherwise.
254
+
255
+ Raises:
256
+ ConnectionError: If there's a network or connection issue (excluding not found errors)
257
+ """
258
+ try:
259
+ self.client.stat_object(self.bucket, object_key)
260
+ return True
261
+ except S3Error as e:
262
+ if e.code in (S3_ERR_NO_SUCH_KEY, S3_ERR_NO_SUCH_BUCKET):
263
+ return False
264
+ raise ConnectionError(f"Failed to check object existence '{object_key}': {str(e)}") from e
265
+ except HTTPError as e:
266
+ raise ConnectionError(f"A network error occurred while checking object existence: {str(e)}") from e
267
+
268
+ def list_objects(self, prefix: str = "") -> list[str]:
269
+ """List objects in the bucket with optional prefix filter.
270
+
271
+ Args:
272
+ prefix: Optional prefix to filter objects
273
+
274
+ Returns:
275
+ List of object keys
276
+
277
+ Raises:
278
+ ConnectionError: If there's an issue listing objects
279
+ """
280
+ try:
281
+ objects = self.client.list_objects(self.bucket, prefix=prefix)
282
+ return [obj.object_name for obj in objects]
283
+ except S3Error as e:
284
+ raise ConnectionError(f"Failed to list objects in bucket '{self.bucket}': {str(e)}") from e
285
+ except HTTPError as e:
286
+ raise ConnectionError(f"A network error occurred while listing objects: {str(e)}") from e
287
+
288
+ def generate_presigned_url(
289
+ self, object_key: str, expires: int = 24, response_headers: dict[str, str] | None = None
290
+ ) -> str:
291
+ """Generate a presigned URL for accessing the object.
292
+
293
+ Args:
294
+ object_key: The key of the object
295
+ expires: Expiration time in hours (defaults to 24)
296
+ response_headers: Additional response headers (optional)
297
+
298
+ Returns:
299
+ A presigned URL
300
+
301
+ Raises:
302
+ ValueError: If expiration time is not positive
303
+ ConnectionError: If there's an issue generating the URL
304
+ """
305
+ if expires <= 0:
306
+ raise ValueError("Expiration time must be positive")
307
+
308
+ try:
309
+ return self.client.presigned_get_object(
310
+ bucket_name=self.bucket,
311
+ object_name=object_key,
312
+ expires=datetime.timedelta(hours=expires),
313
+ response_headers=response_headers,
314
+ )
315
+ except S3Error as e:
316
+ raise ConnectionError(f"Failed to generate presigned URL for '{object_key}': {str(e)}") from e
317
+ except HTTPError as e:
318
+ raise ConnectionError(f"A network error occurred while generating presigned URL: {str(e)}") from e
@@ -0,0 +1,62 @@
1
+ """Storage configuration system.
2
+
3
+ This module keeps factory logic while delegating data schemas to ``aip_agents.schema.storage``.
4
+ """
5
+
6
+ from aip_agents.schema.storage import OBJECT_STORAGE_PREFIX, StorageConfig, StorageType
7
+ from aip_agents.storage.base import BaseObjectStorageClient
8
+ from aip_agents.storage.clients.minio_client import MinioConfig, MinioObjectStorage
9
+ from aip_agents.storage.providers.base import BaseStorageProvider
10
+ from aip_agents.storage.providers.memory import InMemoryStorageProvider
11
+ from aip_agents.storage.providers.object_storage import ObjectStorageProvider
12
+
13
+ __all__ = ["OBJECT_STORAGE_PREFIX", "StorageConfig", "StorageType", "StorageProviderFactory"]
14
+
15
+
16
+ class StorageProviderFactory:
17
+ """Factory for creating storage providers based on configuration."""
18
+
19
+ @staticmethod
20
+ def create(
21
+ config: StorageConfig, object_storage_client: BaseObjectStorageClient | None = None
22
+ ) -> BaseStorageProvider:
23
+ """Create storage provider based on configuration.
24
+
25
+ Args:
26
+ config (StorageConfig): Storage configuration object.
27
+ object_storage_client (BaseObjectStorageClient | None, optional): Optional object storage client for object storage type.
28
+
29
+ Returns:
30
+ BaseStorageProvider: The created storage provider instance.
31
+ """
32
+ if config.storage_type == StorageType.MEMORY:
33
+ return InMemoryStorageProvider()
34
+
35
+ if config.storage_type == StorageType.OBJECT_STORAGE:
36
+ if object_storage_client is None:
37
+ try:
38
+ minio_config = MinioConfig.from_env()
39
+ object_storage_client = MinioObjectStorage(minio_config)
40
+ except ValueError as exc:
41
+ raise ValueError(
42
+ f"Object storage client required but not provided and cannot create from env: {exc}"
43
+ ) from exc
44
+
45
+ return ObjectStorageProvider(
46
+ client=object_storage_client, prefix=config.object_prefix, use_json=config.object_use_json
47
+ )
48
+
49
+ raise ValueError(f"Unknown storage type: {config.storage_type}")
50
+
51
+ @staticmethod
52
+ def create_from_env(object_storage_client: BaseObjectStorageClient | None = None) -> BaseStorageProvider:
53
+ """Create storage provider from environment variables.
54
+
55
+ Args:
56
+ object_storage_client (BaseObjectStorageClient | None, optional): Optional object storage client for object storage type.
57
+
58
+ Returns:
59
+ BaseStorageProvider: The created storage provider instance.
60
+ """
61
+ config = StorageConfig.from_env()
62
+ return StorageProviderFactory.create(config, object_storage_client)