aip-agents-binary 0.5.20__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/a2a/__init__.py +19 -0
- aip_agents/a2a/server/__init__.py +10 -0
- aip_agents/a2a/server/base_executor.py +1086 -0
- aip_agents/a2a/server/google_adk_executor.py +198 -0
- aip_agents/a2a/server/langflow_executor.py +180 -0
- aip_agents/a2a/server/langgraph_executor.py +270 -0
- aip_agents/a2a/types.py +232 -0
- aip_agents/agent/__init__.py +27 -0
- aip_agents/agent/base_agent.py +970 -0
- aip_agents/agent/base_langgraph_agent.py +2942 -0
- aip_agents/agent/google_adk_agent.py +926 -0
- aip_agents/agent/google_adk_constants.py +6 -0
- aip_agents/agent/hitl/__init__.py +24 -0
- aip_agents/agent/hitl/config.py +28 -0
- aip_agents/agent/hitl/langgraph_hitl_mixin.py +515 -0
- aip_agents/agent/hitl/manager.py +532 -0
- aip_agents/agent/hitl/models.py +18 -0
- aip_agents/agent/hitl/prompt/__init__.py +9 -0
- aip_agents/agent/hitl/prompt/base.py +42 -0
- aip_agents/agent/hitl/prompt/deferred.py +73 -0
- aip_agents/agent/hitl/registry.py +149 -0
- aip_agents/agent/interface.py +138 -0
- aip_agents/agent/interfaces.py +65 -0
- aip_agents/agent/langflow_agent.py +464 -0
- aip_agents/agent/langgraph_memory_enhancer_agent.py +433 -0
- aip_agents/agent/langgraph_react_agent.py +2514 -0
- aip_agents/agent/system_instruction_context.py +34 -0
- aip_agents/clients/__init__.py +10 -0
- aip_agents/clients/langflow/__init__.py +10 -0
- aip_agents/clients/langflow/client.py +477 -0
- aip_agents/clients/langflow/types.py +18 -0
- aip_agents/constants.py +23 -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_server.py +142 -0
- aip_agents/examples/demo_memory_recall.py +401 -0
- aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
- aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_google_adk_server.py +79 -0
- aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
- aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
- aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
- aip_agents/examples/hello_world_a2a_langchain_reference_server.py +105 -0
- aip_agents/examples/hello_world_a2a_langchain_server.py +79 -0
- aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +78 -0
- aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
- aip_agents/examples/hello_world_a2a_langflow_server.py +82 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
- aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +92 -0
- aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
- aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
- aip_agents/examples/hello_world_a2a_langgraph_server.py +84 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +79 -0
- aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +132 -0
- aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -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_server.py +251 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
- aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +80 -0
- 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_stream.py +42 -0
- aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -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_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_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_sentry.py +133 -0
- aip_agents/examples/hello_world_step_limits.py +273 -0
- aip_agents/examples/hello_world_stock_a2a_server.py +103 -0
- aip_agents/examples/hello_world_tool_output_client.py +46 -0
- aip_agents/examples/hello_world_tool_output_server.py +114 -0
- aip_agents/examples/hitl_demo.py +724 -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_server.py +126 -0
- aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
- aip_agents/examples/pii_demo_multi_agent_server.py +247 -0
- aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
- aip_agents/examples/todolist_planning_a2a_langgraph_server.py +88 -0
- aip_agents/examples/tools/__init__.py +27 -0
- aip_agents/examples/tools/adk_arithmetic_tools.py +36 -0
- aip_agents/examples/tools/adk_weather_tool.py +60 -0
- aip_agents/examples/tools/data_generator_tool.py +103 -0
- aip_agents/examples/tools/data_visualization_tool.py +312 -0
- aip_agents/examples/tools/image_artifact_tool.py +136 -0
- aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
- aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
- aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
- aip_agents/examples/tools/langchain_weather_tool.py +48 -0
- aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
- aip_agents/examples/tools/mock_retrieval_tool.py +56 -0
- aip_agents/examples/tools/pii_demo_tools.py +189 -0
- aip_agents/examples/tools/random_chart_tool.py +142 -0
- aip_agents/examples/tools/serper_tool.py +202 -0
- aip_agents/examples/tools/stock_tools.py +82 -0
- 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/base_mcp_client.py +369 -0
- aip_agents/mcp/client/connection_manager.py +193 -0
- aip_agents/mcp/client/google_adk/__init__.py +11 -0
- aip_agents/mcp/client/google_adk/client.py +381 -0
- aip_agents/mcp/client/langchain/__init__.py +11 -0
- aip_agents/mcp/client/langchain/client.py +265 -0
- aip_agents/mcp/client/persistent_session.py +359 -0
- aip_agents/mcp/client/session_pool.py +351 -0
- aip_agents/mcp/client/transports.py +215 -0
- aip_agents/mcp/utils/__init__.py +7 -0
- aip_agents/mcp/utils/config_validator.py +139 -0
- aip_agents/memory/__init__.py +14 -0
- aip_agents/memory/adapters/__init__.py +10 -0
- aip_agents/memory/adapters/base_adapter.py +717 -0
- aip_agents/memory/adapters/mem0.py +84 -0
- aip_agents/memory/base.py +84 -0
- aip_agents/memory/constants.py +49 -0
- aip_agents/memory/factory.py +86 -0
- aip_agents/memory/guidance.py +20 -0
- aip_agents/memory/simple_memory.py +47 -0
- aip_agents/middleware/__init__.py +17 -0
- aip_agents/middleware/base.py +88 -0
- aip_agents/middleware/manager.py +128 -0
- aip_agents/middleware/todolist.py +274 -0
- aip_agents/schema/__init__.py +69 -0
- aip_agents/schema/a2a.py +56 -0
- aip_agents/schema/agent.py +111 -0
- aip_agents/schema/hitl.py +157 -0
- aip_agents/schema/langgraph.py +37 -0
- aip_agents/schema/model_id.py +97 -0
- aip_agents/schema/step_limit.py +108 -0
- aip_agents/schema/storage.py +40 -0
- aip_agents/sentry/__init__.py +11 -0
- aip_agents/sentry/sentry.py +151 -0
- aip_agents/storage/__init__.py +41 -0
- aip_agents/storage/base.py +85 -0
- 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/providers/__init__.py +15 -0
- aip_agents/storage/providers/base.py +106 -0
- aip_agents/storage/providers/memory.py +114 -0
- aip_agents/storage/providers/object_storage.py +214 -0
- aip_agents/tools/__init__.py +33 -0
- aip_agents/tools/bosa_tools.py +105 -0
- aip_agents/tools/browser_use/__init__.py +82 -0
- aip_agents/tools/browser_use/action_parser.py +103 -0
- aip_agents/tools/browser_use/browser_use_tool.py +1112 -0
- aip_agents/tools/browser_use/llm_config.py +120 -0
- aip_agents/tools/browser_use/minio_storage.py +198 -0
- aip_agents/tools/browser_use/schemas.py +119 -0
- aip_agents/tools/browser_use/session.py +76 -0
- aip_agents/tools/browser_use/session_errors.py +132 -0
- aip_agents/tools/browser_use/steel_session_recording.py +317 -0
- aip_agents/tools/browser_use/streaming.py +813 -0
- aip_agents/tools/browser_use/structured_data_parser.py +257 -0
- aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
- aip_agents/tools/browser_use/types.py +78 -0
- aip_agents/tools/code_sandbox/__init__.py +26 -0
- aip_agents/tools/code_sandbox/constant.py +13 -0
- aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +257 -0
- aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +411 -0
- aip_agents/tools/constants.py +165 -0
- aip_agents/tools/document_loader/__init__.py +44 -0
- aip_agents/tools/document_loader/base_reader.py +302 -0
- aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
- aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
- aip_agents/tools/document_loader/pdf_reader_tool.py +79 -0
- aip_agents/tools/document_loader/pdf_splitter.py +169 -0
- aip_agents/tools/gl_connector/__init__.py +5 -0
- aip_agents/tools/gl_connector/tool.py +351 -0
- aip_agents/tools/memory_search/__init__.py +22 -0
- aip_agents/tools/memory_search/base.py +200 -0
- aip_agents/tools/memory_search/mem0.py +258 -0
- aip_agents/tools/memory_search/schema.py +48 -0
- aip_agents/tools/memory_search_tool.py +26 -0
- aip_agents/tools/time_tool.py +117 -0
- aip_agents/tools/tool_config_injector.py +300 -0
- aip_agents/tools/web_search/__init__.py +15 -0
- aip_agents/tools/web_search/serper_tool.py +187 -0
- aip_agents/types/__init__.py +70 -0
- aip_agents/types/a2a_events.py +13 -0
- aip_agents/utils/__init__.py +79 -0
- aip_agents/utils/a2a_connector.py +1757 -0
- aip_agents/utils/artifact_helpers.py +502 -0
- aip_agents/utils/constants.py +22 -0
- aip_agents/utils/datetime/__init__.py +34 -0
- aip_agents/utils/datetime/normalization.py +231 -0
- aip_agents/utils/datetime/timezone.py +206 -0
- aip_agents/utils/env_loader.py +27 -0
- aip_agents/utils/event_handler_registry.py +58 -0
- aip_agents/utils/file_prompt_utils.py +176 -0
- aip_agents/utils/final_response_builder.py +211 -0
- aip_agents/utils/formatter_llm_client.py +231 -0
- aip_agents/utils/langgraph/__init__.py +19 -0
- aip_agents/utils/langgraph/converter.py +128 -0
- 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/base_tool_manager.py +66 -0
- aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1071 -0
- aip_agents/utils/langgraph/tool_output_management.py +967 -0
- aip_agents/utils/logger.py +195 -0
- aip_agents/utils/metadata/__init__.py +27 -0
- aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
- aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
- aip_agents/utils/metadata/activity_narrative/builder.py +817 -0
- aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
- aip_agents/utils/metadata/activity_narrative/context.py +49 -0
- aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
- aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
- aip_agents/utils/metadata/schemas/__init__.py +16 -0
- aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
- aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
- aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
- aip_agents/utils/metadata_helper.py +358 -0
- 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/google_name_preprocessor.py +100 -0
- aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
- aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
- aip_agents/utils/pii/__init__.py +25 -0
- aip_agents/utils/pii/pii_handler.py +397 -0
- aip_agents/utils/pii/pii_helper.py +207 -0
- aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
- aip_agents/utils/reference_helper.py +273 -0
- aip_agents/utils/sse_chunk_transformer.py +831 -0
- aip_agents/utils/step_limit_manager.py +265 -0
- aip_agents/utils/token_usage_helper.py +156 -0
- aip_agents_binary-0.5.20.dist-info/METADATA +681 -0
- aip_agents_binary-0.5.20.dist-info/RECORD +280 -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,37 @@
|
|
|
1
|
+
"""LangGraph-related schema definitions for agent tool interactions."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
from gllm_core.schema import Chunk
|
|
9
|
+
from langchain_core.messages import ToolMessage
|
|
10
|
+
from langchain_core.messages.ai import UsageMetadata
|
|
11
|
+
from langchain_core.tools import BaseTool
|
|
12
|
+
|
|
13
|
+
__all__ = ["ToolCallResult", "ToolStorageParams"]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass
|
|
17
|
+
class ToolCallResult:
|
|
18
|
+
"""Container for the results of a single tool call execution."""
|
|
19
|
+
|
|
20
|
+
messages: list[ToolMessage]
|
|
21
|
+
artifacts: list[dict[str, Any]]
|
|
22
|
+
metadata_delta: dict[str, Any]
|
|
23
|
+
references: list[Chunk]
|
|
24
|
+
step_usage: UsageMetadata | None
|
|
25
|
+
pii_mapping: dict[str, str] | None = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@dataclass
|
|
29
|
+
class ToolStorageParams:
|
|
30
|
+
"""Parameters required for automatically storing tool outputs."""
|
|
31
|
+
|
|
32
|
+
tool: BaseTool
|
|
33
|
+
tool_output: Any
|
|
34
|
+
tool_call: dict[str, Any]
|
|
35
|
+
tool_call_id: str
|
|
36
|
+
resolved_args: dict[str, Any]
|
|
37
|
+
state: dict[str, Any]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Model identifiers and provider definitions for the AI agent platform."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from enum import StrEnum
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class ModelProvider(StrEnum):
|
|
9
|
+
"""Enumeration of supported model providers for the AI agent platform."""
|
|
10
|
+
|
|
11
|
+
OPENAI = "openai"
|
|
12
|
+
ANTHROPIC = "anthropic"
|
|
13
|
+
AZURE_OPENAI = "azure-openai"
|
|
14
|
+
GOOGLE_GENAI = "google"
|
|
15
|
+
GROQ = "groq"
|
|
16
|
+
TOGETHER_AI = "together"
|
|
17
|
+
DEEPINFRA = "deepinfra"
|
|
18
|
+
DEEPSEEK = "deepseek"
|
|
19
|
+
OPENAI_COMPATIBLE = "openai-compatible"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ModelId:
|
|
23
|
+
"""Model identifier class for representing language models."""
|
|
24
|
+
|
|
25
|
+
def __init__(self, provider: str, name: str, path: str | None = None):
|
|
26
|
+
"""Initialize a ModelId.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
provider: The model provider (e.g., 'openai', 'anthropic')
|
|
30
|
+
name: The specific model name
|
|
31
|
+
path: Optional path component for some providers
|
|
32
|
+
"""
|
|
33
|
+
self.provider = provider
|
|
34
|
+
self.name = name
|
|
35
|
+
self.path = path
|
|
36
|
+
|
|
37
|
+
@classmethod
|
|
38
|
+
def from_string(cls, model_string: str) -> ModelId:
|
|
39
|
+
"""Create a ModelId from a string representation.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
model_string: String in format 'provider:name' or 'provider/path:name'
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
ModelId instance
|
|
46
|
+
|
|
47
|
+
Raises:
|
|
48
|
+
ValueError: If the string format is invalid
|
|
49
|
+
"""
|
|
50
|
+
if ":" not in model_string:
|
|
51
|
+
raise ValueError(
|
|
52
|
+
f"Invalid model string format: {model_string}. Expected 'provider:name' or 'provider/path:name'"
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
# Find the last colon to separate provider+path from name
|
|
56
|
+
last_colon_idx = model_string.rindex(":")
|
|
57
|
+
provider_part = model_string[:last_colon_idx]
|
|
58
|
+
name = model_string[last_colon_idx + 1 :]
|
|
59
|
+
|
|
60
|
+
# Split provider_part on "/" to separate provider from path
|
|
61
|
+
if "/" in provider_part:
|
|
62
|
+
provider, path = provider_part.split("/", 1)
|
|
63
|
+
else:
|
|
64
|
+
provider = provider_part
|
|
65
|
+
path = None
|
|
66
|
+
|
|
67
|
+
return cls(provider, name, path)
|
|
68
|
+
|
|
69
|
+
def __str__(self) -> str:
|
|
70
|
+
"""String representation of the ModelId."""
|
|
71
|
+
if self.path:
|
|
72
|
+
return f"{self.provider}/{self.path}:{self.name}"
|
|
73
|
+
return f"{self.provider}:{self.name}"
|
|
74
|
+
|
|
75
|
+
def __repr__(self) -> str:
|
|
76
|
+
"""String representation of the ModelId for debugging."""
|
|
77
|
+
return f"ModelId(provider='{self.provider}', name='{self.name}', path='{self.path}')"
|
|
78
|
+
|
|
79
|
+
def __eq__(self, other: object) -> bool:
|
|
80
|
+
"""Check equality with another ModelId object.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
other (object): The object to compare with.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
bool: True if the objects are equal, False otherwise.
|
|
87
|
+
"""
|
|
88
|
+
if not isinstance(other, ModelId):
|
|
89
|
+
return NotImplemented
|
|
90
|
+
return self.provider == other.provider and self.name == other.name and self.path == other.path
|
|
91
|
+
|
|
92
|
+
def __hash__(self) -> int:
|
|
93
|
+
"""Return hash of the ModelId."""
|
|
94
|
+
return hash((self.provider, self.name, self.path))
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
__all__ = ["ModelId", "ModelProvider"]
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"""Step limit configuration and error classes for agent execution limits."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass, field
|
|
5
|
+
from enum import StrEnum
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class StepLimitErrorType(StrEnum):
|
|
9
|
+
"""Types of step-related limit violations."""
|
|
10
|
+
|
|
11
|
+
STEP_LIMIT_EXCEEDED = "STEP_LIMIT_EXCEEDED"
|
|
12
|
+
DELEGATION_DEPTH_EXCEEDED = "DELEGATION_DEPTH_EXCEEDED"
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@dataclass
|
|
16
|
+
class StepLimitConfig:
|
|
17
|
+
"""Configuration for agent step and delegation limits.
|
|
18
|
+
|
|
19
|
+
Attributes:
|
|
20
|
+
max_steps: Maximum number of execution steps allowed per invocation.
|
|
21
|
+
Includes agent node (LLM call) and every tool call (parallel batches count per call).
|
|
22
|
+
max_delegation_depth: Maximum depth of delegation chain allowed.
|
|
23
|
+
Depth 0 means no delegation allowed.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
max_steps: int = field(
|
|
27
|
+
default_factory=lambda: int(os.getenv("STEP_LIMIT_MAX_STEPS_DEFAULT", "100")),
|
|
28
|
+
)
|
|
29
|
+
max_delegation_depth: int = field(
|
|
30
|
+
default_factory=lambda: int(os.getenv("STEP_LIMIT_MAX_DELEGATION_DEPTH_DEFAULT", "5")),
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
def __post_init__(self):
|
|
34
|
+
"""Validate configuration values and normalize range."""
|
|
35
|
+
from aip_agents.utils.logger import get_logger
|
|
36
|
+
|
|
37
|
+
logger = get_logger(__name__)
|
|
38
|
+
|
|
39
|
+
# Validate and clamp max_steps
|
|
40
|
+
if self.max_steps < 1:
|
|
41
|
+
logger.warning(f"Invalid max_steps={self.max_steps}, resetting to default (25). max_steps must be >= 1.")
|
|
42
|
+
self.max_steps = 25
|
|
43
|
+
elif self.max_steps > 1000:
|
|
44
|
+
logger.warning(f"Invalid max_steps={self.max_steps}, capping at 1000.")
|
|
45
|
+
self.max_steps = 1000
|
|
46
|
+
|
|
47
|
+
# Validate and clamp max_delegation_depth
|
|
48
|
+
if self.max_delegation_depth < 0:
|
|
49
|
+
logger.warning(
|
|
50
|
+
f"Invalid max_delegation_depth={self.max_delegation_depth}, resetting to default (5). "
|
|
51
|
+
"max_delegation_depth must be >= 0."
|
|
52
|
+
)
|
|
53
|
+
self.max_delegation_depth = 5
|
|
54
|
+
elif self.max_delegation_depth > 10:
|
|
55
|
+
logger.warning(f"Invalid max_delegation_depth={self.max_delegation_depth}, capping at 10.")
|
|
56
|
+
self.max_delegation_depth = 10
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
@dataclass
|
|
60
|
+
class StepLimitErrorResponse:
|
|
61
|
+
"""Structured error response for step limit violations.
|
|
62
|
+
|
|
63
|
+
Attributes:
|
|
64
|
+
error_type: The type of limit that was exceeded.
|
|
65
|
+
agent_name: Name of the agent that hit the limit.
|
|
66
|
+
current_value: Current step count or delegation depth.
|
|
67
|
+
configured_limit: The configured limit that was exceeded.
|
|
68
|
+
message: Human-readable error message.
|
|
69
|
+
delegation_chain: Full chain for delegation errors.
|
|
70
|
+
partial_result: Any output generated before hitting the limit.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
error_type: StepLimitErrorType
|
|
74
|
+
agent_name: str
|
|
75
|
+
current_value: int
|
|
76
|
+
configured_limit: int
|
|
77
|
+
message: str
|
|
78
|
+
delegation_chain: list[str] | None = None
|
|
79
|
+
partial_result: str | None = None
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class StepLimitError(Exception):
|
|
83
|
+
"""Base exception for step and delegation limit violations.
|
|
84
|
+
|
|
85
|
+
Attributes:
|
|
86
|
+
error_response: Structured error response with details.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
def __init__(self, error_response: StepLimitErrorResponse):
|
|
90
|
+
"""Initialize with error response.
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
error_response: Structured error details.
|
|
94
|
+
"""
|
|
95
|
+
self.error_response = error_response
|
|
96
|
+
super().__init__(error_response.message)
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
class MaxStepsExceededError(StepLimitError):
|
|
100
|
+
"""Raised when agent exceeds configured max_steps limit."""
|
|
101
|
+
|
|
102
|
+
pass
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
class MaxDelegationDepthExceededError(StepLimitError):
|
|
106
|
+
"""Raised when delegation would exceed max_delegation_depth limit."""
|
|
107
|
+
|
|
108
|
+
pass
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"""Schema definitions for storage configuration."""
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
from enum import StrEnum
|
|
6
|
+
|
|
7
|
+
__all__ = ["OBJECT_STORAGE_PREFIX", "StorageType", "StorageConfig"]
|
|
8
|
+
|
|
9
|
+
OBJECT_STORAGE_PREFIX = "tool_outputs/"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class StorageType(StrEnum):
|
|
13
|
+
"""Supported storage types."""
|
|
14
|
+
|
|
15
|
+
MEMORY = "memory"
|
|
16
|
+
OBJECT_STORAGE = "object_storage"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
@dataclass
|
|
20
|
+
class StorageConfig:
|
|
21
|
+
"""Configuration for storage providers."""
|
|
22
|
+
|
|
23
|
+
storage_type: StorageType = StorageType.MEMORY
|
|
24
|
+
object_prefix: str = OBJECT_STORAGE_PREFIX
|
|
25
|
+
object_use_json: bool = False
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def from_env(cls) -> "StorageConfig":
|
|
29
|
+
"""Create StorageConfig from environment variables."""
|
|
30
|
+
storage_type_str = os.getenv("TOOL_OUTPUT_STORAGE_TYPE", StorageType.MEMORY.value).lower()
|
|
31
|
+
if storage_type_str == StorageType.MEMORY.value:
|
|
32
|
+
storage_type = StorageType.MEMORY
|
|
33
|
+
else:
|
|
34
|
+
storage_type = StorageType.OBJECT_STORAGE
|
|
35
|
+
|
|
36
|
+
object_prefix = os.getenv("TOOL_OUTPUT_OBJECT_PREFIX", OBJECT_STORAGE_PREFIX)
|
|
37
|
+
use_json_str = os.getenv("TOOL_OUTPUT_USE_JSON", "false").lower()
|
|
38
|
+
use_json = use_json_str in ("true", "1", "yes", "on")
|
|
39
|
+
|
|
40
|
+
return cls(storage_type=storage_type, object_prefix=object_prefix, object_use_json=use_json)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""This module provides a centralized way to handle Sentry and OpenTelemetry configuration for BOSA SDK.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Saul Sayers (saul.sayers@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from aip_agents.sentry.sentry import setup_telemetry
|
|
8
|
+
|
|
9
|
+
__all__ = [
|
|
10
|
+
"setup_telemetry",
|
|
11
|
+
]
|
|
@@ -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()
|
|
@@ -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
|
|
@@ -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"]
|