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,149 @@
|
|
|
1
|
+
"""Registry for tracking HITL approval manager ownership across agent hierarchies.
|
|
2
|
+
|
|
3
|
+
This module provides a thread-safe singleton registry that maps request IDs to their
|
|
4
|
+
owning ApprovalManager instances. This enables proper decision routing in hierarchical
|
|
5
|
+
agent architectures where sub-agents have HITL enabled but parents do not.
|
|
6
|
+
|
|
7
|
+
Authors:
|
|
8
|
+
Raymond Christopher (raymond.christopher@gdplabs.id)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import threading
|
|
14
|
+
from typing import TYPE_CHECKING
|
|
15
|
+
from weakref import WeakValueDictionary
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from aip_agents.agent.hitl.manager import ApprovalManager
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class HITLManagerRegistry:
|
|
22
|
+
"""Global registry mapping request_id → owning ApprovalManager.
|
|
23
|
+
|
|
24
|
+
Uses weak references to avoid preventing manager garbage collection.
|
|
25
|
+
Thread-safe for concurrent agent execution.
|
|
26
|
+
|
|
27
|
+
This singleton registry allows the HITL decision endpoint to route decisions
|
|
28
|
+
to the correct manager in hierarchical agent setups, where a sub-agent may
|
|
29
|
+
create a pending request but the parent agent receives the decision.
|
|
30
|
+
|
|
31
|
+
Example:
|
|
32
|
+
>>> from aip_agents.agent.hitl.registry import hitl_registry
|
|
33
|
+
>>> # Manager auto-registers when creating requests
|
|
34
|
+
>>> manager.create_approval_request(...)
|
|
35
|
+
>>> # Later, decision handler looks up the owning manager
|
|
36
|
+
>>> owning_manager = hitl_registry.get_manager(request_id)
|
|
37
|
+
>>> owning_manager.resolve_pending_request(request_id, "approved")
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
_instance: HITLManagerRegistry | None = None
|
|
41
|
+
_lock = threading.RLock()
|
|
42
|
+
_registry: WeakValueDictionary[str, ApprovalManager]
|
|
43
|
+
_registry_lock: threading.RLock
|
|
44
|
+
|
|
45
|
+
def __new__(cls) -> HITLManagerRegistry:
|
|
46
|
+
"""Ensure only one instance exists (singleton pattern).
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
The singleton HITLManagerRegistry instance.
|
|
50
|
+
"""
|
|
51
|
+
if cls._instance is None:
|
|
52
|
+
with cls._lock:
|
|
53
|
+
if cls._instance is None:
|
|
54
|
+
instance = super().__new__(cls)
|
|
55
|
+
instance._registry = WeakValueDictionary()
|
|
56
|
+
instance._registry_lock = threading.RLock()
|
|
57
|
+
cls._instance = instance
|
|
58
|
+
return cls._instance
|
|
59
|
+
|
|
60
|
+
def register(self, request_id: str, manager: ApprovalManager) -> None:
|
|
61
|
+
"""Register a pending request with its owning manager.
|
|
62
|
+
|
|
63
|
+
This method is typically called automatically by ApprovalManager when
|
|
64
|
+
creating a new pending request. It establishes the ownership mapping
|
|
65
|
+
needed for proper decision routing.
|
|
66
|
+
|
|
67
|
+
Args:
|
|
68
|
+
request_id: Unique identifier for the pending request
|
|
69
|
+
manager: ApprovalManager instance that owns this request
|
|
70
|
+
|
|
71
|
+
Example:
|
|
72
|
+
>>> hitl_registry.register("req_abc123", my_manager)
|
|
73
|
+
"""
|
|
74
|
+
with self._registry_lock:
|
|
75
|
+
self._registry[request_id] = manager
|
|
76
|
+
|
|
77
|
+
def unregister(self, request_id: str) -> None:
|
|
78
|
+
"""Remove a request from the registry.
|
|
79
|
+
|
|
80
|
+
This method is called when a request is resolved, times out, or expires.
|
|
81
|
+
It's important for cleanup to prevent the registry from growing unbounded.
|
|
82
|
+
|
|
83
|
+
Args:
|
|
84
|
+
request_id: Unique identifier to remove
|
|
85
|
+
|
|
86
|
+
Example:
|
|
87
|
+
>>> hitl_registry.unregister("req_abc123")
|
|
88
|
+
"""
|
|
89
|
+
with self._registry_lock:
|
|
90
|
+
self._registry.pop(request_id, None)
|
|
91
|
+
|
|
92
|
+
def get_manager(self, request_id: str) -> ApprovalManager | None:
|
|
93
|
+
"""Retrieve the manager owning a specific request.
|
|
94
|
+
|
|
95
|
+
This is the primary lookup method used by decision handlers to route
|
|
96
|
+
decisions to the correct manager in hierarchical agent setups.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
request_id: Unique identifier to lookup
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
ApprovalManager instance if found, None otherwise. None can indicate
|
|
103
|
+
the request was resolved, timed out, or the manager was garbage collected.
|
|
104
|
+
|
|
105
|
+
Example:
|
|
106
|
+
>>> manager = hitl_registry.get_manager("req_abc123")
|
|
107
|
+
>>> if manager:
|
|
108
|
+
... manager.resolve_pending_request("req_abc123", "approved")
|
|
109
|
+
"""
|
|
110
|
+
with self._registry_lock:
|
|
111
|
+
return self._registry.get(request_id)
|
|
112
|
+
|
|
113
|
+
def clear(self) -> None:
|
|
114
|
+
"""Clear all registrations.
|
|
115
|
+
|
|
116
|
+
This method is primarily intended for testing to ensure a clean state
|
|
117
|
+
between test cases. It removes all registered mappings.
|
|
118
|
+
|
|
119
|
+
Warning:
|
|
120
|
+
This should not be called in production code as it will prevent
|
|
121
|
+
pending requests from being resolved.
|
|
122
|
+
|
|
123
|
+
Example:
|
|
124
|
+
>>> hitl_registry.clear() # For testing only
|
|
125
|
+
"""
|
|
126
|
+
with self._registry_lock:
|
|
127
|
+
self._registry.clear()
|
|
128
|
+
|
|
129
|
+
def list_all(self) -> list[str]:
|
|
130
|
+
"""List all currently registered request IDs.
|
|
131
|
+
|
|
132
|
+
Returns:
|
|
133
|
+
List of request IDs currently in the registry.
|
|
134
|
+
|
|
135
|
+
Note:
|
|
136
|
+
Due to weak references, managers may be garbage collected between
|
|
137
|
+
calling this method and accessing them, so the actual available
|
|
138
|
+
managers might be fewer than the returned list length.
|
|
139
|
+
|
|
140
|
+
Example:
|
|
141
|
+
>>> request_ids = hitl_registry.list_all()
|
|
142
|
+
>>> print(f"Pending requests: {request_ids}")
|
|
143
|
+
"""
|
|
144
|
+
with self._registry_lock:
|
|
145
|
+
return list(self._registry.keys())
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
# Global singleton instance
|
|
149
|
+
hitl_registry = HITLManagerRegistry()
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"""Defines the abstract base class AgentInterface for all agent implementations, now with MCP and A2A support.
|
|
2
|
+
|
|
3
|
+
Authors:
|
|
4
|
+
Raymond Christopher (raymond.christopher@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 collections.abc import AsyncGenerator
|
|
10
|
+
from typing import Any
|
|
11
|
+
|
|
12
|
+
from a2a.types import AgentCard
|
|
13
|
+
from gllm_inference.lm_invoker.lm_invoker import BaseLMInvoker
|
|
14
|
+
|
|
15
|
+
from aip_agents.schema.agent import BaseAgentConfig
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AgentInterface(ABC):
|
|
19
|
+
"""A general and minimal interface for agent implementations.
|
|
20
|
+
|
|
21
|
+
Defines core execution methods (`__init__`, `run`, `arun`, `arun_stream`).
|
|
22
|
+
Concrete subclasses must implement all abstract methods.
|
|
23
|
+
"""
|
|
24
|
+
|
|
25
|
+
name: str
|
|
26
|
+
instruction: str
|
|
27
|
+
description: str | None
|
|
28
|
+
mcp_config: dict[str, Any] = {}
|
|
29
|
+
lm_invoker: BaseLMInvoker | None = None
|
|
30
|
+
config: BaseAgentConfig | None = None
|
|
31
|
+
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
name: str,
|
|
35
|
+
instruction: str,
|
|
36
|
+
description: str | None = None,
|
|
37
|
+
lm_invoker: BaseLMInvoker | None = None,
|
|
38
|
+
config: BaseAgentConfig | None = None,
|
|
39
|
+
**kwargs: Any,
|
|
40
|
+
):
|
|
41
|
+
"""Initializes the agent.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
name: The name of the agent.
|
|
45
|
+
instruction: The core directive or system prompt for the agent.
|
|
46
|
+
description: Human-readable description. Defaults to instruction if not provided.
|
|
47
|
+
lm_invoker: The language model invoker to use for LLM interactions. Defaults to None.
|
|
48
|
+
config: Additional configuration for the agent.
|
|
49
|
+
**kwargs: Additional keyword arguments for concrete implementations.
|
|
50
|
+
"""
|
|
51
|
+
self.name = name
|
|
52
|
+
self.instruction = instruction
|
|
53
|
+
self.description = description or self.instruction
|
|
54
|
+
self.lm_invoker = lm_invoker
|
|
55
|
+
self.config = config
|
|
56
|
+
|
|
57
|
+
@abstractmethod
|
|
58
|
+
def run(
|
|
59
|
+
self,
|
|
60
|
+
query: str,
|
|
61
|
+
**kwargs: Any,
|
|
62
|
+
) -> dict[str, Any]:
|
|
63
|
+
"""Synchronously runs the agent.
|
|
64
|
+
|
|
65
|
+
Args:
|
|
66
|
+
query: The input query for the agent.
|
|
67
|
+
**kwargs: Additional keyword arguments for execution.
|
|
68
|
+
|
|
69
|
+
Returns:
|
|
70
|
+
Dict containing at least {'output': ...}.
|
|
71
|
+
"""
|
|
72
|
+
raise NotImplementedError(
|
|
73
|
+
f"'{self.__class__.__name__}' has not implemented the 'run' method."
|
|
74
|
+
) # pragma: no cover
|
|
75
|
+
|
|
76
|
+
@abstractmethod
|
|
77
|
+
async def arun(
|
|
78
|
+
self,
|
|
79
|
+
query: str,
|
|
80
|
+
**kwargs: Any,
|
|
81
|
+
) -> dict[str, Any]:
|
|
82
|
+
"""Asynchronously runs the agent.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
query: The input query for the agent.
|
|
86
|
+
**kwargs: Additional keyword arguments for execution.
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Dict containing at least {'output': ...}.
|
|
90
|
+
"""
|
|
91
|
+
raise NotImplementedError(
|
|
92
|
+
f"'{self.__class__.__name__}' has not implemented the 'arun' method."
|
|
93
|
+
) # pragma: no cover
|
|
94
|
+
|
|
95
|
+
@abstractmethod
|
|
96
|
+
async def arun_stream(
|
|
97
|
+
self,
|
|
98
|
+
query: str,
|
|
99
|
+
**kwargs: Any,
|
|
100
|
+
) -> AsyncGenerator[str | dict[str, Any], None]:
|
|
101
|
+
"""Asynchronously streams the agent's response.
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
query: The input query.
|
|
105
|
+
**kwargs: Extra parameters for execution.
|
|
106
|
+
|
|
107
|
+
Yields:
|
|
108
|
+
Chunks of output (strings or dicts).
|
|
109
|
+
"""
|
|
110
|
+
raise NotImplementedError(
|
|
111
|
+
f"'{self.__class__.__name__}' has not implemented the 'arun_stream' method."
|
|
112
|
+
) # pragma: no cover
|
|
113
|
+
|
|
114
|
+
@abstractmethod
|
|
115
|
+
def add_mcp_server(self, mcp_config: dict[str, dict[str, Any]]) -> None:
|
|
116
|
+
"""Adds a new MCP server configuration.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
mcp_config: Dictionary containing server name as key and its configuration as value.
|
|
120
|
+
|
|
121
|
+
Raises:
|
|
122
|
+
ValueError: If mcp_config is empty or None, or if any server configuration is invalid.
|
|
123
|
+
KeyError: If any server name already exists in the configuration.
|
|
124
|
+
"""
|
|
125
|
+
raise NotImplementedError(
|
|
126
|
+
f"'{self.__class__.__name__}' has not implemented the 'add_mcp_server' method."
|
|
127
|
+
) # pragma: no cover
|
|
128
|
+
|
|
129
|
+
@abstractmethod
|
|
130
|
+
def register_a2a_agents(self, agents: list[AgentCard]):
|
|
131
|
+
"""Registers A2A agents from a list of AgentCards.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
agents: A list of AgentCard instances.
|
|
135
|
+
"""
|
|
136
|
+
raise NotImplementedError(
|
|
137
|
+
f"'{self.__class__.__name__}' has not implemented the 'register_a2a_agents' method."
|
|
138
|
+
) # pragma: no cover
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Common agent-facing protocols used by A2A executors.
|
|
2
|
+
|
|
3
|
+
These runtime-checkable protocols let executors validate agent instances
|
|
4
|
+
without importing the concrete implementation classes, which avoids
|
|
5
|
+
introducing circular import chains at runtime.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
from collections.abc import AsyncIterator
|
|
11
|
+
from typing import Any, Protocol, runtime_checkable
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@runtime_checkable
|
|
15
|
+
class LangGraphAgentProtocol(Protocol):
|
|
16
|
+
"""Minimal interface required by LangGraphA2AExecutor."""
|
|
17
|
+
|
|
18
|
+
name: str
|
|
19
|
+
|
|
20
|
+
async def arun_a2a_stream(self, query: str, **kwargs: Any) -> AsyncIterator[dict[str, Any]]:
|
|
21
|
+
"""Stream A2A-compatible chunks for the given query.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
query (str): The query to execute and stream.
|
|
25
|
+
**kwargs (Any): Additional keyword arguments for execution.
|
|
26
|
+
|
|
27
|
+
Yields:
|
|
28
|
+
dict[str, Any]: A2A-compatible streaming chunks.
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
@runtime_checkable
|
|
33
|
+
class LangflowAgentProtocol(Protocol):
|
|
34
|
+
"""Minimal interface required by LangflowA2AExecutor."""
|
|
35
|
+
|
|
36
|
+
name: str
|
|
37
|
+
|
|
38
|
+
async def arun_a2a_stream(self, query: str, **kwargs: Any) -> AsyncIterator[dict[str, Any]]:
|
|
39
|
+
"""Stream A2A-compatible chunks for the given query.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
query (str): The query to execute and stream.
|
|
43
|
+
**kwargs (Any): Additional keyword arguments for execution.
|
|
44
|
+
|
|
45
|
+
Yields:
|
|
46
|
+
dict[str, Any]: A2A-compatible streaming chunks.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
@runtime_checkable
|
|
51
|
+
class GoogleADKAgentProtocol(Protocol):
|
|
52
|
+
"""Minimal interface required by GoogleADKExecutor."""
|
|
53
|
+
|
|
54
|
+
name: str
|
|
55
|
+
|
|
56
|
+
async def arun_a2a_stream(self, query: str, **kwargs: Any) -> AsyncIterator[dict[str, Any]]:
|
|
57
|
+
"""Stream A2A-compatible chunks for the given query.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
query (str): The query to execute and stream.
|
|
61
|
+
**kwargs (Any): Additional keyword arguments for execution.
|
|
62
|
+
|
|
63
|
+
Yields:
|
|
64
|
+
dict[str, Any]: A2A-compatible streaming chunks.
|
|
65
|
+
"""
|