agentpool 2.1.9__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.

Potentially problematic release.


This version of agentpool might be problematic. Click here for more details.

Files changed (474) hide show
  1. acp/README.md +64 -0
  2. acp/__init__.py +172 -0
  3. acp/__main__.py +10 -0
  4. acp/acp_requests.py +285 -0
  5. acp/agent/__init__.py +6 -0
  6. acp/agent/connection.py +256 -0
  7. acp/agent/implementations/__init__.py +6 -0
  8. acp/agent/implementations/debug_server/__init__.py +1 -0
  9. acp/agent/implementations/debug_server/cli.py +79 -0
  10. acp/agent/implementations/debug_server/debug.html +234 -0
  11. acp/agent/implementations/debug_server/debug_server.py +496 -0
  12. acp/agent/implementations/testing.py +91 -0
  13. acp/agent/protocol.py +65 -0
  14. acp/bridge/README.md +162 -0
  15. acp/bridge/__init__.py +6 -0
  16. acp/bridge/__main__.py +91 -0
  17. acp/bridge/bridge.py +246 -0
  18. acp/bridge/py.typed +0 -0
  19. acp/bridge/settings.py +15 -0
  20. acp/client/__init__.py +7 -0
  21. acp/client/connection.py +251 -0
  22. acp/client/implementations/__init__.py +7 -0
  23. acp/client/implementations/default_client.py +185 -0
  24. acp/client/implementations/headless_client.py +266 -0
  25. acp/client/implementations/noop_client.py +110 -0
  26. acp/client/protocol.py +61 -0
  27. acp/connection.py +280 -0
  28. acp/exceptions.py +46 -0
  29. acp/filesystem.py +524 -0
  30. acp/notifications.py +832 -0
  31. acp/py.typed +0 -0
  32. acp/schema/__init__.py +265 -0
  33. acp/schema/agent_plan.py +30 -0
  34. acp/schema/agent_requests.py +126 -0
  35. acp/schema/agent_responses.py +256 -0
  36. acp/schema/base.py +39 -0
  37. acp/schema/capabilities.py +230 -0
  38. acp/schema/client_requests.py +247 -0
  39. acp/schema/client_responses.py +96 -0
  40. acp/schema/common.py +81 -0
  41. acp/schema/content_blocks.py +188 -0
  42. acp/schema/mcp.py +82 -0
  43. acp/schema/messages.py +171 -0
  44. acp/schema/notifications.py +82 -0
  45. acp/schema/protocol_stuff.md +3 -0
  46. acp/schema/session_state.py +160 -0
  47. acp/schema/session_updates.py +419 -0
  48. acp/schema/slash_commands.py +51 -0
  49. acp/schema/terminal.py +15 -0
  50. acp/schema/tool_call.py +347 -0
  51. acp/stdio.py +250 -0
  52. acp/task/__init__.py +53 -0
  53. acp/task/debug.py +197 -0
  54. acp/task/dispatcher.py +93 -0
  55. acp/task/queue.py +69 -0
  56. acp/task/sender.py +82 -0
  57. acp/task/state.py +87 -0
  58. acp/task/supervisor.py +93 -0
  59. acp/terminal_handle.py +30 -0
  60. acp/tool_call_reporter.py +199 -0
  61. acp/tool_call_state.py +178 -0
  62. acp/transports.py +104 -0
  63. acp/utils.py +240 -0
  64. agentpool/__init__.py +63 -0
  65. agentpool/__main__.py +7 -0
  66. agentpool/agents/__init__.py +30 -0
  67. agentpool/agents/acp_agent/__init__.py +5 -0
  68. agentpool/agents/acp_agent/acp_agent.py +837 -0
  69. agentpool/agents/acp_agent/acp_converters.py +294 -0
  70. agentpool/agents/acp_agent/client_handler.py +317 -0
  71. agentpool/agents/acp_agent/session_state.py +44 -0
  72. agentpool/agents/agent.py +1264 -0
  73. agentpool/agents/agui_agent/__init__.py +19 -0
  74. agentpool/agents/agui_agent/agui_agent.py +677 -0
  75. agentpool/agents/agui_agent/agui_converters.py +423 -0
  76. agentpool/agents/agui_agent/chunk_transformer.py +204 -0
  77. agentpool/agents/agui_agent/event_types.py +83 -0
  78. agentpool/agents/agui_agent/helpers.py +192 -0
  79. agentpool/agents/architect.py +71 -0
  80. agentpool/agents/base_agent.py +177 -0
  81. agentpool/agents/claude_code_agent/__init__.py +11 -0
  82. agentpool/agents/claude_code_agent/claude_code_agent.py +1021 -0
  83. agentpool/agents/claude_code_agent/converters.py +243 -0
  84. agentpool/agents/context.py +105 -0
  85. agentpool/agents/events/__init__.py +61 -0
  86. agentpool/agents/events/builtin_handlers.py +129 -0
  87. agentpool/agents/events/event_emitter.py +320 -0
  88. agentpool/agents/events/events.py +561 -0
  89. agentpool/agents/events/tts_handlers.py +186 -0
  90. agentpool/agents/interactions.py +419 -0
  91. agentpool/agents/slashed_agent.py +244 -0
  92. agentpool/agents/sys_prompts.py +178 -0
  93. agentpool/agents/tool_wrapping.py +184 -0
  94. agentpool/base_provider.py +28 -0
  95. agentpool/common_types.py +226 -0
  96. agentpool/config_resources/__init__.py +16 -0
  97. agentpool/config_resources/acp_assistant.yml +24 -0
  98. agentpool/config_resources/agents.yml +109 -0
  99. agentpool/config_resources/agents_template.yml +18 -0
  100. agentpool/config_resources/agui_test.yml +18 -0
  101. agentpool/config_resources/claude_code_agent.yml +16 -0
  102. agentpool/config_resources/claude_style_subagent.md +30 -0
  103. agentpool/config_resources/external_acp_agents.yml +77 -0
  104. agentpool/config_resources/opencode_style_subagent.md +19 -0
  105. agentpool/config_resources/tts_test_agents.yml +78 -0
  106. agentpool/delegation/__init__.py +8 -0
  107. agentpool/delegation/base_team.py +504 -0
  108. agentpool/delegation/message_flow_tracker.py +39 -0
  109. agentpool/delegation/pool.py +1129 -0
  110. agentpool/delegation/team.py +325 -0
  111. agentpool/delegation/teamrun.py +343 -0
  112. agentpool/docs/__init__.py +5 -0
  113. agentpool/docs/gen_examples.py +42 -0
  114. agentpool/docs/utils.py +370 -0
  115. agentpool/functional/__init__.py +20 -0
  116. agentpool/functional/py.typed +0 -0
  117. agentpool/functional/run.py +80 -0
  118. agentpool/functional/structure.py +136 -0
  119. agentpool/hooks/__init__.py +20 -0
  120. agentpool/hooks/agent_hooks.py +247 -0
  121. agentpool/hooks/base.py +119 -0
  122. agentpool/hooks/callable.py +140 -0
  123. agentpool/hooks/command.py +180 -0
  124. agentpool/hooks/prompt.py +122 -0
  125. agentpool/jinja_filters.py +132 -0
  126. agentpool/log.py +224 -0
  127. agentpool/mcp_server/__init__.py +17 -0
  128. agentpool/mcp_server/client.py +429 -0
  129. agentpool/mcp_server/constants.py +32 -0
  130. agentpool/mcp_server/conversions.py +172 -0
  131. agentpool/mcp_server/helpers.py +47 -0
  132. agentpool/mcp_server/manager.py +232 -0
  133. agentpool/mcp_server/message_handler.py +164 -0
  134. agentpool/mcp_server/registries/__init__.py +1 -0
  135. agentpool/mcp_server/registries/official_registry_client.py +345 -0
  136. agentpool/mcp_server/registries/pulsemcp_client.py +88 -0
  137. agentpool/mcp_server/tool_bridge.py +548 -0
  138. agentpool/messaging/__init__.py +58 -0
  139. agentpool/messaging/compaction.py +928 -0
  140. agentpool/messaging/connection_manager.py +319 -0
  141. agentpool/messaging/context.py +66 -0
  142. agentpool/messaging/event_manager.py +426 -0
  143. agentpool/messaging/events.py +39 -0
  144. agentpool/messaging/message_container.py +209 -0
  145. agentpool/messaging/message_history.py +491 -0
  146. agentpool/messaging/messagenode.py +377 -0
  147. agentpool/messaging/messages.py +655 -0
  148. agentpool/messaging/processing.py +76 -0
  149. agentpool/mime_utils.py +95 -0
  150. agentpool/models/__init__.py +21 -0
  151. agentpool/models/acp_agents/__init__.py +22 -0
  152. agentpool/models/acp_agents/base.py +308 -0
  153. agentpool/models/acp_agents/mcp_capable.py +790 -0
  154. agentpool/models/acp_agents/non_mcp.py +842 -0
  155. agentpool/models/agents.py +450 -0
  156. agentpool/models/agui_agents.py +89 -0
  157. agentpool/models/claude_code_agents.py +238 -0
  158. agentpool/models/file_agents.py +116 -0
  159. agentpool/models/file_parsing.py +367 -0
  160. agentpool/models/manifest.py +658 -0
  161. agentpool/observability/__init__.py +9 -0
  162. agentpool/observability/observability_registry.py +97 -0
  163. agentpool/prompts/__init__.py +1 -0
  164. agentpool/prompts/base.py +27 -0
  165. agentpool/prompts/builtin_provider.py +75 -0
  166. agentpool/prompts/conversion_manager.py +95 -0
  167. agentpool/prompts/convert.py +96 -0
  168. agentpool/prompts/manager.py +204 -0
  169. agentpool/prompts/parts/zed.md +33 -0
  170. agentpool/prompts/prompts.py +581 -0
  171. agentpool/py.typed +0 -0
  172. agentpool/queries/tree-sitter-language-pack/README.md +7 -0
  173. agentpool/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
  174. agentpool/queries/tree-sitter-language-pack/c-tags.scm +9 -0
  175. agentpool/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
  176. agentpool/queries/tree-sitter-language-pack/clojure-tags.scm +7 -0
  177. agentpool/queries/tree-sitter-language-pack/commonlisp-tags.scm +122 -0
  178. agentpool/queries/tree-sitter-language-pack/cpp-tags.scm +15 -0
  179. agentpool/queries/tree-sitter-language-pack/csharp-tags.scm +26 -0
  180. agentpool/queries/tree-sitter-language-pack/d-tags.scm +26 -0
  181. agentpool/queries/tree-sitter-language-pack/dart-tags.scm +92 -0
  182. agentpool/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
  183. agentpool/queries/tree-sitter-language-pack/elixir-tags.scm +54 -0
  184. agentpool/queries/tree-sitter-language-pack/elm-tags.scm +19 -0
  185. agentpool/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
  186. agentpool/queries/tree-sitter-language-pack/go-tags.scm +42 -0
  187. agentpool/queries/tree-sitter-language-pack/java-tags.scm +20 -0
  188. agentpool/queries/tree-sitter-language-pack/javascript-tags.scm +88 -0
  189. agentpool/queries/tree-sitter-language-pack/lua-tags.scm +34 -0
  190. agentpool/queries/tree-sitter-language-pack/matlab-tags.scm +10 -0
  191. agentpool/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
  192. agentpool/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +98 -0
  193. agentpool/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
  194. agentpool/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
  195. agentpool/queries/tree-sitter-language-pack/python-tags.scm +14 -0
  196. agentpool/queries/tree-sitter-language-pack/r-tags.scm +21 -0
  197. agentpool/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
  198. agentpool/queries/tree-sitter-language-pack/ruby-tags.scm +64 -0
  199. agentpool/queries/tree-sitter-language-pack/rust-tags.scm +60 -0
  200. agentpool/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
  201. agentpool/queries/tree-sitter-language-pack/swift-tags.scm +51 -0
  202. agentpool/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
  203. agentpool/queries/tree-sitter-languages/README.md +24 -0
  204. agentpool/queries/tree-sitter-languages/c-tags.scm +9 -0
  205. agentpool/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
  206. agentpool/queries/tree-sitter-languages/cpp-tags.scm +15 -0
  207. agentpool/queries/tree-sitter-languages/dart-tags.scm +91 -0
  208. agentpool/queries/tree-sitter-languages/elisp-tags.scm +8 -0
  209. agentpool/queries/tree-sitter-languages/elixir-tags.scm +54 -0
  210. agentpool/queries/tree-sitter-languages/elm-tags.scm +19 -0
  211. agentpool/queries/tree-sitter-languages/fortran-tags.scm +15 -0
  212. agentpool/queries/tree-sitter-languages/go-tags.scm +30 -0
  213. agentpool/queries/tree-sitter-languages/haskell-tags.scm +3 -0
  214. agentpool/queries/tree-sitter-languages/hcl-tags.scm +77 -0
  215. agentpool/queries/tree-sitter-languages/java-tags.scm +20 -0
  216. agentpool/queries/tree-sitter-languages/javascript-tags.scm +88 -0
  217. agentpool/queries/tree-sitter-languages/julia-tags.scm +60 -0
  218. agentpool/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
  219. agentpool/queries/tree-sitter-languages/matlab-tags.scm +10 -0
  220. agentpool/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
  221. agentpool/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
  222. agentpool/queries/tree-sitter-languages/php-tags.scm +26 -0
  223. agentpool/queries/tree-sitter-languages/python-tags.scm +12 -0
  224. agentpool/queries/tree-sitter-languages/ql-tags.scm +26 -0
  225. agentpool/queries/tree-sitter-languages/ruby-tags.scm +64 -0
  226. agentpool/queries/tree-sitter-languages/rust-tags.scm +60 -0
  227. agentpool/queries/tree-sitter-languages/scala-tags.scm +65 -0
  228. agentpool/queries/tree-sitter-languages/typescript-tags.scm +41 -0
  229. agentpool/queries/tree-sitter-languages/zig-tags.scm +3 -0
  230. agentpool/repomap.py +1231 -0
  231. agentpool/resource_providers/__init__.py +17 -0
  232. agentpool/resource_providers/aggregating.py +54 -0
  233. agentpool/resource_providers/base.py +172 -0
  234. agentpool/resource_providers/codemode/__init__.py +9 -0
  235. agentpool/resource_providers/codemode/code_executor.py +215 -0
  236. agentpool/resource_providers/codemode/default_prompt.py +19 -0
  237. agentpool/resource_providers/codemode/helpers.py +83 -0
  238. agentpool/resource_providers/codemode/progress_executor.py +212 -0
  239. agentpool/resource_providers/codemode/provider.py +150 -0
  240. agentpool/resource_providers/codemode/remote_mcp_execution.py +143 -0
  241. agentpool/resource_providers/codemode/remote_provider.py +171 -0
  242. agentpool/resource_providers/filtering.py +42 -0
  243. agentpool/resource_providers/mcp_provider.py +246 -0
  244. agentpool/resource_providers/plan_provider.py +196 -0
  245. agentpool/resource_providers/pool.py +69 -0
  246. agentpool/resource_providers/static.py +289 -0
  247. agentpool/running/__init__.py +20 -0
  248. agentpool/running/decorators.py +56 -0
  249. agentpool/running/discovery.py +101 -0
  250. agentpool/running/executor.py +284 -0
  251. agentpool/running/injection.py +111 -0
  252. agentpool/running/py.typed +0 -0
  253. agentpool/running/run_nodes.py +87 -0
  254. agentpool/server.py +122 -0
  255. agentpool/sessions/__init__.py +13 -0
  256. agentpool/sessions/manager.py +302 -0
  257. agentpool/sessions/models.py +71 -0
  258. agentpool/sessions/session.py +239 -0
  259. agentpool/sessions/store.py +163 -0
  260. agentpool/skills/__init__.py +5 -0
  261. agentpool/skills/manager.py +120 -0
  262. agentpool/skills/registry.py +210 -0
  263. agentpool/skills/skill.py +36 -0
  264. agentpool/storage/__init__.py +17 -0
  265. agentpool/storage/manager.py +419 -0
  266. agentpool/storage/serialization.py +136 -0
  267. agentpool/talk/__init__.py +13 -0
  268. agentpool/talk/registry.py +128 -0
  269. agentpool/talk/stats.py +159 -0
  270. agentpool/talk/talk.py +604 -0
  271. agentpool/tasks/__init__.py +20 -0
  272. agentpool/tasks/exceptions.py +25 -0
  273. agentpool/tasks/registry.py +33 -0
  274. agentpool/testing.py +129 -0
  275. agentpool/text_templates/__init__.py +39 -0
  276. agentpool/text_templates/system_prompt.jinja +30 -0
  277. agentpool/text_templates/tool_call_default.jinja +13 -0
  278. agentpool/text_templates/tool_call_markdown.jinja +25 -0
  279. agentpool/text_templates/tool_call_simple.jinja +5 -0
  280. agentpool/tools/__init__.py +16 -0
  281. agentpool/tools/base.py +269 -0
  282. agentpool/tools/exceptions.py +9 -0
  283. agentpool/tools/manager.py +255 -0
  284. agentpool/tools/tool_call_info.py +87 -0
  285. agentpool/ui/__init__.py +2 -0
  286. agentpool/ui/base.py +89 -0
  287. agentpool/ui/mock_provider.py +81 -0
  288. agentpool/ui/stdlib_provider.py +150 -0
  289. agentpool/utils/__init__.py +44 -0
  290. agentpool/utils/baseregistry.py +185 -0
  291. agentpool/utils/count_tokens.py +62 -0
  292. agentpool/utils/dag.py +184 -0
  293. agentpool/utils/importing.py +206 -0
  294. agentpool/utils/inspection.py +334 -0
  295. agentpool/utils/model_capabilities.py +25 -0
  296. agentpool/utils/network.py +28 -0
  297. agentpool/utils/now.py +22 -0
  298. agentpool/utils/parse_time.py +87 -0
  299. agentpool/utils/result_utils.py +35 -0
  300. agentpool/utils/signatures.py +305 -0
  301. agentpool/utils/streams.py +112 -0
  302. agentpool/utils/tasks.py +186 -0
  303. agentpool/vfs_registry.py +250 -0
  304. agentpool-2.1.9.dist-info/METADATA +336 -0
  305. agentpool-2.1.9.dist-info/RECORD +474 -0
  306. agentpool-2.1.9.dist-info/WHEEL +4 -0
  307. agentpool-2.1.9.dist-info/entry_points.txt +14 -0
  308. agentpool-2.1.9.dist-info/licenses/LICENSE +22 -0
  309. agentpool_cli/__init__.py +34 -0
  310. agentpool_cli/__main__.py +66 -0
  311. agentpool_cli/agent.py +175 -0
  312. agentpool_cli/cli_types.py +23 -0
  313. agentpool_cli/common.py +163 -0
  314. agentpool_cli/create.py +175 -0
  315. agentpool_cli/history.py +217 -0
  316. agentpool_cli/log.py +78 -0
  317. agentpool_cli/py.typed +0 -0
  318. agentpool_cli/run.py +84 -0
  319. agentpool_cli/serve_acp.py +177 -0
  320. agentpool_cli/serve_api.py +69 -0
  321. agentpool_cli/serve_mcp.py +74 -0
  322. agentpool_cli/serve_vercel.py +233 -0
  323. agentpool_cli/store.py +171 -0
  324. agentpool_cli/task.py +84 -0
  325. agentpool_cli/utils.py +104 -0
  326. agentpool_cli/watch.py +54 -0
  327. agentpool_commands/__init__.py +180 -0
  328. agentpool_commands/agents.py +199 -0
  329. agentpool_commands/base.py +45 -0
  330. agentpool_commands/commands.py +58 -0
  331. agentpool_commands/completers.py +110 -0
  332. agentpool_commands/connections.py +175 -0
  333. agentpool_commands/markdown_utils.py +31 -0
  334. agentpool_commands/models.py +62 -0
  335. agentpool_commands/prompts.py +78 -0
  336. agentpool_commands/py.typed +0 -0
  337. agentpool_commands/read.py +77 -0
  338. agentpool_commands/resources.py +210 -0
  339. agentpool_commands/session.py +48 -0
  340. agentpool_commands/tools.py +269 -0
  341. agentpool_commands/utils.py +189 -0
  342. agentpool_commands/workers.py +163 -0
  343. agentpool_config/__init__.py +53 -0
  344. agentpool_config/builtin_tools.py +265 -0
  345. agentpool_config/commands.py +237 -0
  346. agentpool_config/conditions.py +301 -0
  347. agentpool_config/converters.py +30 -0
  348. agentpool_config/durable.py +331 -0
  349. agentpool_config/event_handlers.py +600 -0
  350. agentpool_config/events.py +153 -0
  351. agentpool_config/forward_targets.py +251 -0
  352. agentpool_config/hook_conditions.py +331 -0
  353. agentpool_config/hooks.py +241 -0
  354. agentpool_config/jinja.py +206 -0
  355. agentpool_config/knowledge.py +41 -0
  356. agentpool_config/loaders.py +350 -0
  357. agentpool_config/mcp_server.py +243 -0
  358. agentpool_config/nodes.py +202 -0
  359. agentpool_config/observability.py +191 -0
  360. agentpool_config/output_types.py +55 -0
  361. agentpool_config/pool_server.py +267 -0
  362. agentpool_config/prompt_hubs.py +105 -0
  363. agentpool_config/prompts.py +185 -0
  364. agentpool_config/py.typed +0 -0
  365. agentpool_config/resources.py +33 -0
  366. agentpool_config/session.py +119 -0
  367. agentpool_config/skills.py +17 -0
  368. agentpool_config/storage.py +288 -0
  369. agentpool_config/system_prompts.py +190 -0
  370. agentpool_config/task.py +162 -0
  371. agentpool_config/teams.py +52 -0
  372. agentpool_config/tools.py +112 -0
  373. agentpool_config/toolsets.py +1033 -0
  374. agentpool_config/workers.py +86 -0
  375. agentpool_prompts/__init__.py +1 -0
  376. agentpool_prompts/braintrust_hub.py +235 -0
  377. agentpool_prompts/fabric.py +75 -0
  378. agentpool_prompts/langfuse_hub.py +79 -0
  379. agentpool_prompts/promptlayer_provider.py +59 -0
  380. agentpool_prompts/py.typed +0 -0
  381. agentpool_server/__init__.py +9 -0
  382. agentpool_server/a2a_server/__init__.py +5 -0
  383. agentpool_server/a2a_server/a2a_types.py +41 -0
  384. agentpool_server/a2a_server/server.py +190 -0
  385. agentpool_server/a2a_server/storage.py +81 -0
  386. agentpool_server/acp_server/__init__.py +22 -0
  387. agentpool_server/acp_server/acp_agent.py +786 -0
  388. agentpool_server/acp_server/acp_tools.py +43 -0
  389. agentpool_server/acp_server/commands/__init__.py +18 -0
  390. agentpool_server/acp_server/commands/acp_commands.py +594 -0
  391. agentpool_server/acp_server/commands/debug_commands.py +376 -0
  392. agentpool_server/acp_server/commands/docs_commands/__init__.py +39 -0
  393. agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +169 -0
  394. agentpool_server/acp_server/commands/docs_commands/get_schema.py +176 -0
  395. agentpool_server/acp_server/commands/docs_commands/get_source.py +110 -0
  396. agentpool_server/acp_server/commands/docs_commands/git_diff.py +111 -0
  397. agentpool_server/acp_server/commands/docs_commands/helpers.py +33 -0
  398. agentpool_server/acp_server/commands/docs_commands/url_to_markdown.py +90 -0
  399. agentpool_server/acp_server/commands/spawn.py +210 -0
  400. agentpool_server/acp_server/converters.py +235 -0
  401. agentpool_server/acp_server/input_provider.py +338 -0
  402. agentpool_server/acp_server/server.py +288 -0
  403. agentpool_server/acp_server/session.py +969 -0
  404. agentpool_server/acp_server/session_manager.py +313 -0
  405. agentpool_server/acp_server/syntax_detection.py +250 -0
  406. agentpool_server/acp_server/zed_tools.md +90 -0
  407. agentpool_server/aggregating_server.py +309 -0
  408. agentpool_server/agui_server/__init__.py +11 -0
  409. agentpool_server/agui_server/server.py +128 -0
  410. agentpool_server/base.py +189 -0
  411. agentpool_server/http_server.py +164 -0
  412. agentpool_server/mcp_server/__init__.py +6 -0
  413. agentpool_server/mcp_server/server.py +314 -0
  414. agentpool_server/mcp_server/zed_wrapper.py +110 -0
  415. agentpool_server/openai_api_server/__init__.py +5 -0
  416. agentpool_server/openai_api_server/completions/__init__.py +1 -0
  417. agentpool_server/openai_api_server/completions/helpers.py +81 -0
  418. agentpool_server/openai_api_server/completions/models.py +98 -0
  419. agentpool_server/openai_api_server/responses/__init__.py +1 -0
  420. agentpool_server/openai_api_server/responses/helpers.py +74 -0
  421. agentpool_server/openai_api_server/responses/models.py +96 -0
  422. agentpool_server/openai_api_server/server.py +242 -0
  423. agentpool_server/py.typed +0 -0
  424. agentpool_storage/__init__.py +9 -0
  425. agentpool_storage/base.py +310 -0
  426. agentpool_storage/file_provider.py +378 -0
  427. agentpool_storage/formatters.py +129 -0
  428. agentpool_storage/memory_provider.py +396 -0
  429. agentpool_storage/models.py +108 -0
  430. agentpool_storage/py.typed +0 -0
  431. agentpool_storage/session_store.py +262 -0
  432. agentpool_storage/sql_provider/__init__.py +21 -0
  433. agentpool_storage/sql_provider/cli.py +146 -0
  434. agentpool_storage/sql_provider/models.py +249 -0
  435. agentpool_storage/sql_provider/queries.py +15 -0
  436. agentpool_storage/sql_provider/sql_provider.py +444 -0
  437. agentpool_storage/sql_provider/utils.py +234 -0
  438. agentpool_storage/text_log_provider.py +275 -0
  439. agentpool_toolsets/__init__.py +15 -0
  440. agentpool_toolsets/builtin/__init__.py +33 -0
  441. agentpool_toolsets/builtin/agent_management.py +239 -0
  442. agentpool_toolsets/builtin/chain.py +288 -0
  443. agentpool_toolsets/builtin/code.py +398 -0
  444. agentpool_toolsets/builtin/debug.py +291 -0
  445. agentpool_toolsets/builtin/execution_environment.py +381 -0
  446. agentpool_toolsets/builtin/file_edit/__init__.py +11 -0
  447. agentpool_toolsets/builtin/file_edit/file_edit.py +747 -0
  448. agentpool_toolsets/builtin/file_edit/fuzzy_matcher/__init__.py +5 -0
  449. agentpool_toolsets/builtin/file_edit/fuzzy_matcher/example_usage.py +311 -0
  450. agentpool_toolsets/builtin/file_edit/fuzzy_matcher/streaming_fuzzy_matcher.py +443 -0
  451. agentpool_toolsets/builtin/history.py +36 -0
  452. agentpool_toolsets/builtin/integration.py +85 -0
  453. agentpool_toolsets/builtin/skills.py +77 -0
  454. agentpool_toolsets/builtin/subagent_tools.py +324 -0
  455. agentpool_toolsets/builtin/tool_management.py +90 -0
  456. agentpool_toolsets/builtin/user_interaction.py +52 -0
  457. agentpool_toolsets/builtin/workers.py +128 -0
  458. agentpool_toolsets/composio_toolset.py +96 -0
  459. agentpool_toolsets/config_creation.py +192 -0
  460. agentpool_toolsets/entry_points.py +47 -0
  461. agentpool_toolsets/fsspec_toolset/__init__.py +7 -0
  462. agentpool_toolsets/fsspec_toolset/diagnostics.py +115 -0
  463. agentpool_toolsets/fsspec_toolset/grep.py +450 -0
  464. agentpool_toolsets/fsspec_toolset/helpers.py +631 -0
  465. agentpool_toolsets/fsspec_toolset/streaming_diff_parser.py +249 -0
  466. agentpool_toolsets/fsspec_toolset/toolset.py +1384 -0
  467. agentpool_toolsets/mcp_run_toolset.py +61 -0
  468. agentpool_toolsets/notifications.py +146 -0
  469. agentpool_toolsets/openapi.py +118 -0
  470. agentpool_toolsets/py.typed +0 -0
  471. agentpool_toolsets/search_toolset.py +202 -0
  472. agentpool_toolsets/semantic_memory_toolset.py +536 -0
  473. agentpool_toolsets/streaming_tools.py +265 -0
  474. agentpool_toolsets/vfs_toolset.py +124 -0
@@ -0,0 +1,255 @@
1
+ """Tool management for AgentPool."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from collections.abc import Callable, Sequence
7
+ from contextlib import asynccontextmanager
8
+ from typing import TYPE_CHECKING, Literal, assert_never
9
+
10
+ from agentpool.log import get_logger
11
+ from agentpool.resource_providers import StaticResourceProvider
12
+ from agentpool.tools.base import Tool
13
+ from agentpool.utils.baseregistry import AgentPoolError
14
+
15
+
16
+ if TYPE_CHECKING:
17
+ from collections.abc import AsyncIterator
18
+
19
+ from agentpool.common_types import ToolType
20
+ from agentpool.prompts.prompts import MCPClientPrompt
21
+ from agentpool.resource_providers import ResourceProvider
22
+ from agentpool.resource_providers.codemode.provider import CodeModeResourceProvider
23
+
24
+
25
+ logger = get_logger(__name__)
26
+
27
+ MAX_LEN_DESCRIPTION = 2000
28
+ ToolState = Literal["all", "enabled", "disabled"]
29
+ ProviderName = str
30
+ OwnerType = Literal["pool", "team", "node"]
31
+ ToolMode = Literal["codemode"]
32
+
33
+
34
+ class ToolError(AgentPoolError):
35
+ """Base exception for tool-related errors."""
36
+
37
+
38
+ class ToolManager:
39
+ """Manages tool registration, enabling/disabling and access."""
40
+
41
+ def __init__(
42
+ self,
43
+ tools: Sequence[ToolType] | None = None,
44
+ tool_mode: ToolMode | None = None,
45
+ ) -> None:
46
+ """Initialize tool manager.
47
+
48
+ Args:
49
+ tools: Initial tools to register
50
+ tool_mode: Tool execution mode (None or "codemode")
51
+ """
52
+ super().__init__()
53
+ self.external_providers: list[ResourceProvider] = []
54
+ self.worker_provider = StaticResourceProvider(name="workers")
55
+ self.builtin_provider = StaticResourceProvider(name="builtin")
56
+ self.tool_mode = tool_mode
57
+
58
+ # CodeModeResourceProvider gets populated with providers in providers property
59
+ from agentpool.resource_providers.codemode.provider import CodeModeResourceProvider
60
+
61
+ self._codemode_provider: CodeModeResourceProvider = CodeModeResourceProvider([])
62
+
63
+ # Forward to provider methods
64
+ self.tool = self.builtin_provider.tool
65
+ self.register_tool = self.builtin_provider.register_tool
66
+ self.register_worker = self.worker_provider.register_worker
67
+
68
+ # Register initial tools
69
+ for tool in tools or []:
70
+ t = self._validate_item(tool)
71
+ self.builtin_provider.add_tool(t)
72
+
73
+ @property
74
+ def providers(self) -> list[ResourceProvider]:
75
+ """Get all providers: external + worker + builtin providers."""
76
+ if self.tool_mode == "codemode":
77
+ # Update the providers list with current providers
78
+ self._codemode_provider.providers[:] = [
79
+ *self.external_providers,
80
+ self.worker_provider,
81
+ self.builtin_provider,
82
+ ]
83
+ return [self._codemode_provider]
84
+
85
+ return [*self.external_providers, self.worker_provider, self.builtin_provider]
86
+
87
+ async def __prompt__(self) -> str:
88
+ enabled_tools = [t.name for t in await self.get_tools() if t.enabled]
89
+ if not enabled_tools:
90
+ return "No tools available"
91
+ return f"Available tools: {', '.join(enabled_tools)}"
92
+
93
+ def add_provider(self, provider: ResourceProvider, owner: str | None = None) -> None:
94
+ """Add an external resource provider.
95
+
96
+ Args:
97
+ provider: ResourceProvider instance (e.g., MCP server, custom provider)
98
+ owner: Optional owner for the provider
99
+ """
100
+ if owner:
101
+ provider.owner = owner
102
+ self.external_providers.append(provider)
103
+
104
+ def remove_provider(self, provider: ResourceProvider | ProviderName) -> None:
105
+ """Remove an external resource provider."""
106
+ from agentpool.resource_providers import ResourceProvider
107
+
108
+ match provider:
109
+ case ResourceProvider():
110
+ self.external_providers.remove(provider)
111
+ case str():
112
+ for p in self.external_providers:
113
+ if p.name == provider:
114
+ self.external_providers.remove(p)
115
+ case _ as unreachable:
116
+ assert_never(unreachable)
117
+
118
+ async def reset_states(self) -> None:
119
+ """Reset all tools to their default enabled states."""
120
+ for info in await self.get_tools():
121
+ info.enabled = True
122
+
123
+ def _validate_item(self, item: ToolType) -> Tool:
124
+ """Validate and convert items before registration."""
125
+ match item:
126
+ case Tool():
127
+ return item
128
+ case Callable() | str():
129
+ return Tool.from_callable(item)
130
+ case _:
131
+ typ = type(item)
132
+ msg = f"Item must be Tool or callable. Got {typ}"
133
+ raise ToolError(msg)
134
+
135
+ async def enable_tool(self, tool_name: str) -> None:
136
+ """Enable a previously disabled tool."""
137
+ tool_info = await self.get_tool(tool_name)
138
+ tool_info.enabled = True
139
+ logger.debug("Enabled tool", tool_name=tool_name)
140
+
141
+ async def disable_tool(self, tool_name: str) -> None:
142
+ """Disable a tool."""
143
+ tool_info = await self.get_tool(tool_name)
144
+ tool_info.enabled = False
145
+ logger.debug("Disabled tool", tool_name=tool_name)
146
+
147
+ async def list_tools(self) -> dict[str, bool]:
148
+ """Get a mapping of all tools and their enabled status."""
149
+ return {tool.name: tool.enabled for tool in await self.get_tools()}
150
+
151
+ async def get_tools(
152
+ self,
153
+ state: ToolState = "all",
154
+ names: str | list[str] | None = None,
155
+ ) -> list[Tool]:
156
+ """Get tool objects based on filters."""
157
+ tools: list[Tool] = []
158
+ # Get tools from providers concurrently
159
+ provider_coroutines = [provider.get_tools() for provider in self.providers]
160
+ results = await asyncio.gather(*provider_coroutines, return_exceptions=True)
161
+ for provider, result in zip(self.providers, results, strict=False):
162
+ if isinstance(result, BaseException):
163
+ msg = "Failed to get tools from provider"
164
+ logger.warning(msg, provider=provider, result=result)
165
+ continue
166
+ tools.extend(t for t in result if t.matches_filter(state))
167
+
168
+ match names:
169
+ case str():
170
+ tools = [t for t in tools if t.name == names]
171
+ case list():
172
+ tools = [t for t in tools if t.name in names]
173
+ return tools
174
+
175
+ async def get_tool(self, name: str) -> Tool:
176
+ """Get a specific tool by name.
177
+
178
+ First checks local tools, then uses concurrent provider fetching.
179
+ """
180
+ tool = next((tool for tool in await self.get_tools() if tool.name == name), None)
181
+ if not tool:
182
+ msg = f"Tool not found: {tool}"
183
+ raise ToolError(msg)
184
+ return tool
185
+
186
+ async def list_prompts(self) -> list[MCPClientPrompt]:
187
+ """Get all prompts from all providers."""
188
+ from agentpool.mcp_server.manager import MCPManager
189
+
190
+ all_prompts: list[MCPClientPrompt] = []
191
+ # Get prompts from all external providers (check if they're MCP providers)
192
+ for provider in self.external_providers:
193
+ if isinstance(provider, MCPManager):
194
+ try:
195
+ # Get prompts from MCP providers via the aggregating provider
196
+ agg_provider = provider.get_aggregating_provider()
197
+ prompts = await agg_provider.get_prompts()
198
+ all_prompts.extend(prompts)
199
+ except Exception:
200
+ logger.exception("Failed to get prompts from provider", provider=provider)
201
+
202
+ return all_prompts
203
+
204
+ @asynccontextmanager
205
+ async def temporary_tools(
206
+ self,
207
+ tools: ToolType | Sequence[ToolType],
208
+ *,
209
+ exclusive: bool = False,
210
+ ) -> AsyncIterator[list[Tool]]:
211
+ """Temporarily register tools.
212
+
213
+ Args:
214
+ tools: Tool(s) to register
215
+ exclusive: Whether to temporarily disable all other tools
216
+
217
+ Yields:
218
+ List of registered tool infos
219
+ """
220
+ # Normalize inputs to lists
221
+ tools_list: list[ToolType] = [tools] if not isinstance(tools, Sequence) else list(tools)
222
+ # Store original tool states if exclusive
223
+ tools = await self.get_tools()
224
+ original_states: dict[str, bool] = {}
225
+ if exclusive:
226
+ original_states = {t.name: t.enabled for t in tools}
227
+ # Disable all existing tools
228
+ for t in tools:
229
+ t.enabled = False
230
+ # Register all tools
231
+ registered_tools: list[Tool] = []
232
+ try:
233
+ for tool in tools_list:
234
+ tool_info = self.register_tool(tool)
235
+ registered_tools.append(tool_info)
236
+ yield registered_tools
237
+
238
+ finally:
239
+ # Remove temporary tools
240
+ for tool_info in registered_tools:
241
+ self.builtin_provider.remove_tool(tool_info.name)
242
+ # Restore original tool states if exclusive
243
+ if exclusive:
244
+ for name_, was_enabled in original_states.items():
245
+ t_ = await self.get_tool(name_)
246
+ t_.enabled = was_enabled
247
+
248
+
249
+ if __name__ == "__main__":
250
+ manager = ToolManager()
251
+
252
+ @manager.tool(name="custom_name", description="Custom description")
253
+ def with_params(query: str) -> str:
254
+ """With parameters."""
255
+ return query.upper()
@@ -0,0 +1,87 @@
1
+ """Tool management for AgentPool."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from datetime import datetime
6
+ from typing import TYPE_CHECKING, Any, Literal
7
+ from uuid import uuid4
8
+
9
+ from pydantic import Field
10
+ from schemez import Schema
11
+
12
+ from agentpool.text_templates import get_tool_call_template
13
+ from agentpool.utils.now import get_now
14
+
15
+
16
+ if TYPE_CHECKING:
17
+ from agentpool.text_templates import FormatStyle
18
+
19
+
20
+ class ToolCallInfo(Schema):
21
+ """Information about an executed tool call."""
22
+
23
+ tool_name: str
24
+ """Name of the tool that was called."""
25
+
26
+ args: dict[str, Any]
27
+ """Arguments passed to the tool."""
28
+
29
+ result: Any
30
+ """Result returned by the tool."""
31
+
32
+ agent_name: str
33
+ """Name of the calling agent."""
34
+
35
+ tool_call_id: str = Field(default_factory=lambda: str(uuid4()))
36
+ """ID provided by the model (e.g. OpenAI function call ID)."""
37
+
38
+ timestamp: datetime = Field(default_factory=get_now)
39
+ """When the tool was called."""
40
+
41
+ message_id: str | None = None
42
+ """ID of the message that triggered this tool call."""
43
+
44
+ error: str | None = None
45
+ """Error message if the tool call failed."""
46
+
47
+ timing: float | None = None
48
+ """Time taken for this specific tool call in seconds."""
49
+
50
+ agent_tool_name: str | None = None
51
+ """If this tool is agent-based, the name of that agent."""
52
+
53
+ def format(
54
+ self,
55
+ style: FormatStyle | Literal["custom"] = "simple",
56
+ *,
57
+ template: str | None = None,
58
+ variables: dict[str, Any] | None = None,
59
+ show_timing: bool = True,
60
+ ) -> str:
61
+ """Format tool call information with configurable style.
62
+
63
+ Args:
64
+ style: Predefined style to use:
65
+ - simple: Compact single-line format
66
+ - detailed: Multi-line with all details
67
+ - markdown: Formatted markdown with syntax highlighting
68
+ template: Optional custom template (required if style="custom")
69
+ variables: Additional variables for template rendering
70
+ show_timing: Whether to include execution timing
71
+
72
+ Raises:
73
+ ValueError: If style is invalid or custom template is missing
74
+ """
75
+ from jinjarope import Environment
76
+
77
+ template_str = template if style == "custom" else get_tool_call_template(style)
78
+ if not template_str:
79
+ raise ValueError("Custom template is required for style='custom'")
80
+ env = Environment(trim_blocks=True, lstrip_blocks=True)
81
+ env.filters["repr"] = repr
82
+ template_obj = env.from_string(template_str)
83
+ vars_ = self.model_dump()
84
+ vars_["show_timing"] = show_timing
85
+ if variables:
86
+ vars_.update(variables)
87
+ return template_obj.render(**vars_)
@@ -0,0 +1,2 @@
1
+ # src/agentpool/interfaces/__init__.py
2
+ """Interface definitions for AgentPool."""
agentpool/ui/base.py ADDED
@@ -0,0 +1,89 @@
1
+ """Base input provider class."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import ABC, abstractmethod
6
+ from typing import TYPE_CHECKING, Any
7
+
8
+
9
+ if TYPE_CHECKING:
10
+ from collections.abc import Coroutine
11
+
12
+ from mcp import types
13
+ from pydantic import BaseModel
14
+
15
+ from agentpool.agents.context import ConfirmationResult
16
+ from agentpool.messaging import ChatMessage
17
+ from agentpool.messaging.context import NodeContext
18
+ from agentpool.tools.base import Tool
19
+
20
+
21
+ class InputProvider(ABC):
22
+ """Base class for handling all UI interactions."""
23
+
24
+ async def get_input(
25
+ self,
26
+ context: NodeContext,
27
+ prompt: str,
28
+ output_type: type | None = None,
29
+ message_history: list[ChatMessage[Any]] | None = None,
30
+ ) -> Any:
31
+ """Get normal input (used by HumanProvider).
32
+
33
+ Args:
34
+ context: Current agent context
35
+ prompt: The prompt to show to the user
36
+ output_type: Optional type for structured responses
37
+ message_history: Optional conversation history
38
+ """
39
+ if output_type:
40
+ return await self.get_structured_input(context, prompt, output_type, message_history)
41
+ return await self.get_text_input(context, prompt, message_history)
42
+
43
+ async def get_text_input(
44
+ self,
45
+ context: NodeContext[Any],
46
+ prompt: str,
47
+ message_history: list[ChatMessage[Any]] | None = None,
48
+ ) -> str:
49
+ """Get normal text input."""
50
+ raise NotImplementedError
51
+
52
+ async def get_structured_input(
53
+ self,
54
+ context: NodeContext[Any],
55
+ prompt: str,
56
+ output_type: type[BaseModel],
57
+ message_history: list[ChatMessage[Any]] | None = None,
58
+ ) -> BaseModel:
59
+ """Get structured input."""
60
+ raise NotImplementedError
61
+
62
+ @abstractmethod
63
+ def get_tool_confirmation(
64
+ self,
65
+ context: NodeContext[Any],
66
+ tool: Tool,
67
+ args: dict[str, Any],
68
+ message_history: list[ChatMessage[Any]] | None = None,
69
+ ) -> Coroutine[Any, Any, ConfirmationResult]:
70
+ """Get tool execution confirmation.
71
+
72
+ Args:
73
+ context: Current node context
74
+ tool: Information about the tool to be executed
75
+ args: Tool arguments
76
+ message_history: Optional conversation history
77
+ """
78
+
79
+ @abstractmethod
80
+ def get_elicitation(
81
+ self,
82
+ params: types.ElicitRequestParams,
83
+ ) -> Coroutine[Any, Any, types.ElicitResult | types.ErrorData]:
84
+ """Get user response to elicitation request.
85
+
86
+ Args:
87
+ context: Current agent context
88
+ params: MCP elicit request parameters
89
+ """
@@ -0,0 +1,81 @@
1
+ """Mock input provider implementation."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import TYPE_CHECKING, Any, Literal
7
+
8
+ from agentpool.ui.base import InputProvider
9
+
10
+
11
+ if TYPE_CHECKING:
12
+ from mcp import types
13
+
14
+ from agentpool.agents.context import ConfirmationResult
15
+ from agentpool.messaging import ChatMessage
16
+ from agentpool.messaging.context import NodeContext
17
+ from agentpool.tools.base import Tool
18
+
19
+ InputMethod = Literal["get_input", "get_tool_confirmation", "get_elicitation"]
20
+
21
+
22
+ @dataclass
23
+ class InputCall:
24
+ """Record of an input provider call."""
25
+
26
+ method: InputMethod
27
+ args: tuple[Any, ...]
28
+ kwargs: dict[str, Any]
29
+ result: Any
30
+
31
+
32
+ class MockInputProvider(InputProvider):
33
+ """Provider that records calls and returns pre-configured responses."""
34
+
35
+ def __init__(
36
+ self,
37
+ *,
38
+ input_response: str = "mock response",
39
+ tool_confirmation: ConfirmationResult = "allow",
40
+ elicitation_response: dict[str, Any] | None = None,
41
+ ) -> None:
42
+ self.input_response = input_response
43
+ self.tool_confirmation = tool_confirmation
44
+ self.elicitation_response = elicitation_response or {"response": "mock response"}
45
+ self.calls: list[InputCall] = []
46
+
47
+ async def get_input(
48
+ self,
49
+ context: NodeContext,
50
+ prompt: str,
51
+ output_type: type | None = None,
52
+ message_history: list[ChatMessage[Any]] | None = None,
53
+ ) -> Any:
54
+ kwargs = {"output_type": output_type, "message_history": message_history}
55
+ call = InputCall("get_input", (context, prompt), kwargs, result=self.input_response)
56
+ self.calls.append(call)
57
+ return self.input_response
58
+
59
+ async def get_tool_confirmation(
60
+ self,
61
+ context: NodeContext,
62
+ tool: Tool,
63
+ args: dict[str, Any],
64
+ message_history: list[ChatMessage[Any]] | None = None,
65
+ ) -> ConfirmationResult:
66
+ kwargs = {"message_history": message_history}
67
+ result = self.tool_confirmation
68
+ call = InputCall("get_tool_confirmation", (context, tool, args), kwargs, result=result)
69
+ self.calls.append(call)
70
+ return result # pyright: ignore
71
+
72
+ async def get_elicitation(
73
+ self,
74
+ params: types.ElicitRequestParams,
75
+ ) -> types.ElicitResult | types.ErrorData:
76
+ from mcp import types
77
+
78
+ result = types.ElicitResult(action="accept", content=self.elicitation_response)
79
+ call = InputCall("get_elicitation", (params,), {}, result=result)
80
+ self.calls.append(call)
81
+ return result
@@ -0,0 +1,150 @@
1
+ """Stdlib input provider."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import sys
6
+ from textwrap import dedent
7
+ from typing import TYPE_CHECKING, Any
8
+
9
+ import anyenv
10
+ from mcp import types
11
+
12
+ from agentpool.log import get_logger
13
+ from agentpool.tools.exceptions import ToolError
14
+ from agentpool.ui.base import InputProvider
15
+
16
+
17
+ if TYPE_CHECKING:
18
+ from pydantic import BaseModel
19
+
20
+ from agentpool.agents.context import ConfirmationResult
21
+ from agentpool.messaging import ChatMessage
22
+ from agentpool.messaging.context import NodeContext
23
+ from agentpool.tools.base import Tool
24
+
25
+
26
+ logger = get_logger(__name__)
27
+
28
+
29
+ class StdlibInputProvider(InputProvider):
30
+ """Input provider using only Python stdlib functionality."""
31
+
32
+ async def get_text_input(
33
+ self,
34
+ context: NodeContext,
35
+ prompt: str,
36
+ message_history: list[ChatMessage[Any]] | None = None,
37
+ ) -> str:
38
+ print(f"{prompt}\n> ", end="", file=sys.stderr, flush=True)
39
+ return input()
40
+
41
+ async def get_structured_input(
42
+ self,
43
+ context: NodeContext,
44
+ prompt: str,
45
+ output_type: type[BaseModel],
46
+ message_history: list[ChatMessage[Any]] | None = None,
47
+ ) -> BaseModel:
48
+ """Get structured input, with promptantic and fallback handling."""
49
+ if result := await _get_promptantic_result(output_type):
50
+ return result
51
+
52
+ # Fallback: Get raw input and validate
53
+ prompt = f"{prompt}\n(Please provide response as {output_type.__name__})"
54
+ raw_input = await self.get_input(context, prompt, message_history=message_history)
55
+ try:
56
+ return output_type.model_validate_json(raw_input)
57
+ except Exception as e:
58
+ msg = f"Invalid response format: {e}"
59
+ raise ToolError(msg) from e
60
+
61
+ async def get_tool_confirmation(
62
+ self,
63
+ context: NodeContext,
64
+ tool: Tool,
65
+ args: dict[str, Any],
66
+ message_history: list[ChatMessage[Any]] | None = None,
67
+ ) -> ConfirmationResult:
68
+ agent_name = context.node_name
69
+ prompt = dedent(f"""
70
+ Tool Execution Confirmation
71
+ -------------------------
72
+ Tool: {tool.name}
73
+ Description: {tool.description or "No description"}
74
+ Agent: {agent_name}
75
+
76
+ Arguments:
77
+ {anyenv.dump_json(args, indent=True)}
78
+
79
+ Options:
80
+ - y: allow execution
81
+ - n/skip: skip this tool
82
+ - abort: abort current run
83
+ - quit: abort entire chain
84
+ """).strip()
85
+
86
+ print(f"{prompt}\nChoice [y/n/abort/quit]: ", end="", file=sys.stderr, flush=True)
87
+ response = input().lower()
88
+ match response:
89
+ case "y" | "yes":
90
+ return "allow"
91
+ case "abort":
92
+ return "abort_run"
93
+ case "quit":
94
+ return "abort_chain"
95
+ case _:
96
+ return "skip"
97
+
98
+ async def get_elicitation(
99
+ self,
100
+ params: types.ElicitRequestParams,
101
+ ) -> types.ElicitResult | types.ErrorData:
102
+ """Get user response to elicitation request using stdlib input."""
103
+ try:
104
+ print(f"\n{params.message}", file=sys.stderr)
105
+
106
+ # URL mode: prompt user to open external URL
107
+ if isinstance(params, types.ElicitRequestURLParams):
108
+ print(f"URL: {params.url}", file=sys.stderr)
109
+ print("Open this URL? [y/n]: ", end="", file=sys.stderr, flush=True)
110
+ response = input().strip().lower()
111
+ action = (
112
+ "accept"
113
+ if response in ("y", "yes")
114
+ else ("decline" if response in ("n", "no") else "cancel")
115
+ )
116
+ return types.ElicitResult(action=action)
117
+
118
+ # Form mode: collect structured JSON input
119
+ print("Please provide response as JSON:", file=sys.stderr)
120
+ if params.requestedSchema:
121
+ schema_json = anyenv.dump_json(params.requestedSchema, indent=True)
122
+ print(f"Expected schema:\n{schema_json}", file=sys.stderr)
123
+ print("> ", end="", file=sys.stderr, flush=True)
124
+ response = input()
125
+ try:
126
+ content = anyenv.load_json(response, return_type=dict)
127
+ return types.ElicitResult(action="accept", content=content)
128
+ except anyenv.JsonLoadError as e:
129
+ return types.ErrorData(code=types.INVALID_REQUEST, message=f"Invalid JSON: {e}")
130
+
131
+ except KeyboardInterrupt:
132
+ return types.ElicitResult(action="cancel")
133
+ except Exception as e: # noqa: BLE001
134
+ return types.ErrorData(code=types.INVALID_REQUEST, message=f"Elicitation failed: {e}")
135
+
136
+
137
+ async def _get_promptantic_result(output_type: type[BaseModel]) -> BaseModel | None:
138
+ """Helper to get structured input via promptantic.
139
+
140
+ Returns None if promptantic is not available or fails.
141
+ """
142
+ try:
143
+ from promptantic import ModelGenerator
144
+
145
+ return await ModelGenerator().apopulate(output_type)
146
+ except ImportError:
147
+ return None
148
+ except Exception as e: # noqa: BLE001
149
+ logger.warning("Promptantic failed", error=e)
150
+ return None