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,19 @@
1
+ """Module containing the AGUIAgent class and supporting utilities."""
2
+
3
+ from agentpool.agents.agui_agent.agui_agent import AGUIAgent
4
+ from agentpool.agents.agui_agent.agui_converters import (
5
+ ToolCallAccumulator,
6
+ agui_to_native_event,
7
+ to_agui_input_content,
8
+ to_agui_tool,
9
+ )
10
+ from agentpool.agents.agui_agent.chunk_transformer import ChunkTransformer
11
+
12
+ __all__ = [
13
+ "AGUIAgent",
14
+ "ChunkTransformer",
15
+ "ToolCallAccumulator",
16
+ "agui_to_native_event",
17
+ "to_agui_input_content",
18
+ "to_agui_tool",
19
+ ]
@@ -0,0 +1,677 @@
1
+ """AG-UI remote agent implementation.
2
+
3
+ This module provides a MessageNode adapter that connects to remote AG-UI protocol servers,
4
+ enabling remote agent execution with streaming support.
5
+
6
+ Supports client-side tool execution: tools can be defined locally and sent to the
7
+ remote AG-UI agent. When the agent requests tool execution, the tools are executed
8
+ locally and results sent back.
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import asyncio
14
+ from typing import TYPE_CHECKING, Any, Self
15
+ from uuid import uuid4
16
+
17
+ from anyenv.processes import hard_kill
18
+ import anyio
19
+ import httpx
20
+ from pydantic_ai import (
21
+ ModelRequest,
22
+ ModelResponse,
23
+ TextPart,
24
+ ThinkingPart,
25
+ ToolCallPart,
26
+ ToolReturnPart,
27
+ UserPromptPart,
28
+ )
29
+
30
+ from agentpool.agents.agui_agent.chunk_transformer import ChunkTransformer
31
+ from agentpool.agents.agui_agent.helpers import execute_tool_calls, parse_sse_stream
32
+ from agentpool.agents.base_agent import BaseAgent
33
+ from agentpool.agents.events import RunStartedEvent, StreamCompleteEvent
34
+ from agentpool.log import get_logger
35
+ from agentpool.messaging import ChatMessage
36
+ from agentpool.messaging.processing import prepare_prompts
37
+ from agentpool.talk.stats import MessageStats
38
+ from agentpool.tools import ToolManager
39
+
40
+
41
+ if TYPE_CHECKING:
42
+ from asyncio.subprocess import Process
43
+ from collections.abc import AsyncIterator, Sequence
44
+ from types import TracebackType
45
+
46
+ from ag_ui.core import Message, ToolMessage
47
+ from evented.configs import EventConfig
48
+
49
+ from agentpool.agents.base_agent import ToolConfirmationMode
50
+ from agentpool.agents.context import AgentContext
51
+ from agentpool.agents.events import RichAgentStreamEvent
52
+ from agentpool.common_types import (
53
+ BuiltinEventHandlerType,
54
+ IndividualEventHandler,
55
+ PromptCompatible,
56
+ ToolType,
57
+ )
58
+ from agentpool.delegation import AgentPool
59
+ from agentpool.messaging import MessageHistory
60
+ from agentpool.tools import Tool
61
+ from agentpool.ui.base import InputProvider
62
+ from agentpool_config.mcp_server import MCPServerConfig
63
+
64
+
65
+ logger = get_logger(__name__)
66
+
67
+
68
+ def get_client(headers: dict[str, str], timeout: float) -> httpx.AsyncClient:
69
+ headers = {**headers, "Accept": "text/event-stream", "Content-Type": "application/json"}
70
+ return httpx.AsyncClient(timeout=httpx.Timeout(timeout), headers=headers)
71
+
72
+
73
+ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
74
+ """MessageNode that wraps a remote AG-UI protocol server.
75
+
76
+ Connects to AG-UI compatible endpoints via HTTP/SSE and provides the same
77
+ interface as native agents, enabling composition with other nodes via
78
+ connections, teams, etc.
79
+
80
+ The agent manages:
81
+ - HTTP client lifecycle (create on enter, close on exit)
82
+ - AG-UI protocol communication via SSE streams
83
+ - Event conversion to native agentpool events
84
+ - Message accumulation and final response generation
85
+ - Client-side tool execution (tools defined locally, executed when requested)
86
+ - Subscriber system for event hooks
87
+ - Chunk transformation for compatibility with different server modes
88
+
89
+ Client-Side Tools:
90
+ Tools can be registered with this agent and sent to the remote AG-UI server.
91
+ When the server requests a tool call, the tool is executed locally and the
92
+ result is sent back. This enables human-in-the-loop workflows and local
93
+ capability exposure to remote agents.
94
+
95
+ Example:
96
+ ```python
97
+ # Connect to existing server
98
+ async with AGUIAgent(
99
+ endpoint="http://localhost:8000/agent/run",
100
+ name="tool-agent",
101
+ tools=[my_tool_function],
102
+ ) as agent:
103
+ # Remote agent can request execution of my_tool_function
104
+ result = await agent.run("Use the tool to help me")
105
+
106
+ # Start server automatically (useful for testing)
107
+ async with AGUIAgent(
108
+ endpoint="http://localhost:8000/agent/run",
109
+ name="test-agent",
110
+ startup_command="ag ui agent config.yml",
111
+ startup_delay=2.0,
112
+ ) as agent:
113
+ result = await agent.run("Test prompt")
114
+ ```
115
+ """
116
+
117
+ def __init__(
118
+ self,
119
+ endpoint: str,
120
+ *,
121
+ name: str = "agui-agent",
122
+ description: str | None = None,
123
+ display_name: str | None = None,
124
+ timeout: float = 60.0,
125
+ headers: dict[str, str] | None = None,
126
+ startup_command: str | None = None,
127
+ startup_delay: float = 2.0,
128
+ tools: Sequence[ToolType] | None = None,
129
+ mcp_servers: Sequence[str | MCPServerConfig] | None = None,
130
+ agent_pool: AgentPool[Any] | None = None,
131
+ enable_logging: bool = True,
132
+ event_configs: Sequence[EventConfig] | None = None,
133
+ event_handlers: Sequence[IndividualEventHandler | BuiltinEventHandlerType] | None = None,
134
+ tool_confirmation_mode: ToolConfirmationMode = "per_tool",
135
+ ) -> None:
136
+ """Initialize AG-UI agent client.
137
+
138
+ Args:
139
+ endpoint: HTTP endpoint for the AG-UI agent
140
+ name: Agent name for identification
141
+ description: Agent description
142
+ display_name: Human-readable display name
143
+ timeout: Request timeout in seconds
144
+ headers: Additional HTTP headers
145
+ startup_command: Optional shell command to start server automatically.
146
+ Useful for testing - server lifecycle is managed by the agent.
147
+ Example: "ag ui agent config.yml"
148
+ startup_delay: Seconds to wait after starting server before connecting (default: 2.0)
149
+ tools: Tools to expose to the remote agent (executed locally when called)
150
+ mcp_servers: MCP servers to connect
151
+ agent_pool: Agent pool for multi-agent coordination
152
+ enable_logging: Whether to enable database logging
153
+ event_configs: Event trigger configurations
154
+ event_handlers: Sequence of event handlers to register
155
+ tool_confirmation_mode: Tool confirmation mode
156
+ """
157
+ super().__init__(
158
+ name=name,
159
+ description=description,
160
+ display_name=display_name,
161
+ mcp_servers=mcp_servers,
162
+ agent_pool=agent_pool,
163
+ enable_logging=enable_logging,
164
+ event_configs=event_configs,
165
+ tool_confirmation_mode=tool_confirmation_mode,
166
+ event_handlers=event_handlers,
167
+ )
168
+
169
+ # AG-UI specific configuration
170
+ self.endpoint = endpoint
171
+ self.timeout = timeout
172
+ self.headers = headers or {}
173
+
174
+ # Startup command configuration
175
+ self._startup_command = startup_command
176
+ self._startup_delay = startup_delay
177
+ self._startup_process: Process | None = None
178
+
179
+ # Client state
180
+ self._client: httpx.AsyncClient | None = None
181
+ self._thread_id: str | None = None
182
+ self._run_id: str | None = None
183
+
184
+ # Override tools with provided tools
185
+ self.tools = ToolManager(tools)
186
+
187
+ # Chunk transformer for normalizing CHUNK events
188
+ self._chunk_transformer = ChunkTransformer()
189
+
190
+ def get_context(self, data: Any = None) -> AgentContext:
191
+ """Create a new context for this agent.
192
+
193
+ Args:
194
+ data: Optional custom data to attach to the context
195
+
196
+ Returns:
197
+ A new AgentContext instance
198
+ """
199
+ from agentpool.agents.context import AgentContext
200
+ from agentpool.models.agui_agents import AGUIAgentConfig
201
+ from agentpool.models.manifest import AgentsManifest
202
+
203
+ cfg = AGUIAgentConfig(
204
+ name=self.name,
205
+ description=self.description,
206
+ display_name=self.display_name,
207
+ endpoint=self.endpoint,
208
+ timeout=self.timeout,
209
+ headers=self.headers,
210
+ input_provider=self._input_provider,
211
+ startup_command=self._startup_command,
212
+ startup_delay=self._startup_delay,
213
+ )
214
+ defn = self.agent_pool.manifest if self.agent_pool else AgentsManifest()
215
+ return AgentContext(node=self, pool=self.agent_pool, config=cfg, definition=defn, data=data)
216
+
217
+ async def __aenter__(self) -> Self:
218
+ """Enter async context - initialize client and base resources."""
219
+ await super().__aenter__()
220
+ self._client = get_client(self.headers, self.timeout)
221
+ self._thread_id = self.conversation_id
222
+ if self._startup_command: # Start server if startup command is provided
223
+ await self._start_server()
224
+ self.log.debug("AG-UI client initialized", endpoint=self.endpoint)
225
+ return self
226
+
227
+ async def __aexit__(
228
+ self,
229
+ exc_type: type[BaseException] | None,
230
+ exc_val: BaseException | None,
231
+ exc_tb: TracebackType | None,
232
+ ) -> None:
233
+ """Exit async context - cleanup client and base resources."""
234
+ if self._client:
235
+ await self._client.aclose()
236
+ self._client = None
237
+ self._thread_id = None
238
+ self._run_id = None
239
+ if self._startup_process: # Stop server if we started it
240
+ await self._stop_server()
241
+ self.log.debug("AG-UI client closed")
242
+ await super().__aexit__(exc_type, exc_val, exc_tb)
243
+
244
+ def register_tool(self, tool: ToolType) -> Tool:
245
+ """Register a tool for client-side execution.
246
+
247
+ Args:
248
+ tool: Tool instance or callable to register
249
+
250
+ Returns:
251
+ Registered Tool instance
252
+ """
253
+ return self.tools.register_tool(tool)
254
+
255
+ async def set_tool_confirmation_mode(self, mode: ToolConfirmationMode) -> None:
256
+ """Set the tool confirmation mode for this agent.
257
+
258
+ Args:
259
+ mode: Tool confirmation mode:
260
+ - "always": Always require confirmation for all tools
261
+ - "never": Never require confirmation
262
+ - "per_tool": Use individual tool settings
263
+ """
264
+ self.tool_confirmation_mode = mode
265
+ self.log.info("Tool confirmation mode changed", mode=mode)
266
+
267
+ async def _start_server(self) -> None:
268
+ """Start the AG-UI server subprocess."""
269
+ if not self._startup_command:
270
+ return
271
+
272
+ self.log.info("Starting AG-UI server", command=self._startup_command)
273
+ self._startup_process = await asyncio.create_subprocess_shell(
274
+ self._startup_command,
275
+ stdout=asyncio.subprocess.PIPE,
276
+ stderr=asyncio.subprocess.PIPE,
277
+ start_new_session=True, # Create new process group
278
+ )
279
+ self.log.debug("Waiting for server startup", delay=self._startup_delay)
280
+ await anyio.sleep(self._startup_delay)
281
+ # Check if process is still running
282
+ if self._startup_process.returncode is not None:
283
+ stderr = ""
284
+ if self._startup_process.stderr:
285
+ stderr = (await self._startup_process.stderr.read()).decode()
286
+ msg = f"Startup process exited with code {self._startup_process.returncode}: {stderr}"
287
+ raise RuntimeError(msg)
288
+
289
+ self.log.info("AG-UI server started")
290
+
291
+ async def _stop_server(self) -> None:
292
+ """Stop the AG-UI server subprocess."""
293
+ if not self._startup_process:
294
+ return
295
+
296
+ self.log.info("Stopping AG-UI server")
297
+ try:
298
+ await hard_kill(self._startup_process) # Use cross-platform hard kill helper
299
+ except Exception: # Log but don't fail if kill has issues
300
+ self.log.exception("Error during process termination")
301
+ finally:
302
+ self._startup_process = None
303
+ self.log.info("AG-UI server stopped")
304
+
305
+ async def run(
306
+ self,
307
+ *prompts: PromptCompatible,
308
+ message_id: str | None = None,
309
+ input_provider: InputProvider | None = None,
310
+ message_history: MessageHistory | None = None,
311
+ **kwargs: Any,
312
+ ) -> ChatMessage[str]:
313
+ """Execute prompt against AG-UI agent.
314
+
315
+ Sends the prompt to the AG-UI server and waits for completion.
316
+ Events are collected via run_stream and event handlers are called.
317
+ The final text content is returned as a ChatMessage.
318
+
319
+ Args:
320
+ prompts: Prompts to send (will be joined with spaces)
321
+ message_id: Optional message id for the returned message
322
+ input_provider: Optional input provider for tool confirmation requests
323
+ message_history: Optional MessageHistory to use instead of agent's own
324
+ **kwargs: Additional arguments (ignored for compatibility)
325
+
326
+ Returns:
327
+ ChatMessage containing the agent's aggregated text response
328
+ """
329
+ final_message: ChatMessage[str] | None = None
330
+ async for event in self.run_stream(
331
+ *prompts,
332
+ message_id=message_id,
333
+ input_provider=input_provider,
334
+ message_history=message_history,
335
+ ):
336
+ if isinstance(event, StreamCompleteEvent):
337
+ final_message = event.message
338
+
339
+ if final_message is None:
340
+ raise RuntimeError("No final message received from stream")
341
+ return final_message
342
+
343
+ async def run_stream( # noqa: PLR0915
344
+ self,
345
+ *prompts: PromptCompatible,
346
+ message_id: str | None = None,
347
+ input_provider: InputProvider | None = None,
348
+ message_history: MessageHistory | None = None,
349
+ **kwargs: Any,
350
+ ) -> AsyncIterator[RichAgentStreamEvent[str]]:
351
+ """Execute prompt with streaming events.
352
+
353
+ Sends the prompt to the remote AG-UI agent along with any registered tools.
354
+ When the agent requests a tool call, the tool is executed locally and the
355
+ result is sent back in a continuation request.
356
+
357
+ Args:
358
+ prompts: Prompts to send
359
+ message_id: Optional message ID
360
+ input_provider: Optional input provider for tool confirmation requests
361
+ message_history: Optional MessageHistory to use instead of agent's own
362
+ **kwargs: Additional arguments (ignored for compatibility)
363
+
364
+ Yields:
365
+ Native streaming events converted from AG-UI protocol
366
+ """
367
+ # Update input provider if provided
368
+ if input_provider is not None:
369
+ self._input_provider = input_provider
370
+ from ag_ui.core import (
371
+ RunAgentInput,
372
+ TextMessageChunkEvent,
373
+ TextMessageContentEvent,
374
+ ThinkingTextMessageContentEvent,
375
+ ToolCallArgsEvent as AGUIToolCallArgsEvent,
376
+ ToolCallEndEvent as AGUIToolCallEndEvent,
377
+ ToolCallStartEvent as AGUIToolCallStartEvent,
378
+ UserMessage,
379
+ )
380
+
381
+ from agentpool.agents.agui_agent.agui_converters import (
382
+ ToolCallAccumulator,
383
+ agui_to_native_event,
384
+ to_agui_input_content,
385
+ to_agui_tool,
386
+ )
387
+
388
+ if not self._client or not self._thread_id:
389
+ msg = "Agent not initialized - use async context manager"
390
+ raise RuntimeError(msg)
391
+
392
+ # Reset cancellation state
393
+ self._cancelled = False
394
+ self._current_stream_task = asyncio.current_task()
395
+
396
+ conversation = message_history if message_history is not None else self.conversation
397
+ user_msg, processed_prompts, _original_message = await prepare_prompts(*prompts)
398
+ self._run_id = str(uuid4()) # New run ID for each run
399
+ self._chunk_transformer.reset() # Reset chunk transformer
400
+ # Track messages in pydantic-ai format: ModelRequest -> ModelResponse -> ModelRequest...
401
+ # This mirrors pydantic-ai's new_messages() which includes the initial user request.
402
+ model_messages: list[ModelResponse | ModelRequest] = []
403
+ # Start with the user's request (same as pydantic-ai's new_messages())
404
+ initial_request = ModelRequest(parts=[UserPromptPart(content=processed_prompts)])
405
+ model_messages.append(initial_request)
406
+ current_response_parts: list[TextPart | ThinkingPart | ToolCallPart] = []
407
+ text_chunks: list[str] = [] # For final content string
408
+
409
+ run_started = RunStartedEvent(
410
+ thread_id=self._thread_id or self.conversation_id,
411
+ run_id=self._run_id or str(uuid4()),
412
+ agent_name=self.name,
413
+ )
414
+ for handler in self.event_handler._wrapped_handlers:
415
+ await handler(None, run_started)
416
+ yield run_started
417
+
418
+ # Get pending parts from conversation and convert them
419
+ pending_parts = conversation.get_pending_parts()
420
+ pending_content = to_agui_input_content(pending_parts)
421
+ # Convert user message content to AGUI format using processed prompts
422
+ user_content = to_agui_input_content(processed_prompts)
423
+ # Combine pending parts with new content
424
+ final_content = [*pending_content, *user_content]
425
+ user_message = UserMessage(id=str(uuid4()), content=final_content)
426
+ # Convert registered tools to AG-UI format
427
+ available_tools = await self.tools.get_tools(state="enabled")
428
+ agui_tools = [to_agui_tool(t) for t in available_tools]
429
+ tools_by_name = {t.name: t for t in available_tools}
430
+ # Build initial messages list
431
+ messages: list[Message] = [user_message]
432
+ tool_accumulator = ToolCallAccumulator()
433
+ pending_tool_results: list[ToolMessage] = []
434
+ self.log.debug("Sending prompt to AG-UI agent", tool_names=[t.name for t in agui_tools])
435
+ # Loop to handle tool calls - agent may request multiple rounds
436
+ try:
437
+ while True:
438
+ # Check for cancellation at start of each iteration
439
+ if self._cancelled:
440
+ self.log.info("Stream cancelled by user")
441
+ break
442
+
443
+ request_data = RunAgentInput(
444
+ thread_id=self._thread_id or self.conversation_id,
445
+ run_id=self._run_id,
446
+ state={},
447
+ messages=messages,
448
+ tools=agui_tools,
449
+ context=[],
450
+ forwarded_props={},
451
+ )
452
+
453
+ data = request_data.model_dump(by_alias=True)
454
+ tool_calls_pending: list[tuple[str, str, dict[str, Any]]] = []
455
+
456
+ try:
457
+ async with self._client.stream("POST", self.endpoint, json=data) as response:
458
+ response.raise_for_status()
459
+ async for raw_event in parse_sse_stream(response):
460
+ # Check for cancellation during streaming
461
+ if self._cancelled:
462
+ self.log.info("Stream cancelled during event processing")
463
+ break
464
+
465
+ # Transform chunks to proper START/CONTENT/END sequences
466
+ transformed_events = self._chunk_transformer.transform(raw_event)
467
+
468
+ for event in transformed_events:
469
+ # Handle events for accumulation and tool calls
470
+ match event:
471
+ case TextMessageContentEvent(delta=delta):
472
+ text_chunks.append(delta)
473
+ current_response_parts.append(TextPart(content=delta))
474
+ case TextMessageChunkEvent(delta=delta) if delta:
475
+ text_chunks.append(delta)
476
+ current_response_parts.append(TextPart(content=delta))
477
+ case ThinkingTextMessageContentEvent(delta=delta):
478
+ current_response_parts.append(ThinkingPart(content=delta))
479
+ case AGUIToolCallStartEvent(
480
+ tool_call_id=tc_id, tool_call_name=name
481
+ ) if name:
482
+ tool_accumulator.start(tc_id, name)
483
+ self.log.debug(
484
+ "Tool call started",
485
+ tool_call_id=tc_id,
486
+ tool=name,
487
+ )
488
+
489
+ case AGUIToolCallArgsEvent(tool_call_id=tc_id, delta=delta):
490
+ tool_accumulator.add_args(tc_id, delta)
491
+
492
+ case AGUIToolCallEndEvent(tool_call_id=tc_id):
493
+ if result := tool_accumulator.complete(tc_id):
494
+ tool_name, args = result
495
+ tool_calls_pending.append((tc_id, tool_name, args))
496
+ current_response_parts.append(
497
+ ToolCallPart(
498
+ tool_name=tool_name,
499
+ args=args,
500
+ tool_call_id=tc_id,
501
+ )
502
+ )
503
+ self.log.debug(
504
+ "Tool call completed",
505
+ tool_call_id=tc_id,
506
+ tool=tool_name,
507
+ args=args,
508
+ )
509
+
510
+ # Convert to native event and distribute to handlers
511
+ if native_event := agui_to_native_event(event):
512
+ # Check for queued custom events first
513
+ while not self._event_queue.empty():
514
+ try:
515
+ custom_event = self._event_queue.get_nowait()
516
+ for handler in self.event_handler._wrapped_handlers:
517
+ await handler(None, custom_event)
518
+ yield custom_event
519
+ except asyncio.QueueEmpty:
520
+ break
521
+ # Distribute to handlers
522
+ for handler in self.event_handler._wrapped_handlers:
523
+ await handler(None, native_event)
524
+ yield native_event
525
+
526
+ # Flush any pending chunk events at end of stream
527
+ for event in self._chunk_transformer.flush():
528
+ if native_event := agui_to_native_event(event):
529
+ for handler in self.event_handler._wrapped_handlers:
530
+ await handler(None, native_event)
531
+ yield native_event
532
+
533
+ except httpx.HTTPError:
534
+ self.log.exception("HTTP error during AG-UI run")
535
+ raise
536
+
537
+ # If cancelled, break out of the while loop
538
+ if self._cancelled:
539
+ break
540
+
541
+ # If no tool calls pending, we're done
542
+ if not tool_calls_pending:
543
+ break
544
+
545
+ # Execute pending tool calls locally and collect results
546
+ pending_tool_results = await execute_tool_calls(
547
+ tool_calls_pending,
548
+ tools_by_name,
549
+ confirmation_mode=self.tool_confirmation_mode,
550
+ input_provider=self._input_provider,
551
+ context=self.get_context(),
552
+ )
553
+ # If no results (all tools were server-side), we're done
554
+ if not pending_tool_results:
555
+ break
556
+
557
+ # Flush current response parts to model_messages
558
+ if current_response_parts:
559
+ model_messages.append(ModelResponse(parts=current_response_parts))
560
+ current_response_parts = []
561
+
562
+ # Create ModelRequest with tool return parts
563
+ tc_id_to_name = {tc_id: name for tc_id, name, _ in tool_calls_pending}
564
+ tool_return_parts: list[ToolReturnPart] = [
565
+ ToolReturnPart(
566
+ tool_name=tc_id_to_name.get(r.tool_call_id, "unknown"),
567
+ content=r.content,
568
+ tool_call_id=r.tool_call_id,
569
+ )
570
+ for r in pending_tool_results
571
+ ]
572
+ model_messages.append(ModelRequest(parts=tool_return_parts))
573
+
574
+ # Add tool results to messages for next iteration
575
+ messages = [*pending_tool_results]
576
+ self.log.debug("Continuing with tool results", count=len(pending_tool_results))
577
+
578
+ except asyncio.CancelledError:
579
+ self.log.info("Stream cancelled via task cancellation")
580
+ self._cancelled = True
581
+
582
+ # Handle cancellation - emit partial message
583
+ if self._cancelled:
584
+ # Flush any remaining response parts
585
+ if current_response_parts:
586
+ model_messages.append(ModelResponse(parts=current_response_parts))
587
+
588
+ text_content = "".join(text_chunks)
589
+ final_message = ChatMessage[str](
590
+ content=text_content,
591
+ role="assistant",
592
+ name=self.name,
593
+ message_id=message_id or str(uuid4()),
594
+ conversation_id=self.conversation_id,
595
+ messages=model_messages,
596
+ finish_reason="stop",
597
+ )
598
+ complete_event = StreamCompleteEvent(message=final_message)
599
+ for handler in self.event_handler._wrapped_handlers:
600
+ await handler(None, complete_event)
601
+ yield complete_event
602
+ self._current_stream_task = None
603
+ return
604
+
605
+ # Flush any remaining response parts
606
+ if current_response_parts:
607
+ model_messages.append(ModelResponse(parts=current_response_parts))
608
+
609
+ # Final drain of event queue after stream completes
610
+ while not self._event_queue.empty():
611
+ try:
612
+ queued_event = self._event_queue.get_nowait()
613
+ for handler in self.event_handler._wrapped_handlers:
614
+ await handler(None, queued_event)
615
+ yield queued_event
616
+ except asyncio.QueueEmpty:
617
+ break
618
+
619
+ text_content = "".join(text_chunks)
620
+ final_message = ChatMessage[str](
621
+ content=text_content,
622
+ role="assistant",
623
+ name=self.name,
624
+ message_id=message_id or str(uuid4()),
625
+ conversation_id=self.conversation_id,
626
+ messages=model_messages,
627
+ )
628
+ complete_event = StreamCompleteEvent(message=final_message)
629
+ for handler in self.event_handler._wrapped_handlers:
630
+ await handler(None, complete_event)
631
+ yield complete_event
632
+ # Record to conversation history
633
+ conversation.add_chat_messages([user_msg, final_message])
634
+
635
+ async def run_iter(
636
+ self,
637
+ *prompt_groups: Sequence[PromptCompatible],
638
+ message_id: str | None = None,
639
+ **kwargs: Any,
640
+ ) -> AsyncIterator[ChatMessage[str]]:
641
+ """Execute multiple prompt groups sequentially.
642
+
643
+ Args:
644
+ prompt_groups: Groups of prompts to execute
645
+ message_id: Optional message ID base
646
+ **kwargs: Additional arguments (ignored for compatibility)
647
+
648
+ Yields:
649
+ ChatMessage for each completed prompt group
650
+ """
651
+ for i, prompts in enumerate(prompt_groups):
652
+ mid = f"{message_id or 'msg'}_{i}" if message_id else None
653
+ yield await self.run(*prompts, message_id=mid)
654
+
655
+ @property
656
+ def model_name(self) -> str | None:
657
+ """Get model name (AG-UI doesn't expose this)."""
658
+ return None
659
+
660
+ async def get_stats(self) -> MessageStats:
661
+ """Get message statistics for this node."""
662
+ return MessageStats()
663
+
664
+
665
+ if __name__ == "__main__":
666
+
667
+ async def main() -> None:
668
+ """Example usage."""
669
+ endpoint = "http://localhost:8000/agent/run"
670
+ async with AGUIAgent(endpoint=endpoint, name="test-agent") as agent:
671
+ result = await agent.run("What is 2+2?")
672
+ print(f"Result: {result.content}")
673
+ print("\nStreaming:")
674
+ async for event in agent.run_stream("Tell me a short joke"):
675
+ print(f"Event: {event}")
676
+
677
+ anyio.run(main)