aip-agents-binary 0.5.11__py3-none-any.whl → 0.5.12__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.
Files changed (271) hide show
  1. aip_agents/a2a/server/langgraph_executor.py +4 -1
  2. aip_agents/agent/hitl/manager.py +10 -0
  3. aip_agents/agent/hitl/registry.py +149 -0
  4. {aip_agents_binary-0.5.11.dist-info → aip_agents_binary-0.5.12.dist-info}/METADATA +1 -1
  5. {aip_agents_binary-0.5.11.dist-info → aip_agents_binary-0.5.12.dist-info}/RECORD +7 -270
  6. aip_agents/__init__.pyi +0 -19
  7. aip_agents/a2a/__init__.pyi +0 -3
  8. aip_agents/a2a/server/__init__.pyi +0 -4
  9. aip_agents/a2a/server/base_executor.pyi +0 -73
  10. aip_agents/a2a/server/google_adk_executor.pyi +0 -51
  11. aip_agents/a2a/server/langflow_executor.pyi +0 -43
  12. aip_agents/a2a/server/langgraph_executor.pyi +0 -47
  13. aip_agents/a2a/types.pyi +0 -132
  14. aip_agents/agent/__init__.pyi +0 -9
  15. aip_agents/agent/base_agent.pyi +0 -221
  16. aip_agents/agent/base_langgraph_agent.pyi +0 -232
  17. aip_agents/agent/google_adk_agent.pyi +0 -141
  18. aip_agents/agent/google_adk_constants.pyi +0 -3
  19. aip_agents/agent/hitl/__init__.pyi +0 -6
  20. aip_agents/agent/hitl/config.pyi +0 -15
  21. aip_agents/agent/hitl/langgraph_hitl_mixin.pyi +0 -42
  22. aip_agents/agent/hitl/manager.pyi +0 -199
  23. aip_agents/agent/hitl/models.pyi +0 -3
  24. aip_agents/agent/hitl/prompt/__init__.pyi +0 -4
  25. aip_agents/agent/hitl/prompt/base.pyi +0 -24
  26. aip_agents/agent/hitl/prompt/deferred.pyi +0 -30
  27. aip_agents/agent/interface.pyi +0 -81
  28. aip_agents/agent/interfaces.pyi +0 -44
  29. aip_agents/agent/langflow_agent.pyi +0 -133
  30. aip_agents/agent/langgraph_memory_enhancer_agent.pyi +0 -49
  31. aip_agents/agent/langgraph_react_agent.pyi +0 -126
  32. aip_agents/agent/system_instruction_context.pyi +0 -13
  33. aip_agents/clients/__init__.pyi +0 -4
  34. aip_agents/clients/langflow/__init__.pyi +0 -4
  35. aip_agents/clients/langflow/client.pyi +0 -140
  36. aip_agents/clients/langflow/types.pyi +0 -7
  37. aip_agents/constants.pyi +0 -7
  38. aip_agents/examples/__init__.pyi +0 -0
  39. aip_agents/examples/compare_streaming_client.pyi +0 -48
  40. aip_agents/examples/compare_streaming_server.pyi +0 -18
  41. aip_agents/examples/demo_memory_recall.pyi +0 -58
  42. aip_agents/examples/hello_world_a2a_google_adk_client.pyi +0 -9
  43. aip_agents/examples/hello_world_a2a_google_adk_client_agent.pyi +0 -9
  44. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.pyi +0 -9
  45. aip_agents/examples/hello_world_a2a_google_adk_server.pyi +0 -15
  46. aip_agents/examples/hello_world_a2a_langchain_client.pyi +0 -5
  47. aip_agents/examples/hello_world_a2a_langchain_client_agent.pyi +0 -5
  48. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.pyi +0 -5
  49. aip_agents/examples/hello_world_a2a_langchain_client_streaming.pyi +0 -5
  50. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.pyi +0 -5
  51. aip_agents/examples/hello_world_a2a_langchain_reference_server.pyi +0 -15
  52. aip_agents/examples/hello_world_a2a_langchain_server.pyi +0 -15
  53. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.pyi +0 -15
  54. aip_agents/examples/hello_world_a2a_langflow_client.pyi +0 -9
  55. aip_agents/examples/hello_world_a2a_langflow_server.pyi +0 -14
  56. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.pyi +0 -5
  57. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.pyi +0 -5
  58. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.pyi +0 -16
  59. aip_agents/examples/hello_world_a2a_langgraph_client.pyi +0 -9
  60. aip_agents/examples/hello_world_a2a_langgraph_client_agent.pyi +0 -9
  61. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.pyi +0 -2
  62. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.pyi +0 -9
  63. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.pyi +0 -5
  64. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.pyi +0 -5
  65. aip_agents/examples/hello_world_a2a_langgraph_server.pyi +0 -14
  66. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.pyi +0 -15
  67. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.pyi +0 -15
  68. aip_agents/examples/hello_world_a2a_mcp_langgraph.pyi +0 -48
  69. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.pyi +0 -48
  70. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.pyi +0 -45
  71. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.pyi +0 -5
  72. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.pyi +0 -15
  73. aip_agents/examples/hello_world_google_adk.pyi +0 -5
  74. aip_agents/examples/hello_world_google_adk_mcp_http.pyi +0 -5
  75. aip_agents/examples/hello_world_google_adk_mcp_http_stream.pyi +0 -5
  76. aip_agents/examples/hello_world_google_adk_mcp_sse.pyi +0 -5
  77. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.pyi +0 -5
  78. aip_agents/examples/hello_world_google_adk_mcp_stdio.pyi +0 -5
  79. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.pyi +0 -5
  80. aip_agents/examples/hello_world_google_adk_stream.pyi +0 -5
  81. aip_agents/examples/hello_world_langchain.pyi +0 -5
  82. aip_agents/examples/hello_world_langchain_lm_invoker.pyi +0 -2
  83. aip_agents/examples/hello_world_langchain_mcp_http.pyi +0 -5
  84. aip_agents/examples/hello_world_langchain_mcp_http_interactive.pyi +0 -16
  85. aip_agents/examples/hello_world_langchain_mcp_http_stream.pyi +0 -5
  86. aip_agents/examples/hello_world_langchain_mcp_multi_server.pyi +0 -18
  87. aip_agents/examples/hello_world_langchain_mcp_sse.pyi +0 -5
  88. aip_agents/examples/hello_world_langchain_mcp_sse_stream.pyi +0 -5
  89. aip_agents/examples/hello_world_langchain_mcp_stdio.pyi +0 -5
  90. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.pyi +0 -5
  91. aip_agents/examples/hello_world_langchain_stream.pyi +0 -5
  92. aip_agents/examples/hello_world_langchain_stream_lm_invoker.pyi +0 -5
  93. aip_agents/examples/hello_world_langflow_agent.pyi +0 -35
  94. aip_agents/examples/hello_world_langgraph.pyi +0 -5
  95. aip_agents/examples/hello_world_langgraph_bosa_twitter.pyi +0 -5
  96. aip_agents/examples/hello_world_langgraph_mcp_http.pyi +0 -5
  97. aip_agents/examples/hello_world_langgraph_mcp_http_stream.pyi +0 -5
  98. aip_agents/examples/hello_world_langgraph_mcp_sse.pyi +0 -5
  99. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.pyi +0 -5
  100. aip_agents/examples/hello_world_langgraph_mcp_stdio.pyi +0 -5
  101. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.pyi +0 -5
  102. aip_agents/examples/hello_world_langgraph_stream.pyi +0 -5
  103. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.pyi +0 -5
  104. aip_agents/examples/hello_world_model_switch_cli.pyi +0 -30
  105. aip_agents/examples/hello_world_multi_agent_adk.pyi +0 -6
  106. aip_agents/examples/hello_world_multi_agent_langchain.pyi +0 -5
  107. aip_agents/examples/hello_world_multi_agent_langgraph.pyi +0 -5
  108. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.pyi +0 -5
  109. aip_agents/examples/hello_world_pii_logger.pyi +0 -5
  110. aip_agents/examples/hello_world_sentry.pyi +0 -21
  111. aip_agents/examples/hello_world_step_limits.pyi +0 -17
  112. aip_agents/examples/hello_world_stock_a2a_server.pyi +0 -17
  113. aip_agents/examples/hello_world_tool_output_client.pyi +0 -5
  114. aip_agents/examples/hello_world_tool_output_server.pyi +0 -19
  115. aip_agents/examples/hitl_demo.pyi +0 -67
  116. aip_agents/examples/pii_demo_langgraph_client.pyi +0 -5
  117. aip_agents/examples/pii_demo_langgraph_server.pyi +0 -20
  118. aip_agents/examples/pii_demo_multi_agent_client.pyi +0 -5
  119. aip_agents/examples/pii_demo_multi_agent_server.pyi +0 -40
  120. aip_agents/examples/todolist_planning_a2a_langchain_client.pyi +0 -5
  121. aip_agents/examples/todolist_planning_a2a_langgraph_server.pyi +0 -19
  122. aip_agents/examples/tools/__init__.pyi +0 -9
  123. aip_agents/examples/tools/adk_arithmetic_tools.pyi +0 -24
  124. aip_agents/examples/tools/adk_weather_tool.pyi +0 -18
  125. aip_agents/examples/tools/data_generator_tool.pyi +0 -15
  126. aip_agents/examples/tools/data_visualization_tool.pyi +0 -19
  127. aip_agents/examples/tools/image_artifact_tool.pyi +0 -26
  128. aip_agents/examples/tools/langchain_arithmetic_tools.pyi +0 -17
  129. aip_agents/examples/tools/langchain_currency_exchange_tool.pyi +0 -20
  130. aip_agents/examples/tools/langchain_graph_artifact_tool.pyi +0 -25
  131. aip_agents/examples/tools/langchain_weather_tool.pyi +0 -19
  132. aip_agents/examples/tools/langgraph_streaming_tool.pyi +0 -43
  133. aip_agents/examples/tools/mock_retrieval_tool.pyi +0 -13
  134. aip_agents/examples/tools/pii_demo_tools.pyi +0 -54
  135. aip_agents/examples/tools/random_chart_tool.pyi +0 -20
  136. aip_agents/examples/tools/serper_tool.pyi +0 -16
  137. aip_agents/examples/tools/stock_tools.pyi +0 -36
  138. aip_agents/examples/tools/table_generator_tool.pyi +0 -22
  139. aip_agents/examples/tools/time_tool.pyi +0 -15
  140. aip_agents/examples/tools/weather_forecast_tool.pyi +0 -14
  141. aip_agents/mcp/__init__.pyi +0 -0
  142. aip_agents/mcp/client/__init__.pyi +0 -5
  143. aip_agents/mcp/client/base_mcp_client.pyi +0 -148
  144. aip_agents/mcp/client/connection_manager.pyi +0 -48
  145. aip_agents/mcp/client/google_adk/__init__.pyi +0 -3
  146. aip_agents/mcp/client/google_adk/client.pyi +0 -75
  147. aip_agents/mcp/client/langchain/__init__.pyi +0 -3
  148. aip_agents/mcp/client/langchain/client.pyi +0 -48
  149. aip_agents/mcp/client/persistent_session.pyi +0 -113
  150. aip_agents/mcp/client/session_pool.pyi +0 -101
  151. aip_agents/mcp/client/transports.pyi +0 -123
  152. aip_agents/mcp/utils/__init__.pyi +0 -0
  153. aip_agents/mcp/utils/config_validator.pyi +0 -82
  154. aip_agents/memory/__init__.pyi +0 -5
  155. aip_agents/memory/adapters/__init__.pyi +0 -4
  156. aip_agents/memory/adapters/base_adapter.pyi +0 -150
  157. aip_agents/memory/adapters/mem0.pyi +0 -22
  158. aip_agents/memory/base.pyi +0 -60
  159. aip_agents/memory/constants.pyi +0 -25
  160. aip_agents/memory/factory.pyi +0 -24
  161. aip_agents/memory/guidance.pyi +0 -3
  162. aip_agents/memory/simple_memory.pyi +0 -23
  163. aip_agents/middleware/__init__.pyi +0 -5
  164. aip_agents/middleware/base.pyi +0 -71
  165. aip_agents/middleware/manager.pyi +0 -80
  166. aip_agents/middleware/todolist.pyi +0 -125
  167. aip_agents/schema/__init__.pyi +0 -9
  168. aip_agents/schema/a2a.pyi +0 -40
  169. aip_agents/schema/agent.pyi +0 -65
  170. aip_agents/schema/hitl.pyi +0 -89
  171. aip_agents/schema/langgraph.pyi +0 -28
  172. aip_agents/schema/model_id.pyi +0 -54
  173. aip_agents/schema/step_limit.pyi +0 -63
  174. aip_agents/schema/storage.pyi +0 -21
  175. aip_agents/sentry/__init__.pyi +0 -3
  176. aip_agents/sentry/sentry.pyi +0 -48
  177. aip_agents/storage/__init__.pyi +0 -8
  178. aip_agents/storage/base.pyi +0 -58
  179. aip_agents/storage/clients/__init__.pyi +0 -3
  180. aip_agents/storage/clients/minio_client.pyi +0 -137
  181. aip_agents/storage/config.pyi +0 -29
  182. aip_agents/storage/providers/__init__.pyi +0 -5
  183. aip_agents/storage/providers/base.pyi +0 -88
  184. aip_agents/storage/providers/memory.pyi +0 -79
  185. aip_agents/storage/providers/object_storage.pyi +0 -98
  186. aip_agents/tools/__init__.pyi +0 -4
  187. aip_agents/tools/bosa_tools.pyi +0 -37
  188. aip_agents/tools/browser_use/__init__.pyi +0 -14
  189. aip_agents/tools/browser_use/action_parser.pyi +0 -18
  190. aip_agents/tools/browser_use/browser_use_tool.pyi +0 -50
  191. aip_agents/tools/browser_use/llm_config.pyi +0 -52
  192. aip_agents/tools/browser_use/minio_storage.pyi +0 -109
  193. aip_agents/tools/browser_use/schemas.pyi +0 -32
  194. aip_agents/tools/browser_use/session.pyi +0 -4
  195. aip_agents/tools/browser_use/session_errors.pyi +0 -53
  196. aip_agents/tools/browser_use/steel_session_recording.pyi +0 -63
  197. aip_agents/tools/browser_use/streaming.pyi +0 -81
  198. aip_agents/tools/browser_use/structured_data_parser.pyi +0 -86
  199. aip_agents/tools/browser_use/structured_data_recovery.pyi +0 -43
  200. aip_agents/tools/browser_use/types.pyi +0 -45
  201. aip_agents/tools/code_sandbox/__init__.pyi +0 -3
  202. aip_agents/tools/code_sandbox/constant.pyi +0 -4
  203. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.pyi +0 -86
  204. aip_agents/tools/code_sandbox/e2b_sandbox_tool.pyi +0 -29
  205. aip_agents/tools/constants.pyi +0 -135
  206. aip_agents/tools/document_loader/__init__.pyi +0 -7
  207. aip_agents/tools/document_loader/base_reader.pyi +0 -62
  208. aip_agents/tools/document_loader/docx_reader_tool.pyi +0 -6
  209. aip_agents/tools/document_loader/excel_reader_tool.pyi +0 -26
  210. aip_agents/tools/document_loader/pdf_reader_tool.pyi +0 -11
  211. aip_agents/tools/document_loader/pdf_splitter.pyi +0 -18
  212. aip_agents/tools/gl_connector/__init__.pyi +0 -3
  213. aip_agents/tools/gl_connector/tool.pyi +0 -74
  214. aip_agents/tools/memory_search/__init__.pyi +0 -5
  215. aip_agents/tools/memory_search/base.pyi +0 -69
  216. aip_agents/tools/memory_search/mem0.pyi +0 -19
  217. aip_agents/tools/memory_search/schema.pyi +0 -15
  218. aip_agents/tools/memory_search_tool.pyi +0 -3
  219. aip_agents/tools/tool_config_injector.pyi +0 -26
  220. aip_agents/tools/web_search/__init__.pyi +0 -3
  221. aip_agents/tools/web_search/serper_tool.pyi +0 -19
  222. aip_agents/types/__init__.pyi +0 -36
  223. aip_agents/types/a2a_events.pyi +0 -3
  224. aip_agents/utils/__init__.pyi +0 -11
  225. aip_agents/utils/a2a_connector.pyi +0 -146
  226. aip_agents/utils/artifact_helpers.pyi +0 -203
  227. aip_agents/utils/constants.pyi +0 -10
  228. aip_agents/utils/datetime/__init__.pyi +0 -4
  229. aip_agents/utils/datetime/normalization.pyi +0 -95
  230. aip_agents/utils/datetime/timezone.pyi +0 -48
  231. aip_agents/utils/env_loader.pyi +0 -10
  232. aip_agents/utils/event_handler_registry.pyi +0 -23
  233. aip_agents/utils/file_prompt_utils.pyi +0 -21
  234. aip_agents/utils/final_response_builder.pyi +0 -34
  235. aip_agents/utils/formatter_llm_client.pyi +0 -71
  236. aip_agents/utils/langgraph/__init__.pyi +0 -3
  237. aip_agents/utils/langgraph/converter.pyi +0 -49
  238. aip_agents/utils/langgraph/tool_managers/__init__.pyi +0 -5
  239. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.pyi +0 -35
  240. aip_agents/utils/langgraph/tool_managers/base_tool_manager.pyi +0 -48
  241. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.pyi +0 -56
  242. aip_agents/utils/langgraph/tool_output_management.pyi +0 -292
  243. aip_agents/utils/logger.pyi +0 -60
  244. aip_agents/utils/metadata/__init__.pyi +0 -5
  245. aip_agents/utils/metadata/activity_metadata_helper.pyi +0 -25
  246. aip_agents/utils/metadata/activity_narrative/__init__.pyi +0 -7
  247. aip_agents/utils/metadata/activity_narrative/builder.pyi +0 -35
  248. aip_agents/utils/metadata/activity_narrative/constants.pyi +0 -10
  249. aip_agents/utils/metadata/activity_narrative/context.pyi +0 -32
  250. aip_agents/utils/metadata/activity_narrative/formatters.pyi +0 -48
  251. aip_agents/utils/metadata/activity_narrative/utils.pyi +0 -12
  252. aip_agents/utils/metadata/schemas/__init__.pyi +0 -4
  253. aip_agents/utils/metadata/schemas/activity_schema.pyi +0 -18
  254. aip_agents/utils/metadata/schemas/thinking_schema.pyi +0 -20
  255. aip_agents/utils/metadata/thinking_metadata_helper.pyi +0 -4
  256. aip_agents/utils/metadata_helper.pyi +0 -117
  257. aip_agents/utils/name_preprocessor/__init__.pyi +0 -6
  258. aip_agents/utils/name_preprocessor/base_name_preprocessor.pyi +0 -52
  259. aip_agents/utils/name_preprocessor/google_name_preprocessor.pyi +0 -38
  260. aip_agents/utils/name_preprocessor/name_preprocessor.pyi +0 -41
  261. aip_agents/utils/name_preprocessor/openai_name_preprocessor.pyi +0 -34
  262. aip_agents/utils/pii/__init__.pyi +0 -5
  263. aip_agents/utils/pii/pii_handler.pyi +0 -96
  264. aip_agents/utils/pii/pii_helper.pyi +0 -78
  265. aip_agents/utils/pii/uuid_deanonymizer_mapping.pyi +0 -73
  266. aip_agents/utils/reference_helper.pyi +0 -81
  267. aip_agents/utils/sse_chunk_transformer.pyi +0 -166
  268. aip_agents/utils/step_limit_manager.pyi +0 -112
  269. aip_agents/utils/token_usage_helper.pyi +0 -60
  270. {aip_agents_binary-0.5.11.dist-info → aip_agents_binary-0.5.12.dist-info}/WHEEL +0 -0
  271. {aip_agents_binary-0.5.11.dist-info → aip_agents_binary-0.5.12.dist-info}/top_level.txt +0 -0
@@ -255,6 +255,7 @@ class LangGraphA2AExecutor(BaseA2AExecutor, ABC):
255
255
  return []
256
256
 
257
257
  normalized_files: list[str | dict[str, Any]] = []
258
+ invalid_entry_logged = False
258
259
  for entry in raw_files:
259
260
  if isinstance(entry, str) and entry:
260
261
  normalized_files.append(entry)
@@ -262,6 +263,8 @@ class LangGraphA2AExecutor(BaseA2AExecutor, ABC):
262
263
  if isinstance(entry, dict):
263
264
  normalized_files.append(entry)
264
265
  continue
265
- logger.warning("Invalid file metadata entry received; expected string or dict.")
266
+ if not invalid_entry_logged:
267
+ logger.warning("Invalid file metadata entry received; expected string or dict.")
268
+ invalid_entry_logged = True
266
269
 
267
270
  return normalized_files
@@ -15,6 +15,7 @@ from typing import Any
15
15
 
16
16
  from aip_agents.agent.hitl.config import ToolApprovalConfig
17
17
  from aip_agents.agent.hitl.prompt import BasePromptHandler, DeferredPromptHandler
18
+ from aip_agents.agent.hitl.registry import hitl_registry
18
19
  from aip_agents.schema.hitl import ApprovalDecision, ApprovalDecisionType, ApprovalLogEntry, ApprovalRequest
19
20
 
20
21
  # Constants
@@ -197,6 +198,9 @@ class ApprovalManager:
197
198
 
198
199
  self._active_requests[request.request_id] = request
199
200
 
201
+ # Register ownership in global registry for hierarchical routing
202
+ hitl_registry.register(request.request_id, self)
203
+
200
204
  def get_pending_request(self, request_id: str) -> ApprovalRequest | None:
201
205
  """Get a pending approval request by ID.
202
206
 
@@ -312,6 +316,10 @@ class ApprovalManager:
312
316
  decision.latency_ms = int(latency.total_seconds() * 1000)
313
317
 
314
318
  self._active_requests.pop(request.request_id, None)
319
+
320
+ # Unregister from global registry when finalized
321
+ hitl_registry.unregister(request.request_id)
322
+
315
323
  return decision
316
324
 
317
325
  async def prompt_for_decision(
@@ -459,6 +467,8 @@ class ApprovalManager:
459
467
 
460
468
  for request_id in expired_ids:
461
469
  self._active_requests.pop(request_id, None)
470
+ # Unregister expired requests from global registry
471
+ hitl_registry.unregister(request_id)
462
472
 
463
473
  return len(expired_ids)
464
474
 
@@ -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()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aip-agents-binary
3
- Version: 0.5.11
3
+ Version: 0.5.12
4
4
  Summary: A library for managing agents in Gen AI applications.
5
5
  Author-email: Raymond Christopher <raymond.christopher@gdplabs.id>
6
6
  Requires-Python: <3.13,>=3.11