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.
- aip_agents/__init__.py +65 -0
- aip_agents/__init__.pyi +19 -0
- aip_agents/a2a/__init__.py +19 -0
- aip_agents/a2a/__init__.pyi +1 -1
- aip_agents/a2a/server/__init__.py +10 -0
- aip_agents/a2a/server/base_executor.py +1086 -0
- aip_agents/a2a/server/base_executor.pyi +16 -6
- aip_agents/a2a/server/google_adk_executor.py +198 -0
- aip_agents/a2a/server/google_adk_executor.pyi +11 -11
- aip_agents/a2a/server/langflow_executor.py +180 -0
- aip_agents/a2a/server/langflow_executor.pyi +43 -0
- aip_agents/a2a/server/langgraph_executor.py +267 -0
- aip_agents/a2a/server/langgraph_executor.pyi +11 -12
- aip_agents/a2a/types.py +232 -0
- aip_agents/a2a/types.pyi +54 -47
- aip_agents/agent/__init__.py +27 -0
- aip_agents/agent/__init__.pyi +3 -1
- aip_agents/agent/base_agent.py +970 -0
- aip_agents/agent/base_agent.pyi +24 -8
- aip_agents/agent/base_langgraph_agent.py +2942 -0
- aip_agents/agent/base_langgraph_agent.pyi +93 -25
- aip_agents/agent/google_adk_agent.py +926 -0
- aip_agents/agent/google_adk_agent.pyi +34 -21
- aip_agents/agent/google_adk_constants.py +6 -0
- aip_agents/agent/google_adk_constants.pyi +3 -0
- aip_agents/agent/hitl/__init__.py +24 -0
- aip_agents/agent/hitl/__init__.pyi +6 -0
- aip_agents/agent/hitl/config.py +28 -0
- aip_agents/agent/hitl/config.pyi +15 -0
- aip_agents/agent/hitl/langgraph_hitl_mixin.py +515 -0
- aip_agents/agent/hitl/langgraph_hitl_mixin.pyi +42 -0
- aip_agents/agent/hitl/manager.py +522 -0
- aip_agents/agent/hitl/manager.pyi +199 -0
- aip_agents/agent/hitl/models.py +18 -0
- aip_agents/agent/hitl/models.pyi +3 -0
- aip_agents/agent/hitl/prompt/__init__.py +9 -0
- aip_agents/agent/hitl/prompt/__init__.pyi +4 -0
- aip_agents/agent/hitl/prompt/base.py +42 -0
- aip_agents/agent/hitl/prompt/base.pyi +24 -0
- aip_agents/agent/hitl/prompt/deferred.py +73 -0
- aip_agents/agent/hitl/prompt/deferred.pyi +30 -0
- aip_agents/agent/interface.py +138 -0
- aip_agents/agent/interface.pyi +5 -5
- aip_agents/agent/interfaces.py +65 -0
- aip_agents/agent/interfaces.pyi +44 -0
- aip_agents/agent/langflow_agent.py +464 -0
- aip_agents/agent/langflow_agent.pyi +133 -0
- aip_agents/agent/langgraph_memory_enhancer_agent.py +433 -0
- aip_agents/agent/langgraph_memory_enhancer_agent.pyi +49 -0
- aip_agents/agent/langgraph_react_agent.py +2514 -0
- aip_agents/agent/langgraph_react_agent.pyi +51 -56
- aip_agents/agent/system_instruction_context.py +34 -0
- aip_agents/agent/system_instruction_context.pyi +13 -0
- aip_agents/clients/__init__.py +10 -0
- aip_agents/clients/__init__.pyi +4 -0
- aip_agents/clients/langflow/__init__.py +10 -0
- aip_agents/clients/langflow/__init__.pyi +4 -0
- aip_agents/clients/langflow/client.py +477 -0
- aip_agents/clients/langflow/client.pyi +140 -0
- aip_agents/clients/langflow/types.py +18 -0
- aip_agents/clients/langflow/types.pyi +7 -0
- aip_agents/constants.py +23 -0
- aip_agents/constants.pyi +1 -0
- aip_agents/credentials/manager.py +132 -0
- aip_agents/examples/__init__.py +5 -0
- aip_agents/examples/compare_streaming_client.py +783 -0
- aip_agents/examples/compare_streaming_client.pyi +48 -0
- aip_agents/examples/compare_streaming_server.py +142 -0
- aip_agents/examples/compare_streaming_server.pyi +18 -0
- aip_agents/examples/demo_memory_recall.py +401 -0
- aip_agents/examples/demo_memory_recall.pyi +58 -0
- aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
- aip_agents/examples/hello_world_a2a_google_adk_client.pyi +2 -2
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +2 -2
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +2 -2
- aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
- aip_agents/examples/hello_world_a2a_google_adk_server.pyi +7 -2
- aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client.pyi +1 -1
- aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +1 -1
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +1 -1
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +1 -1
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +1 -1
- aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +8 -3
- aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
- aip_agents/examples/hello_world_a2a_langchain_server.pyi +7 -2
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +7 -2
- aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
- aip_agents/examples/hello_world_a2a_langflow_client.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
- aip_agents/examples/hello_world_a2a_langflow_server.pyi +14 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +1 -1
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +1 -1
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +7 -2
- aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client.pyi +2 -2
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +2 -2
- aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +1 -1
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +3 -3
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +1 -1
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +1 -1
- aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
- aip_agents/examples/hello_world_a2a_langgraph_server.pyi +7 -2
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +7 -2
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +7 -2
- aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
- aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +1 -1
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +31 -6
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +251 -0
- aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +33 -5
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +1 -1
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +7 -2
- aip_agents/examples/hello_world_google_adk.py +41 -0
- aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
- aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
- aip_agents/examples/hello_world_google_adk_stream.py +44 -0
- aip_agents/examples/hello_world_langchain.py +28 -0
- aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
- aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
- aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
- aip_agents/examples/hello_world_langchain_mcp_http_interactive.pyi +16 -0
- aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
- aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
- aip_agents/examples/hello_world_langchain_mcp_multi_server.pyi +18 -0
- aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
- aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
- aip_agents/examples/hello_world_langchain_stream.py +36 -0
- aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
- aip_agents/examples/hello_world_langflow_agent.py +163 -0
- aip_agents/examples/hello_world_langflow_agent.pyi +35 -0
- aip_agents/examples/hello_world_langgraph.py +39 -0
- aip_agents/examples/hello_world_langgraph_bosa_twitter.py +41 -0
- aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
- aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
- aip_agents/examples/hello_world_langgraph_stream.py +43 -0
- aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
- aip_agents/examples/hello_world_model_switch_cli.py +210 -0
- aip_agents/examples/hello_world_model_switch_cli.pyi +18 -3
- aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
- aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
- aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
- aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
- aip_agents/examples/hello_world_pii_logger.py +21 -0
- aip_agents/examples/hello_world_pii_logger.pyi +1 -1
- aip_agents/examples/hello_world_sentry.py +133 -0
- aip_agents/examples/hello_world_sentry.pyi +1 -1
- aip_agents/examples/hello_world_step_limits.py +273 -0
- aip_agents/examples/hello_world_step_limits.pyi +17 -0
- aip_agents/examples/hello_world_stock_a2a_server.py +103 -0
- aip_agents/examples/hello_world_stock_a2a_server.pyi +7 -2
- aip_agents/examples/hello_world_tool_output_client.py +46 -0
- aip_agents/examples/hello_world_tool_output_client.pyi +1 -1
- aip_agents/examples/hello_world_tool_output_server.py +114 -0
- aip_agents/examples/hello_world_tool_output_server.pyi +7 -2
- aip_agents/examples/hitl_demo.py +724 -0
- aip_agents/examples/hitl_demo.pyi +67 -0
- aip_agents/examples/mcp_configs/configs.py +63 -0
- aip_agents/examples/mcp_servers/common.py +76 -0
- aip_agents/examples/mcp_servers/mcp_name.py +29 -0
- aip_agents/examples/mcp_servers/mcp_server_http.py +19 -0
- aip_agents/examples/mcp_servers/mcp_server_sse.py +19 -0
- aip_agents/examples/mcp_servers/mcp_server_stdio.py +19 -0
- aip_agents/examples/mcp_servers/mcp_time.py +10 -0
- aip_agents/examples/pii_demo_langgraph_client.py +69 -0
- aip_agents/examples/pii_demo_langgraph_client.pyi +5 -0
- aip_agents/examples/pii_demo_langgraph_server.py +126 -0
- aip_agents/examples/pii_demo_langgraph_server.pyi +20 -0
- aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
- aip_agents/examples/pii_demo_multi_agent_client.pyi +5 -0
- aip_agents/examples/pii_demo_multi_agent_server.py +247 -0
- aip_agents/examples/pii_demo_multi_agent_server.pyi +40 -0
- aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
- aip_agents/examples/todolist_planning_a2a_langchain_client.pyi +5 -0
- aip_agents/examples/todolist_planning_a2a_langgraph_server.py +88 -0
- aip_agents/examples/todolist_planning_a2a_langgraph_server.pyi +19 -0
- aip_agents/examples/tools/__init__.py +27 -0
- aip_agents/examples/tools/__init__.pyi +3 -1
- aip_agents/examples/tools/adk_arithmetic_tools.py +36 -0
- aip_agents/examples/tools/adk_weather_tool.py +60 -0
- aip_agents/examples/tools/adk_weather_tool.pyi +1 -1
- aip_agents/examples/tools/data_generator_tool.py +103 -0
- aip_agents/examples/tools/data_visualization_tool.py +312 -0
- aip_agents/examples/tools/data_visualization_tool.pyi +2 -0
- aip_agents/examples/tools/image_artifact_tool.py +136 -0
- aip_agents/examples/tools/image_artifact_tool.pyi +2 -0
- aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
- aip_agents/examples/tools/langchain_arithmetic_tools.pyi +7 -0
- aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
- aip_agents/examples/tools/langchain_currency_exchange_tool.pyi +0 -1
- aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
- aip_agents/examples/tools/langchain_graph_artifact_tool.pyi +2 -0
- aip_agents/examples/tools/langchain_weather_tool.py +48 -0
- aip_agents/examples/tools/langchain_weather_tool.pyi +1 -1
- aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
- aip_agents/examples/tools/langgraph_streaming_tool.pyi +1 -1
- aip_agents/examples/tools/mock_retrieval_tool.py +56 -0
- aip_agents/examples/tools/mock_retrieval_tool.pyi +13 -0
- aip_agents/examples/tools/pii_demo_tools.py +189 -0
- aip_agents/examples/tools/pii_demo_tools.pyi +54 -0
- aip_agents/examples/tools/random_chart_tool.py +142 -0
- aip_agents/examples/tools/random_chart_tool.pyi +20 -0
- aip_agents/examples/tools/serper_tool.py +202 -0
- aip_agents/examples/tools/stock_tools.py +82 -0
- aip_agents/examples/tools/stock_tools.pyi +18 -3
- aip_agents/examples/tools/table_generator_tool.py +167 -0
- aip_agents/examples/tools/time_tool.py +82 -0
- aip_agents/examples/tools/weather_forecast_tool.py +38 -0
- aip_agents/executor/agent_executor.py +473 -0
- aip_agents/executor/base.py +48 -0
- aip_agents/mcp/__init__.py +1 -0
- aip_agents/mcp/client/__init__.py +14 -0
- aip_agents/mcp/client/__init__.pyi +4 -3
- aip_agents/mcp/client/base_mcp_client.py +369 -0
- aip_agents/mcp/client/base_mcp_client.pyi +148 -0
- aip_agents/mcp/client/connection_manager.py +193 -0
- aip_agents/mcp/client/connection_manager.pyi +48 -0
- aip_agents/mcp/client/google_adk/__init__.py +11 -0
- aip_agents/mcp/client/google_adk/__init__.pyi +1 -1
- aip_agents/mcp/client/google_adk/client.py +381 -0
- aip_agents/mcp/client/google_adk/client.pyi +50 -13
- aip_agents/mcp/client/langchain/__init__.py +11 -0
- aip_agents/mcp/client/langchain/__init__.pyi +1 -1
- aip_agents/mcp/client/langchain/client.py +265 -0
- aip_agents/mcp/client/langchain/client.pyi +47 -2
- aip_agents/mcp/client/persistent_session.py +359 -0
- aip_agents/mcp/client/persistent_session.pyi +113 -0
- aip_agents/mcp/client/session_pool.py +351 -0
- aip_agents/mcp/client/session_pool.pyi +101 -0
- aip_agents/mcp/client/transports.py +215 -0
- aip_agents/mcp/client/transports.pyi +123 -0
- aip_agents/mcp/utils/__init__.py +7 -0
- aip_agents/mcp/utils/__init__.pyi +0 -0
- aip_agents/mcp/utils/config_validator.py +139 -0
- aip_agents/mcp/utils/config_validator.pyi +82 -0
- aip_agents/memory/__init__.py +14 -0
- aip_agents/memory/__init__.pyi +5 -0
- aip_agents/memory/adapters/__init__.py +10 -0
- aip_agents/memory/adapters/__init__.pyi +4 -0
- aip_agents/memory/adapters/base_adapter.py +717 -0
- aip_agents/memory/adapters/base_adapter.pyi +150 -0
- aip_agents/memory/adapters/mem0.py +84 -0
- aip_agents/memory/adapters/mem0.pyi +22 -0
- aip_agents/memory/base.py +84 -0
- aip_agents/memory/base.pyi +15 -4
- aip_agents/memory/constants.py +49 -0
- aip_agents/memory/constants.pyi +25 -0
- aip_agents/memory/factory.py +86 -0
- aip_agents/memory/factory.pyi +24 -0
- aip_agents/memory/guidance.py +20 -0
- aip_agents/memory/guidance.pyi +3 -0
- aip_agents/memory/simple_memory.py +47 -0
- aip_agents/memory/simple_memory.pyi +6 -5
- aip_agents/middleware/__init__.py +17 -0
- aip_agents/middleware/__init__.pyi +5 -0
- aip_agents/middleware/base.py +88 -0
- aip_agents/middleware/base.pyi +71 -0
- aip_agents/middleware/manager.py +128 -0
- aip_agents/middleware/manager.pyi +80 -0
- aip_agents/middleware/todolist.py +274 -0
- aip_agents/middleware/todolist.pyi +125 -0
- aip_agents/schema/__init__.py +69 -0
- aip_agents/schema/__init__.pyi +9 -0
- aip_agents/schema/a2a.py +56 -0
- aip_agents/schema/a2a.pyi +40 -0
- aip_agents/schema/agent.py +111 -0
- aip_agents/schema/agent.pyi +65 -0
- aip_agents/schema/hitl.py +157 -0
- aip_agents/schema/hitl.pyi +89 -0
- aip_agents/schema/langgraph.py +37 -0
- aip_agents/schema/langgraph.pyi +28 -0
- aip_agents/schema/model_id.py +97 -0
- aip_agents/schema/model_id.pyi +54 -0
- aip_agents/schema/step_limit.py +108 -0
- aip_agents/schema/step_limit.pyi +63 -0
- aip_agents/schema/storage.py +40 -0
- aip_agents/schema/storage.pyi +21 -0
- aip_agents/sentry/__init__.py +11 -0
- aip_agents/sentry/__init__.pyi +1 -1
- aip_agents/sentry/sentry.py +151 -0
- aip_agents/sentry/sentry.pyi +2 -2
- aip_agents/storage/__init__.py +41 -0
- aip_agents/storage/base.py +85 -0
- aip_agents/storage/base.pyi +1 -2
- aip_agents/storage/clients/__init__.py +12 -0
- aip_agents/storage/clients/minio_client.py +318 -0
- aip_agents/storage/config.py +62 -0
- aip_agents/storage/config.pyi +9 -46
- aip_agents/storage/providers/__init__.py +15 -0
- aip_agents/storage/providers/base.py +106 -0
- aip_agents/storage/providers/base.pyi +2 -3
- aip_agents/storage/providers/memory.py +114 -0
- aip_agents/storage/providers/object_storage.py +214 -0
- aip_agents/storage/providers/object_storage.pyi +1 -1
- aip_agents/tools/__init__.py +6 -0
- aip_agents/tools/__init__.pyi +3 -2
- aip_agents/tools/bosa_tools.py +105 -0
- aip_agents/tools/bosa_tools.pyi +2 -2
- aip_agents/tools/browser_use/__init__.py +82 -0
- aip_agents/tools/browser_use/__init__.pyi +14 -0
- aip_agents/tools/browser_use/action_parser.py +103 -0
- aip_agents/tools/browser_use/action_parser.pyi +18 -0
- aip_agents/tools/browser_use/browser_use_tool.py +1112 -0
- aip_agents/tools/browser_use/browser_use_tool.pyi +50 -0
- aip_agents/tools/browser_use/llm_config.py +120 -0
- aip_agents/tools/browser_use/llm_config.pyi +52 -0
- aip_agents/tools/browser_use/minio_storage.py +198 -0
- aip_agents/tools/browser_use/minio_storage.pyi +109 -0
- aip_agents/tools/browser_use/schemas.py +119 -0
- aip_agents/tools/browser_use/schemas.pyi +32 -0
- aip_agents/tools/browser_use/session.py +76 -0
- aip_agents/tools/browser_use/session.pyi +4 -0
- aip_agents/tools/browser_use/session_errors.py +132 -0
- aip_agents/tools/browser_use/session_errors.pyi +53 -0
- aip_agents/tools/browser_use/steel_session_recording.py +317 -0
- aip_agents/tools/browser_use/steel_session_recording.pyi +63 -0
- aip_agents/tools/browser_use/streaming.py +813 -0
- aip_agents/tools/browser_use/streaming.pyi +81 -0
- aip_agents/tools/browser_use/structured_data_parser.py +257 -0
- aip_agents/tools/browser_use/structured_data_parser.pyi +86 -0
- aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
- aip_agents/tools/browser_use/structured_data_recovery.pyi +43 -0
- aip_agents/tools/browser_use/types.py +78 -0
- aip_agents/tools/browser_use/types.pyi +45 -0
- aip_agents/tools/code_sandbox/__init__.py +26 -0
- aip_agents/tools/code_sandbox/__init__.pyi +3 -0
- aip_agents/tools/code_sandbox/constant.py +13 -0
- aip_agents/tools/code_sandbox/constant.pyi +4 -0
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +257 -0
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +86 -0
- aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
- aip_agents/tools/code_sandbox/e2b_sandbox_tool.pyi +29 -0
- aip_agents/tools/constants.py +165 -0
- aip_agents/tools/constants.pyi +105 -100
- aip_agents/tools/document_loader/__init__.py +37 -0
- aip_agents/tools/document_loader/__init__.pyi +7 -0
- aip_agents/tools/document_loader/base_reader.py +262 -0
- aip_agents/tools/document_loader/base_reader.pyi +62 -0
- aip_agents/tools/document_loader/docx_reader_tool.py +53 -0
- aip_agents/tools/document_loader/docx_reader_tool.pyi +6 -0
- aip_agents/tools/document_loader/excel_reader_tool.py +160 -0
- aip_agents/tools/document_loader/excel_reader_tool.pyi +26 -0
- aip_agents/tools/document_loader/pdf_reader_tool.py +67 -0
- aip_agents/tools/document_loader/pdf_reader_tool.pyi +11 -0
- aip_agents/tools/document_loader/pdf_splitter.py +169 -0
- aip_agents/tools/document_loader/pdf_splitter.pyi +18 -0
- aip_agents/tools/gl_connector/__init__.py +5 -0
- aip_agents/tools/gl_connector/__init__.pyi +3 -0
- aip_agents/tools/gl_connector/tool.py +351 -0
- aip_agents/tools/gl_connector/tool.pyi +74 -0
- aip_agents/tools/memory_search/__init__.py +22 -0
- aip_agents/tools/memory_search/__init__.pyi +5 -0
- aip_agents/tools/memory_search/base.py +200 -0
- aip_agents/tools/memory_search/base.pyi +69 -0
- aip_agents/tools/memory_search/mem0.py +258 -0
- aip_agents/tools/memory_search/mem0.pyi +19 -0
- aip_agents/tools/memory_search/schema.py +48 -0
- aip_agents/tools/memory_search/schema.pyi +15 -0
- aip_agents/tools/memory_search_tool.py +26 -0
- aip_agents/tools/memory_search_tool.pyi +3 -0
- aip_agents/tools/tool_config_injector.py +300 -0
- aip_agents/tools/web_search/__init__.py +15 -0
- aip_agents/tools/web_search/__init__.pyi +3 -0
- aip_agents/tools/web_search/serper_tool.py +187 -0
- aip_agents/tools/web_search/serper_tool.pyi +19 -0
- aip_agents/types/__init__.py +70 -0
- aip_agents/types/__init__.pyi +35 -2
- aip_agents/types/a2a_events.py +13 -0
- aip_agents/types/a2a_events.pyi +2 -73
- aip_agents/utils/__init__.py +79 -0
- aip_agents/utils/__init__.pyi +8 -2
- aip_agents/utils/a2a_connector.py +1757 -0
- aip_agents/utils/a2a_connector.pyi +15 -4
- aip_agents/utils/artifact_helpers.py +502 -0
- aip_agents/utils/artifact_helpers.pyi +26 -2
- aip_agents/utils/constants.py +22 -0
- aip_agents/utils/constants.pyi +10 -0
- aip_agents/utils/datetime/__init__.py +34 -0
- aip_agents/utils/datetime/__init__.pyi +4 -0
- aip_agents/utils/datetime/normalization.py +231 -0
- aip_agents/utils/datetime/normalization.pyi +95 -0
- aip_agents/utils/datetime/timezone.py +206 -0
- aip_agents/utils/datetime/timezone.pyi +48 -0
- aip_agents/utils/env_loader.py +27 -0
- aip_agents/utils/env_loader.pyi +10 -0
- aip_agents/utils/event_handler_registry.py +58 -0
- aip_agents/utils/event_handler_registry.pyi +23 -0
- aip_agents/utils/file_prompt_utils.py +176 -0
- aip_agents/utils/file_prompt_utils.pyi +21 -0
- aip_agents/utils/final_response_builder.py +211 -0
- aip_agents/utils/final_response_builder.pyi +34 -0
- aip_agents/utils/formatter_llm_client.py +231 -0
- aip_agents/utils/formatter_llm_client.pyi +71 -0
- aip_agents/utils/langgraph/__init__.py +19 -0
- aip_agents/utils/langgraph/converter.py +128 -0
- aip_agents/utils/langgraph/converter.pyi +1 -1
- aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
- aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
- aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +2 -2
- aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
- aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +2 -3
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1071 -0
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +17 -11
- aip_agents/utils/langgraph/tool_output_management.py +967 -0
- aip_agents/utils/langgraph/tool_output_management.pyi +15 -33
- aip_agents/utils/logger.py +195 -0
- aip_agents/utils/logger.pyi +60 -0
- aip_agents/utils/metadata/__init__.py +27 -0
- aip_agents/utils/metadata/__init__.pyi +5 -0
- aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
- aip_agents/utils/metadata/activity_metadata_helper.pyi +25 -0
- aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
- aip_agents/utils/metadata/activity_narrative/__init__.pyi +7 -0
- aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
- aip_agents/utils/metadata/activity_narrative/builder.pyi +35 -0
- aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
- aip_agents/utils/metadata/activity_narrative/constants.pyi +10 -0
- aip_agents/utils/metadata/activity_narrative/context.py +49 -0
- aip_agents/utils/metadata/activity_narrative/context.pyi +32 -0
- aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
- aip_agents/utils/metadata/activity_narrative/formatters.pyi +48 -0
- aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
- aip_agents/utils/metadata/activity_narrative/utils.pyi +12 -0
- aip_agents/utils/metadata/schemas/__init__.py +16 -0
- aip_agents/utils/metadata/schemas/__init__.pyi +4 -0
- aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
- aip_agents/utils/metadata/schemas/activity_schema.pyi +18 -0
- aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
- aip_agents/utils/metadata/schemas/thinking_schema.pyi +20 -0
- aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
- aip_agents/utils/metadata/thinking_metadata_helper.pyi +4 -0
- aip_agents/utils/metadata_helper.py +358 -0
- aip_agents/utils/metadata_helper.pyi +55 -48
- aip_agents/utils/name_preprocessor/__init__.py +17 -0
- aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
- aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +1 -2
- aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
- aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +1 -1
- aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
- aip_agents/utils/name_preprocessor/name_preprocessor.pyi +4 -4
- aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
- aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +1 -1
- aip_agents/utils/pii/__init__.py +25 -0
- aip_agents/utils/pii/__init__.pyi +5 -0
- aip_agents/utils/pii/pii_handler.py +397 -0
- aip_agents/utils/pii/pii_handler.pyi +96 -0
- aip_agents/utils/pii/pii_helper.py +207 -0
- aip_agents/utils/pii/pii_helper.pyi +78 -0
- aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
- aip_agents/utils/pii/uuid_deanonymizer_mapping.pyi +73 -0
- aip_agents/utils/reference_helper.py +273 -0
- aip_agents/utils/reference_helper.pyi +38 -6
- aip_agents/utils/sse_chunk_transformer.py +831 -0
- aip_agents/utils/sse_chunk_transformer.pyi +166 -0
- aip_agents/utils/step_limit_manager.py +265 -0
- aip_agents/utils/step_limit_manager.pyi +112 -0
- aip_agents/utils/token_usage_helper.py +156 -0
- aip_agents/utils/token_usage_helper.pyi +1 -1
- aip_agents_binary-0.5.11.dist-info/METADATA +689 -0
- aip_agents_binary-0.5.11.dist-info/RECORD +542 -0
- {aip_agents_binary-0.0.0b2.dist-info → aip_agents_binary-0.5.11.dist-info}/WHEEL +2 -1
- aip_agents_binary-0.5.11.dist-info/top_level.txt +1 -0
- aip_agents/agent/types.pyi +0 -106
- aip_agents/examples/hello_world_a2a_multi_agent_coordinator_client.pyi +0 -15
- aip_agents/examples/hello_world_a2a_multi_agent_coordinator_client_streaming.pyi +0 -5
- aip_agents/examples/hello_world_a2a_multi_agent_coordinator_server.pyi +0 -11
- aip_agents/examples/hello_world_langgraph_bosa.pyi +0 -5
- aip_agents/examples/tools/pr_details_bosa_tool.pyi +0 -26
- aip_agents/tools/base.pyi +0 -44
- aip_agents/tools/base_bosa_tools.pyi +0 -12
- aip_agents/tools/bosa_connector.pyi +0 -30
- aip_agents/tools/bosa_tools_interface.pyi +0 -26
- aip_agents/tools/nested_agent_tool.pyi +0 -45
- aip_agents/utils/logger_manager.pyi +0 -151
- aip_agents_binary-0.0.0b2.dist-info/METADATA +0 -277
- 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()
|
aip_agents/sentry/sentry.pyi
CHANGED
|
@@ -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.
|
|
4
|
-
from fastapi import 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
|
aip_agents/storage/base.pyi
CHANGED
|
@@ -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
|
|
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)
|