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,679 @@
1
+ """Sandbox Bridge for PTC.
2
+
3
+ This module generates the sandbox payload (config + tool modules) that allows
4
+ LLM-generated code to call MCP tools inside an E2B sandbox.
5
+
6
+ The payload includes:
7
+ - ptc_config.json: MCP server configs for the sandbox MCP client
8
+ - tools/__init__.py: Package init with server imports
9
+ - tools/<server>.py: Per-server module with sync tool functions
10
+ - tools/mcp_client.py: HTTP JSON-RPC client for MCP calls
11
+
12
+ Authors:
13
+ Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
14
+ """
15
+
16
+ import json
17
+ from dataclasses import dataclass, field
18
+ from typing import Any
19
+
20
+ from aip_agents.mcp.client.base_mcp_client import BaseMCPClient
21
+ from aip_agents.ptc.doc_gen import (
22
+ render_tool_doc,
23
+ )
24
+ from aip_agents.ptc.naming import (
25
+ DEFAULT_EXAMPLE_PLACEHOLDER,
26
+ example_value_from_schema,
27
+ sanitize_function_name,
28
+ sanitize_module_name_with_reserved,
29
+ schema_to_params,
30
+ )
31
+ from aip_agents.ptc.payload import SandboxPayload
32
+ from aip_agents.ptc.ptc_helper import _generate_ptc_helper_module
33
+ from aip_agents.ptc.template_utils import render_template
34
+ from aip_agents.utils.logger import get_logger
35
+
36
+ logger = get_logger(__name__)
37
+
38
+ # Transport types supported in sandbox (HTTP-based only)
39
+ # Using normalized hyphenated format to align with connection_manager
40
+ SUPPORTED_TRANSPORTS = {"sse", "streamable-http"}
41
+ TRANSPORT_ALIASES = {
42
+ "http": "streamable-http",
43
+ "streamable-http": "streamable-http",
44
+ "sse": "sse",
45
+ }
46
+
47
+ _TEMPLATE_PACKAGE = "aip_agents.ptc.mcp.templates"
48
+
49
+
50
+ @dataclass
51
+ class ServerConfig:
52
+ """Extracted server configuration for sandbox payload.
53
+
54
+ Attributes:
55
+ name: Server name identifier.
56
+ transport: Transport type (sse or streamable_http).
57
+ url: Server URL.
58
+ headers: HTTP headers for authentication.
59
+ allowed_tools: List of allowed tool names, or None for all.
60
+ tools: List of tool definitions from the server.
61
+ timeout: Request timeout in seconds. None means no default timeout.
62
+ """
63
+
64
+ name: str
65
+ transport: str
66
+ url: str
67
+ headers: dict[str, str] = field(default_factory=dict)
68
+ allowed_tools: list[str] | None = None
69
+ tools: list[dict[str, Any]] = field(default_factory=list)
70
+ timeout: float | None = None
71
+
72
+
73
+ async def build_mcp_payload(
74
+ mcp_client: BaseMCPClient,
75
+ default_tool_timeout: float | None = None,
76
+ ) -> SandboxPayload:
77
+ """Build MCP sandbox payload from MCP client configuration.
78
+
79
+ Extracts server configs, tools, and generates the necessary files
80
+ for the sandbox to execute PTC code.
81
+
82
+ Args:
83
+ mcp_client: The MCP client with configured servers.
84
+ default_tool_timeout: Optional default timeout for nested MCP tool calls in seconds.
85
+ When None, no default timeout is injected.
86
+
87
+ Returns:
88
+ SandboxPayload containing files and env vars for the sandbox.
89
+ """
90
+ payload = SandboxPayload()
91
+
92
+ # Extract server configs
93
+ server_configs = await _extract_server_configs(mcp_client, default_tool_timeout)
94
+
95
+ if not server_configs:
96
+ logger.warning("No supported MCP servers found for sandbox payload")
97
+ return payload
98
+
99
+ # Generate ptc_config.json
100
+ config_json = _generate_config_json(server_configs)
101
+ payload.files["ptc_config.json"] = config_json
102
+
103
+ # Generate tools/mcp_client.py
104
+ payload.files["tools/mcp_client.py"] = _generate_mcp_client_module()
105
+
106
+ # Generate tools/__init__.py
107
+ server_names = [cfg.name for cfg in server_configs]
108
+ payload.files["tools/__init__.py"] = _generate_tools_init(server_names)
109
+
110
+ # Generate tools/<server>.py for each server (using reserved-aware sanitization)
111
+ for server_cfg in server_configs:
112
+ module_content = _generate_server_module(server_cfg)
113
+ safe_name = sanitize_module_name_with_reserved(server_cfg.name)
114
+ payload.files[f"tools/{safe_name}.py"] = module_content
115
+
116
+ # Generate tools/ptc_helper.py for discovery
117
+ payload.files["tools/ptc_helper.py"] = _generate_ptc_helper_module()
118
+
119
+ # Generate tools/ptc_index.json for tool index
120
+ payload.files["tools/ptc_index.json"] = _generate_ptc_index(server_configs)
121
+
122
+ # Generate tools/docs/<package>/<tool>.md for each tool
123
+ docs = _generate_all_docs(server_configs)
124
+ payload.files.update(docs)
125
+
126
+ logger.info(f"Built sandbox payload with {len(server_configs)} servers, {len(payload.files)} files")
127
+
128
+ return payload
129
+
130
+
131
+ def _get_config_value(config: Any, key: str, default: Any = None) -> Any:
132
+ """Extract value from config dict or object.
133
+
134
+ Args:
135
+ config: Configuration dict or object.
136
+ key: Key to extract.
137
+ default: Default value if key not found.
138
+
139
+ Returns:
140
+ Extracted value or default.
141
+ """
142
+ if isinstance(config, dict):
143
+ return config.get(key, default)
144
+ return getattr(config, key, default)
145
+
146
+
147
+ def _normalize_transport(transport: Any) -> str | None:
148
+ """Normalize transport format.
149
+
150
+ Args:
151
+ transport: Raw transport value.
152
+
153
+ Returns:
154
+ Normalized transport string or None.
155
+ """
156
+ if not transport:
157
+ return None
158
+
159
+ normalized = str(transport).strip().lower().replace("_", "-")
160
+ if not normalized:
161
+ return None
162
+
163
+ return TRANSPORT_ALIASES.get(normalized, normalized)
164
+
165
+
166
+ def _extract_headers(config: Any) -> dict[str, str]:
167
+ """Extract headers from config.
168
+
169
+ Args:
170
+ config: Configuration dict or object.
171
+
172
+ Returns:
173
+ Headers dictionary.
174
+ """
175
+ raw_headers = _get_config_value(config, "headers")
176
+ if raw_headers and isinstance(raw_headers, dict):
177
+ return dict(raw_headers)
178
+ return {}
179
+
180
+
181
+ def _extract_timeout(config: Any, default_timeout: float | None = None) -> float | None:
182
+ """Extract timeout from config.
183
+
184
+ Args:
185
+ config: Configuration dict or object.
186
+ default_timeout: Optional default timeout value. None means no default timeout.
187
+
188
+ Returns:
189
+ Timeout in seconds, or None for no timeout.
190
+ """
191
+ raw_timeout = _get_config_value(config, "timeout")
192
+ if raw_timeout is not None:
193
+ return float(raw_timeout)
194
+ return default_timeout
195
+
196
+
197
+ def _extract_allowed_tools(mcp_client: BaseMCPClient, server_name: str, config: Any) -> list[str] | None:
198
+ """Extract allowed tools from session or config.
199
+
200
+ Args:
201
+ mcp_client: MCP client instance.
202
+ server_name: Name of the server.
203
+ config: Configuration dict or object.
204
+
205
+ Returns:
206
+ List of allowed tool names or None.
207
+ """
208
+ try:
209
+ session = mcp_client.session_pool.get_session(server_name)
210
+ if session.allowed_tools:
211
+ return list(session.allowed_tools)
212
+ except (KeyError, AttributeError):
213
+ pass
214
+
215
+ raw_allowed = _get_config_value(config, "allowed_tools")
216
+ if raw_allowed and isinstance(raw_allowed, list):
217
+ return list(raw_allowed)
218
+ return None
219
+
220
+
221
+ async def _extract_tools(
222
+ mcp_client: BaseMCPClient,
223
+ server_name: str,
224
+ allowed_tools: list[str] | None,
225
+ ) -> list[dict[str, Any]]:
226
+ """Extract tools from MCP client.
227
+
228
+ When tools are not loaded but allowed_tools exists, returns stub tool entries.
229
+
230
+ Args:
231
+ mcp_client: MCP client instance.
232
+ server_name: Name of the server.
233
+ allowed_tools: List of allowed tool names or None.
234
+
235
+ Returns:
236
+ List of tool definitions. Stubs have minimal schema when tools not loaded.
237
+ """
238
+ tools: list[dict[str, Any]] = []
239
+ try:
240
+ raw_tools = await mcp_client.get_raw_mcp_tools(server_name)
241
+ for tool in raw_tools:
242
+ if allowed_tools and tool.name not in allowed_tools:
243
+ continue
244
+ tools.append(
245
+ {
246
+ "name": tool.name,
247
+ "description": tool.description or "",
248
+ "input_schema": tool.inputSchema,
249
+ "stub": False,
250
+ }
251
+ )
252
+ except Exception as e:
253
+ logger.warning(f"Failed to get tools from server '{server_name}': {e}")
254
+ # If tools not loaded but allowlist exists, create stub entries
255
+ if allowed_tools:
256
+ for tool_name in sorted(allowed_tools):
257
+ tools.append(
258
+ {
259
+ "name": tool_name,
260
+ "description": "",
261
+ "input_schema": {"type": "object", "properties": {}},
262
+ "stub": True,
263
+ }
264
+ )
265
+ return tools
266
+
267
+
268
+ async def _extract_server_configs(
269
+ mcp_client: BaseMCPClient,
270
+ default_tool_timeout: float | None,
271
+ ) -> list[ServerConfig]:
272
+ """Extract server configurations from MCP client.
273
+
274
+ Args:
275
+ mcp_client: The MCP client with configured servers.
276
+ default_tool_timeout: Optional default timeout for nested MCP tool calls.
277
+
278
+ Returns:
279
+ List of ServerConfig objects for supported servers.
280
+ """
281
+ server_configs: list[ServerConfig] = []
282
+
283
+ for server_name, config in mcp_client.servers.items():
284
+ transport = _normalize_transport(_get_config_value(config, "transport"))
285
+
286
+ if transport not in SUPPORTED_TRANSPORTS:
287
+ logger.warning(
288
+ f"Skipping server '{server_name}': transport '{transport}' not supported in sandbox "
289
+ f"(supported: {SUPPORTED_TRANSPORTS})"
290
+ )
291
+ continue
292
+
293
+ url = _get_config_value(config, "url")
294
+ if not url:
295
+ logger.warning(f"Skipping server '{server_name}': no URL configured")
296
+ continue
297
+
298
+ headers = _extract_headers(config)
299
+ timeout = _extract_timeout(config, default_tool_timeout)
300
+ allowed_tools = _extract_allowed_tools(mcp_client, server_name, config)
301
+ tools = await _extract_tools(mcp_client, server_name, allowed_tools)
302
+
303
+ server_configs.append(
304
+ ServerConfig(
305
+ name=server_name,
306
+ transport=transport,
307
+ url=url,
308
+ headers=headers,
309
+ allowed_tools=allowed_tools,
310
+ tools=tools,
311
+ timeout=timeout,
312
+ )
313
+ )
314
+
315
+ logger.debug(f"Extracted config for server '{server_name}': {len(tools)} tools")
316
+
317
+ return server_configs
318
+
319
+
320
+ def _generate_config_json(server_configs: list[ServerConfig]) -> str:
321
+ """Generate ptc_config.json content.
322
+
323
+ Args:
324
+ server_configs: List of server configurations.
325
+
326
+ Returns:
327
+ JSON string of the config.
328
+ """
329
+ config = {
330
+ "servers": {
331
+ cfg.name: {
332
+ "transport": cfg.transport,
333
+ "url": cfg.url,
334
+ "headers": cfg.headers,
335
+ "timeout": cfg.timeout,
336
+ "allowed_tools": cfg.allowed_tools,
337
+ }
338
+ for cfg in server_configs
339
+ }
340
+ }
341
+ return json.dumps(config, indent=2)
342
+
343
+
344
+ def _generate_mcp_client_module() -> str:
345
+ """Generate the tools/mcp_client.py module.
346
+
347
+ This module uses the official MCP Python SDK to call MCP tools from the sandbox.
348
+ It provides sync wrappers around the async MCP SDK for simpler LLM-generated code.
349
+
350
+ Returns:
351
+ Python source code for the MCP client module.
352
+ """
353
+ return render_template(_TEMPLATE_PACKAGE, "mcp_client.py.template")
354
+
355
+
356
+ def _generate_tools_init(server_names: list[str]) -> str:
357
+ """Generate tools/__init__.py content.
358
+
359
+ Args:
360
+ server_names: List of server names.
361
+
362
+ Returns:
363
+ Python source code for the __init__.py module.
364
+ """
365
+ # Use reserved-safe sanitization and sort for deterministic output
366
+ safe_names = sorted(sanitize_module_name_with_reserved(name) for name in server_names)
367
+
368
+ imports = "\n".join(f"from tools import {name}" for name in safe_names)
369
+ all_list = ", ".join(f'"{name}"' for name in safe_names)
370
+
371
+ return f'''"""Generated tools package for PTC sandbox execution.
372
+
373
+ This package provides access to MCP tools configured for this agent.
374
+ Import tools from specific server modules:
375
+
376
+ from tools.server_name import tool_name
377
+ """
378
+
379
+ {imports}
380
+
381
+ __all__ = [{all_list}]
382
+ '''
383
+
384
+
385
+ def _generate_server_module(server_cfg: ServerConfig) -> str:
386
+ """Generate tools/<server>.py module content.
387
+
388
+ Args:
389
+ server_cfg: Server configuration with tools.
390
+
391
+ Returns:
392
+ Python source code for the server module.
393
+ """
394
+ functions: list[str] = []
395
+ function_names: list[str] = []
396
+
397
+ for tool in server_cfg.tools:
398
+ func_name = sanitize_function_name(tool["name"])
399
+ function_names.append(func_name)
400
+
401
+ # Build function signature from input_schema
402
+ schema = tool.get("input_schema", {})
403
+ params = schema_to_params(schema)
404
+ doc = _build_docstring(tool)
405
+
406
+ func_code = f'''
407
+ def {func_name}({params}) -> Any:
408
+ """{doc}"""
409
+ arguments = {_build_arguments_dict(schema)}
410
+ return call_tool("{server_cfg.name}", "{tool["name"]}", arguments)
411
+ '''
412
+ functions.append(func_code)
413
+
414
+ all_list = ", ".join(f'"{name}"' for name in function_names)
415
+ functions_code = "\n".join(functions)
416
+
417
+ return f'''"""Generated module for MCP server: {server_cfg.name}
418
+
419
+ This module provides Python functions for each tool exposed by the MCP server.
420
+ """
421
+
422
+ from typing import Any
423
+
424
+ from tools.mcp_client import call_tool
425
+
426
+ __all__ = [{all_list}]
427
+
428
+ {functions_code}
429
+ '''
430
+
431
+
432
+ # Note: sanitize_module_name, sanitize_function_name, schema_to_params, and
433
+ # json_type_to_python are imported from aip_agents.ptc.naming
434
+
435
+
436
+ def _build_arguments_dict(schema: dict[str, Any]) -> str:
437
+ """Build arguments dict code from schema.
438
+
439
+ Args:
440
+ schema: JSON schema for tool input.
441
+
442
+ Returns:
443
+ Python code for building arguments dict.
444
+ """
445
+ properties = schema.get("properties", {})
446
+
447
+ if not properties:
448
+ return "kwargs"
449
+
450
+ items: list[str] = []
451
+ for prop_name in properties:
452
+ safe_name = sanitize_function_name(prop_name)
453
+ items.append(f'"{prop_name}": {safe_name}')
454
+
455
+ return "{" + ", ".join(items) + "}"
456
+
457
+
458
+ def _build_docstring(tool: dict[str, Any]) -> str:
459
+ """Build docstring for a tool function.
460
+
461
+ Args:
462
+ tool: Tool definition with name, description, input_schema.
463
+
464
+ Returns:
465
+ Docstring content.
466
+ """
467
+ desc = tool.get("description", f"Call {tool['name']} tool.")
468
+ # Escape triple quotes in description
469
+ desc = desc.replace('"""', '\\"\\"\\"')
470
+ return desc
471
+
472
+
473
+ def _generate_tool_doc(
474
+ tool: dict[str, Any],
475
+ ) -> str:
476
+ """Generate markdown documentation for a single tool.
477
+
478
+ Args:
479
+ tool: Tool definition with name, description, input_schema, optional stub flag.
480
+
481
+ Returns:
482
+ Markdown documentation string.
483
+ """
484
+ func_name = sanitize_function_name(tool["name"])
485
+ schema = tool.get("input_schema", {})
486
+
487
+ # Use schema_to_params for consistent signatures (stubs and loaded tools)
488
+ params = schema_to_params(schema)
489
+ signature = f"{func_name}({params})"
490
+
491
+ # Add example section
492
+ example_args, uses_placeholder = _build_example_args_with_placeholder(schema)
493
+ if tool.get("stub"):
494
+ uses_placeholder = True
495
+ example_heading = "## Example (placeholder)" if uses_placeholder else "## Example"
496
+ example_code = f"{func_name}({example_args})"
497
+
498
+ return render_tool_doc(
499
+ func_name=func_name,
500
+ signature=signature,
501
+ description=tool.get("description", ""),
502
+ schema=schema,
503
+ is_stub=tool.get("stub", False),
504
+ example_code=example_code,
505
+ example_heading=example_heading,
506
+ )
507
+
508
+
509
+ def _build_example_args(schema: dict[str, Any]) -> str:
510
+ """Build example argument string for a tool call.
511
+
512
+ Uses schema defaults, enums, or examples when available.
513
+ Falls back to neutral placeholders. Required params come first.
514
+
515
+ Args:
516
+ schema: Tool input schema.
517
+
518
+ Returns:
519
+ Example arguments string.
520
+ """
521
+ args, _ = _build_example_args_with_placeholder(schema)
522
+ return args
523
+
524
+
525
+ def _is_placeholder(prop_schema: dict[str, Any]) -> bool:
526
+ """Check if a property schema uses a placeholder value.
527
+
528
+ Args:
529
+ prop_schema: Property schema dict.
530
+
531
+ Returns:
532
+ True if the schema doesn't have examples, default, or enum values.
533
+ """
534
+ return not (prop_schema.get("examples") or "default" in prop_schema or prop_schema.get("enum"))
535
+
536
+
537
+ def _process_property_args(
538
+ properties: dict[str, Any],
539
+ required: set[str],
540
+ filter_required: bool,
541
+ ) -> tuple[list[str], bool]:
542
+ """Process properties and generate argument strings.
543
+
544
+ Args:
545
+ properties: Schema properties dict.
546
+ required: Set of required property names.
547
+ filter_required: If True, process only required params; if False, only optional.
548
+
549
+ Returns:
550
+ Tuple of (list of arg strings, uses_placeholder flag).
551
+ """
552
+ args: list[str] = []
553
+ uses_placeholder = False
554
+
555
+ for prop_name in sorted(properties.keys()):
556
+ is_required = prop_name in required
557
+ if (filter_required and not is_required) or (not filter_required and is_required):
558
+ continue
559
+
560
+ prop_schema = properties[prop_name]
561
+ safe_name = sanitize_function_name(prop_name)
562
+ example_value = _get_doc_example_value(prop_schema, prop_name)
563
+ args.append(f"{safe_name}={example_value}")
564
+
565
+ if _is_placeholder(prop_schema):
566
+ uses_placeholder = True
567
+
568
+ return args, uses_placeholder
569
+
570
+
571
+ def _build_example_args_with_placeholder(schema: dict[str, Any]) -> tuple[str, bool]:
572
+ """Build example arguments with placeholder tracking.
573
+
574
+ Args:
575
+ schema: Tool input schema.
576
+
577
+ Returns:
578
+ Tuple of (arguments string, uses_placeholder flag).
579
+ """
580
+ properties = schema.get("properties", {})
581
+ required = set(schema.get("required", []))
582
+
583
+ if not properties:
584
+ return "", False
585
+
586
+ # Process required params first
587
+ required_args, required_has_placeholder = _process_property_args(properties, required, filter_required=True)
588
+
589
+ # Then add optional params
590
+ optional_args, optional_has_placeholder = _process_property_args(properties, required, filter_required=False)
591
+
592
+ all_args = required_args + optional_args
593
+ uses_placeholder = required_has_placeholder or optional_has_placeholder
594
+
595
+ return ", ".join(all_args), uses_placeholder
596
+
597
+
598
+ def _get_doc_example_value(prop_schema: dict[str, Any], prop_name: str) -> str:
599
+ """Get example value for documentation.
600
+
601
+ Prefers schema-provided examples, defaults, or enums.
602
+ Falls back to neutral placeholders.
603
+
604
+ Args:
605
+ prop_schema: Property schema.
606
+ prop_name: Property name.
607
+
608
+ Returns:
609
+ Example value as Python literal string.
610
+ """
611
+ return example_value_from_schema(prop_schema, default_placeholder=DEFAULT_EXAMPLE_PLACEHOLDER)
612
+
613
+
614
+ def _generate_all_docs(server_configs: list[ServerConfig]) -> dict[str, str]:
615
+ """Generate all tool documentation files.
616
+
617
+ Args:
618
+ server_configs: List of server configurations.
619
+
620
+ Returns:
621
+ Dict mapping file path to content.
622
+ """
623
+ docs: dict[str, str] = {}
624
+
625
+ sorted_configs = sorted(server_configs, key=lambda cfg: sanitize_module_name_with_reserved(cfg.name))
626
+
627
+ for cfg in sorted_configs:
628
+ safe_name = sanitize_module_name_with_reserved(cfg.name)
629
+ sorted_tools = sorted(cfg.tools, key=lambda tool: sanitize_function_name(tool["name"]))
630
+
631
+ for tool in sorted_tools:
632
+ func_name = sanitize_function_name(tool["name"])
633
+ doc_path = f"tools/docs/{safe_name}/{func_name}.md"
634
+ doc_content = _generate_tool_doc(tool)
635
+ docs[doc_path] = doc_content
636
+
637
+ return docs
638
+
639
+
640
+ def _generate_ptc_index(server_configs: list[ServerConfig]) -> str:
641
+ """Generate the tools/ptc_index.json tool index.
642
+
643
+ Args:
644
+ server_configs: List of server configurations with tools.
645
+
646
+ Returns:
647
+ JSON string of the tool index.
648
+ """
649
+ packages: dict[str, Any] = {}
650
+
651
+ # Sort server configs by sanitized name for deterministic output
652
+ sorted_configs = sorted(server_configs, key=lambda c: sanitize_module_name_with_reserved(c.name))
653
+
654
+ for cfg in sorted_configs:
655
+ safe_name = sanitize_module_name_with_reserved(cfg.name)
656
+
657
+ # Sort tools by sanitized name
658
+ sorted_tools = sorted(cfg.tools, key=lambda t: sanitize_function_name(t["name"]))
659
+
660
+ tool_entries = []
661
+ for tool in sorted_tools:
662
+ func_name = sanitize_function_name(tool["name"])
663
+ schema = tool.get("input_schema", {})
664
+
665
+ # Use schema_to_params for consistent signatures (stubs and loaded tools)
666
+ signature = f"{func_name}({schema_to_params(schema)})"
667
+
668
+ tool_entries.append(
669
+ {
670
+ "name": func_name,
671
+ "signature": signature,
672
+ "doc_path": f"tools/docs/{safe_name}/{func_name}.md",
673
+ }
674
+ )
675
+
676
+ packages[safe_name] = {"tools": tool_entries}
677
+
678
+ index = {"packages": packages}
679
+ return json.dumps(index, indent=2, sort_keys=True)
@@ -0,0 +1 @@
1
+ """Templates package for PTC sandbox code generation."""