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,214 @@
|
|
|
1
|
+
"""Object storage provider implementation.
|
|
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
|
+
import json
|
|
9
|
+
import pickle
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from aip_agents.storage.base import BaseObjectStorageClient
|
|
13
|
+
from aip_agents.storage.providers.base import BaseStorageProvider, StorageError
|
|
14
|
+
from aip_agents.utils.logger import get_logger
|
|
15
|
+
|
|
16
|
+
logger = get_logger(__name__)
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ObjectStorageProvider(BaseStorageProvider):
|
|
20
|
+
"""Object storage provider for S3-compatible storage.
|
|
21
|
+
|
|
22
|
+
Works with any S3-compatible storage including AWS S3, MinIO,
|
|
23
|
+
Google Cloud Storage (with S3 compatibility), etc.
|
|
24
|
+
|
|
25
|
+
Best for:
|
|
26
|
+
- Very large datasets
|
|
27
|
+
- Distributed systems
|
|
28
|
+
- Cloud deployments
|
|
29
|
+
- Long-term storage
|
|
30
|
+
- Multi-region access
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(self, client: BaseObjectStorageClient, prefix: str = "", use_json: bool = False):
|
|
34
|
+
"""Initialize object storage provider.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
client: Object storage client instance
|
|
38
|
+
prefix: Prefix for all keys (like a directory)
|
|
39
|
+
use_json: Use JSON format (True) or pickle (False)
|
|
40
|
+
"""
|
|
41
|
+
self.client = client
|
|
42
|
+
self.prefix = prefix.rstrip("/") + "/" if prefix else ""
|
|
43
|
+
self.use_json = use_json
|
|
44
|
+
|
|
45
|
+
def _get_object_key(self, key: str) -> str:
|
|
46
|
+
"""Get full object key with prefix.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
key: Storage key
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Full object key with prefix
|
|
53
|
+
"""
|
|
54
|
+
return f"{self.prefix}{key}"
|
|
55
|
+
|
|
56
|
+
def _serialize_data(self, data: Any) -> bytes:
|
|
57
|
+
"""Serialize data to bytes.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
data: Data to serialize
|
|
61
|
+
|
|
62
|
+
Returns:
|
|
63
|
+
Serialized data as bytes
|
|
64
|
+
|
|
65
|
+
Raises:
|
|
66
|
+
StorageError: If serialization fails
|
|
67
|
+
"""
|
|
68
|
+
try:
|
|
69
|
+
if self.use_json:
|
|
70
|
+
return json.dumps(data, default=str).encode("utf-8")
|
|
71
|
+
return pickle.dumps(data)
|
|
72
|
+
except Exception as e:
|
|
73
|
+
raise StorageError(f"Failed to serialize data: {e}") from e
|
|
74
|
+
|
|
75
|
+
def _deserialize_data(self, data_bytes: bytes) -> Any:
|
|
76
|
+
"""Deserialize data from bytes.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
data_bytes: Serialized data
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
Deserialized data
|
|
83
|
+
|
|
84
|
+
Raises:
|
|
85
|
+
StorageError: If deserialization fails
|
|
86
|
+
"""
|
|
87
|
+
try:
|
|
88
|
+
if self.use_json:
|
|
89
|
+
return json.loads(data_bytes.decode("utf-8"))
|
|
90
|
+
return pickle.loads(data_bytes)
|
|
91
|
+
except Exception as e:
|
|
92
|
+
raise StorageError(f"Failed to deserialize data: {e}") from e
|
|
93
|
+
|
|
94
|
+
def store(self, key: str, data: Any) -> None:
|
|
95
|
+
"""Store data in object storage.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
key: Unique identifier for the data
|
|
99
|
+
data: Data to store
|
|
100
|
+
|
|
101
|
+
Raises:
|
|
102
|
+
StorageError: If storage operation fails
|
|
103
|
+
"""
|
|
104
|
+
object_key = self._get_object_key(key)
|
|
105
|
+
|
|
106
|
+
try:
|
|
107
|
+
data_bytes = self._serialize_data(data)
|
|
108
|
+
|
|
109
|
+
self.client.upload(
|
|
110
|
+
object_key=object_key,
|
|
111
|
+
file_stream=data_bytes,
|
|
112
|
+
content_type="application/json" if self.use_json else "application/octet-stream",
|
|
113
|
+
metadata={"storage_key": key, "format": "json" if self.use_json else "pickle"},
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
logger.debug(f"Stored data to object storage: {object_key}")
|
|
117
|
+
|
|
118
|
+
except Exception as e:
|
|
119
|
+
raise StorageError(f"Failed to store data in object storage: {e}") from e
|
|
120
|
+
|
|
121
|
+
def retrieve(self, key: str) -> Any:
|
|
122
|
+
"""Retrieve data from object storage.
|
|
123
|
+
|
|
124
|
+
Args:
|
|
125
|
+
key: Unique identifier for the data
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
The stored data
|
|
129
|
+
|
|
130
|
+
Raises:
|
|
131
|
+
KeyError: If key not found
|
|
132
|
+
StorageError: If retrieval operation fails
|
|
133
|
+
"""
|
|
134
|
+
object_key = self._get_object_key(key)
|
|
135
|
+
|
|
136
|
+
try:
|
|
137
|
+
data_bytes = self.client.get(object_key)
|
|
138
|
+
return self._deserialize_data(data_bytes)
|
|
139
|
+
|
|
140
|
+
except KeyError as e:
|
|
141
|
+
raise KeyError(f"Key '{key}' not found in object storage: {e}") from e
|
|
142
|
+
except Exception as e:
|
|
143
|
+
raise StorageError(f"Failed to retrieve data from object storage: {e}") from e
|
|
144
|
+
|
|
145
|
+
def exists(self, key: str) -> bool:
|
|
146
|
+
"""Check if object exists.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
key: Unique identifier to check
|
|
150
|
+
|
|
151
|
+
Returns:
|
|
152
|
+
True if key exists, False otherwise
|
|
153
|
+
"""
|
|
154
|
+
object_key = self._get_object_key(key)
|
|
155
|
+
|
|
156
|
+
try:
|
|
157
|
+
return self.client.object_exists(object_key)
|
|
158
|
+
except Exception as e:
|
|
159
|
+
logger.warning(f"Failed to check object existence: {e}")
|
|
160
|
+
return False
|
|
161
|
+
|
|
162
|
+
def delete(self, key: str) -> None:
|
|
163
|
+
"""Delete object.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
key: Unique identifier for the data
|
|
167
|
+
"""
|
|
168
|
+
object_key = self._get_object_key(key)
|
|
169
|
+
|
|
170
|
+
try:
|
|
171
|
+
self.client.delete(object_key)
|
|
172
|
+
logger.debug(f"Deleted object: {object_key}")
|
|
173
|
+
except Exception as e:
|
|
174
|
+
logger.warning(f"Failed to delete object {object_key}: {e}")
|
|
175
|
+
|
|
176
|
+
def list_keys(self, prefix: str = "") -> list[str]:
|
|
177
|
+
"""List all keys with optional prefix.
|
|
178
|
+
|
|
179
|
+
Args:
|
|
180
|
+
prefix: Optional prefix to filter keys
|
|
181
|
+
|
|
182
|
+
Raises:
|
|
183
|
+
NotImplementedError: list_keys is not implemented
|
|
184
|
+
"""
|
|
185
|
+
raise NotImplementedError("list_keys not yet implemented for object storage")
|
|
186
|
+
|
|
187
|
+
def clear(self) -> None:
|
|
188
|
+
"""Clear all objects with the configured prefix.
|
|
189
|
+
|
|
190
|
+
Warning:
|
|
191
|
+
This is a dangerous operation!
|
|
192
|
+
"""
|
|
193
|
+
logger.warning("clear() not implemented for object storage - too dangerous")
|
|
194
|
+
raise NotImplementedError("Batch clear not implemented for safety reasons")
|
|
195
|
+
|
|
196
|
+
def get_presigned_url(self, key: str, expires_hours: int = 24) -> str | None:
|
|
197
|
+
"""Generate presigned URL for direct access.
|
|
198
|
+
|
|
199
|
+
Args:
|
|
200
|
+
key: Storage key
|
|
201
|
+
expires_hours: URL expiration in hours
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
Presigned URL for direct access
|
|
205
|
+
|
|
206
|
+
Raises:
|
|
207
|
+
StorageError: If URL generation fails
|
|
208
|
+
"""
|
|
209
|
+
object_key = self._get_object_key(key)
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
return self.client.generate_presigned_url(object_key=object_key, expires=expires_hours)
|
|
213
|
+
except Exception as e:
|
|
214
|
+
raise StorageError(f"Failed to generate presigned URL: {e}") from e
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"""Initialize Tools Module for AIP Agents."""
|
|
2
|
+
|
|
3
|
+
from importlib import import_module
|
|
4
|
+
|
|
5
|
+
from aip_agents.tools.bosa_tools import BOSA_AUTOMATED_TOOLS
|
|
6
|
+
from aip_agents.tools.gl_connector import GLConnectorTool
|
|
7
|
+
from aip_agents.tools.time_tool import TimeTool
|
|
8
|
+
from aip_agents.tools.web_search import GoogleSerperTool
|
|
9
|
+
|
|
10
|
+
__all__ = ["BOSA_AUTOMATED_TOOLS", "GLConnectorTool", "GoogleSerperTool", "TimeTool"]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _register_optional(module_path: str, export_name: str) -> None:
|
|
14
|
+
"""Try to import optional tool module and expose it in __all__.
|
|
15
|
+
|
|
16
|
+
Args:
|
|
17
|
+
module_path: The module path to import.
|
|
18
|
+
export_name: The name to export in __all__.
|
|
19
|
+
"""
|
|
20
|
+
try:
|
|
21
|
+
module = import_module(module_path)
|
|
22
|
+
except ImportError:
|
|
23
|
+
return
|
|
24
|
+
|
|
25
|
+
globals()[export_name] = getattr(module, export_name)
|
|
26
|
+
__all__.append(export_name)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
_register_optional("aip_agents.tools.browser_use", "BrowserUseTool")
|
|
30
|
+
_register_optional("aip_agents.tools.code_sandbox", "E2BCodeSandboxTool")
|
|
31
|
+
_register_optional("aip_agents.tools.document_loader", "DocxReaderTool")
|
|
32
|
+
_register_optional("aip_agents.tools.document_loader", "ExcelReaderTool")
|
|
33
|
+
_register_optional("aip_agents.tools.document_loader", "PDFReaderTool")
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
"""Auto-generated tools from BOSA connector.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Saul Sayers (saul.sayers@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from bosa_connectors import BosaConnector, BOSAConnectorToolGenerator
|
|
8
|
+
from langchain_core.tools import BaseTool
|
|
9
|
+
|
|
10
|
+
from aip_agents.tools.constants import BOSA_API_BASE_URL, BOSA_API_KEY, BOSA_FETCH_MAX_RETRIES, ToolType
|
|
11
|
+
from aip_agents.utils.logger import get_logger
|
|
12
|
+
|
|
13
|
+
logger = get_logger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_bosa_modules_with_retry() -> list[str]:
|
|
17
|
+
"""Try to get available modules with retries.
|
|
18
|
+
|
|
19
|
+
Returns:
|
|
20
|
+
List of available modules.
|
|
21
|
+
"""
|
|
22
|
+
if not BOSA_API_BASE_URL or not BOSA_API_KEY:
|
|
23
|
+
logger.warning("BOSA credentials missing (base_url or api_key); returning empty modules list")
|
|
24
|
+
return []
|
|
25
|
+
|
|
26
|
+
connector = BosaConnector(api_base_url=BOSA_API_BASE_URL, api_key=BOSA_API_KEY)
|
|
27
|
+
modules = []
|
|
28
|
+
for attempt in range(BOSA_FETCH_MAX_RETRIES):
|
|
29
|
+
try:
|
|
30
|
+
modules = list(connector.get_available_modules())
|
|
31
|
+
if modules:
|
|
32
|
+
return modules
|
|
33
|
+
logger.warning(
|
|
34
|
+
f"Failed to get BOSA available modules, retrying... (attempt {attempt + 1} / {BOSA_FETCH_MAX_RETRIES})"
|
|
35
|
+
)
|
|
36
|
+
except Exception as e:
|
|
37
|
+
logger.exception(
|
|
38
|
+
f"Exception when getting BOSA available modules (attempt {attempt + 1} / {BOSA_FETCH_MAX_RETRIES}): {e}"
|
|
39
|
+
)
|
|
40
|
+
logger.error("Failed to get BOSA available modules after maximum retries")
|
|
41
|
+
return modules
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class LazyBosaToolsDict(dict):
|
|
45
|
+
"""Lazy dictionary for BOSA tools."""
|
|
46
|
+
|
|
47
|
+
def __missing__(self, app):
|
|
48
|
+
"""When a key is missing, create the tools and store them in the dictionary.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
app: Name of the BOSA connector.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
List of tools generated by BOSAConnectorToolGenerator.
|
|
55
|
+
"""
|
|
56
|
+
if app not in get_bosa_modules():
|
|
57
|
+
return []
|
|
58
|
+
tools = []
|
|
59
|
+
for attempt in range(BOSA_FETCH_MAX_RETRIES):
|
|
60
|
+
try:
|
|
61
|
+
tools = BOSAConnectorToolGenerator(
|
|
62
|
+
api_base_url=BOSA_API_BASE_URL,
|
|
63
|
+
api_key=BOSA_API_KEY,
|
|
64
|
+
app_name=app,
|
|
65
|
+
).generate_tools(tool_type=ToolType.LANGCHAIN)
|
|
66
|
+
if tools:
|
|
67
|
+
self[app] = tools
|
|
68
|
+
return tools
|
|
69
|
+
logger.warning(
|
|
70
|
+
f"Failed to create BOSA tools, retrying... (attempt {attempt + 1} / {BOSA_FETCH_MAX_RETRIES})"
|
|
71
|
+
)
|
|
72
|
+
except Exception as e:
|
|
73
|
+
logger.exception(
|
|
74
|
+
f"Exception when creating BOSA tools for app '{app}' "
|
|
75
|
+
f"(attempt {attempt + 1} / {BOSA_FETCH_MAX_RETRIES}): {e}"
|
|
76
|
+
)
|
|
77
|
+
logger.error("Failed to create BOSA tools after maximum retries")
|
|
78
|
+
return tools
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
# Supported modules (dynamic)
|
|
82
|
+
def get_bosa_modules() -> list[str]:
|
|
83
|
+
"""Lazily fetch and cache BOSA modules.
|
|
84
|
+
|
|
85
|
+
This is for backwards compatibility with the old BOSA modules.
|
|
86
|
+
|
|
87
|
+
Returns:
|
|
88
|
+
List of BOSA modules.
|
|
89
|
+
"""
|
|
90
|
+
if not hasattr(get_bosa_modules, "_cache"):
|
|
91
|
+
get_bosa_modules._cache = get_bosa_modules_with_retry()
|
|
92
|
+
return get_bosa_modules._cache
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
# FOR BACKWARDS COMPATIBILITY
|
|
96
|
+
BOSA_MODULES = [
|
|
97
|
+
"github",
|
|
98
|
+
"twitter",
|
|
99
|
+
"google",
|
|
100
|
+
"google_drive",
|
|
101
|
+
"google_mail",
|
|
102
|
+
"google_docs",
|
|
103
|
+
]
|
|
104
|
+
|
|
105
|
+
BOSA_AUTOMATED_TOOLS: dict[str, list[BaseTool]] = LazyBosaToolsDict()
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# flake8: noqa: F401
|
|
2
|
+
"""Browser use tools package for AI Agent Platform.
|
|
3
|
+
|
|
4
|
+
Authors:
|
|
5
|
+
Reinhart Linanda (reinhart.linanda@gdplabs.id)
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import warnings
|
|
9
|
+
from enum import StrEnum
|
|
10
|
+
|
|
11
|
+
try:
|
|
12
|
+
import json_repair
|
|
13
|
+
import minio
|
|
14
|
+
from browser_use import Agent
|
|
15
|
+
from steel import Steel
|
|
16
|
+
|
|
17
|
+
_TOOL_AVAILABLE = True
|
|
18
|
+
|
|
19
|
+
except ImportError:
|
|
20
|
+
_TOOL_AVAILABLE = False
|
|
21
|
+
warnings.warn(
|
|
22
|
+
"Browser use tools not available. Install with: pip install aip-agents[local]",
|
|
23
|
+
ImportWarning,
|
|
24
|
+
stacklevel=2,
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ImportableName(StrEnum):
|
|
29
|
+
"""Names of the importable attributes."""
|
|
30
|
+
|
|
31
|
+
BROWSER_USE_TOOL = "BrowserUseTool"
|
|
32
|
+
BROWSER_USE_TOOL_INPUT = "BrowserUseToolInput"
|
|
33
|
+
BROWSER_USE_TOOL_CONFIG = "BrowserUseToolConfig"
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
if _TOOL_AVAILABLE:
|
|
37
|
+
__all__ = [
|
|
38
|
+
ImportableName.BROWSER_USE_TOOL,
|
|
39
|
+
ImportableName.BROWSER_USE_TOOL_INPUT,
|
|
40
|
+
ImportableName.BROWSER_USE_TOOL_CONFIG,
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
_LAZY_IMPORTS = {}
|
|
44
|
+
else:
|
|
45
|
+
# No tools available
|
|
46
|
+
__all__ = []
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def __getattr__(name: str):
|
|
50
|
+
"""Lazy import to avoid circular dependencies and import errors in tests.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
name (str): The name of the attribute to get.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
The attribute value.
|
|
57
|
+
"""
|
|
58
|
+
if not _TOOL_AVAILABLE:
|
|
59
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
60
|
+
|
|
61
|
+
if name in _LAZY_IMPORTS:
|
|
62
|
+
return _LAZY_IMPORTS[name]
|
|
63
|
+
|
|
64
|
+
if name == ImportableName.BROWSER_USE_TOOL:
|
|
65
|
+
from aip_agents.tools.browser_use.browser_use_tool import BrowserUseTool
|
|
66
|
+
|
|
67
|
+
_LAZY_IMPORTS[name] = BrowserUseTool
|
|
68
|
+
return BrowserUseTool
|
|
69
|
+
|
|
70
|
+
if name == ImportableName.BROWSER_USE_TOOL_INPUT:
|
|
71
|
+
from aip_agents.tools.browser_use.schemas import BrowserUseToolInput
|
|
72
|
+
|
|
73
|
+
_LAZY_IMPORTS[name] = BrowserUseToolInput
|
|
74
|
+
return BrowserUseToolInput
|
|
75
|
+
|
|
76
|
+
if name == ImportableName.BROWSER_USE_TOOL_CONFIG:
|
|
77
|
+
from aip_agents.tools.browser_use.schemas import BrowserUseToolConfig
|
|
78
|
+
|
|
79
|
+
_LAZY_IMPORTS[name] = BrowserUseToolConfig
|
|
80
|
+
return BrowserUseToolConfig
|
|
81
|
+
|
|
82
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Helper utilities for parsing browser-use agent actions.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from browser_use.agent.views import ActionResult, AgentOutput
|
|
12
|
+
from browser_use.controller.registry.views import ActionModel
|
|
13
|
+
|
|
14
|
+
from aip_agents.tools.browser_use.types import ToolCallInfo
|
|
15
|
+
from aip_agents.utils.logger import get_logger
|
|
16
|
+
|
|
17
|
+
logger = get_logger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ActionParser:
|
|
21
|
+
"""Dedicated class for parsing agent actions with improved error handling."""
|
|
22
|
+
|
|
23
|
+
@staticmethod
|
|
24
|
+
def extract_actions(
|
|
25
|
+
model_output: AgentOutput | None, last_result: list[ActionResult] | None = None
|
|
26
|
+
) -> list[ToolCallInfo]:
|
|
27
|
+
"""Extract action information from model output.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
model_output: The model output containing action information.
|
|
31
|
+
last_result: The last result from the agent state for output extraction.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
list[ToolCallInfo]: Structured action information.
|
|
35
|
+
"""
|
|
36
|
+
if model_output is None or getattr(model_output, "action", None) is None:
|
|
37
|
+
return []
|
|
38
|
+
|
|
39
|
+
actions = model_output.action
|
|
40
|
+
outputs = ActionParser._extract_outputs_from_result(last_result)
|
|
41
|
+
|
|
42
|
+
return [ActionParser._parse_single_action(action_model, outputs, i) for i, action_model in enumerate(actions)]
|
|
43
|
+
|
|
44
|
+
@staticmethod
|
|
45
|
+
def _extract_outputs_from_result(last_result: list[ActionResult] | None) -> list[str]:
|
|
46
|
+
"""Extract output strings from agent result.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
last_result: The last result from the agent state for output extraction.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
list[str]: List of output strings.
|
|
53
|
+
"""
|
|
54
|
+
if not last_result:
|
|
55
|
+
return []
|
|
56
|
+
|
|
57
|
+
outputs: list[str] = []
|
|
58
|
+
for result in last_result:
|
|
59
|
+
if result.extracted_content:
|
|
60
|
+
outputs.append(result.extracted_content)
|
|
61
|
+
elif result.error:
|
|
62
|
+
outputs.append(f"Error: {result.error}")
|
|
63
|
+
else:
|
|
64
|
+
outputs.append("")
|
|
65
|
+
|
|
66
|
+
return outputs
|
|
67
|
+
|
|
68
|
+
@staticmethod
|
|
69
|
+
def _parse_single_action(action_model: ActionModel, outputs: list[str], index: int) -> ToolCallInfo:
|
|
70
|
+
"""Parse a single action model into ToolCallInfo.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
action_model: The action model to parse.
|
|
74
|
+
outputs: List of output strings.
|
|
75
|
+
index: Index of the action in the outputs list.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
ToolCallInfo: Parsed action information.
|
|
79
|
+
"""
|
|
80
|
+
try:
|
|
81
|
+
specific_action = action_model.root
|
|
82
|
+
action_data: dict[str, Any] = specific_action.model_dump(exclude_unset=True)
|
|
83
|
+
|
|
84
|
+
tool_name = list(action_data.keys())[0]
|
|
85
|
+
tool_args = action_data[tool_name]
|
|
86
|
+
|
|
87
|
+
if not isinstance(tool_args, dict):
|
|
88
|
+
tool_args = {"value": tool_args}
|
|
89
|
+
|
|
90
|
+
output = outputs[index] if index < len(outputs) else ""
|
|
91
|
+
|
|
92
|
+
return ToolCallInfo(name=tool_name, args=tool_args, output=output)
|
|
93
|
+
|
|
94
|
+
except Exception as exc:
|
|
95
|
+
logger.warning("Error parsing action structure: %s", exc)
|
|
96
|
+
return ToolCallInfo(
|
|
97
|
+
name="parsing_error",
|
|
98
|
+
args={"error": str(exc)},
|
|
99
|
+
output=outputs[index] if index < len(outputs) else "",
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
__all__ = ["ActionParser"]
|