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,297 @@
1
+ """Top-level PTC Sandbox Bridge.
2
+
3
+ This module provides the unified entry point for building sandbox payloads
4
+ across different tool sources (MCP, custom tools, etc.).
5
+
6
+ Authors:
7
+ Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ from typing import Any
14
+
15
+ from aip_agents.mcp.client.base_mcp_client import BaseMCPClient
16
+ from aip_agents.ptc.custom_tools import (
17
+ PTCCustomToolConfig,
18
+ validate_custom_tool_config,
19
+ )
20
+ from aip_agents.ptc.custom_tools_payload import build_custom_tools_payload
21
+ from aip_agents.ptc.doc_gen import (
22
+ render_tool_doc,
23
+ )
24
+ from aip_agents.ptc.exceptions import PTCPayloadConflictError
25
+ from aip_agents.ptc.mcp.sandbox_bridge import build_mcp_payload
26
+ from aip_agents.ptc.naming import (
27
+ example_value_from_schema,
28
+ project_custom_tool_signature,
29
+ sanitize_function_name,
30
+ sanitize_param_name,
31
+ )
32
+ from aip_agents.ptc.payload import SandboxPayload
33
+ from aip_agents.ptc.ptc_helper import _generate_ptc_helper_module
34
+
35
+
36
+ async def build_sandbox_payload(
37
+ mcp_client: BaseMCPClient | None = None,
38
+ default_tool_timeout: float | None = None,
39
+ custom_tools_config: PTCCustomToolConfig | None = None,
40
+ tool_configs: dict[str, dict] | None = None,
41
+ ) -> SandboxPayload:
42
+ """Build sandbox payload from all configured tool sources.
43
+
44
+ Composes MCP and custom LangChain tool payloads into a single payload.
45
+
46
+ Args:
47
+ mcp_client: The MCP client with configured servers. Can be None if only custom tools.
48
+ default_tool_timeout: Optional default timeout for nested MCP tool calls in seconds.
49
+ When None, no default timeout is injected.
50
+ custom_tools_config: Optional custom LangChain tools configuration.
51
+ tool_configs: Optional per-tool config values for custom tools.
52
+
53
+ Returns:
54
+ SandboxPayload containing files and env vars for the sandbox.
55
+ """
56
+ # Build MCP payload
57
+ mcp_payload = SandboxPayload()
58
+ if mcp_client:
59
+ mcp_payload = await build_mcp_payload(mcp_client, default_tool_timeout)
60
+
61
+ # Build custom tools payload if enabled
62
+ custom_payload = SandboxPayload()
63
+ if custom_tools_config and custom_tools_config.enabled:
64
+ # Validate config before building payload (fail fast)
65
+ validate_custom_tool_config(custom_tools_config)
66
+ result = build_custom_tools_payload(custom_tools_config, tool_configs)
67
+ custom_payload = result.payload
68
+
69
+ # Check for conflicts before merging payloads
70
+ _check_payload_conflicts(mcp_payload, custom_payload)
71
+
72
+ # Merge payloads (custom tools files should not conflict with MCP files)
73
+ merged = SandboxPayload()
74
+ merged.files.update(mcp_payload.files)
75
+ merged.files.update(custom_payload.files)
76
+ merged.per_run_files.update(mcp_payload.per_run_files)
77
+ merged.per_run_files.update(custom_payload.per_run_files)
78
+ merged.env.update(mcp_payload.env)
79
+ merged.env.update(custom_payload.env)
80
+
81
+ # Merge custom tools into ptc_index.json
82
+ if custom_tools_config and custom_tools_config.enabled and custom_tools_config.tools:
83
+ merged.files["tools/ptc_index.json"] = _merge_custom_tools_into_index(
84
+ merged.files.get("tools/ptc_index.json"),
85
+ custom_tools_config,
86
+ )
87
+ if "tools/ptc_helper.py" not in merged.files:
88
+ merged.files["tools/ptc_helper.py"] = _generate_ptc_helper_module()
89
+ # Generate documentation for custom tools
90
+ custom_docs = _generate_custom_tool_docs(custom_tools_config)
91
+ merged.files.update(custom_docs)
92
+
93
+ return merged
94
+
95
+
96
+ def _check_payload_conflicts(
97
+ mcp_payload: SandboxPayload,
98
+ custom_payload: SandboxPayload,
99
+ ) -> None:
100
+ """Check for conflicts between MCP and custom tool payloads.
101
+
102
+ Args:
103
+ mcp_payload: Payload from MCP tool configuration.
104
+ custom_payload: Payload from custom tool configuration.
105
+
106
+ Raises:
107
+ PTCPayloadConflictError: If any conflicts are detected in files,
108
+ per-run files, or environment variables.
109
+ """
110
+ mcp_files = set(mcp_payload.files.keys())
111
+ custom_files = set(custom_payload.files.keys())
112
+ file_conflicts = mcp_files & custom_files
113
+
114
+ mcp_per_run = set(mcp_payload.per_run_files.keys())
115
+ custom_per_run = set(custom_payload.per_run_files.keys())
116
+ per_run_conflicts = mcp_per_run & custom_per_run
117
+
118
+ mcp_env_keys = set(mcp_payload.env.keys())
119
+ custom_env_keys = set(custom_payload.env.keys())
120
+ env_conflicts = mcp_env_keys & custom_env_keys
121
+
122
+ all_conflicts = file_conflicts | per_run_conflicts | env_conflicts
123
+ if all_conflicts:
124
+ raise PTCPayloadConflictError(
125
+ f"Conflicts detected when merging MCP and custom tool payloads. "
126
+ f"Files: {sorted(file_conflicts)}, "
127
+ f"Per-run files: {sorted(per_run_conflicts)}, "
128
+ f"Environment variables: {sorted(env_conflicts)}",
129
+ conflicts=all_conflicts,
130
+ )
131
+
132
+
133
+ def _merge_custom_tools_into_index(
134
+ existing_index_json: str | None,
135
+ custom_tools_config: PTCCustomToolConfig,
136
+ ) -> str:
137
+ """Merge custom tools into the ptc_index.json.
138
+
139
+ Args:
140
+ existing_index_json: Existing ptc_index.json content (may be None).
141
+ custom_tools_config: Custom tools configuration.
142
+
143
+ Returns:
144
+ Updated JSON string with custom tools included.
145
+ """
146
+ # Parse existing index or create new one
147
+ if existing_index_json:
148
+ index = json.loads(existing_index_json)
149
+ else:
150
+ index = {"packages": {}}
151
+
152
+ # Add custom tools package
153
+ tool_entries = []
154
+ for tool_def in sorted(custom_tools_config.tools, key=lambda t: sanitize_function_name(t.get("name", ""))):
155
+ name = tool_def.get("name", "")
156
+ func_name = sanitize_function_name(name)
157
+ schema = tool_def.get("input_schema", {"type": "object", "properties": {}})
158
+ signature = f"{func_name}({project_custom_tool_signature(schema).canonical_params})"
159
+
160
+ tool_entries.append(
161
+ {
162
+ "name": func_name,
163
+ "signature": signature,
164
+ "doc_path": f"tools/docs/custom/{func_name}.md",
165
+ }
166
+ )
167
+
168
+ index["packages"]["custom"] = {"tools": tool_entries}
169
+
170
+ return json.dumps(index, indent=2, sort_keys=True)
171
+
172
+
173
+ def _generate_custom_tool_docs(custom_tools_config: PTCCustomToolConfig) -> dict[str, str]:
174
+ """Generate documentation files for custom tools.
175
+
176
+ Args:
177
+ custom_tools_config: Custom tools configuration.
178
+
179
+ Returns:
180
+ Dict mapping file path to content.
181
+ """
182
+ docs: dict[str, str] = {}
183
+
184
+ for tool_def in sorted(custom_tools_config.tools, key=lambda t: sanitize_function_name(t.get("name", ""))):
185
+ name = tool_def.get("name", "")
186
+ func_name = sanitize_function_name(name)
187
+ description = tool_def.get("description", "")
188
+ schema = tool_def.get("input_schema", {"type": "object", "properties": {}})
189
+
190
+ doc_content = _generate_tool_doc_content(func_name, description, schema)
191
+ docs[f"tools/docs/custom/{func_name}.md"] = doc_content
192
+
193
+ return docs
194
+
195
+
196
+ def _generate_tool_doc_content(
197
+ func_name: str,
198
+ description: str,
199
+ schema: dict[str, Any],
200
+ ) -> str:
201
+ """Generate markdown documentation for a single tool.
202
+
203
+ Args:
204
+ func_name: Sanitized function name.
205
+ description: Tool description.
206
+ schema: JSON schema for tool input.
207
+
208
+ Returns:
209
+ Markdown documentation string.
210
+ """
211
+ # Use custom projection helper for runtime/prompt/index/docs parity
212
+ params = project_custom_tool_signature(schema).canonical_params
213
+ signature = f"{func_name}({params})"
214
+
215
+ example_code = _build_custom_tool_example_code(func_name, schema)
216
+
217
+ return render_tool_doc(
218
+ func_name=func_name,
219
+ signature=signature,
220
+ description=description,
221
+ schema=schema,
222
+ example_code=example_code,
223
+ )
224
+
225
+
226
+ def _build_custom_tool_example_code(func_name: str, schema: dict[str, Any]) -> str:
227
+ """Build custom-tool docs example with keyword-first and compatibility calls."""
228
+ properties = schema.get("properties", {})
229
+ required = set(schema.get("required", []))
230
+
231
+ keyword_args: list[str] = []
232
+ compatibility_payload: dict[str, str] = {}
233
+
234
+ for prop_name, prop_schema in properties.items():
235
+ safe_name = sanitize_param_name(prop_name)
236
+ example_value = example_value_from_schema(prop_schema)
237
+
238
+ keyword_args.append(f"{safe_name}={example_value}")
239
+ compatibility_payload[prop_name] = example_value
240
+
241
+ if prop_name in required and len(keyword_args) >= 2:
242
+ break
243
+
244
+ if not keyword_args:
245
+ return f'from tools.custom import {func_name}\nresult = {func_name}(**{{"example": "value"}})\nprint(result)'
246
+
247
+ kwargs_expr = ", ".join(keyword_args)
248
+ payload_items = ", ".join(f"{repr(key)}: {value}" for key, value in compatibility_payload.items())
249
+ payload_expr = "{" + payload_items + "}"
250
+
251
+ return (
252
+ f"from tools.custom import {func_name}\n"
253
+ f"result = {func_name}({kwargs_expr})\n"
254
+ "print(result)\n\n"
255
+ "# Compatibility path: single positional dict is also accepted\n"
256
+ f"compat_result = {func_name}({payload_expr})\n"
257
+ "print(compat_result)"
258
+ )
259
+
260
+
261
+ def wrap_ptc_code(code: str, include_packages_path: bool = False) -> str:
262
+ """Wrap user PTC code with necessary imports and setup.
263
+
264
+ This prepends sys.path setup to ensure the tools package is importable.
265
+ When custom tools with bundled package sources are enabled, also adds
266
+ the packages/ directory to sys.path.
267
+
268
+ Args:
269
+ code: User-provided Python code.
270
+ include_packages_path: If True, also add packages/ dir to sys.path
271
+ for bundled package sources from custom LangChain tools.
272
+
273
+ Returns:
274
+ Wrapped code ready for sandbox execution.
275
+ """
276
+ preamble = """# PTC Code Wrapper - Auto-generated
277
+ import sys
278
+ import os
279
+
280
+ # Add tools package to path
281
+ _tools_dir = os.path.dirname(os.path.abspath(__file__)) if "__file__" in dir() else os.getcwd()
282
+ if _tools_dir not in sys.path:
283
+ sys.path.insert(0, _tools_dir)
284
+ """
285
+
286
+ if include_packages_path:
287
+ preamble += """
288
+ # Add packages directory to path for bundled custom tool sources
289
+ _packages_dir = os.path.join(_tools_dir, "packages")
290
+ if os.path.isdir(_packages_dir) and _packages_dir not in sys.path:
291
+ sys.path.insert(0, _packages_dir)
292
+ """
293
+
294
+ preamble += """
295
+ # User code below
296
+ """
297
+ return preamble + code
@@ -0,0 +1,33 @@
1
+ """Template rendering helpers for PTC payloads.
2
+
3
+ Authors:
4
+ Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from collections.abc import Mapping
10
+ from importlib import resources
11
+ from string import Template
12
+
13
+
14
+ def render_template(
15
+ package: str,
16
+ template_name: str,
17
+ values: Mapping[str, str] | None = None,
18
+ ) -> str:
19
+ """Render a template from package resources with optional substitutions.
20
+
21
+ Args:
22
+ package: Package path containing the template.
23
+ template_name: Template filename.
24
+ values: Optional mapping of template variables.
25
+
26
+ Returns:
27
+ Rendered template content.
28
+ """
29
+ template_file = resources.files(package).joinpath(template_name)
30
+ template_text = template_file.read_text(encoding="utf-8")
31
+ if not values:
32
+ return template_text
33
+ return Template(template_text).substitute(values)
@@ -0,0 +1 @@
1
+ """Shared templates for PTC sandbox code generation."""
@@ -0,0 +1,134 @@
1
+ """PTC Discovery Helper Module.
2
+
3
+ This module provides discovery functions for exploring available PTC tools
4
+ inside the PTC sandbox. Use these functions to find packages, list tools,
5
+ and get detailed documentation.
6
+
7
+ Usage:
8
+ from tools.ptc_helper import list_packages, list_tools, describe_tool
9
+
10
+ # List all available packages
11
+ packages = list_packages()
12
+
13
+ # List tools in a package
14
+ tools = list_tools("package_name")
15
+
16
+ # Get tool documentation
17
+ doc = describe_tool("package_name", "tool_name")
18
+ """
19
+
20
+ import difflib
21
+ import json
22
+ import os
23
+ from typing import Any
24
+
25
+ # Load the index at module import time
26
+ _INDEX_PATH = os.path.join(os.path.dirname(__file__), "ptc_index.json")
27
+ _DOCS_DIR = os.path.join(os.path.dirname(__file__), "docs")
28
+
29
+ _index: dict[str, Any] = {}
30
+ if os.path.exists(_INDEX_PATH):
31
+ with open(_INDEX_PATH, "r") as f:
32
+ _index = json.load(f)
33
+
34
+
35
+ def _suggest_closest(name: str, valid_names: list[str], kind: str = "name") -> str:
36
+ """Generate a suggestion message for closest match.
37
+
38
+ Args:
39
+ name: The name that was not found.
40
+ valid_names: List of valid names to match against.
41
+ kind: Type of name (package or tool) for the error message.
42
+
43
+ Returns:
44
+ Suggestion string or empty string if no close match.
45
+ """
46
+ matches = difflib.get_close_matches(name, valid_names, n=1, cutoff=0.6)
47
+ if matches:
48
+ return f" Did you mean '{matches[0]}'?"
49
+ return ""
50
+
51
+
52
+ def list_packages() -> list[str]:
53
+ """List all available package names.
54
+
55
+ Returns:
56
+ Sorted list of sanitized package names.
57
+ """
58
+ packages = _index.get("packages", {})
59
+ return sorted(packages.keys())
60
+
61
+
62
+ def list_tools(package: str) -> list[dict[str, str]]:
63
+ """List tools available in a package.
64
+
65
+ Args:
66
+ package: Sanitized package name (e.g., 'deepwiki').
67
+
68
+ Returns:
69
+ List of tool info dicts with 'name' keys.
70
+
71
+ Raises:
72
+ ValueError: If package is not found.
73
+ """
74
+ packages = _index.get("packages", {})
75
+ if package not in packages:
76
+ valid = list(packages.keys())
77
+ suggestion = _suggest_closest(package, valid, "package")
78
+ raise ValueError(f"Unknown package '{package}'.{suggestion}")
79
+
80
+ pkg_data = packages[package]
81
+ tools = pkg_data.get("tools", [])
82
+ return [{"name": t["name"]} for t in tools]
83
+
84
+
85
+ def describe_tool(package: str, tool: str) -> dict[str, Any]:
86
+ """Get detailed documentation for a tool.
87
+
88
+ Args:
89
+ package: Sanitized package name.
90
+ tool: Sanitized tool name.
91
+
92
+ Returns:
93
+ Dict with 'name', 'signature', 'doc', and 'doc_path' keys.
94
+
95
+ Raises:
96
+ ValueError: If package or tool is not found.
97
+ """
98
+ packages = _index.get("packages", {})
99
+ if package not in packages:
100
+ valid = list(packages.keys())
101
+ suggestion = _suggest_closest(package, valid, "package")
102
+ raise ValueError(f"Unknown package '{package}'.{suggestion}")
103
+
104
+ pkg_data = packages[package]
105
+ tools = pkg_data.get("tools", [])
106
+ tool_names = [t["name"] for t in tools]
107
+
108
+ if tool not in tool_names:
109
+ suggestion = _suggest_closest(tool, tool_names, "tool")
110
+ raise ValueError(f"Unknown tool '{tool}' in package '{package}'.{suggestion}")
111
+
112
+ tool_info = next(t for t in tools if t["name"] == tool)
113
+ doc_path = tool_info.get("doc_path", "")
114
+
115
+ doc_content = ""
116
+ if doc_path:
117
+ full_path = os.path.join(os.path.dirname(__file__), doc_path.replace("tools/", ""))
118
+ if os.path.exists(full_path):
119
+ with open(full_path, "r") as f:
120
+ doc_content = f.read()
121
+ else:
122
+ doc_content = f"# {tool}\n\n**Signature:** `{tool_info.get('signature', f'{tool}(**kwargs: Any)')}`"
123
+ else:
124
+ doc_content = f"# {tool}\n\n**Signature:** `{tool_info.get('signature', f'{tool}(**kwargs: Any)')}`"
125
+
126
+ return {
127
+ "name": tool,
128
+ "signature": tool_info.get("signature", f"{tool}(**kwargs)"),
129
+ "doc": doc_content,
130
+ "doc_path": doc_path,
131
+ }
132
+
133
+
134
+ __all__ = ["list_packages", "list_tools", "describe_tool"]
@@ -0,0 +1,101 @@
1
+ """Helper functions for constructing PTC tool definitions.
2
+
3
+ Author: Putu Ravindra Wiguna (putu.r.wiguna@gdplabs.id)
4
+
5
+ These helpers provide a cleaner API for defining custom tools in PTCCustomToolConfig.
6
+ They return properly-typed dictionaries that can be used in PTCCustomToolConfig.tools.
7
+
8
+ Example:
9
+ >>> from aip_agents.ptc import package_tool, file_tool, PTCCustomToolConfig
10
+ >>> config = PTCCustomToolConfig(
11
+ ... enabled=True,
12
+ ... tools=[
13
+ ... package_tool("time_tool", import_path="aip_agents.tools.time_tool", class_name="TimeTool"),
14
+ ... file_tool("multiply", file_path="/path/to/multiply.py", class_name="MultiplyTool"),
15
+ ... ]
16
+ ... )
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ from typing import Any
22
+
23
+ from aip_agents.ptc.custom_tools import PTCFileToolDef, PTCPackageToolDef
24
+
25
+
26
+ def package_tool(
27
+ name: str,
28
+ *,
29
+ import_path: str,
30
+ class_name: str,
31
+ package_path: str | None = None,
32
+ description: str | None = None,
33
+ input_schema: dict[str, Any] | None = None,
34
+ ) -> PTCPackageToolDef:
35
+ """Create a package-based tool definition.
36
+
37
+ Args:
38
+ name: Tool name (will be sanitized for Python compatibility).
39
+ import_path: Python import path (e.g., "aip_agents.tools.time_tool").
40
+ class_name: Tool class name to instantiate.
41
+ package_path: Optional local package path for bundling.
42
+ description: Optional tool description (auto-derived from tool if not provided).
43
+ input_schema: Optional JSON schema (auto-derived from tool if not provided).
44
+
45
+ Returns:
46
+ PTCPackageToolDef dict ready for use in PTCCustomToolConfig.tools.
47
+
48
+ Example:
49
+ >>> package_tool("time_tool", import_path="aip_agents.tools.time_tool", class_name="TimeTool")
50
+ {'name': 'time_tool', 'kind': 'package', 'import_path': 'aip_agents.tools.time_tool', 'class_name': 'TimeTool'}
51
+ """
52
+ result: PTCPackageToolDef = {
53
+ "name": name,
54
+ "kind": "package",
55
+ "import_path": import_path,
56
+ "class_name": class_name,
57
+ }
58
+ if package_path is not None:
59
+ result["package_path"] = package_path
60
+ if description is not None:
61
+ result["description"] = description
62
+ if input_schema is not None:
63
+ result["input_schema"] = input_schema
64
+ return result
65
+
66
+
67
+ def file_tool(
68
+ name: str,
69
+ *,
70
+ file_path: str,
71
+ class_name: str,
72
+ description: str | None = None,
73
+ input_schema: dict[str, Any] | None = None,
74
+ ) -> PTCFileToolDef:
75
+ """Create a file-based tool definition.
76
+
77
+ Args:
78
+ name: Tool name (will be sanitized for Python compatibility).
79
+ file_path: Absolute path to the Python file containing the tool.
80
+ class_name: Tool class name to instantiate.
81
+ description: Optional tool description (auto-derived from tool if not provided).
82
+ input_schema: Optional JSON schema (auto-derived from tool if not provided).
83
+
84
+ Returns:
85
+ PTCFileToolDef dict ready for use in PTCCustomToolConfig.tools.
86
+
87
+ Example:
88
+ >>> file_tool("multiply", file_path="/path/to/multiply_tool.py", class_name="MultiplyTool")
89
+ {'name': 'multiply', 'kind': 'file', 'file_path': '/path/to/multiply_tool.py', 'class_name': 'MultiplyTool'}
90
+ """
91
+ result: PTCFileToolDef = {
92
+ "name": name,
93
+ "kind": "file",
94
+ "file_path": file_path,
95
+ "class_name": class_name,
96
+ }
97
+ if description is not None:
98
+ result["description"] = description
99
+ if input_schema is not None:
100
+ result["input_schema"] = input_schema
101
+ return result