aip-agents-binary 0.0.0__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 (447) hide show
  1. aip_agents/__init__.py +66 -0
  2. aip_agents/a2a/__init__.py +19 -0
  3. aip_agents/a2a/server/__init__.py +10 -0
  4. aip_agents/a2a/server/base_executor.py +1125 -0
  5. aip_agents/a2a/server/google_adk_executor.py +198 -0
  6. aip_agents/a2a/server/langflow_executor.py +180 -0
  7. aip_agents/a2a/server/langgraph_executor.py +270 -0
  8. aip_agents/a2a/types.py +232 -0
  9. aip_agents/a2ui/__init__.py +26 -0
  10. aip_agents/a2ui/catalog_provider.py +109 -0
  11. aip_agents/a2ui/examples/0.8/booking_form.json +1 -0
  12. aip_agents/a2ui/examples/0.8/confirmation.json +1 -0
  13. aip_agents/a2ui/examples/0.8/single_column_list.json +1 -0
  14. aip_agents/a2ui/examples/0.9/booking_form.json +1 -0
  15. aip_agents/a2ui/examples/0.9/confirmation.json +1 -0
  16. aip_agents/a2ui/examples/0.9/single_column_list.json +1 -0
  17. aip_agents/a2ui/middleware.py +754 -0
  18. aip_agents/a2ui/models.py +153 -0
  19. aip_agents/a2ui/public_url.py +138 -0
  20. aip_agents/a2ui/stream_filter.py +67 -0
  21. aip_agents/agent/__init__.py +72 -0
  22. aip_agents/agent/base_agent.py +1437 -0
  23. aip_agents/agent/base_langgraph_agent.py +4048 -0
  24. aip_agents/agent/google_adk_agent.py +932 -0
  25. aip_agents/agent/google_adk_constants.py +11 -0
  26. aip_agents/agent/graph_runtime.py +185 -0
  27. aip_agents/agent/hitl/__init__.py +24 -0
  28. aip_agents/agent/hitl/config.py +28 -0
  29. aip_agents/agent/hitl/langgraph_hitl_mixin.py +515 -0
  30. aip_agents/agent/hitl/manager.py +532 -0
  31. aip_agents/agent/hitl/models.py +18 -0
  32. aip_agents/agent/hitl/prompt/__init__.py +9 -0
  33. aip_agents/agent/hitl/prompt/base.py +42 -0
  34. aip_agents/agent/hitl/prompt/deferred.py +73 -0
  35. aip_agents/agent/hitl/registry.py +149 -0
  36. aip_agents/agent/interface.py +138 -0
  37. aip_agents/agent/interfaces.py +65 -0
  38. aip_agents/agent/langflow_agent.py +464 -0
  39. aip_agents/agent/langgraph_react_agent.py +3741 -0
  40. aip_agents/agent/model_invocation_adapter.py +346 -0
  41. aip_agents/agent/system_instruction_context.py +34 -0
  42. aip_agents/agent/tool_execution_engine.py +587 -0
  43. aip_agents/audio_interface/__init__.py +30 -0
  44. aip_agents/audio_interface/audio_agent_adapter.py +254 -0
  45. aip_agents/audio_interface/config.py +146 -0
  46. aip_agents/audio_interface/errors.py +15 -0
  47. aip_agents/audio_interface/livekit_audio_session.py +504 -0
  48. aip_agents/audio_interface/livekit_realtime_audio_session.py +142 -0
  49. aip_agents/audio_interface/session_factory.py +40 -0
  50. aip_agents/clients/__init__.py +10 -0
  51. aip_agents/clients/langflow/__init__.py +10 -0
  52. aip_agents/clients/langflow/client.py +477 -0
  53. aip_agents/clients/langflow/types.py +18 -0
  54. aip_agents/common/__init__.py +5 -0
  55. aip_agents/common/callable_introspection.py +17 -0
  56. aip_agents/constants.py +23 -0
  57. aip_agents/context/__init__.py +5 -0
  58. aip_agents/context/budget.py +237 -0
  59. aip_agents/context/compaction.py +339 -0
  60. aip_agents/context/metadata.py +169 -0
  61. aip_agents/context/offload.py +449 -0
  62. aip_agents/context/preparation.py +196 -0
  63. aip_agents/context/prompt.py +61 -0
  64. aip_agents/context/runtime.py +149 -0
  65. aip_agents/context/session_recall.py +69 -0
  66. aip_agents/context/state.py +48 -0
  67. aip_agents/context/utils.py +44 -0
  68. aip_agents/credentials/manager.py +132 -0
  69. aip_agents/examples/__init__.py +5 -0
  70. aip_agents/examples/audio_livekit_session.py +116 -0
  71. aip_agents/examples/compare_streaming_client.py +783 -0
  72. aip_agents/examples/compare_streaming_server.py +141 -0
  73. aip_agents/examples/gl_connectors_smoke.py +148 -0
  74. aip_agents/examples/hello_world_a2a_google_adk_client.py +49 -0
  75. aip_agents/examples/hello_world_a2a_google_adk_client_agent.py +48 -0
  76. aip_agents/examples/hello_world_a2a_google_adk_client_streaming.py +60 -0
  77. aip_agents/examples/hello_world_a2a_google_adk_server.py +78 -0
  78. aip_agents/examples/hello_world_a2a_langchain_client.py +39 -0
  79. aip_agents/examples/hello_world_a2a_langchain_client_agent.py +39 -0
  80. aip_agents/examples/hello_world_a2a_langchain_client_lm_invoker.py +37 -0
  81. aip_agents/examples/hello_world_a2a_langchain_client_streaming.py +41 -0
  82. aip_agents/examples/hello_world_a2a_langchain_reference_client_streaming.py +60 -0
  83. aip_agents/examples/hello_world_a2a_langchain_reference_server.py +104 -0
  84. aip_agents/examples/hello_world_a2a_langchain_server.py +78 -0
  85. aip_agents/examples/hello_world_a2a_langchain_server_lm_invoker.py +77 -0
  86. aip_agents/examples/hello_world_a2a_langflow_client.py +83 -0
  87. aip_agents/examples/hello_world_a2a_langflow_server.py +80 -0
  88. aip_agents/examples/hello_world_a2a_langgraph_artifact_client.py +73 -0
  89. aip_agents/examples/hello_world_a2a_langgraph_artifact_client_streaming.py +76 -0
  90. aip_agents/examples/hello_world_a2a_langgraph_artifact_server.py +91 -0
  91. aip_agents/examples/hello_world_a2a_langgraph_client.py +54 -0
  92. aip_agents/examples/hello_world_a2a_langgraph_client_agent.py +54 -0
  93. aip_agents/examples/hello_world_a2a_langgraph_client_agent_lm_invoker.py +32 -0
  94. aip_agents/examples/hello_world_a2a_langgraph_client_streaming.py +50 -0
  95. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_lm_invoker.py +44 -0
  96. aip_agents/examples/hello_world_a2a_langgraph_client_streaming_tool_streaming.py +92 -0
  97. aip_agents/examples/hello_world_a2a_langgraph_server.py +83 -0
  98. aip_agents/examples/hello_world_a2a_langgraph_server_lm_invoker.py +78 -0
  99. aip_agents/examples/hello_world_a2a_langgraph_server_tool_streaming.py +131 -0
  100. aip_agents/examples/hello_world_a2a_mcp_langgraph.py +196 -0
  101. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_client.py +244 -0
  102. aip_agents/examples/hello_world_a2a_three_level_agent_hierarchy_server.py +250 -0
  103. aip_agents/examples/hello_world_a2a_with_metadata_langchain_client.py +57 -0
  104. aip_agents/examples/hello_world_a2a_with_metadata_langchain_server_lm_invoker.py +79 -0
  105. aip_agents/examples/hello_world_filesystem.py +162 -0
  106. aip_agents/examples/hello_world_google_adk.py +41 -0
  107. aip_agents/examples/hello_world_google_adk_mcp_http.py +34 -0
  108. aip_agents/examples/hello_world_google_adk_mcp_http_stream.py +40 -0
  109. aip_agents/examples/hello_world_google_adk_mcp_sse.py +44 -0
  110. aip_agents/examples/hello_world_google_adk_mcp_sse_stream.py +48 -0
  111. aip_agents/examples/hello_world_google_adk_mcp_stdio.py +44 -0
  112. aip_agents/examples/hello_world_google_adk_mcp_stdio_stream.py +48 -0
  113. aip_agents/examples/hello_world_google_adk_stream.py +44 -0
  114. aip_agents/examples/hello_world_langchain.py +28 -0
  115. aip_agents/examples/hello_world_langchain_lm_invoker.py +15 -0
  116. aip_agents/examples/hello_world_langchain_mcp_http.py +34 -0
  117. aip_agents/examples/hello_world_langchain_mcp_http_interactive.py +130 -0
  118. aip_agents/examples/hello_world_langchain_mcp_http_stream.py +42 -0
  119. aip_agents/examples/hello_world_langchain_mcp_multi_server.py +155 -0
  120. aip_agents/examples/hello_world_langchain_mcp_sse.py +34 -0
  121. aip_agents/examples/hello_world_langchain_mcp_sse_stream.py +40 -0
  122. aip_agents/examples/hello_world_langchain_mcp_stdio.py +30 -0
  123. aip_agents/examples/hello_world_langchain_mcp_stdio_stream.py +41 -0
  124. aip_agents/examples/hello_world_langchain_stream.py +36 -0
  125. aip_agents/examples/hello_world_langchain_stream_lm_invoker.py +39 -0
  126. aip_agents/examples/hello_world_langflow_agent.py +163 -0
  127. aip_agents/examples/hello_world_langgraph.py +39 -0
  128. aip_agents/examples/hello_world_langgraph_gl_connector_twitter.py +44 -0
  129. aip_agents/examples/hello_world_langgraph_mcp_http.py +31 -0
  130. aip_agents/examples/hello_world_langgraph_mcp_http_stream.py +34 -0
  131. aip_agents/examples/hello_world_langgraph_mcp_sse.py +35 -0
  132. aip_agents/examples/hello_world_langgraph_mcp_sse_stream.py +50 -0
  133. aip_agents/examples/hello_world_langgraph_mcp_stdio.py +35 -0
  134. aip_agents/examples/hello_world_langgraph_mcp_stdio_stream.py +50 -0
  135. aip_agents/examples/hello_world_langgraph_skills.py +62 -0
  136. aip_agents/examples/hello_world_langgraph_stream.py +43 -0
  137. aip_agents/examples/hello_world_langgraph_stream_lm_invoker.py +37 -0
  138. aip_agents/examples/hello_world_model_switch_cli.py +210 -0
  139. aip_agents/examples/hello_world_multi_agent_adk.py +75 -0
  140. aip_agents/examples/hello_world_multi_agent_langchain.py +54 -0
  141. aip_agents/examples/hello_world_multi_agent_langgraph.py +66 -0
  142. aip_agents/examples/hello_world_multi_agent_langgraph_lm_invoker.py +69 -0
  143. aip_agents/examples/hello_world_multi_agent_tool_output_client.py +57 -0
  144. aip_agents/examples/hello_world_multi_agent_tool_output_server.py +131 -0
  145. aip_agents/examples/hello_world_pii_logger.py +21 -0
  146. aip_agents/examples/hello_world_ptc.py +49 -0
  147. aip_agents/examples/hello_world_ptc_custom_tools.py +83 -0
  148. aip_agents/examples/hello_world_sentry.py +133 -0
  149. aip_agents/examples/hello_world_step_limits.py +273 -0
  150. aip_agents/examples/hello_world_stock_a2a_server.py +100 -0
  151. aip_agents/examples/hello_world_tool_output_client.py +55 -0
  152. aip_agents/examples/hello_world_tool_output_server.py +113 -0
  153. aip_agents/examples/hitl_demo.py +724 -0
  154. aip_agents/examples/mcp_configs/configs.py +63 -0
  155. aip_agents/examples/mcp_servers/common.py +76 -0
  156. aip_agents/examples/mcp_servers/mcp_name.py +29 -0
  157. aip_agents/examples/mcp_servers/mcp_server_http.py +19 -0
  158. aip_agents/examples/mcp_servers/mcp_server_sse.py +19 -0
  159. aip_agents/examples/mcp_servers/mcp_server_stdio.py +19 -0
  160. aip_agents/examples/mcp_servers/mcp_time.py +10 -0
  161. aip_agents/examples/pii_demo_langgraph_client.py +69 -0
  162. aip_agents/examples/pii_demo_langgraph_server.py +125 -0
  163. aip_agents/examples/pii_demo_multi_agent_client.py +80 -0
  164. aip_agents/examples/pii_demo_multi_agent_server.py +246 -0
  165. aip_agents/examples/todolist_planning_a2a_langchain_client.py +70 -0
  166. aip_agents/examples/todolist_planning_a2a_langgraph_server.py +87 -0
  167. aip_agents/examples/tools/__init__.py +27 -0
  168. aip_agents/examples/tools/adk_arithmetic_tools.py +36 -0
  169. aip_agents/examples/tools/adk_weather_tool.py +60 -0
  170. aip_agents/examples/tools/data_generator_tool.py +103 -0
  171. aip_agents/examples/tools/data_visualization_tool.py +312 -0
  172. aip_agents/examples/tools/image_artifact_tool.py +136 -0
  173. aip_agents/examples/tools/langchain_arithmetic_tools.py +26 -0
  174. aip_agents/examples/tools/langchain_currency_exchange_tool.py +88 -0
  175. aip_agents/examples/tools/langchain_graph_artifact_tool.py +172 -0
  176. aip_agents/examples/tools/langchain_weather_tool.py +48 -0
  177. aip_agents/examples/tools/langgraph_streaming_tool.py +130 -0
  178. aip_agents/examples/tools/mock_retrieval_tool.py +56 -0
  179. aip_agents/examples/tools/multiply_tool.py +43 -0
  180. aip_agents/examples/tools/pii_demo_tools.py +189 -0
  181. aip_agents/examples/tools/random_chart_tool.py +142 -0
  182. aip_agents/examples/tools/serper_tool.py +202 -0
  183. aip_agents/examples/tools/stock_tools.py +82 -0
  184. aip_agents/examples/tools/table_generator_tool.py +167 -0
  185. aip_agents/examples/tools/time_tool.py +82 -0
  186. aip_agents/examples/tools/weather_forecast_tool.py +38 -0
  187. aip_agents/guardrails/__init__.py +83 -0
  188. aip_agents/guardrails/engines/__init__.py +69 -0
  189. aip_agents/guardrails/engines/base.py +90 -0
  190. aip_agents/guardrails/engines/nemo.py +101 -0
  191. aip_agents/guardrails/engines/phrase_matcher.py +113 -0
  192. aip_agents/guardrails/exceptions.py +39 -0
  193. aip_agents/guardrails/manager.py +163 -0
  194. aip_agents/guardrails/middleware.py +199 -0
  195. aip_agents/guardrails/schemas.py +63 -0
  196. aip_agents/guardrails/utils.py +45 -0
  197. aip_agents/integration/__init__.py +43 -0
  198. aip_agents/integration/agent.py +58 -0
  199. aip_agents/integration/guardrails.py +52 -0
  200. aip_agents/integration/hitl.py +71 -0
  201. aip_agents/integration/ptc.py +95 -0
  202. aip_agents/integration/skills.py +37 -0
  203. aip_agents/integration/storage.py +81 -0
  204. aip_agents/integration/version.py +103 -0
  205. aip_agents/mcp/__init__.py +1 -0
  206. aip_agents/mcp/client/__init__.py +60 -0
  207. aip_agents/mcp/client/base_mcp_client.py +377 -0
  208. aip_agents/mcp/client/connection_manager.py +231 -0
  209. aip_agents/mcp/client/errors.py +119 -0
  210. aip_agents/mcp/client/google_adk/__init__.py +45 -0
  211. aip_agents/mcp/client/google_adk/client.py +383 -0
  212. aip_agents/mcp/client/langchain/__init__.py +11 -0
  213. aip_agents/mcp/client/langchain/client.py +265 -0
  214. aip_agents/mcp/client/persistent_session.py +704 -0
  215. aip_agents/mcp/client/session_pool.py +358 -0
  216. aip_agents/mcp/client/transports.py +288 -0
  217. aip_agents/mcp/utils/__init__.py +7 -0
  218. aip_agents/mcp/utils/config_validator.py +139 -0
  219. aip_agents/memory/__init__.py +14 -0
  220. aip_agents/memory/adapters/__init__.py +10 -0
  221. aip_agents/memory/adapters/base_adapter.py +815 -0
  222. aip_agents/memory/adapters/mem0.py +286 -0
  223. aip_agents/memory/base.py +84 -0
  224. aip_agents/memory/constants.py +49 -0
  225. aip_agents/memory/factory.py +86 -0
  226. aip_agents/memory/guidance.py +20 -0
  227. aip_agents/memory/simple_memory.py +47 -0
  228. aip_agents/middleware/__init__.py +65 -0
  229. aip_agents/middleware/backends/__init__.py +72 -0
  230. aip_agents/middleware/backends/in_memory.py +578 -0
  231. aip_agents/middleware/backends/local_disk.py +1203 -0
  232. aip_agents/middleware/backends/protocol.py +353 -0
  233. aip_agents/middleware/backends/sandbox.py +1431 -0
  234. aip_agents/middleware/backends/sandbox_files.py +113 -0
  235. aip_agents/middleware/backends/utils.py +293 -0
  236. aip_agents/middleware/base.py +239 -0
  237. aip_agents/middleware/filesystem.py +690 -0
  238. aip_agents/middleware/manager.py +291 -0
  239. aip_agents/middleware/memory.py +532 -0
  240. aip_agents/middleware/pii_middleware.py +192 -0
  241. aip_agents/middleware/schema.py +19 -0
  242. aip_agents/middleware/skills.py +872 -0
  243. aip_agents/middleware/task_delegation.py +1656 -0
  244. aip_agents/middleware/todolist.py +276 -0
  245. aip_agents/middleware/tools/__init__.py +23 -0
  246. aip_agents/middleware/tools/edit_file.py +70 -0
  247. aip_agents/middleware/tools/execute.py +428 -0
  248. aip_agents/middleware/tools/grep_file.py +79 -0
  249. aip_agents/middleware/tools/ls.py +71 -0
  250. aip_agents/middleware/tools/read_file.py +239 -0
  251. aip_agents/middleware/tools/skill_load.py +193 -0
  252. aip_agents/middleware/tools/skill_resource.py +338 -0
  253. aip_agents/middleware/tools/write_file.py +114 -0
  254. aip_agents/middleware/vision.py +322 -0
  255. aip_agents/ptc/__init__.py +87 -0
  256. aip_agents/ptc/custom_tools.py +511 -0
  257. aip_agents/ptc/custom_tools_payload.py +499 -0
  258. aip_agents/ptc/custom_tools_templates/__init__.py +1 -0
  259. aip_agents/ptc/custom_tools_templates/custom_build_function.py.template +24 -0
  260. aip_agents/ptc/custom_tools_templates/custom_init.py.template +26 -0
  261. aip_agents/ptc/custom_tools_templates/custom_invoke.py.template +149 -0
  262. aip_agents/ptc/custom_tools_templates/custom_registry.py.template +112 -0
  263. aip_agents/ptc/custom_tools_templates/custom_sources_init.py.template +7 -0
  264. aip_agents/ptc/custom_tools_templates/custom_wrapper.py.template +87 -0
  265. aip_agents/ptc/doc_gen.py +122 -0
  266. aip_agents/ptc/exceptions.py +57 -0
  267. aip_agents/ptc/executor.py +627 -0
  268. aip_agents/ptc/mcp/__init__.py +45 -0
  269. aip_agents/ptc/mcp/sandbox_bridge.py +679 -0
  270. aip_agents/ptc/mcp/templates/__init__.py +1 -0
  271. aip_agents/ptc/mcp/templates/mcp_client.py.template +240 -0
  272. aip_agents/ptc/naming.py +430 -0
  273. aip_agents/ptc/payload.py +26 -0
  274. aip_agents/ptc/prompt_builder.py +674 -0
  275. aip_agents/ptc/ptc_helper.py +16 -0
  276. aip_agents/ptc/sandbox_bridge.py +297 -0
  277. aip_agents/ptc/template_utils.py +33 -0
  278. aip_agents/ptc/templates/__init__.py +1 -0
  279. aip_agents/ptc/templates/ptc_helper.py.template +134 -0
  280. aip_agents/ptc/tool_def_helpers.py +101 -0
  281. aip_agents/ptc/tool_enrichment.py +163 -0
  282. aip_agents/resilience/__init__.py +10 -0
  283. aip_agents/resilience/base.py +46 -0
  284. aip_agents/resilience/tool.py +1661 -0
  285. aip_agents/sandbox/__init__.py +62 -0
  286. aip_agents/sandbox/defaults.py +220 -0
  287. aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-1-datasaur.Dockerfile +120 -0
  288. aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-1.Dockerfile +100 -0
  289. aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-2-datasaur.Dockerfile +143 -0
  290. aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-2.Dockerfile +119 -0
  291. aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-3-datasaur.Dockerfile +173 -0
  292. aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-3.Dockerfile +130 -0
  293. aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-4-runner-managed.Dockerfile +164 -0
  294. aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-4-runner-managed.patch_js_context.py +41 -0
  295. aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2-4-runner-managed.requirements.txt +29 -0
  296. aip_agents/sandbox/dockerfiles/aip-agents-sandbox-v2.Dockerfile +87 -0
  297. aip_agents/sandbox/e2b_runtime.py +27 -0
  298. aip_agents/sandbox/image_registry.py +98 -0
  299. aip_agents/sandbox/providers/__init__.py +76 -0
  300. aip_agents/sandbox/providers/base.py +392 -0
  301. aip_agents/sandbox/providers/bedrock.py +28 -0
  302. aip_agents/sandbox/providers/e2b.py +230 -0
  303. aip_agents/sandbox/providers/opensandbox.py +163 -0
  304. aip_agents/sandbox/sandbox_runtime.py +967 -0
  305. aip_agents/sandbox/template_builder.py +240 -0
  306. aip_agents/sandbox/types.py +141 -0
  307. aip_agents/sandbox/validation.py +50 -0
  308. aip_agents/schema/__init__.py +106 -0
  309. aip_agents/schema/a2a.py +58 -0
  310. aip_agents/schema/agent.py +117 -0
  311. aip_agents/schema/artifacts.py +75 -0
  312. aip_agents/schema/attachments.py +425 -0
  313. aip_agents/schema/hitl.py +157 -0
  314. aip_agents/schema/langgraph.py +47 -0
  315. aip_agents/schema/model_id.py +103 -0
  316. aip_agents/schema/model_usage.py +50 -0
  317. aip_agents/schema/runtime_metadata.py +78 -0
  318. aip_agents/schema/step_limit.py +108 -0
  319. aip_agents/schema/storage.py +40 -0
  320. aip_agents/schema/tool_payloads.py +68 -0
  321. aip_agents/sentry/__init__.py +11 -0
  322. aip_agents/sentry/sentry.py +267 -0
  323. aip_agents/skills/__init__.py +30 -0
  324. aip_agents/skills/errors.py +110 -0
  325. aip_agents/skills/installer.py +479 -0
  326. aip_agents/skills/models.py +769 -0
  327. aip_agents/skills/stager.py +224 -0
  328. aip_agents/skills/validation.py +53 -0
  329. aip_agents/storage/__init__.py +41 -0
  330. aip_agents/storage/base.py +85 -0
  331. aip_agents/storage/clients/__init__.py +12 -0
  332. aip_agents/storage/clients/minio_client.py +318 -0
  333. aip_agents/storage/config.py +62 -0
  334. aip_agents/storage/providers/__init__.py +15 -0
  335. aip_agents/storage/providers/base.py +106 -0
  336. aip_agents/storage/providers/memory.py +114 -0
  337. aip_agents/storage/providers/object_storage.py +214 -0
  338. aip_agents/tools/__init__.py +65 -0
  339. aip_agents/tools/agent_schedule_tool.py +392 -0
  340. aip_agents/tools/browser_use/__init__.py +83 -0
  341. aip_agents/tools/browser_use/action_parser.py +104 -0
  342. aip_agents/tools/browser_use/browser_use_tool.py +1118 -0
  343. aip_agents/tools/browser_use/llm_config.py +120 -0
  344. aip_agents/tools/browser_use/minio_storage.py +203 -0
  345. aip_agents/tools/browser_use/schemas.py +121 -0
  346. aip_agents/tools/browser_use/session.py +13 -0
  347. aip_agents/tools/browser_use/session_errors.py +132 -0
  348. aip_agents/tools/browser_use/steel_session_recording.py +321 -0
  349. aip_agents/tools/browser_use/streaming.py +263 -0
  350. aip_agents/tools/browser_use/structured_data_parser.py +257 -0
  351. aip_agents/tools/browser_use/structured_data_recovery.py +204 -0
  352. aip_agents/tools/browser_use/types.py +37 -0
  353. aip_agents/tools/code_sandbox/__init__.py +48 -0
  354. aip_agents/tools/code_sandbox/code_sandbox_tool.py +350 -0
  355. aip_agents/tools/code_sandbox/constant.py +13 -0
  356. aip_agents/tools/code_sandbox/e2b_cloud_sandbox_extended.py +346 -0
  357. aip_agents/tools/code_sandbox/e2b_sandbox_tool.py +65 -0
  358. aip_agents/tools/computer_use/__init__.py +75 -0
  359. aip_agents/tools/computer_use/computer_use_tool.py +910 -0
  360. aip_agents/tools/computer_use/schemas.py +78 -0
  361. aip_agents/tools/computer_use/streaming.py +198 -0
  362. aip_agents/tools/computer_use/types.py +32 -0
  363. aip_agents/tools/constants.py +177 -0
  364. aip_agents/tools/date_range_tool.py +554 -0
  365. aip_agents/tools/document_loader/__init__.py +44 -0
  366. aip_agents/tools/document_loader/base_reader.py +302 -0
  367. aip_agents/tools/document_loader/docx_reader_tool.py +68 -0
  368. aip_agents/tools/document_loader/excel_reader_tool.py +171 -0
  369. aip_agents/tools/document_loader/pdf_reader_tool.py +79 -0
  370. aip_agents/tools/document_loader/pdf_splitter.py +169 -0
  371. aip_agents/tools/execute_ptc_code.py +582 -0
  372. aip_agents/tools/gl_connector/__init__.py +5 -0
  373. aip_agents/tools/gl_connector/tool.py +518 -0
  374. aip_agents/tools/gl_connector_tools.py +170 -0
  375. aip_agents/tools/memory_search/__init__.py +29 -0
  376. aip_agents/tools/memory_search/base.py +213 -0
  377. aip_agents/tools/memory_search/mem0.py +424 -0
  378. aip_agents/tools/memory_search/schema.py +81 -0
  379. aip_agents/tools/memory_search_tool.py +34 -0
  380. aip_agents/tools/streaming_common.py +577 -0
  381. aip_agents/tools/time_tool.py +117 -0
  382. aip_agents/tools/tool_config_injector.py +300 -0
  383. aip_agents/tools/web_search/__init__.py +15 -0
  384. aip_agents/tools/web_search/serper_tool.py +187 -0
  385. aip_agents/types/__init__.py +73 -0
  386. aip_agents/types/a2a_events.py +13 -0
  387. aip_agents/utils/__init__.py +91 -0
  388. aip_agents/utils/a2a_connector.py +1758 -0
  389. aip_agents/utils/artifact_helpers.py +542 -0
  390. aip_agents/utils/artifacts/__init__.py +20 -0
  391. aip_agents/utils/artifacts/tracker.py +367 -0
  392. aip_agents/utils/attachment_helpers.py +178 -0
  393. aip_agents/utils/constants.py +22 -0
  394. aip_agents/utils/datetime/__init__.py +34 -0
  395. aip_agents/utils/datetime/normalization.py +231 -0
  396. aip_agents/utils/datetime/timezone.py +206 -0
  397. aip_agents/utils/env_loader.py +27 -0
  398. aip_agents/utils/event_handler_registry.py +58 -0
  399. aip_agents/utils/file_prompt_utils.py +276 -0
  400. aip_agents/utils/file_watchers/__init__.py +33 -0
  401. aip_agents/utils/file_watchers/base.py +46 -0
  402. aip_agents/utils/file_watchers/e2b.py +128 -0
  403. aip_agents/utils/file_watchers/factory.py +39 -0
  404. aip_agents/utils/file_watchers/ls_diff.py +88 -0
  405. aip_agents/utils/file_watchers/sandbox.py +66 -0
  406. aip_agents/utils/file_watchers/watchdog.py +97 -0
  407. aip_agents/utils/final_response_builder.py +211 -0
  408. aip_agents/utils/formatter_llm_client.py +258 -0
  409. aip_agents/utils/langgraph/__init__.py +19 -0
  410. aip_agents/utils/langgraph/converter.py +399 -0
  411. aip_agents/utils/langgraph/delegation_context.py +22 -0
  412. aip_agents/utils/langgraph/tool_managers/__init__.py +15 -0
  413. aip_agents/utils/langgraph/tool_managers/a2a_tool_manager.py +99 -0
  414. aip_agents/utils/langgraph/tool_managers/base_tool_manager.py +66 -0
  415. aip_agents/utils/langgraph/tool_managers/delegation_tool_manager.py +1329 -0
  416. aip_agents/utils/langgraph/tool_output_management.py +1047 -0
  417. aip_agents/utils/logger.py +195 -0
  418. aip_agents/utils/metadata/__init__.py +27 -0
  419. aip_agents/utils/metadata/activity_metadata_helper.py +407 -0
  420. aip_agents/utils/metadata/activity_narrative/__init__.py +35 -0
  421. aip_agents/utils/metadata/activity_narrative/builder.py +822 -0
  422. aip_agents/utils/metadata/activity_narrative/constants.py +51 -0
  423. aip_agents/utils/metadata/activity_narrative/context.py +49 -0
  424. aip_agents/utils/metadata/activity_narrative/formatters.py +230 -0
  425. aip_agents/utils/metadata/activity_narrative/utils.py +35 -0
  426. aip_agents/utils/metadata/schemas/__init__.py +16 -0
  427. aip_agents/utils/metadata/schemas/activity_schema.py +29 -0
  428. aip_agents/utils/metadata/schemas/thinking_schema.py +31 -0
  429. aip_agents/utils/metadata/thinking_metadata_helper.py +38 -0
  430. aip_agents/utils/metadata_helper.py +363 -0
  431. aip_agents/utils/name_preprocessor/__init__.py +17 -0
  432. aip_agents/utils/name_preprocessor/base_name_preprocessor.py +73 -0
  433. aip_agents/utils/name_preprocessor/google_name_preprocessor.py +100 -0
  434. aip_agents/utils/name_preprocessor/name_preprocessor.py +87 -0
  435. aip_agents/utils/name_preprocessor/openai_name_preprocessor.py +48 -0
  436. aip_agents/utils/pii/__init__.py +29 -0
  437. aip_agents/utils/pii/pii_handler.py +555 -0
  438. aip_agents/utils/pii/pii_helper.py +225 -0
  439. aip_agents/utils/pii/uuid_deanonymizer_mapping.py +195 -0
  440. aip_agents/utils/reference_helper.py +273 -0
  441. aip_agents/utils/sse_chunk_transformer.py +836 -0
  442. aip_agents/utils/step_limit_manager.py +265 -0
  443. aip_agents/utils/token_usage_helper.py +531 -0
  444. aip_agents_binary-0.0.0.dist-info/METADATA +825 -0
  445. aip_agents_binary-0.0.0.dist-info/RECORD +447 -0
  446. aip_agents_binary-0.0.0.dist-info/WHEEL +5 -0
  447. aip_agents_binary-0.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,322 @@
1
+ """Vision middleware and read_image tool for image context engineering.
2
+
3
+ Authors:
4
+ Raymond Christopher (raymond.christopher@gdplabs.id)
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ import asyncio
10
+ import base64
11
+ import os
12
+ from typing import Any, Literal
13
+
14
+ from langchain_core.runnables import RunnableConfig
15
+ from langchain_core.tools import BaseTool
16
+ from pydantic import BaseModel, Field
17
+
18
+ from aip_agents.schema.attachments import MAX_IMAGE_ATTACHMENT_BYTES
19
+ from aip_agents.utils.attachment_helpers import (
20
+ _artifact_attachment,
21
+ _matches_attachment,
22
+ resolve_attachment_reference,
23
+ )
24
+
25
+ VisionDetail = Literal["auto", "low", "high"]
26
+
27
+
28
+ VISION_SYSTEM_PROMPT = """## Vision Tool `read_image`
29
+
30
+ You can inspect registered image attachments or generated image artifacts by calling `read_image`.
31
+ Use it when a user's request depends on visual details. Do not assume a file path alone means you can see the image.
32
+ """
33
+
34
+
35
+ class ReadImageInput(BaseModel):
36
+ """Input schema for read_image."""
37
+
38
+ image: str = Field(description="Image attachment/artifact id, registered filename, or allowed local path")
39
+ query: str | None = Field(default=None, description="Optional targeted question about the image")
40
+
41
+
42
+ class VisionToolConfig(BaseModel):
43
+ """Configuration for the vision model used by read_image."""
44
+
45
+ model: str | None = None
46
+ api_key: str | None = None
47
+ base_url: str | None = None
48
+ detail: VisionDetail = "auto" # internal/reserved - not wired through gllm-inference yet
49
+
50
+
51
+ class ReadImageTool(BaseTool):
52
+ """Analyze a registered image and return text context."""
53
+
54
+ name: str = "read_image"
55
+ description: str = (
56
+ "Inspect an image attachment or generated image artifact and return text context. "
57
+ "Use this for visual questions about images passed by the user or created by tools."
58
+ )
59
+ args_schema: type[BaseModel] = ReadImageInput
60
+ vision_config: VisionToolConfig = Field(default_factory=VisionToolConfig)
61
+ vision_analyzer: Any | None = None
62
+
63
+ def invoke(self, input: Any, config: RunnableConfig | None = None, **kwargs: Any) -> str:
64
+ """Invoke while preserving RunnableConfig metadata for attachment lookup."""
65
+ tool_args = self._normalize_tool_input(input, kwargs)
66
+ return self._run(**tool_args, config=config)
67
+
68
+ async def ainvoke(self, input: Any, config: RunnableConfig | None = None, **kwargs: Any) -> str:
69
+ """Async invoke while preserving RunnableConfig metadata for attachment lookup."""
70
+ tool_args = self._normalize_tool_input(input, kwargs)
71
+ return await self._arun(**tool_args, config=config)
72
+
73
+ @staticmethod
74
+ def _normalize_tool_input(input: Any, kwargs: dict[str, Any]) -> dict[str, Any]:
75
+ if isinstance(input, dict):
76
+ tool_args = dict(input)
77
+ else:
78
+ tool_args = {"image": input}
79
+ tool_args.update(kwargs)
80
+ return tool_args
81
+
82
+ def _run(
83
+ self,
84
+ image: str,
85
+ query: str | None = None,
86
+ *,
87
+ detail: VisionDetail | None = None,
88
+ config: RunnableConfig | None = None,
89
+ ) -> str:
90
+ """Analyze an image using configured vision settings."""
91
+ metadata = self._extract_metadata(config)
92
+ resolved = self._resolve_image(image, metadata)
93
+ if resolved.get("error"):
94
+ return f"Error: {resolved['error']}"
95
+
96
+ prompt = query or "Describe this image in detail. Include visible objects, text, and important context."
97
+ data_url = resolved["data_url"]
98
+ try:
99
+ return self._analyze_image(data_url=data_url, prompt=prompt)
100
+ except Exception as exc:
101
+ return f"Error: {self._describe_exception(exc)}"
102
+
103
+ async def _arun(
104
+ self,
105
+ image: str,
106
+ query: str | None = None,
107
+ *,
108
+ detail: VisionDetail | None = None,
109
+ config: RunnableConfig | None = None,
110
+ ) -> str:
111
+ """Async entry point for LangChain tool execution."""
112
+ metadata = self._extract_metadata(config)
113
+ resolved = self._resolve_image(image, metadata)
114
+ if resolved.get("error"):
115
+ return f"Error: {resolved['error']}" # pragma: no cover
116
+
117
+ prompt = query or "Describe this image in detail. Include visible objects, text, and important context."
118
+ data_url = resolved["data_url"]
119
+
120
+ if self.vision_analyzer is not None:
121
+ return str(self.vision_analyzer(data_url=data_url, prompt=prompt, detail=self.vision_config.detail))
122
+
123
+ try:
124
+ return await self._analyze_image_live_async(data_url=data_url, prompt=prompt)
125
+ except Exception as exc: # pragma: no cover
126
+ return f"Error: {self._describe_exception(exc)}" # pragma: no cover
127
+
128
+ @staticmethod
129
+ def _extract_metadata(config: RunnableConfig | None) -> dict[str, Any]:
130
+ if not isinstance(config, dict):
131
+ return {}
132
+ metadata = config.get("metadata")
133
+ return metadata if isinstance(metadata, dict) else {}
134
+
135
+ def _resolve_image(self, image: str, metadata: dict[str, Any]) -> dict[str, str]:
136
+ attachment = resolve_attachment_reference(image, metadata)
137
+ if attachment is None:
138
+ return {"error": f"Image not found: {image}"}
139
+
140
+ mime_type = str(attachment.get("mime_type") or "")
141
+ if not mime_type.startswith("image/"):
142
+ return {"error": f"Unsupported image MIME type: {mime_type or 'unknown'}"}
143
+
144
+ data_ref = str(attachment.get("data_ref") or "")
145
+ if data_ref.startswith("artifact://"):
146
+ return self._resolve_artifact_data_url(image, attachment, metadata, mime_type)
147
+
148
+ if os.path.isfile(data_ref):
149
+ unsafe_ref_error = self._unsafe_local_data_ref_error(image, attachment, data_ref)
150
+ if unsafe_ref_error:
151
+ return {"error": unsafe_ref_error}
152
+ oversized_error = self._oversized_error(image, attachment, data_ref)
153
+ if oversized_error:
154
+ return {"error": oversized_error}
155
+ with open(data_ref, "rb") as handle:
156
+ encoded = base64.b64encode(handle.read()).decode("ascii")
157
+ return {"data_url": f"data:{mime_type};base64,{encoded}"}
158
+
159
+ return {"error": f"Image data is not locally readable: {image}"}
160
+
161
+ @staticmethod
162
+ def _unsafe_local_data_ref_error(image: str, attachment: dict[str, Any], data_ref: str) -> str | None:
163
+ """Reject local refs that do not match the registered filename."""
164
+ if attachment.get("source") != "user_input":
165
+ return None
166
+ filename = str(attachment.get("filename") or "")
167
+ if filename and os.path.basename(data_ref) != filename:
168
+ return f"Image data reference does not match registered image: {image}"
169
+ return None
170
+
171
+ @staticmethod
172
+ def _oversized_error(image: str, attachment: dict[str, Any], data_ref: str) -> str | None:
173
+ """Return an error message if an image exceeds the runtime size limit."""
174
+ candidates: list[int] = []
175
+ size_value = attachment.get("size_bytes")
176
+ if isinstance(size_value, int):
177
+ candidates.append(size_value)
178
+ try:
179
+ candidates.append(os.path.getsize(data_ref))
180
+ except OSError:
181
+ pass
182
+ if candidates and max(candidates) > MAX_IMAGE_ATTACHMENT_BYTES:
183
+ return f"Image is too large: {image} exceeds {MAX_IMAGE_ATTACHMENT_BYTES} bytes"
184
+ return None
185
+
186
+ def _resolve_artifact_data_url(
187
+ self, image: str, attachment: dict[str, Any], metadata: dict[str, Any], mime_type: str
188
+ ) -> dict[str, str]:
189
+ artifacts = metadata.get("artifacts")
190
+ if not isinstance(artifacts, list):
191
+ return {"error": f"Image artifact data is unavailable: {image}"}
192
+
193
+ for artifact in artifacts:
194
+ if not isinstance(artifact, dict):
195
+ continue
196
+ artifact_attachment = _artifact_attachment(artifact)
197
+ if artifact_attachment == attachment or _matches_attachment(image, artifact_attachment):
198
+ encoded = artifact.get("data")
199
+ if isinstance(encoded, str) and encoded:
200
+ oversized_error = self._oversized_artifact_error(image, artifact_attachment, encoded)
201
+ if oversized_error:
202
+ return {"error": oversized_error}
203
+ return {"data_url": f"data:{mime_type};base64,{encoded}"}
204
+ return {"error": f"Image artifact data is unavailable: {image}"}
205
+
206
+ @staticmethod
207
+ def _oversized_artifact_error(image: str, attachment: dict[str, Any] | None, encoded: str) -> str | None:
208
+ """Return an error if an artifact image exceeds the runtime size limit."""
209
+ size_value = attachment.get("size_bytes") if isinstance(attachment, dict) else None
210
+ size_bytes = size_value if isinstance(size_value, int) else None
211
+ if size_bytes is None:
212
+ try:
213
+ size_bytes = len(base64.b64decode(encoded, validate=True))
214
+ except ValueError:
215
+ size_bytes = None
216
+ if size_bytes is not None and size_bytes > MAX_IMAGE_ATTACHMENT_BYTES:
217
+ return f"Image is too large: {image} exceeds {MAX_IMAGE_ATTACHMENT_BYTES} bytes"
218
+ return None
219
+
220
+ @staticmethod
221
+ def _infer_image_mime(filename: str) -> str | None:
222
+ lower = filename.lower()
223
+ if lower.endswith(".png"):
224
+ return "image/png"
225
+ if lower.endswith((".jpg", ".jpeg")):
226
+ return "image/jpeg"
227
+ if lower.endswith(".webp"):
228
+ return "image/webp"
229
+ return None
230
+
231
+ def _analyze_image(self, *, data_url: str, prompt: str) -> str:
232
+ if self.vision_analyzer is not None:
233
+ return str(self.vision_analyzer(data_url=data_url, prompt=prompt, detail=self.vision_config.detail))
234
+
235
+ if not self.vision_config.model:
236
+ return (
237
+ "Error: read_image could not determine a vision-capable model. "
238
+ "By default it uses the agent model; set vision.model when the agent model cannot be resolved."
239
+ )
240
+
241
+ return asyncio.run(self._analyze_image_live_async(data_url=data_url, prompt=prompt))
242
+
243
+ async def _analyze_image_live_async(self, *, data_url: str, prompt: str) -> str:
244
+ """Async live model path using gllm-inference."""
245
+ from gllm_inference.lm_invoker.build_lm_invoker import build_lm_invoker
246
+ from gllm_inference.schema.attachment import Attachment
247
+ from gllm_inference.schema.lm_output import LMOutput
248
+ from gllm_inference.schema.message import Message
249
+
250
+ model_str = self.vision_config.model
251
+ if self.vision_config.base_url:
252
+ model_str = f"openai-chat-completions/{self.vision_config.base_url}:{self.vision_config.model}"
253
+
254
+ invoker = build_lm_invoker(
255
+ model_id=model_str,
256
+ credentials=self.vision_config.api_key,
257
+ )
258
+
259
+ attachment = Attachment.from_data_url(data_url, filename="image.png")
260
+ message = Message.user([prompt, attachment])
261
+
262
+ result = await invoker.invoke([message])
263
+ if isinstance(result, str):
264
+ return result
265
+ if isinstance(result, LMOutput): # pragma: no cover
266
+ texts = result.texts # pragma: no cover
267
+ if texts: # pragma: no cover
268
+ return texts[0] # pragma: no cover
269
+ return str(result) # pragma: no cover
270
+
271
+ @staticmethod
272
+ def _describe_exception(exc: Exception) -> str:
273
+ message = str(exc).strip()
274
+ return message or exc.__class__.__name__
275
+
276
+
277
+ __all__ = ["ReadImageTool", "VisionMiddleware", "VisionToolConfig"]
278
+
279
+
280
+ class VisionMiddleware:
281
+ """Middleware that contributes the read_image tool."""
282
+
283
+ def __init__(
284
+ self, vision_config: dict[str, Any] | VisionToolConfig | None = None, vision_analyzer: Any | None = None
285
+ ):
286
+ """Initialize the middleware with optional model config or analyzer hook."""
287
+ if isinstance(vision_config, VisionToolConfig):
288
+ config = vision_config
289
+ elif isinstance(vision_config, dict):
290
+ config = VisionToolConfig(**vision_config)
291
+ else:
292
+ config = VisionToolConfig()
293
+
294
+ self.tools: list[BaseTool] = [ReadImageTool(vision_config=config, vision_analyzer=vision_analyzer)]
295
+ self.system_prompt_additions = VISION_SYSTEM_PROMPT
296
+
297
+ def before_model(self, state: dict[str, Any]) -> dict[str, Any]:
298
+ """No-op model hook for middleware manager compatibility."""
299
+ del state
300
+ return {}
301
+
302
+ async def abefore_model(self, state: dict[str, Any]) -> dict[str, Any]:
303
+ """Async no-op model hook for middleware manager compatibility."""
304
+ del state
305
+ await asyncio.sleep(0)
306
+ return {}
307
+
308
+ def modify_model_request(self, request: dict[str, Any], state: dict[str, Any]) -> dict[str, Any]:
309
+ """Return model requests unchanged."""
310
+ del state
311
+ return request
312
+
313
+ def after_model(self, state: dict[str, Any]) -> dict[str, Any]:
314
+ """No-op after-model hook for middleware manager compatibility."""
315
+ del state
316
+ return {}
317
+
318
+ async def aafter_model(self, state: dict[str, Any]) -> dict[str, Any]:
319
+ """Async no-op after-model hook for middleware manager compatibility."""
320
+ del state
321
+ await asyncio.sleep(0)
322
+ return {}
@@ -0,0 +1,87 @@
1
+ """PTC (Programmatic Tool Calling) core module.
2
+
3
+ This module provides core PTC functionality, including executor, prompt builder,
4
+ sandbox bridge, and custom tool configuration validation.
5
+
6
+ Authors:
7
+ Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
8
+ """
9
+
10
+ from aip_agents.ptc.custom_tools import (
11
+ PTCCustomToolConfig,
12
+ PTCCustomToolValidationError,
13
+ PTCFileToolDef,
14
+ PTCPackageToolDef,
15
+ PTCToolDef,
16
+ enrich_tool_def_with_metadata,
17
+ extract_tool_metadata,
18
+ validate_custom_tool_config,
19
+ )
20
+ from aip_agents.ptc.custom_tools_payload import (
21
+ CustomToolPayloadResult,
22
+ build_custom_tools_payload,
23
+ )
24
+ from aip_agents.ptc.exceptions import PTCError, PTCToolError
25
+ from aip_agents.ptc.prompt_builder import PromptConfig, build_ptc_prompt, compute_ptc_prompt_hash
26
+ from aip_agents.ptc.tool_def_helpers import file_tool, package_tool
27
+ from aip_agents.ptc.tool_enrichment import (
28
+ build_tool_lookup,
29
+ enrich_custom_tools_from_agent,
30
+ match_tool_by_name,
31
+ )
32
+
33
+ __all__ = [
34
+ # Exceptions
35
+ "PTCError",
36
+ "PTCToolError",
37
+ "PTCCustomToolValidationError",
38
+ # Executor
39
+ "PTCSandboxConfig",
40
+ "PTCSandboxExecutor",
41
+ # Custom tools
42
+ "PTCCustomToolConfig",
43
+ "PTCToolDef",
44
+ "PTCPackageToolDef",
45
+ "PTCFileToolDef",
46
+ "validate_custom_tool_config",
47
+ "extract_tool_metadata",
48
+ "enrich_tool_def_with_metadata",
49
+ # Tool enrichment
50
+ "build_tool_lookup",
51
+ "match_tool_by_name",
52
+ "enrich_custom_tools_from_agent",
53
+ # Tool definition helpers
54
+ "package_tool",
55
+ "file_tool",
56
+ # Custom tools payload
57
+ "CustomToolPayloadResult",
58
+ "build_custom_tools_payload",
59
+ # Prompt builder
60
+ "PromptConfig",
61
+ "build_ptc_prompt",
62
+ "compute_ptc_prompt_hash",
63
+ # Sandbox bridge
64
+ "build_sandbox_payload",
65
+ "wrap_ptc_code",
66
+ ]
67
+
68
+
69
+ def __getattr__(name: str) -> object:
70
+ """Lazy import to avoid circular dependencies."""
71
+ if name == "PTCSandboxConfig":
72
+ from aip_agents.ptc.executor import PTCSandboxConfig
73
+
74
+ return PTCSandboxConfig
75
+ elif name == "PTCSandboxExecutor":
76
+ from aip_agents.ptc.executor import PTCSandboxExecutor
77
+
78
+ return PTCSandboxExecutor
79
+ elif name == "build_sandbox_payload":
80
+ from aip_agents.ptc.sandbox_bridge import build_sandbox_payload
81
+
82
+ return build_sandbox_payload
83
+ elif name == "wrap_ptc_code":
84
+ from aip_agents.ptc.sandbox_bridge import wrap_ptc_code
85
+
86
+ return wrap_ptc_code
87
+ raise AttributeError(f"module '{__name__}' has no attribute '{name}'")