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,504 @@
1
+ """Base class for teams."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import abstractmethod
6
+ import asyncio
7
+ from contextlib import AsyncExitStack, asynccontextmanager
8
+ from dataclasses import dataclass
9
+ from typing import TYPE_CHECKING, Any, Self, overload
10
+
11
+ import anyio
12
+ from psygnal.containers import EventedList
13
+
14
+ from agentpool.log import get_logger
15
+ from agentpool.messaging import MessageNode
16
+ from agentpool.messaging.context import NodeContext
17
+ from agentpool.models.manifest import AgentsManifest
18
+ from agentpool.talk.stats import AggregatedMessageStats
19
+ from agentpool_config.teams import TeamConfig
20
+
21
+
22
+ if TYPE_CHECKING:
23
+ from collections.abc import AsyncIterator, Iterator, Sequence
24
+
25
+ from evented.configs import EventConfig
26
+ from psygnal.containers._evented_list import ListEvents
27
+ from toprompt import AnyPromptType
28
+
29
+ from agentpool import Agent, AgentPool, Team
30
+ from agentpool.common_types import (
31
+ ModelType,
32
+ ProcessorCallback,
33
+ PromptCompatible,
34
+ SupportsStructuredOutput,
35
+ ToolType,
36
+ )
37
+ from agentpool.delegation.teamrun import ExtendedTeamTalk, TeamRun
38
+ from agentpool.messaging import ChatMessage, TeamResponse
39
+ from agentpool.talk.stats import AggregatedTalkStats
40
+ from agentpool_config.mcp_server import MCPServerConfig
41
+ from agentpool_config.session import SessionQuery
42
+
43
+ logger = get_logger(__name__)
44
+
45
+
46
+ @dataclass(kw_only=True)
47
+ class TeamContext[TDeps = object](NodeContext[TDeps]):
48
+ """Context for team nodes."""
49
+
50
+ config: TeamConfig
51
+ """Current team's specific configuration."""
52
+
53
+ pool: AgentPool | None = None
54
+ """Pool the team is part of."""
55
+
56
+
57
+ class BaseTeam[TDeps, TResult](MessageNode[TDeps, TResult]):
58
+ """Base class for Team and TeamRun."""
59
+
60
+ def __init__(
61
+ self,
62
+ agents: Sequence[MessageNode[TDeps, TResult]],
63
+ *,
64
+ name: str | None = None,
65
+ description: str | None = None,
66
+ display_name: str | None = None,
67
+ shared_prompt: str | None = None,
68
+ mcp_servers: list[str | MCPServerConfig] | None = None,
69
+ picker: SupportsStructuredOutput | None = None,
70
+ num_picks: int | None = None,
71
+ pick_prompt: str | None = None,
72
+ event_configs: Sequence[EventConfig] | None = None,
73
+ agent_pool: AgentPool | None = None,
74
+ ) -> None:
75
+ """Common variables only for typing."""
76
+ from agentpool.delegation.teamrun import ExtendedTeamTalk
77
+
78
+ self._name = name or " & ".join([i.name for i in agents])
79
+ self.nodes = EventedList[MessageNode[Any, Any]]()
80
+ self.nodes.events.inserted.connect(self._on_node_added)
81
+ self.nodes.events.removed.connect(self._on_node_removed)
82
+ self.nodes.events.changed.connect(self._on_node_changed)
83
+ mcp_servers = list(mcp_servers) if mcp_servers else []
84
+ team_ctx = self.get_context()
85
+ if team_ctx and (cfg := team_ctx.config) and cfg.mcp_servers:
86
+ mcp_servers.extend(cfg.get_mcp_servers())
87
+ super().__init__(
88
+ name=self._name,
89
+ display_name=display_name,
90
+ mcp_servers=mcp_servers,
91
+ description=description,
92
+ event_configs=event_configs,
93
+ agent_pool=agent_pool,
94
+ )
95
+ self.nodes.extend(list(agents))
96
+ self._team_talk = ExtendedTeamTalk()
97
+ self.shared_prompt = shared_prompt
98
+ self._main_task: asyncio.Task[ChatMessage[Any] | None] | None = None
99
+ self._infinite = False
100
+ self.picker = picker
101
+ self.num_picks = num_picks
102
+ self.pick_prompt = pick_prompt
103
+
104
+ async def pick_agents(self, task: str) -> Sequence[MessageNode[Any, Any]]:
105
+ """Pick agents to run."""
106
+ from agentpool.agents.interactions import Interactions
107
+
108
+ if self.picker:
109
+ interactions = Interactions(self.picker)
110
+ if self.num_picks == 1:
111
+ result = await interactions.pick(self, task, self.pick_prompt)
112
+ return [result.selection]
113
+ multi_result = await interactions.pick_multiple(
114
+ self,
115
+ task,
116
+ min_picks=self.num_picks or 1,
117
+ max_picks=self.num_picks,
118
+ prompt=self.pick_prompt,
119
+ )
120
+ return multi_result.selections
121
+ return list(self.nodes)
122
+
123
+ def _on_node_changed(
124
+ self, index: int, old: MessageNode[Any, Any], new: MessageNode[Any, Any]
125
+ ) -> None:
126
+ """Handle node replacement in the agents list."""
127
+ self._on_node_removed(index, old)
128
+ self._on_node_added(index, new)
129
+
130
+ def _on_node_added(self, index: int, node: MessageNode[Any, Any]) -> None:
131
+ """Handler for adding new nodes to the team."""
132
+ from agentpool.agents import Agent
133
+
134
+ if isinstance(node, Agent):
135
+ # Add MCP aggregating provider from manager
136
+ aggregating_provider = self.mcp.get_aggregating_provider()
137
+ node.tools.add_provider(aggregating_provider)
138
+
139
+ def _on_node_removed(self, index: int, node: MessageNode[Any, Any]) -> None:
140
+ """Handler for removing nodes from the team."""
141
+ from agentpool.agents import Agent
142
+
143
+ if isinstance(node, Agent):
144
+ # Remove MCP aggregating provider
145
+ aggregating_provider = self.mcp.get_aggregating_provider()
146
+ node.tools.remove_provider(aggregating_provider.name)
147
+
148
+ def __repr__(self) -> str:
149
+ """Create readable representation."""
150
+ members = ", ".join(node.name for node in self.nodes)
151
+ name = f" ({self.name})" if self.name else ""
152
+ return f"{self.__class__.__name__}[{len(self.nodes)}]{name}: {members}"
153
+
154
+ def __len__(self) -> int:
155
+ """Get number of team members."""
156
+ return len(self.nodes)
157
+
158
+ def __iter__(self) -> Iterator[MessageNode[TDeps, TResult]]:
159
+ """Iterate over team members."""
160
+ return iter(self.nodes)
161
+
162
+ def __getitem__(self, index_or_name: int | str) -> MessageNode[TDeps, TResult]:
163
+ """Get team member by index or name."""
164
+ if isinstance(index_or_name, str):
165
+ return next(node for node in self.nodes if node.name == index_or_name)
166
+ return self.nodes[index_or_name]
167
+
168
+ def __or__(
169
+ self,
170
+ other: Agent[Any, Any] | ProcessorCallback[Any] | BaseTeam[Any, Any],
171
+ ) -> TeamRun[Any, Any]:
172
+ """Create a sequential pipeline."""
173
+ from agentpool.agents import Agent
174
+ from agentpool.delegation.teamrun import TeamRun
175
+
176
+ # Handle conversion of callables first
177
+ if callable(other):
178
+ other = Agent.from_callback(other)
179
+ other.agent_pool = self.agent_pool
180
+
181
+ # If we're already a TeamRun, extend it
182
+ if isinstance(self, TeamRun):
183
+ if self.validator:
184
+ # If we have a validator, create new TeamRun to preserve validation
185
+ return TeamRun([self, other])
186
+ self.nodes.append(other)
187
+ return self
188
+ # Otherwise create new TeamRun
189
+ return TeamRun([self, other])
190
+
191
+ @overload
192
+ def __and__(self, other: Team[None]) -> Team[None]: ...
193
+
194
+ @overload
195
+ def __and__(self, other: Team[TDeps]) -> Team[TDeps]: ...
196
+
197
+ @overload
198
+ def __and__(self, other: Team[Any]) -> Team[Any]: ...
199
+
200
+ @overload
201
+ def __and__(self, other: Agent[TDeps, Any]) -> Team[TDeps]: ...
202
+
203
+ @overload
204
+ def __and__(self, other: Agent[Any, Any]) -> Team[Any]: ...
205
+
206
+ def __and__(self, other: Team[Any] | Agent[Any, Any] | ProcessorCallback[Any]) -> Team[Any]:
207
+ """Combine teams, preserving type safety for same types."""
208
+ from agentpool.agents import Agent
209
+ from agentpool.delegation.team import Team
210
+
211
+ if callable(other):
212
+ other = Agent.from_callback(other)
213
+ other.agent_pool = self.agent_pool
214
+
215
+ match other:
216
+ case Team():
217
+ # Flatten when combining Teams
218
+ return Team([*self.nodes, *other.nodes])
219
+ case _:
220
+ # Everything else just becomes a member
221
+ return Team([*self.nodes, other])
222
+
223
+ async def get_stats(self) -> AggregatedMessageStats:
224
+ """Get aggregated stats from all team members."""
225
+ stats = [await node.get_stats() for node in self.nodes]
226
+ return AggregatedMessageStats(stats=stats)
227
+
228
+ @property
229
+ def is_running(self) -> bool:
230
+ """Whether execution is currently running."""
231
+ return bool(self._main_task and not self._main_task.done())
232
+
233
+ def is_busy(self) -> bool:
234
+ """Check if team is processing any tasks."""
235
+ return bool(self.task_manager._pending_tasks or self._main_task)
236
+
237
+ async def stop(self) -> None:
238
+ """Stop background execution if running."""
239
+ if self._main_task and not self._main_task.done():
240
+ self._main_task.cancel()
241
+ await self._main_task
242
+ self._main_task = None
243
+ await self.task_manager.cleanup_tasks()
244
+
245
+ async def wait(self) -> ChatMessage[Any] | None:
246
+ """Wait for background execution to complete and return last message."""
247
+ if not self._main_task:
248
+ msg = "No execution running"
249
+ raise RuntimeError(msg)
250
+ if self._infinite:
251
+ msg = "Cannot wait on infinite execution"
252
+ raise RuntimeError(msg)
253
+ try:
254
+ return await self._main_task
255
+ finally:
256
+ await self.task_manager.cleanup_tasks()
257
+ self._main_task = None
258
+
259
+ async def run_in_background(
260
+ self,
261
+ *prompts: PromptCompatible | None,
262
+ max_count: int | None = 1, # 1 = single execution, None = indefinite
263
+ interval: float = 1.0,
264
+ **kwargs: Any,
265
+ ) -> ExtendedTeamTalk:
266
+ """Start execution in background.
267
+
268
+ Args:
269
+ prompts: Prompts to execute
270
+ max_count: Maximum number of executions (None = run indefinitely)
271
+ interval: Seconds between executions
272
+ **kwargs: Additional args for execute()
273
+ """
274
+ if self._main_task:
275
+ msg = "Execution already running"
276
+ raise RuntimeError(msg)
277
+ self._infinite = max_count is None
278
+
279
+ async def _continuous() -> ChatMessage[Any] | None:
280
+ count = 0
281
+ last_message = None
282
+ while max_count is None or count < max_count:
283
+ try:
284
+ result = await self.execute(*prompts, **kwargs)
285
+ last_message = result[-1].message if result else None
286
+ count += 1
287
+ if max_count is None or count < max_count:
288
+ await anyio.sleep(interval)
289
+ except asyncio.CancelledError:
290
+ logger.debug("Background execution cancelled")
291
+ break
292
+ return last_message
293
+
294
+ self._main_task = self.task_manager.create_task(_continuous(), name="main_execution")
295
+ return self._team_talk
296
+
297
+ @property
298
+ def execution_stats(self) -> AggregatedTalkStats:
299
+ """Get current execution statistics."""
300
+ return self._team_talk.stats
301
+
302
+ @property
303
+ def talk(self) -> ExtendedTeamTalk:
304
+ """Get current connection."""
305
+ return self._team_talk
306
+
307
+ @property
308
+ def events(self) -> ListEvents:
309
+ """Get events for the team."""
310
+ return self.nodes.events
311
+
312
+ async def cancel(self) -> None:
313
+ """Cancel execution and cleanup."""
314
+ if self._main_task:
315
+ self._main_task.cancel()
316
+ await self.task_manager.cleanup_tasks()
317
+
318
+ def get_structure_diagram(self) -> str:
319
+ """Generate mermaid flowchart of node hierarchy."""
320
+ lines = ["flowchart TD"]
321
+
322
+ def add_node(node: MessageNode[Any, Any], parent: str | None = None) -> None:
323
+ """Recursively add node and its members to diagram."""
324
+ node_id = f"node_{id(node)}"
325
+ lines.append(f" {node_id}[{node.name}]")
326
+ if parent:
327
+ lines.append(f" {parent} --> {node_id}")
328
+
329
+ # If it's a team, recursively add its members
330
+ from agentpool.delegation.base_team import BaseTeam
331
+
332
+ if isinstance(node, BaseTeam):
333
+ for member in node.nodes:
334
+ add_node(member, node_id)
335
+
336
+ # Start with root nodes (team members)
337
+ for node in self.nodes:
338
+ add_node(node)
339
+
340
+ return "\n".join(lines)
341
+
342
+ def iter_agents(self) -> Iterator[Agent[Any, Any]]:
343
+ """Recursively iterate over all child agents."""
344
+ from agentpool.agents import Agent
345
+
346
+ for node in self.nodes:
347
+ match node:
348
+ case BaseTeam():
349
+ yield from node.iter_agents()
350
+ case Agent():
351
+ yield node
352
+ case _:
353
+ msg = f"Invalid node type: {type(node)}"
354
+ raise ValueError(msg)
355
+
356
+ def get_context(self, data: Any = None) -> TeamContext:
357
+ """Create a new context for this team.
358
+
359
+ Args:
360
+ data: Optional custom data to attach to the context
361
+
362
+ Returns:
363
+ A new TeamContext instance
364
+
365
+ Raises:
366
+ ValueError: If team members belong to different pools
367
+ """
368
+ from agentpool.delegation.team import Team
369
+
370
+ pool_ids: set[int] = set()
371
+ shared_pool: AgentPool | None = None
372
+ team_config: TeamConfig | None = None
373
+
374
+ for agent in self.iter_agents():
375
+ pool = agent.agent_pool
376
+ if pool:
377
+ pool_id = id(pool)
378
+ if pool_id not in pool_ids:
379
+ pool_ids.add(pool_id)
380
+ shared_pool = pool
381
+ if shared_pool.manifest.teams:
382
+ team_config = shared_pool.manifest.teams.get(self.name)
383
+ if not team_config:
384
+ mode = "parallel" if isinstance(self, Team) else "sequential"
385
+ team_config = TeamConfig(name=self.name, mode=mode, members=[])
386
+ if not pool_ids:
387
+ logger.debug("No pool found for team.", team=self.name)
388
+ return TeamContext(
389
+ node=self,
390
+ pool=shared_pool,
391
+ config=team_config,
392
+ definition=shared_pool.manifest if shared_pool else AgentsManifest(),
393
+ data=data,
394
+ )
395
+
396
+ if len(pool_ids) > 1:
397
+ msg = f"Team members in {self.name} belong to different pools"
398
+ raise ValueError(msg)
399
+ return TeamContext(
400
+ node=self,
401
+ pool=shared_pool,
402
+ config=team_config,
403
+ definition=shared_pool.manifest if shared_pool else AgentsManifest(),
404
+ data=data,
405
+ )
406
+
407
+ async def distribute(
408
+ self,
409
+ content: str,
410
+ *,
411
+ tools: list[str] | None = None,
412
+ resources: list[str] | None = None,
413
+ metadata: dict[str, Any] | None = None,
414
+ ) -> None:
415
+ """Distribute content and capabilities to all team members."""
416
+ for agent in self.iter_agents():
417
+ # Add context message
418
+ agent.conversation.add_context_message(
419
+ content, source="distribution", metadata=metadata
420
+ )
421
+
422
+ # Register tools if provided
423
+ if tools:
424
+ for tool in tools:
425
+ agent.tools.register_tool(tool)
426
+
427
+ # Load resources if provided
428
+ if resources:
429
+ for resource in resources:
430
+ await agent.conversation.load_context_source(resource)
431
+
432
+ @asynccontextmanager
433
+ async def temporary_state(
434
+ self,
435
+ *,
436
+ system_prompts: list[AnyPromptType] | None = None,
437
+ replace_prompts: bool = False,
438
+ tools: list[ToolType] | None = None,
439
+ replace_tools: bool = False,
440
+ history: list[AnyPromptType] | SessionQuery | None = None,
441
+ replace_history: bool = False,
442
+ pause_routing: bool = False,
443
+ model: ModelType | None = None,
444
+ ) -> AsyncIterator[Self]:
445
+ """Temporarily modify state of all agents in the team.
446
+
447
+ All agents in the team will enter their temporary state simultaneously.
448
+
449
+ Args:
450
+ system_prompts: Temporary system prompts to use
451
+ replace_prompts: Whether to replace existing prompts
452
+ tools: Temporary tools to make available
453
+ replace_tools: Whether to replace existing tools
454
+ history: Conversation history (prompts or query)
455
+ replace_history: Whether to replace existing history
456
+ pause_routing: Whether to pause message routing
457
+ model: Temporary model override
458
+ """
459
+ # Get all agents (flattened) before entering context
460
+ agents = list(self.iter_agents())
461
+
462
+ async with AsyncExitStack() as stack:
463
+ if pause_routing:
464
+ await stack.enter_async_context(self.connections.paused_routing())
465
+ # Enter temporary state for all agents
466
+ for agent in agents:
467
+ await stack.enter_async_context(
468
+ agent.temporary_state(
469
+ system_prompts=system_prompts,
470
+ replace_prompts=replace_prompts,
471
+ tools=tools,
472
+ replace_tools=replace_tools,
473
+ history=history,
474
+ replace_history=replace_history,
475
+ pause_routing=pause_routing,
476
+ model=model,
477
+ )
478
+ )
479
+ try:
480
+ yield self
481
+ finally:
482
+ # AsyncExitStack will handle cleanup of all states
483
+ pass
484
+
485
+ @abstractmethod
486
+ async def execute(
487
+ self,
488
+ *prompts: PromptCompatible | None,
489
+ **kwargs: Any,
490
+ ) -> TeamResponse: ...
491
+
492
+
493
+ if __name__ == "__main__":
494
+
495
+ async def main() -> None:
496
+ from agentpool import Agent, Team
497
+
498
+ agent = Agent("My Agent")
499
+ agent_2 = Agent("My Agent")
500
+ team = Team([agent, agent_2], mcp_servers=["uvx mcp-server-git"])
501
+ async with team:
502
+ print(await agent.tools.get_tools())
503
+
504
+ anyio.run(main)
@@ -0,0 +1,39 @@
1
+ """Agent pool management for collaboration."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any
6
+
7
+
8
+ if TYPE_CHECKING:
9
+ from agentpool.messaging import ChatMessage
10
+ from agentpool.talk import Talk
11
+
12
+
13
+ class MessageFlowTracker:
14
+ """Class for tracking message flow in conversations."""
15
+
16
+ def __init__(self) -> None:
17
+ self.events: list[Talk.ConnectionProcessed] = []
18
+
19
+ def track(self, event: Talk.ConnectionProcessed) -> None:
20
+ self.events.append(event)
21
+
22
+ def filter(self, message: ChatMessage[Any]) -> list[ChatMessage[Any]]:
23
+ """Filter events for specific conversation."""
24
+ return [
25
+ e.message for e in self.events if e.message.conversation_id == message.conversation_id
26
+ ]
27
+
28
+ def visualize(self, message: ChatMessage[Any]) -> str:
29
+ """Get flow visualization for specific conversation."""
30
+ # Filter events for this conversation
31
+ conv_events = [
32
+ e for e in self.events if e.message.conversation_id == message.conversation_id
33
+ ]
34
+ lines = ["flowchart LR"]
35
+ for event in conv_events:
36
+ source = event.message.name
37
+ for target in event.targets:
38
+ lines.append(f" {source}-->{target.name}") # noqa: PERF401
39
+ return "\n".join(lines)