aip-agents-binary 0.5.20__py3-none-manylinux_2_31_x86_64.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 +3 -0
- aip_agents/a2a/server/__init__.py +10 -0
- aip_agents/a2a/server/__init__.pyi +4 -0
- aip_agents/a2a/server/base_executor.py +1086 -0
- aip_agents/a2a/server/base_executor.pyi +73 -0
- aip_agents/a2a/server/google_adk_executor.py +198 -0
- aip_agents/a2a/server/google_adk_executor.pyi +51 -0
- 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 +270 -0
- aip_agents/a2a/server/langgraph_executor.pyi +47 -0
- aip_agents/a2a/types.py +232 -0
- aip_agents/a2a/types.pyi +132 -0
- aip_agents/agent/__init__.py +27 -0
- aip_agents/agent/__init__.pyi +9 -0
- aip_agents/agent/base_agent.py +970 -0
- aip_agents/agent/base_agent.pyi +221 -0
- aip_agents/agent/base_langgraph_agent.py +2942 -0
- aip_agents/agent/base_langgraph_agent.pyi +232 -0
- aip_agents/agent/google_adk_agent.py +926 -0
- aip_agents/agent/google_adk_agent.pyi +141 -0
- 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 +532 -0
- aip_agents/agent/hitl/manager.pyi +200 -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/hitl/registry.py +149 -0
- aip_agents/agent/hitl/registry.pyi +101 -0
- aip_agents/agent/interface.py +138 -0
- aip_agents/agent/interface.pyi +81 -0
- 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 +126 -0
- 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 +7 -0
- aip_agents/credentials/manager.py +132 -0
- aip_agents/examples/__init__.py +5 -0
- aip_agents/examples/__init__.pyi +0 -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 +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +9 -0
- aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
- aip_agents/examples/hello_world_a2a_google_adk_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
- aip_agents/examples/hello_world_a2a_langchain_server.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +15 -0
- 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 +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +16 -0
- aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client.pyi +9 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +9 -0
- 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 +2 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +9 -0
- 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 +5 -0
- 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 +5 -0
- aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
- aip_agents/examples/hello_world_a2a_langgraph_server.pyi +14 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +15 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +15 -0
- aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
- aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +48 -0
- 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 +48 -0
- 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 +45 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +5 -0
- 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 +15 -0
- aip_agents/examples/hello_world_google_adk.py +41 -0
- aip_agents/examples/hello_world_google_adk.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
- aip_agents/examples/hello_world_google_adk_mcp_http.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
- aip_agents/examples/hello_world_google_adk_mcp_http_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
- aip_agents/examples/hello_world_google_adk_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
- aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_google_adk_stream.py +44 -0
- aip_agents/examples/hello_world_google_adk_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain.py +28 -0
- aip_agents/examples/hello_world_langchain.pyi +5 -0
- aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
- aip_agents/examples/hello_world_langchain_lm_invoker.pyi +2 -0
- aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
- aip_agents/examples/hello_world_langchain_mcp_http.pyi +5 -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_http_stream.pyi +5 -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.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
- aip_agents/examples/hello_world_langchain_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
- aip_agents/examples/hello_world_langchain_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_stream.py +36 -0
- aip_agents/examples/hello_world_langchain_stream.pyi +5 -0
- aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
- aip_agents/examples/hello_world_langchain_stream_lm_invoker.pyi +5 -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.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_bosa_twitter.py +41 -0
- aip_agents/examples/hello_world_langgraph_bosa_twitter.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
- aip_agents/examples/hello_world_langgraph_mcp_http.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
- aip_agents/examples/hello_world_langgraph_mcp_http_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
- aip_agents/examples/hello_world_langgraph_mcp_sse_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
- aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_stream.py +43 -0
- aip_agents/examples/hello_world_langgraph_stream.pyi +5 -0
- aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
- aip_agents/examples/hello_world_langgraph_stream_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_model_switch_cli.py +210 -0
- aip_agents/examples/hello_world_model_switch_cli.pyi +30 -0
- aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
- aip_agents/examples/hello_world_multi_agent_adk.pyi +6 -0
- aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
- aip_agents/examples/hello_world_multi_agent_langchain.pyi +5 -0
- aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
- aip_agents/examples/hello_world_multi_agent_langgraph.pyi +5 -0
- aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
- aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.pyi +5 -0
- aip_agents/examples/hello_world_pii_logger.py +21 -0
- aip_agents/examples/hello_world_pii_logger.pyi +5 -0
- aip_agents/examples/hello_world_sentry.py +133 -0
- aip_agents/examples/hello_world_sentry.pyi +21 -0
- 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 +17 -0
- aip_agents/examples/hello_world_tool_output_client.py +46 -0
- aip_agents/examples/hello_world_tool_output_client.pyi +5 -0
- aip_agents/examples/hello_world_tool_output_server.py +114 -0
- aip_agents/examples/hello_world_tool_output_server.pyi +19 -0
- 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 +9 -0
- aip_agents/examples/tools/adk_arithmetic_tools.py +36 -0
- aip_agents/examples/tools/adk_arithmetic_tools.pyi +24 -0
- aip_agents/examples/tools/adk_weather_tool.py +60 -0
- aip_agents/examples/tools/adk_weather_tool.pyi +18 -0
- aip_agents/examples/tools/data_generator_tool.py +103 -0
- aip_agents/examples/tools/data_generator_tool.pyi +15 -0
- aip_agents/examples/tools/data_visualization_tool.py +312 -0
- aip_agents/examples/tools/data_visualization_tool.pyi +19 -0
- aip_agents/examples/tools/image_artifact_tool.py +136 -0
- aip_agents/examples/tools/image_artifact_tool.pyi +26 -0
- aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
- aip_agents/examples/tools/langchain_arithmetic_tools.pyi +17 -0
- aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
- aip_agents/examples/tools/langchain_currency_exchange_tool.pyi +20 -0
- aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
- aip_agents/examples/tools/langchain_graph_artifact_tool.pyi +25 -0
- aip_agents/examples/tools/langchain_weather_tool.py +48 -0
- aip_agents/examples/tools/langchain_weather_tool.pyi +19 -0
- aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
- aip_agents/examples/tools/langgraph_streaming_tool.pyi +43 -0
- 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/serper_tool.pyi +16 -0
- aip_agents/examples/tools/stock_tools.py +82 -0
- aip_agents/examples/tools/stock_tools.pyi +36 -0
- aip_agents/examples/tools/table_generator_tool.py +167 -0
- aip_agents/examples/tools/table_generator_tool.pyi +22 -0
- aip_agents/examples/tools/time_tool.py +82 -0
- aip_agents/examples/tools/time_tool.pyi +15 -0
- aip_agents/examples/tools/weather_forecast_tool.py +38 -0
- aip_agents/examples/tools/weather_forecast_tool.pyi +14 -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/__init__.pyi +0 -0
- aip_agents/mcp/client/__init__.py +14 -0
- aip_agents/mcp/client/__init__.pyi +5 -0
- 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 +3 -0
- aip_agents/mcp/client/google_adk/client.py +381 -0
- aip_agents/mcp/client/google_adk/client.pyi +75 -0
- aip_agents/mcp/client/langchain/__init__.py +11 -0
- aip_agents/mcp/client/langchain/__init__.pyi +3 -0
- aip_agents/mcp/client/langchain/client.py +265 -0
- aip_agents/mcp/client/langchain/client.pyi +48 -0
- 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 +60 -0
- 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 +23 -0
- 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 +3 -0
- aip_agents/sentry/sentry.py +151 -0
- aip_agents/sentry/sentry.pyi +48 -0
- aip_agents/storage/__init__.py +41 -0
- aip_agents/storage/__init__.pyi +8 -0
- aip_agents/storage/base.py +85 -0
- aip_agents/storage/base.pyi +58 -0
- aip_agents/storage/clients/__init__.py +12 -0
- aip_agents/storage/clients/__init__.pyi +3 -0
- aip_agents/storage/clients/minio_client.py +318 -0
- aip_agents/storage/clients/minio_client.pyi +137 -0
- aip_agents/storage/config.py +62 -0
- aip_agents/storage/config.pyi +29 -0
- aip_agents/storage/providers/__init__.py +15 -0
- aip_agents/storage/providers/__init__.pyi +5 -0
- aip_agents/storage/providers/base.py +106 -0
- aip_agents/storage/providers/base.pyi +88 -0
- aip_agents/storage/providers/memory.py +114 -0
- aip_agents/storage/providers/memory.pyi +79 -0
- aip_agents/storage/providers/object_storage.py +214 -0
- aip_agents/storage/providers/object_storage.pyi +98 -0
- aip_agents/tools/__init__.py +33 -0
- aip_agents/tools/__init__.pyi +13 -0
- aip_agents/tools/bosa_tools.py +105 -0
- aip_agents/tools/bosa_tools.pyi +37 -0
- 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 +135 -0
- aip_agents/tools/document_loader/__init__.py +44 -0
- aip_agents/tools/document_loader/__init__.pyi +7 -0
- aip_agents/tools/document_loader/base_reader.py +302 -0
- aip_agents/tools/document_loader/base_reader.pyi +75 -0
- aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
- aip_agents/tools/document_loader/docx_reader_tool.pyi +10 -0
- aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
- aip_agents/tools/document_loader/excel_reader_tool.pyi +26 -0
- aip_agents/tools/document_loader/pdf_reader_tool.py +79 -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/time_tool.py +117 -0
- aip_agents/tools/time_tool.pyi +16 -0
- aip_agents/tools/tool_config_injector.py +300 -0
- aip_agents/tools/tool_config_injector.pyi +26 -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 +36 -0
- aip_agents/types/a2a_events.py +13 -0
- aip_agents/types/a2a_events.pyi +3 -0
- aip_agents/utils/__init__.py +79 -0
- aip_agents/utils/__init__.pyi +11 -0
- aip_agents/utils/a2a_connector.py +1757 -0
- aip_agents/utils/a2a_connector.pyi +146 -0
- aip_agents/utils/artifact_helpers.py +502 -0
- aip_agents/utils/artifact_helpers.pyi +203 -0
- 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/__init__.pyi +3 -0
- aip_agents/utils/langgraph/converter.py +128 -0
- aip_agents/utils/langgraph/converter.pyi +49 -0
- aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
- aip_agents/utils/langgraph/tool_managers/__init__.pyi +5 -0
- aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
- aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +35 -0
- aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
- aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +48 -0
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1071 -0
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +56 -0
- aip_agents/utils/langgraph/tool_output_management.py +967 -0
- aip_agents/utils/langgraph/tool_output_management.pyi +292 -0
- 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 +117 -0
- aip_agents/utils/name_preprocessor/__init__.py +17 -0
- aip_agents/utils/name_preprocessor/__init__.pyi +6 -0
- aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
- aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +52 -0
- aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
- aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +38 -0
- aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
- aip_agents/utils/name_preprocessor/name_preprocessor.pyi +41 -0
- aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
- aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +34 -0
- 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 +81 -0
- 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 +60 -0
- aip_agents_binary-0.5.20.dist-info/METADATA +681 -0
- aip_agents_binary-0.5.20.dist-info/RECORD +546 -0
- aip_agents_binary-0.5.20.dist-info/WHEEL +5 -0
- aip_agents_binary-0.5.20.dist-info/top_level.txt +1 -0
|
@@ -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,137 @@
|
|
|
1
|
+
from _typeshed import Incomplete
|
|
2
|
+
from aip_agents.storage.base import BaseObjectStorageClient as BaseObjectStorageClient
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
from typing import BinaryIO
|
|
5
|
+
|
|
6
|
+
S3_ERR_NO_SUCH_KEY: str
|
|
7
|
+
S3_ERR_NO_SUCH_BUCKET: str
|
|
8
|
+
S3_ERR_ACCESS_DENIED: str
|
|
9
|
+
|
|
10
|
+
@dataclass
|
|
11
|
+
class MinioConfig:
|
|
12
|
+
"""Configuration for MinIO object storage client.
|
|
13
|
+
|
|
14
|
+
Attributes:
|
|
15
|
+
endpoint: MinIO server endpoint URL
|
|
16
|
+
access_key: Access key for authentication
|
|
17
|
+
secret_key: Secret key for authentication
|
|
18
|
+
bucket: Bucket name to use for storage
|
|
19
|
+
secure: Whether to use HTTPS (defaults to True)
|
|
20
|
+
"""
|
|
21
|
+
endpoint: str
|
|
22
|
+
access_key: str
|
|
23
|
+
secret_key: str
|
|
24
|
+
bucket: str
|
|
25
|
+
secure: bool = ...
|
|
26
|
+
@classmethod
|
|
27
|
+
def from_env(cls) -> MinioConfig:
|
|
28
|
+
"""Create MinioConfig from environment variables.
|
|
29
|
+
|
|
30
|
+
Expected environment variables:
|
|
31
|
+
- OBJECT_STORAGE_URL
|
|
32
|
+
- OBJECT_STORAGE_USER
|
|
33
|
+
- OBJECT_STORAGE_PASSWORD
|
|
34
|
+
- OBJECT_STORAGE_BUCKET
|
|
35
|
+
- OBJECT_STORAGE_SECURE (optional, defaults to True)
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
MinioConfig instance
|
|
39
|
+
|
|
40
|
+
Raises:
|
|
41
|
+
ValueError: If required environment variables are not set
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
class MinioObjectStorage(BaseObjectStorageClient):
|
|
45
|
+
"""Implementation of ObjectStorageInterface using Minio."""
|
|
46
|
+
config: Incomplete
|
|
47
|
+
client: Incomplete
|
|
48
|
+
bucket: Incomplete
|
|
49
|
+
def __init__(self, config: MinioConfig | None = None, ensure_bucket: bool = True) -> None:
|
|
50
|
+
"""Initialize MinioObjectStorage with configuration.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
config: MinioConfig instance. If None, will attempt to load from environment variables.
|
|
54
|
+
ensure_bucket: Whether to ensure bucket exists during initialization (optional). Defaults to True.
|
|
55
|
+
|
|
56
|
+
Raises:
|
|
57
|
+
ValueError: If configuration is invalid or incomplete
|
|
58
|
+
"""
|
|
59
|
+
def upload(self, object_key: str, file_stream: bytes | BinaryIO, filename: str | None = None, content_type: str | None = None, metadata: dict[str, str] | None = None) -> str:
|
|
60
|
+
"""Upload data to Minio object storage.
|
|
61
|
+
|
|
62
|
+
Args:
|
|
63
|
+
object_key: The key to store the object under
|
|
64
|
+
file_stream: The data to upload (bytes or file-like object)
|
|
65
|
+
filename: The filename of the data (optional)
|
|
66
|
+
content_type: The content type of the data (optional)
|
|
67
|
+
metadata: Additional metadata to store with the object (optional)
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
The object key of the uploaded data
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
ValueError: If the file stream is empty or invalid
|
|
74
|
+
ConnectionError: If there's an issue connecting to Minio
|
|
75
|
+
Exception: For other unexpected errors during upload
|
|
76
|
+
"""
|
|
77
|
+
def get(self, object_key: str) -> bytes:
|
|
78
|
+
"""Get data from Minio object storage.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
object_key: The key of the object to retrieve
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
The object data as bytes
|
|
85
|
+
|
|
86
|
+
Raises:
|
|
87
|
+
KeyError: If the object is not found
|
|
88
|
+
ConnectionError: If there's a network or connection issue
|
|
89
|
+
"""
|
|
90
|
+
def delete(self, object_key: str) -> None:
|
|
91
|
+
"""Delete data from Minio object storage.
|
|
92
|
+
|
|
93
|
+
Args:
|
|
94
|
+
object_key: The key of the object to delete
|
|
95
|
+
|
|
96
|
+
Raises:
|
|
97
|
+
ConnectionError: If there's a network or connection issue
|
|
98
|
+
"""
|
|
99
|
+
def object_exists(self, object_key: str) -> bool:
|
|
100
|
+
"""Check if an object exists in the MinIO bucket.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
object_key: The key of the object to check.
|
|
104
|
+
|
|
105
|
+
Returns:
|
|
106
|
+
True if the object exists, False otherwise.
|
|
107
|
+
|
|
108
|
+
Raises:
|
|
109
|
+
ConnectionError: If there's a network or connection issue (excluding not found errors)
|
|
110
|
+
"""
|
|
111
|
+
def list_objects(self, prefix: str = '') -> list[str]:
|
|
112
|
+
"""List objects in the bucket with optional prefix filter.
|
|
113
|
+
|
|
114
|
+
Args:
|
|
115
|
+
prefix: Optional prefix to filter objects
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
List of object keys
|
|
119
|
+
|
|
120
|
+
Raises:
|
|
121
|
+
ConnectionError: If there's an issue listing objects
|
|
122
|
+
"""
|
|
123
|
+
def generate_presigned_url(self, object_key: str, expires: int = 24, response_headers: dict[str, str] | None = None) -> str:
|
|
124
|
+
"""Generate a presigned URL for accessing the object.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
object_key: The key of the object
|
|
128
|
+
expires: Expiration time in hours (defaults to 24)
|
|
129
|
+
response_headers: Additional response headers (optional)
|
|
130
|
+
|
|
131
|
+
Returns:
|
|
132
|
+
A presigned URL
|
|
133
|
+
|
|
134
|
+
Raises:
|
|
135
|
+
ValueError: If expiration time is not positive
|
|
136
|
+
ConnectionError: If there's an issue generating the URL
|
|
137
|
+
"""
|
|
@@ -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)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
from aip_agents.schema.storage import OBJECT_STORAGE_PREFIX as OBJECT_STORAGE_PREFIX, StorageConfig as StorageConfig, StorageType as StorageType
|
|
2
|
+
from aip_agents.storage.base import BaseObjectStorageClient
|
|
3
|
+
from aip_agents.storage.providers.base import BaseStorageProvider
|
|
4
|
+
|
|
5
|
+
__all__ = ['OBJECT_STORAGE_PREFIX', 'StorageConfig', 'StorageType', 'StorageProviderFactory']
|
|
6
|
+
|
|
7
|
+
class StorageProviderFactory:
|
|
8
|
+
"""Factory for creating storage providers based on configuration."""
|
|
9
|
+
@staticmethod
|
|
10
|
+
def create(config: StorageConfig, object_storage_client: BaseObjectStorageClient | None = None) -> BaseStorageProvider:
|
|
11
|
+
"""Create storage provider based on configuration.
|
|
12
|
+
|
|
13
|
+
Args:
|
|
14
|
+
config (StorageConfig): Storage configuration object.
|
|
15
|
+
object_storage_client (BaseObjectStorageClient | None, optional): Optional object storage client for object storage type.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
BaseStorageProvider: The created storage provider instance.
|
|
19
|
+
"""
|
|
20
|
+
@staticmethod
|
|
21
|
+
def create_from_env(object_storage_client: BaseObjectStorageClient | None = None) -> BaseStorageProvider:
|
|
22
|
+
"""Create storage provider from environment variables.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
object_storage_client (BaseObjectStorageClient | None, optional): Optional object storage client for object storage type.
|
|
26
|
+
|
|
27
|
+
Returns:
|
|
28
|
+
BaseStorageProvider: The created storage provider instance.
|
|
29
|
+
"""
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"""Storage providers for tool output management.
|
|
2
|
+
|
|
3
|
+
This module provides different storage backends for tool outputs including
|
|
4
|
+
in-memory, file-based, and object storage providers.
|
|
5
|
+
|
|
6
|
+
Authors:
|
|
7
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
8
|
+
Fachriza Adhiatma (fachriza.d.adhiatma@gdplabs.id)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from aip_agents.storage.providers.base import BaseStorageProvider, StorageError
|
|
12
|
+
from aip_agents.storage.providers.memory import InMemoryStorageProvider
|
|
13
|
+
from aip_agents.storage.providers.object_storage import ObjectStorageProvider
|
|
14
|
+
|
|
15
|
+
__all__ = ["BaseStorageProvider", "StorageError", "InMemoryStorageProvider", "ObjectStorageProvider"]
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
from aip_agents.storage.providers.base import BaseStorageProvider as BaseStorageProvider, StorageError as StorageError
|
|
2
|
+
from aip_agents.storage.providers.memory import InMemoryStorageProvider as InMemoryStorageProvider
|
|
3
|
+
from aip_agents.storage.providers.object_storage import ObjectStorageProvider as ObjectStorageProvider
|
|
4
|
+
|
|
5
|
+
__all__ = ['BaseStorageProvider', 'StorageError', 'InMemoryStorageProvider', 'ObjectStorageProvider']
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"""Base storage provider interface.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Christian Trisno Sen Long Chen (christian.t.s.l.chen@gdplabs.id)
|
|
5
|
+
Fachriza Adhiatma (fachriza.d.adhiatma@gdplabs.id)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from abc import ABC, abstractmethod
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from aip_agents.utils.logger import get_logger
|
|
12
|
+
|
|
13
|
+
logger = get_logger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class StorageError(Exception):
|
|
17
|
+
"""Base exception for storage operations."""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class BaseStorageProvider(ABC):
|
|
21
|
+
"""Base interface for storage providers.
|
|
22
|
+
|
|
23
|
+
This abstract class defines the contract that all storage providers
|
|
24
|
+
must implement to store and retrieve tool outputs.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
@abstractmethod
|
|
28
|
+
def store(self, key: str, data: Any) -> None:
|
|
29
|
+
"""Store data with the given key.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
key: Unique identifier for the data
|
|
33
|
+
data: Data to store (must be serializable)
|
|
34
|
+
|
|
35
|
+
Raises:
|
|
36
|
+
StorageError: If storage operation fails
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
@abstractmethod
|
|
40
|
+
def retrieve(self, key: str) -> Any:
|
|
41
|
+
"""Retrieve data by key.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
key: Unique identifier for the data
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
The stored data
|
|
48
|
+
|
|
49
|
+
Raises:
|
|
50
|
+
KeyError: If key not found
|
|
51
|
+
StorageError: If retrieval operation fails
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
@abstractmethod
|
|
55
|
+
def exists(self, key: str) -> bool:
|
|
56
|
+
"""Check if key exists.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
key: Unique identifier to check
|
|
60
|
+
|
|
61
|
+
Returns:
|
|
62
|
+
True if key exists, False otherwise
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
@abstractmethod
|
|
66
|
+
def delete(self, key: str) -> None:
|
|
67
|
+
"""Delete data by key.
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
key: Unique identifier for the data
|
|
71
|
+
|
|
72
|
+
Note:
|
|
73
|
+
Should not raise error if key doesn't exist
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
@abstractmethod
|
|
77
|
+
def list_keys(self, prefix: str = "") -> list[str]:
|
|
78
|
+
"""List all keys with optional prefix filter.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
prefix: Optional prefix to filter keys
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
List of matching keys
|
|
85
|
+
"""
|
|
86
|
+
|
|
87
|
+
@abstractmethod
|
|
88
|
+
def clear(self) -> None:
|
|
89
|
+
"""Clear all stored data.
|
|
90
|
+
|
|
91
|
+
Warning:
|
|
92
|
+
This operation is irreversible
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
def get_presigned_url(self, key: str, expires_hours: int = 24) -> str | None:
|
|
96
|
+
"""Generate presigned URL for direct access (optional).
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
key: Storage key
|
|
100
|
+
expires_hours: URL expiration in hours
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Presigned URL if supported, None otherwise
|
|
104
|
+
"""
|
|
105
|
+
logger.warning("This class get_presigned_url not implemented for this storage provider")
|
|
106
|
+
return None
|