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,233 @@
1
+ """Command for serving agents via Vercel AI protocol."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import json
6
+ import os
7
+ from typing import TYPE_CHECKING, Annotated, Any
8
+
9
+ import typer as t
10
+
11
+ from agentpool_cli import log, resolve_agent_config
12
+
13
+
14
+ if TYPE_CHECKING:
15
+ from collections.abc import AsyncIterator
16
+
17
+ from agentpool import ChatMessage
18
+
19
+
20
+ logger = log.get_logger(__name__)
21
+
22
+
23
+ def vercel_command( # noqa: PLR0915
24
+ ctx: t.Context,
25
+ config: Annotated[str | None, t.Argument(help="Path to agent configuration")] = None,
26
+ agent_name: Annotated[
27
+ str | None, t.Option("--agent", "-a", help="Specific agent to serve")
28
+ ] = None,
29
+ host: Annotated[str, t.Option(help="Host to bind server to")] = "localhost",
30
+ port: Annotated[int, t.Option(help="Port to listen on")] = 8000,
31
+ cors: Annotated[bool, t.Option(help="Enable CORS")] = True,
32
+ show_messages: Annotated[
33
+ bool, t.Option("--show-messages", help="Show message activity")
34
+ ] = False,
35
+ ) -> None:
36
+ """Serve agents via Vercel AI Data Stream Protocol.
37
+
38
+ This creates a server compatible with Vercel AI SDK frontends,
39
+ allowing you to use your agents with Vercel AI UI components.
40
+
41
+ The server exposes a POST /chat endpoint that accepts Vercel AI
42
+ protocol requests and streams responses back.
43
+
44
+ If --agent is specified, only that agent is served. Otherwise,
45
+ the endpoint accepts an 'agent' field in the request to select
46
+ which agent to use.
47
+ """
48
+ from fastapi import FastAPI
49
+ from fastapi.middleware.cors import CORSMiddleware
50
+ from pydantic_ai import PartDeltaEvent, PartStartEvent, TextPart, TextPartDelta
51
+ from starlette.requests import Request
52
+ from starlette.responses import JSONResponse, Response, StreamingResponse
53
+ import uvicorn
54
+
55
+ from agentpool import AgentPool, AgentsManifest
56
+ from agentpool.agents.events import StreamCompleteEvent
57
+
58
+ logger.info("Server PID", pid=os.getpid())
59
+
60
+ def on_message(message: ChatMessage[Any]) -> None:
61
+ print(message.format(style="simple"))
62
+
63
+ try:
64
+ config_path = resolve_agent_config(config)
65
+ except ValueError as e:
66
+ msg = str(e)
67
+ raise t.BadParameter(msg) from e
68
+
69
+ manifest = AgentsManifest.from_file(config_path)
70
+ pool = AgentPool(manifest)
71
+
72
+ if show_messages:
73
+ for agent in pool.agents.values():
74
+ agent.message_sent.connect(on_message)
75
+
76
+ # Create FastAPI app
77
+ app = FastAPI(
78
+ title="AgentPool - Vercel AI Server",
79
+ description="Vercel AI Data Stream Protocol server for AgentPool",
80
+ )
81
+
82
+ if cors:
83
+ app.add_middleware(
84
+ CORSMiddleware,
85
+ allow_origins=["*"],
86
+ allow_credentials=True,
87
+ allow_methods=["*"],
88
+ allow_headers=["*"],
89
+ )
90
+
91
+ @app.on_event("startup")
92
+ async def startup() -> None:
93
+ await pool.__aenter__()
94
+ logger.info("Agent pool initialized")
95
+
96
+ @app.on_event("shutdown")
97
+ async def shutdown() -> None:
98
+ await pool.__aexit__(None, None, None)
99
+ logger.info("Agent pool shut down")
100
+
101
+ @app.post("/chat")
102
+ async def chat(request: Request) -> Response:
103
+ """Handle Vercel AI protocol chat requests.
104
+
105
+ Implements the Vercel AI Data Stream Protocol:
106
+ https://sdk.vercel.ai/docs/ai-sdk-ui/stream-protocol#data-stream-protocol
107
+ """
108
+ body = await request.body()
109
+ try:
110
+ data = json.loads(body)
111
+ except json.JSONDecodeError as e:
112
+ return JSONResponse({"error": f"Invalid JSON: {e}"}, status_code=400)
113
+
114
+ # Extract messages from the request
115
+ messages = data.get("messages", [])
116
+ if not messages:
117
+ return JSONResponse({"error": "No messages provided"}, status_code=400)
118
+
119
+ # Get the last user message
120
+ last_message = messages[-1]
121
+ user_text = ""
122
+ if last_message.get("role") == "user":
123
+ parts = last_message.get("parts", [])
124
+ for part in parts:
125
+ if part.get("type") == "text":
126
+ user_text = part.get("text", "")
127
+ break
128
+
129
+ if not user_text:
130
+ return JSONResponse({"error": "No user text found"}, status_code=400)
131
+
132
+ # Determine which agent to use
133
+ if agent_name:
134
+ selected_agent = pool.get_agent(agent_name)
135
+ else:
136
+ if not pool.agents:
137
+ return JSONResponse({"error": "No agents available"}, status_code=500)
138
+ first_name = next(iter(pool.agents.keys()))
139
+ selected_agent = pool.get_agent(first_name)
140
+
141
+ async def generate_stream() -> AsyncIterator[str]:
142
+ """Generate Vercel AI Data Stream Protocol events.
143
+
144
+ Protocol format:
145
+ - Text: 0:"text content"
146
+ - Finish: e:{"finishReason":"stop",...}
147
+ - Done: d:{"finishReason":"stop"}
148
+ """
149
+ try:
150
+ async for event in selected_agent.run_stream(user_text):
151
+ # Handle pydantic-ai streaming events
152
+ if isinstance(event, PartStartEvent):
153
+ # New part started - if it's text, emit it
154
+ if isinstance(event.part, TextPart) and event.part.content:
155
+ text = event.part.content
156
+ escaped = json.dumps(text)
157
+ yield f"0:{escaped}\n"
158
+
159
+ elif isinstance(event, PartDeltaEvent):
160
+ # Delta update - emit text deltas
161
+ if isinstance(event.delta, TextPartDelta):
162
+ text = event.delta.content_delta
163
+ if text:
164
+ escaped = json.dumps(text)
165
+ yield f"0:{escaped}\n"
166
+
167
+ elif isinstance(event, StreamCompleteEvent):
168
+ # Stream complete - we've received the final message
169
+ # The content has already been streamed via deltas
170
+ pass
171
+
172
+ # Send finish event
173
+ finish_data = {
174
+ "finishReason": "stop",
175
+ "usage": {"promptTokens": 0, "completionTokens": 0},
176
+ }
177
+ yield f"e:{json.dumps(finish_data)}\n"
178
+
179
+ # Send done marker
180
+ done_data = {"finishReason": "stop"}
181
+ yield f"d:{json.dumps(done_data)}\n"
182
+
183
+ except Exception as e:
184
+ logger.exception("Error during streaming")
185
+ # Send error as text
186
+ error_msg = f"Error: {e}"
187
+ escaped = json.dumps(error_msg)
188
+ yield f"0:{escaped}\n"
189
+ # Still send finish
190
+ finish_data = {"finishReason": "error"}
191
+ yield f"e:{json.dumps(finish_data)}\n"
192
+ done_data = {"finishReason": "error"}
193
+ yield f"d:{json.dumps(done_data)}\n"
194
+
195
+ return StreamingResponse(
196
+ generate_stream(),
197
+ media_type="text/plain; charset=utf-8",
198
+ headers={
199
+ "X-Vercel-AI-Data-Stream": "v1",
200
+ "Cache-Control": "no-cache",
201
+ "Connection": "keep-alive",
202
+ },
203
+ )
204
+
205
+ @app.get("/agents")
206
+ async def list_agents() -> dict[str, Any]:
207
+ """List available agents."""
208
+ return {
209
+ "agents": [
210
+ {"name": name, "description": agent.description}
211
+ for name, agent in pool.agents.items()
212
+ ]
213
+ }
214
+
215
+ @app.get("/health")
216
+ async def health() -> dict[str, str]:
217
+ """Health check endpoint."""
218
+ return {"status": "ok"}
219
+
220
+ # Get log level from the global context
221
+ log_level = ctx.obj.get("log_level", "info") if ctx.obj else "info"
222
+
223
+ print(f"Starting Vercel AI server on http://{host}:{port}")
224
+ print(f"Chat endpoint: POST http://{host}:{port}/chat")
225
+ print(f"Available agents: {list(pool.agents.keys())}")
226
+
227
+ uvicorn.run(app, host=host, port=port, log_level=log_level.lower())
228
+
229
+
230
+ if __name__ == "__main__":
231
+ import typer
232
+
233
+ typer.run(vercel_command)
agentpool_cli/store.py ADDED
@@ -0,0 +1,171 @@
1
+ """Manages stored config mappings."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import TYPE_CHECKING, TypedDict
7
+
8
+ from agentpool_cli.log import get_logger
9
+
10
+
11
+ if TYPE_CHECKING:
12
+ from upath import UPath
13
+ from upathtools import JoinablePathLike
14
+
15
+
16
+ logger = get_logger(__name__)
17
+
18
+
19
+ @dataclass(frozen=True)
20
+ class ConfigFile:
21
+ """Represents an active configuration."""
22
+
23
+ name: str
24
+ path: str
25
+
26
+ def __str__(self) -> str:
27
+ """Format for display."""
28
+ return f"{self.name} ({self.path})"
29
+
30
+
31
+ class ConfigMapping(TypedDict):
32
+ """Type for config storage format."""
33
+
34
+ configs: dict[str, str] # name -> uri mapping
35
+ active: str | None
36
+
37
+
38
+ class ConfigStore:
39
+ """Manages stored config mappings."""
40
+
41
+ def __init__(self, filename: str | None = None) -> None:
42
+ """Initialize store with default paths."""
43
+ self._filename = filename or "configs.json"
44
+
45
+ @property
46
+ def config_dir(self) -> UPath:
47
+ """Get config directory."""
48
+ import platformdirs
49
+ from upathtools import to_upath
50
+
51
+ return to_upath(platformdirs.user_config_dir("agentpool"))
52
+
53
+ @property
54
+ def config_file(self) -> UPath:
55
+ """Get config file path."""
56
+ return self.config_dir / self._filename
57
+
58
+ def _ensure_config_dir(self) -> None:
59
+ """Create config directory if needed."""
60
+ self.config_dir.mkdir(parents=True, exist_ok=True)
61
+ if not self.config_file.exists():
62
+ mapping = ConfigMapping(configs={}, active=None)
63
+ self.save_mapping(mapping)
64
+
65
+ def load_mapping(self) -> ConfigMapping:
66
+ """Load config mapping from disk."""
67
+ import anyenv
68
+
69
+ if not self.config_file.exists():
70
+ return ConfigMapping(configs={}, active=None)
71
+ try:
72
+ text = self.config_file.read_text("utf-8")
73
+ data = anyenv.load_json(text, return_type=dict)
74
+ active = data.get("active")
75
+ configs = data.get("configs", {})
76
+ return ConfigMapping(configs=configs, active=active)
77
+ except Exception:
78
+ logger.exception("Failed to load config mapping")
79
+ return ConfigMapping(configs={}, active=None)
80
+
81
+ def save_mapping(self, mapping: ConfigMapping) -> None:
82
+ """Save config mapping to disk."""
83
+ import anyenv
84
+
85
+ try:
86
+ self.config_file.write_text(anyenv.dump_json(mapping, indent=True))
87
+ except Exception:
88
+ logger.exception("Failed to save config mapping")
89
+
90
+ def add_config(self, name: str, path: JoinablePathLike) -> None:
91
+ """Add a new named config.
92
+
93
+ Args:
94
+ name: Name to register the config under
95
+ path: Path to the config file
96
+
97
+ Raises:
98
+ ValueError: If name is invalid
99
+ FileNotFoundError: If config file doesn't exist
100
+ PermissionError: If config file can't be read
101
+ IsADirectoryError: If path points to a directory
102
+ """
103
+ # Basic validation
104
+ from upathtools import to_upath
105
+
106
+ if not name.isidentifier():
107
+ msg = f"Invalid config name: {name} (must be a valid Python identifier)"
108
+ raise ValueError(msg)
109
+
110
+ path_obj = to_upath(path).resolve()
111
+ if not path_obj.exists():
112
+ msg = f"Config file not found: {path}"
113
+ raise FileNotFoundError(msg)
114
+
115
+ if not path_obj.is_file():
116
+ msg = f"Path is not a file: {path}"
117
+ raise IsADirectoryError(msg)
118
+
119
+ try:
120
+ # Try to read file to verify access
121
+ path_obj.read_bytes()
122
+ except PermissionError as exc:
123
+ msg = f"Cannot read config file: {path}"
124
+ raise PermissionError(msg) from exc
125
+ # All good, save the config
126
+ mapping = self.load_mapping()
127
+ mapping["configs"][name] = str(path_obj)
128
+ logger.debug("Adding config %r -> %s", name, path_obj)
129
+ self.save_mapping(mapping)
130
+
131
+ def remove_config(self, name: str) -> None:
132
+ """Remove a named config."""
133
+ mapping = self.load_mapping()
134
+ if name == mapping["active"]:
135
+ mapping["active"] = None
136
+ mapping["configs"].pop(name, None)
137
+ self.save_mapping(mapping)
138
+
139
+ def set_active(self, name: str) -> None:
140
+ """Set the active config."""
141
+ mapping = self.load_mapping()
142
+ if name not in mapping["configs"]:
143
+ msg = f"Config {name} not found"
144
+ raise KeyError(msg)
145
+ mapping["active"] = name
146
+ self.save_mapping(mapping)
147
+
148
+ def get_active(self) -> ConfigFile | None:
149
+ """Get active config if one is set.
150
+
151
+ Returns:
152
+ ConfigFile if an active config is set, None otherwise
153
+ """
154
+ mapping = self.load_mapping()
155
+ if not mapping["active"]:
156
+ return None
157
+ name = mapping["active"]
158
+ return ConfigFile(name=name, path=mapping["configs"][name])
159
+
160
+ def list_configs(self) -> list[tuple[str, str]]:
161
+ """List all configs with their paths."""
162
+ mapping = self.load_mapping()
163
+ return list(mapping["configs"].items())
164
+
165
+ def get_config(self, name: str) -> str:
166
+ """Get path for a named config."""
167
+ mapping = self.load_mapping()
168
+ if name not in mapping["configs"]:
169
+ msg = f"Config {name} not found"
170
+ raise KeyError(msg)
171
+ return mapping["configs"][name]
agentpool_cli/task.py ADDED
@@ -0,0 +1,84 @@
1
+ """Task execution command."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from typing import TYPE_CHECKING, Annotated
7
+
8
+ import typer as t
9
+
10
+ from agentpool_cli import log, resolve_agent_config
11
+
12
+
13
+ if TYPE_CHECKING:
14
+ from agentpool import AgentsManifest
15
+
16
+
17
+ TASK_HELP = """
18
+ Execute a defined task with the specified agent.
19
+
20
+ Example:
21
+ agentpool task docs write_api_docs --prompt "Include code examples"
22
+ agentpool task docs write_api_docs --log-level DEBUG
23
+ """
24
+
25
+
26
+ async def execute_job(
27
+ agent_name: str,
28
+ task_name: str,
29
+ config: AgentsManifest,
30
+ *,
31
+ prompt: str | None = None,
32
+ ) -> str:
33
+ """Execute task with agent."""
34
+ from agentpool import AgentPool
35
+
36
+ async with AgentPool(config) as pool:
37
+ # Get both agent and task
38
+ agent = pool.get_agent(agent_name)
39
+ task = pool.get_job(task_name)
40
+
41
+ # Create final prompt from task and additional input
42
+ task_prompt = task.prompt
43
+ if prompt:
44
+ task_prompt = f"{task_prompt}\n\nAdditional instructions:\n{prompt}"
45
+
46
+ result = await agent.run(task_prompt)
47
+ return result.data
48
+
49
+
50
+ def task_command(
51
+ agent_name: Annotated[str, t.Argument(help="Name of agent to run task with")],
52
+ task_name: Annotated[str, t.Argument(help="Name of task to execute")],
53
+ config: Annotated[
54
+ str | None, t.Option("--config", "-c", help="Agent configuration file")
55
+ ] = None,
56
+ prompt: Annotated[str | None, t.Option("--prompt", "-p", help="Additional prompt")] = None,
57
+ ) -> None:
58
+ """Execute a task with the specified agent."""
59
+ logger = log.get_logger(__name__)
60
+ try:
61
+ logger.debug("Starting task execution", name=task_name)
62
+
63
+ # Resolve configuration path
64
+ try:
65
+ config_path = resolve_agent_config(config)
66
+ logger.debug("Using config", source=config_path)
67
+ except ValueError as e:
68
+ msg = str(e)
69
+ raise t.BadParameter(msg) from e
70
+
71
+ from agentpool import AgentsManifest
72
+
73
+ manifest = AgentsManifest.from_file(config_path)
74
+ result = asyncio.run(execute_job(agent_name, task_name, manifest, prompt=prompt))
75
+ print(result)
76
+
77
+ except Exception as e:
78
+ t.echo(f"Error: {e}", err=True)
79
+ logger.debug("Exception details", exc_info=True)
80
+ raise t.Exit(1) from e
81
+
82
+
83
+ if __name__ == "__main__":
84
+ t.run(task_command)
agentpool_cli/utils.py ADDED
@@ -0,0 +1,104 @@
1
+ """Utilities for creating Typer commands from Pydantic models."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import inspect
6
+ import types as pytypes
7
+ from typing import TYPE_CHECKING, Annotated, Any, Union, get_args, get_origin
8
+
9
+ import typer
10
+
11
+
12
+ if TYPE_CHECKING:
13
+ from collections.abc import Callable
14
+ from inspect import Parameter
15
+
16
+ from pydantic import BaseModel
17
+
18
+
19
+ def resolve_type(field_type: Any) -> Any:
20
+ """Resolve actual type from Union/Optional types."""
21
+ origin = get_origin(field_type)
22
+
23
+ # Handle Any
24
+ if field_type is Any:
25
+ return str
26
+
27
+ # Handle both Union and | syntax
28
+ if origin is Union or origin is pytypes.UnionType:
29
+ types_ = [t for t in get_args(field_type) if t is not type(None)]
30
+ return resolve_type(types_[0]) if len(types_) == 1 else str
31
+
32
+ # Handle lists/sets
33
+ if origin in {list, set}:
34
+ item_type = get_args(field_type)[0]
35
+ return list[resolve_type(item_type)] # type: ignore[misc]
36
+
37
+ return field_type
38
+
39
+
40
+ def create_typer_command[T: BaseModel](
41
+ config_cls: type[T],
42
+ callback: Callable[[T], Any] | None = None,
43
+ *,
44
+ name: str | None = None,
45
+ ) -> typer.models.CommandInfo:
46
+ """Create a Typer CommandInfo from a Pydantic model."""
47
+
48
+ def make_command(**kwargs: Any) -> Any:
49
+ """Command created from model."""
50
+ config = config_cls(**kwargs)
51
+ if callback:
52
+ return callback(config)
53
+ return config
54
+
55
+ # Create parameters from model fields
56
+ params: dict[str, Parameter] = {}
57
+ for field_name, field in config_cls.model_fields.items():
58
+ if field_name == "type": # Skip discriminator
59
+ continue
60
+
61
+ field_type = resolve_type(field.annotation)
62
+ default = field.default if field.default != ... else None
63
+
64
+ # First field becomes argument
65
+ if not params:
66
+ # For arguments, the param name should be the field name
67
+ params[field_name] = inspect.Parameter(
68
+ field_name,
69
+ inspect.Parameter.POSITIONAL_OR_KEYWORD,
70
+ annotation=Annotated[field_type, typer.Argument(help=field.description)],
71
+ default=default,
72
+ )
73
+ continue
74
+
75
+ # For options, we need proper param_decls
76
+ option_name = field_name.replace("_", "-")
77
+ params[field_name] = inspect.Parameter(
78
+ field_name,
79
+ inspect.Parameter.KEYWORD_ONLY,
80
+ annotation=Annotated[
81
+ field_type,
82
+ typer.Option(
83
+ "--" + option_name, # Explicit param_decls
84
+ help=field.description,
85
+ ),
86
+ ],
87
+ default=default,
88
+ )
89
+
90
+ # Create function with signature
91
+ make_command.__signature__ = inspect.Signature( # type: ignore
92
+ list(params.values()), return_annotation=config_cls
93
+ )
94
+ make_command.__annotations__ = {k: v.annotation for k, v in params.items()}
95
+
96
+ # Create command
97
+ if name is None:
98
+ name = config_cls.__name__.lower().replace("command", "")
99
+
100
+ return typer.models.CommandInfo(
101
+ name=name,
102
+ callback=make_command,
103
+ help=config_cls.__doc__,
104
+ )
agentpool_cli/watch.py ADDED
@@ -0,0 +1,54 @@
1
+ """Command for watching agents and displaying messages."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ from typing import TYPE_CHECKING, Annotated, Any
7
+
8
+ import typer as t
9
+
10
+ from agentpool_cli import log
11
+ from agentpool_cli.cli_types import DetailLevel # noqa: TC001
12
+
13
+
14
+ if TYPE_CHECKING:
15
+ from agentpool import ChatMessage
16
+
17
+
18
+ logger = log.get_logger(__name__)
19
+
20
+
21
+ def watch_command(
22
+ config: Annotated[str, t.Argument(help="Path to agent configuration")],
23
+ show_messages: Annotated[
24
+ bool, t.Option("--show-messages", help="Show all messages (not just final responses)")
25
+ ] = True,
26
+ detail_level: Annotated[
27
+ DetailLevel, t.Option("-d", "--detail", help="Output detail level")
28
+ ] = "simple",
29
+ show_metadata: Annotated[bool, t.Option("--metadata", help="Show message metadata")] = False,
30
+ show_costs: Annotated[bool, t.Option("--costs", help="Show token usage and costs")] = False,
31
+ ) -> None:
32
+ """Run agents in event-watching mode."""
33
+
34
+ def on_message(chat_message: ChatMessage[Any]) -> None:
35
+ text = chat_message.format(
36
+ style=detail_level,
37
+ show_metadata=show_metadata,
38
+ show_costs=show_costs,
39
+ )
40
+ print(text)
41
+
42
+ async def run_watch() -> None:
43
+ from agentpool import AgentPool, AgentsManifest
44
+
45
+ manifest = AgentsManifest.from_file(config)
46
+ async with AgentPool(manifest) as pool:
47
+ # Connect message handlers if showing all messages
48
+ if show_messages:
49
+ for agent in pool.agents.values():
50
+ agent.message_sent.connect(on_message)
51
+
52
+ await pool.run_event_loop()
53
+
54
+ asyncio.run(run_watch())