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,291 @@
1
+ """Debug toolset for agent self-introspection and runtime debugging."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections import deque
6
+ from dataclasses import dataclass, field
7
+ import logging
8
+ from typing import Any, Literal
9
+
10
+ from pydantic_ai import RunContext # noqa: TC002
11
+
12
+ from agentpool.agents.context import AgentContext # noqa: TC001
13
+ from agentpool.resource_providers import StaticResourceProvider
14
+
15
+
16
+ LogLevel = Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
17
+
18
+
19
+ @dataclass
20
+ class LogRecord:
21
+ """A captured log record."""
22
+
23
+ level: str
24
+ logger: str
25
+ message: str
26
+ timestamp: str
27
+ extra: dict[str, Any] = field(default_factory=dict)
28
+
29
+
30
+ LEVEL_PRIORITY = {
31
+ "DEBUG": 10,
32
+ "INFO": 20,
33
+ "WARNING": 30,
34
+ "ERROR": 40,
35
+ "CRITICAL": 50,
36
+ }
37
+
38
+
39
+ class MemoryLogHandler(logging.Handler):
40
+ """A logging handler that stores records in memory for later retrieval."""
41
+
42
+ def __init__(self, max_records: int = 1000) -> None:
43
+ super().__init__()
44
+ self.max_records = max_records
45
+ self.records: deque[LogRecord] = deque(maxlen=max_records)
46
+ self.setFormatter(logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s"))
47
+
48
+ def emit(self, record: logging.LogRecord) -> None:
49
+ """Store the log record."""
50
+ log_record = LogRecord(
51
+ level=record.levelname,
52
+ logger=record.name,
53
+ message=self.format(record),
54
+ timestamp=self.formatter.formatTime(record) if self.formatter else "",
55
+ extra={k: v for k, v in record.__dict__.items() if k not in logging.LogRecord.__dict__},
56
+ )
57
+ self.records.append(log_record)
58
+
59
+ def get_records(
60
+ self,
61
+ level: LogLevel | None = None,
62
+ logger_filter: str | None = None,
63
+ limit: int | None = None,
64
+ ) -> list[LogRecord]:
65
+ """Get filtered log records.
66
+
67
+ Args:
68
+ level: Minimum log level to include
69
+ logger_filter: Only include loggers containing this string
70
+ limit: Maximum number of records to return (newest first)
71
+
72
+ Returns:
73
+ List of matching log records
74
+ """
75
+ min_level = LEVEL_PRIORITY.get(level, 0) if level else 0
76
+ filtered = []
77
+ for record in reversed(self.records):
78
+ if LEVEL_PRIORITY.get(record.level, 0) < min_level:
79
+ continue
80
+ if logger_filter and logger_filter not in record.logger:
81
+ continue
82
+ filtered.append(record)
83
+ if limit and len(filtered) >= limit:
84
+ break
85
+
86
+ return filtered
87
+
88
+ def clear(self) -> None:
89
+ """Clear all stored records."""
90
+ self.records.clear()
91
+
92
+
93
+ # Global memory handler instance
94
+ _memory_handler: MemoryLogHandler | None = None
95
+
96
+
97
+ def get_memory_handler() -> MemoryLogHandler:
98
+ """Get or create the global memory log handler."""
99
+ global _memory_handler # noqa: PLW0603
100
+ if _memory_handler is None:
101
+ _memory_handler = MemoryLogHandler()
102
+ # Attach to root logger to capture everything
103
+ logging.getLogger().addHandler(_memory_handler)
104
+ return _memory_handler
105
+
106
+
107
+ def install_memory_handler(max_records: int = 1000) -> MemoryLogHandler:
108
+ """Install the memory handler if not already installed.
109
+
110
+ Args:
111
+ max_records: Maximum number of records to keep in memory
112
+
113
+ Returns:
114
+ The memory handler instance
115
+ """
116
+ global _memory_handler # noqa: PLW0603
117
+ if _memory_handler is None:
118
+ _memory_handler = MemoryLogHandler(max_records=max_records)
119
+ logging.getLogger().addHandler(_memory_handler)
120
+ return _memory_handler
121
+
122
+
123
+ # =============================================================================
124
+ # Introspection Tool
125
+ # =============================================================================
126
+
127
+ INTROSPECTION_USAGE = """
128
+ Execute Python code with full access to your runtime context.
129
+
130
+ Available in namespace:
131
+ - ctx: AgentContext (ctx.agent, ctx.pool, ctx.config, ctx.definition, etc.)
132
+ - run_ctx: pydantic-ai RunContext (current run state)
133
+ - me: Shortcut for ctx.agent (your Agent instance)
134
+
135
+ You can inspect yourself, the pool, other agents, your tools, and more.
136
+ Write an async main() function that returns the result.
137
+
138
+ Example - inspect your own tools:
139
+ ```python
140
+ async def main():
141
+ tools = me.tools.list_tools()
142
+ return [t.name for t in tools]
143
+ ```
144
+
145
+ Example - check pool state:
146
+ ```python
147
+ async def main():
148
+ if ctx.pool:
149
+ agents = list(ctx.pool.agents.keys())
150
+ return f"Agents in pool: {agents}"
151
+ return "No pool available"
152
+ ```
153
+
154
+ Example - explore with dir():
155
+ ```python
156
+ async def main():
157
+ return dir(ctx)
158
+ ```
159
+ """
160
+
161
+
162
+ async def execute_introspection(ctx: AgentContext, run_ctx: RunContext[Any], code: str) -> str: # noqa: D417
163
+ """Execute Python code with access to your own runtime context.
164
+
165
+ This is a debugging/development tool that gives you full access to
166
+ inspect and interact with your runtime environment.
167
+
168
+ Args:
169
+ code: Python code with async main() function to execute
170
+
171
+ Returns:
172
+ Result of execution or error message
173
+ """
174
+ # Build namespace with runtime context
175
+ namespace: dict[str, Any] = {"ctx": ctx, "run_ctx": run_ctx, "me": ctx.agent}
176
+ try:
177
+ exec(code, namespace)
178
+ if "main" not in namespace:
179
+ return "Error: Code must define an async main() function"
180
+ result = await namespace["main"]()
181
+ return str(result) if result is not None else "Code executed successfully (no return value)"
182
+ except Exception as e: # noqa: BLE001
183
+ return f"Error executing code: {type(e).__name__}: {e}"
184
+
185
+
186
+ # =============================================================================
187
+ # Log Tools
188
+ # =============================================================================
189
+
190
+
191
+ async def get_logs(
192
+ level: LogLevel = "INFO",
193
+ logger_filter: str | None = None,
194
+ limit: int = 50,
195
+ ) -> str:
196
+ """Get recent log entries from memory.
197
+
198
+ Args:
199
+ level: Minimum log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
200
+ logger_filter: Only show logs from loggers containing this string
201
+ limit: Maximum number of log entries to return
202
+
203
+ Returns:
204
+ Formatted log entries
205
+ """
206
+ handler = get_memory_handler()
207
+ records = handler.get_records(level=level, logger_filter=logger_filter, limit=limit)
208
+
209
+ if not records:
210
+ return "No log entries found matching criteria"
211
+
212
+ lines = [f"=== {len(records)} log entries (newest first) ===\n"]
213
+ for record in records:
214
+ lines.append(record.message) # noqa: PERF401
215
+
216
+ return "\n".join(lines)
217
+
218
+
219
+ async def clear_logs() -> str:
220
+ """Clear all captured log entries from memory.
221
+
222
+ Returns:
223
+ Confirmation message
224
+ """
225
+ handler = get_memory_handler()
226
+ count = len(handler.records)
227
+ handler.clear()
228
+ return f"Cleared {count} log entries"
229
+
230
+
231
+ # =============================================================================
232
+ # Path Tools
233
+ # =============================================================================
234
+
235
+
236
+ async def get_platform_paths() -> str:
237
+ """Get platform-specific paths for agentpool.
238
+
239
+ Returns:
240
+ Dictionary of platform paths
241
+ """
242
+ import platformdirs
243
+
244
+ paths = {
245
+ "config": platformdirs.user_config_dir("agentpool"),
246
+ "data": platformdirs.user_data_dir("agentpool"),
247
+ "cache": platformdirs.user_cache_dir("agentpool"),
248
+ "logs": platformdirs.user_log_dir("agentpool"),
249
+ "state": platformdirs.user_state_dir("agentpool"),
250
+ }
251
+
252
+ lines = ["Platform paths for agentpool:", ""]
253
+ for name, path in paths.items():
254
+ lines.append(f" {name}: {path}")
255
+
256
+ return "\n".join(lines)
257
+
258
+
259
+ # =============================================================================
260
+ # Toolset Class
261
+ # =============================================================================
262
+
263
+
264
+ class DebugTools(StaticResourceProvider):
265
+ """Debug and introspection tools for agent development.
266
+
267
+ Provides tools for:
268
+ - Self-introspection via code execution with runtime context access
269
+ - Log inspection and management
270
+ - Platform path discovery
271
+ """
272
+
273
+ def __init__(self, name: str = "debug", install_log_handler: bool = True) -> None:
274
+ """Initialize debug tools.
275
+
276
+ Args:
277
+ name: Toolset name/namespace
278
+ install_log_handler: Whether to install the memory log handler
279
+ """
280
+ super().__init__(name=name)
281
+
282
+ if install_log_handler:
283
+ install_memory_handler()
284
+
285
+ desc = (execute_introspection.__doc__ or "") + "\n\n" + INTROSPECTION_USAGE
286
+ self._tools = [
287
+ self.create_tool(execute_introspection, category="other", description_override=desc),
288
+ self.create_tool(get_logs, category="other", read_only=True, idempotent=True),
289
+ self.create_tool(clear_logs, category="other"),
290
+ self.create_tool(get_platform_paths, category="other", read_only=True, idempotent=True),
291
+ ]
@@ -0,0 +1,381 @@
1
+ """Provider for execution environment tools with event emission."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING, Any
6
+ import uuid
7
+
8
+ from exxec.events import OutputEvent, ProcessCompletedEvent, ProcessErrorEvent, ProcessStartedEvent
9
+
10
+ from agentpool import log
11
+ from agentpool.agents.context import AgentContext # noqa: TC001
12
+ from agentpool.resource_providers import ResourceProvider
13
+
14
+
15
+ logger = log.get_logger(__name__)
16
+
17
+
18
+ if TYPE_CHECKING:
19
+ from exxec import ExecutionEnvironment
20
+
21
+ from agentpool.tools.base import Tool
22
+
23
+
24
+ class ExecutionEnvironmentTools(ResourceProvider):
25
+ """Provider for execution environment tools.
26
+
27
+ Combines code execution and process management capabilities
28
+ using any ExecutionEnvironment backend. Emits events via AgentContext.
29
+
30
+ NOTE: The ACP execution environment used handles the Terminal events of the protocol,
31
+ the toolset should deal with the ToolCall events for UI display purposes.
32
+ """
33
+
34
+ def __init__(self, env: ExecutionEnvironment | None = None, name: str = "execution") -> None:
35
+ """Initialize execution environment toolset.
36
+
37
+ Args:
38
+ env: Execution environment to use (defaults to LocalExecutionEnvironment)
39
+ name: The name of the toolset
40
+ """
41
+ super().__init__(name=name)
42
+ self._env = env
43
+
44
+ def get_env(self, agent_ctx: AgentContext) -> ExecutionEnvironment:
45
+ """Get execution environment, falling back to agent's env if not set.
46
+
47
+ Args:
48
+ agent_ctx: Agent context to get fallback env from
49
+ """
50
+ if self._env is not None:
51
+ return self._env
52
+ return agent_ctx.agent.env
53
+
54
+ async def get_tools(self) -> list[Tool]:
55
+ return [
56
+ # Code execution tools
57
+ self.create_tool(self.execute_code, category="execute"),
58
+ self.create_tool(self.execute_command, category="execute", open_world=True),
59
+ # Process management tools
60
+ self.create_tool(self.start_process, category="execute", open_world=True),
61
+ self.create_tool(
62
+ self.get_process_output, category="execute", read_only=True, idempotent=True
63
+ ),
64
+ self.create_tool(
65
+ self.wait_for_process, category="execute", read_only=True, idempotent=True
66
+ ),
67
+ self.create_tool(self.kill_process, category="execute", destructive=True),
68
+ self.create_tool(self.release_process, category="execute"),
69
+ self.create_tool(
70
+ self.list_processes, category="search", read_only=True, idempotent=True
71
+ ),
72
+ ]
73
+
74
+ async def execute_code(self, agent_ctx: AgentContext, code: str) -> dict[str, Any]: # noqa: D417
75
+ """Execute Python code and return the result.
76
+
77
+ Args:
78
+ code: Python code to execute
79
+ """
80
+ process_id: str | None = None
81
+ output_parts: list[str] = []
82
+ exit_code: int | None = None
83
+ error_msg: str | None = None
84
+ duration: float | None = None
85
+ try:
86
+ async for event in self.get_env(agent_ctx).stream_code(code):
87
+ match event:
88
+ case ProcessStartedEvent(process_id=pid, command=cmd):
89
+ process_id = pid # save for later on.
90
+ await agent_ctx.events.process_started(pid, cmd, success=True)
91
+ case OutputEvent(data=data):
92
+ output_parts.append(data)
93
+ if process_id:
94
+ await agent_ctx.events.process_output(process_id, data)
95
+ case ProcessCompletedEvent(exit_code=code_, duration=dur):
96
+ exit_code = code_
97
+ duration = dur
98
+ out = "".join(output_parts)
99
+ if process_id:
100
+ await agent_ctx.events.process_exit(
101
+ process_id, exit_code, final_output=out
102
+ )
103
+ case ProcessErrorEvent(error=err, exit_code=code_):
104
+ error_msg = err
105
+ exit_code = code_
106
+ if process_id:
107
+ await agent_ctx.events.process_exit(
108
+ process_id, exit_code or 1, final_output=err
109
+ )
110
+
111
+ combined_output = "".join(output_parts)
112
+ if error_msg:
113
+ return {"error": error_msg, "output": combined_output, "exit_code": exit_code}
114
+
115
+ except Exception as e: # noqa: BLE001
116
+ error_id = process_id or f"code_{uuid.uuid4().hex[:8]}"
117
+ await agent_ctx.events.process_started(
118
+ error_id, "execute_code", success=False, error=str(e)
119
+ )
120
+ return {"error": f"Error executing code: {e}"}
121
+ else:
122
+ return {"output": combined_output, "exit_code": exit_code, "duration": duration}
123
+
124
+ async def execute_command( # noqa: PLR0915, D417
125
+ self,
126
+ agent_ctx: AgentContext,
127
+ command: str,
128
+ output_limit: int | None = None,
129
+ ) -> dict[str, Any]:
130
+ """Execute a shell command and return the output.
131
+
132
+ Args:
133
+ command: Shell command to execute
134
+ output_limit: Maximum bytes of output to return
135
+ """
136
+ # process_id comes from exxec events (is terminal_id when using ACP)
137
+ process_id: str | None = None
138
+ stdout_parts: list[str] = []
139
+ stderr_parts: list[str] = []
140
+ exit_code: int | None = None
141
+ error_msg: str | None = None
142
+ duration: float | None = None
143
+ try:
144
+ async for event in self.get_env(agent_ctx).stream_command(command):
145
+ match event:
146
+ case ProcessStartedEvent(process_id=pid, command=cmd):
147
+ process_id = pid
148
+ if pid:
149
+ await agent_ctx.events.process_started(pid, cmd, success=True)
150
+ else:
151
+ logger.warning("ProcessStartedEvent missing process_id", command=cmd)
152
+ case OutputEvent(process_id=pid, data=data, stream=stream):
153
+ if stream == "stderr":
154
+ stderr_parts.append(data)
155
+ else:
156
+ stdout_parts.append(data)
157
+ if pid:
158
+ await agent_ctx.events.process_output(pid, data)
159
+ else:
160
+ logger.warning("OutputEvent missing process_id", stream=stream)
161
+ case ProcessCompletedEvent(process_id=pid, exit_code=code_, duration=dur):
162
+ exit_code = code_
163
+ duration = dur
164
+ combined = "".join(stdout_parts) + "".join(stderr_parts)
165
+ if pid:
166
+ await agent_ctx.events.process_exit(
167
+ pid, exit_code, final_output=combined
168
+ )
169
+ else:
170
+ msg = "ProcessCompletedEvent missing process_id,"
171
+ logger.warning(msg, exit_code=code_)
172
+ case ProcessErrorEvent(process_id=pid, error=err, exit_code=code_):
173
+ error_msg = err
174
+ exit_code = code_
175
+
176
+ stdout = "".join(stdout_parts)
177
+ stderr = "".join(stderr_parts)
178
+ # Apply output limit if specified
179
+ truncated = False
180
+ if output_limit:
181
+ if len(stdout.encode()) > output_limit:
182
+ out = stdout.encode()[-output_limit:].decode(errors="ignore")
183
+ stdout = "...[truncated]\n" + out
184
+ truncated = True
185
+ if len(stderr.encode()) > output_limit:
186
+ out = stderr.encode()[-output_limit:].decode(errors="ignore")
187
+ stderr = "...[truncated]\n" + out
188
+ truncated = True
189
+ if error_msg:
190
+ return {
191
+ "error": error_msg,
192
+ "stdout": stdout,
193
+ "stderr": stderr,
194
+ "exit_code": exit_code,
195
+ }
196
+ except Exception as e: # noqa: BLE001
197
+ # Use process_id from events if available, otherwise generate fallback
198
+ error_id = process_id or f"cmd_{uuid.uuid4().hex[:8]}"
199
+ await agent_ctx.events.process_started(error_id, command, success=False, error=str(e))
200
+ return {"success": False, "error": f"Error executing command: {e}"}
201
+ else:
202
+ return {
203
+ "stdout": stdout,
204
+ "stderr": stderr,
205
+ "exit_code": exit_code,
206
+ "duration": duration,
207
+ "truncated": truncated,
208
+ }
209
+
210
+ async def start_process( # noqa: D417
211
+ self,
212
+ agent_ctx: AgentContext,
213
+ command: str,
214
+ args: list[str] | None = None,
215
+ cwd: str | None = None,
216
+ env: dict[str, str] | None = None,
217
+ output_limit: int | None = None,
218
+ ) -> dict[str, Any]:
219
+ """Start a command in the background and return process ID.
220
+
221
+ Args:
222
+ command: Command to execute
223
+ args: Command arguments
224
+ cwd: Working directory
225
+ env: Environment variables (added to current env)
226
+ output_limit: Maximum bytes of output to retain
227
+ """
228
+ manager = self.get_env(agent_ctx).process_manager
229
+ try:
230
+ process_id = await manager.start_process(
231
+ command=command,
232
+ args=args,
233
+ cwd=cwd,
234
+ env=env,
235
+ output_limit=output_limit,
236
+ )
237
+ await agent_ctx.events.process_started(process_id, command, success=True)
238
+
239
+ except Exception as e: # noqa: BLE001
240
+ await agent_ctx.events.process_started("", command, success=False, error=str(e))
241
+ return {"error": f"Failed to start process: {e}"}
242
+ else:
243
+ return {
244
+ "process_id": process_id,
245
+ "command": command,
246
+ "args": args or [],
247
+ "cwd": cwd,
248
+ "status": "started",
249
+ }
250
+
251
+ async def get_process_output(self, agent_ctx: AgentContext, process_id: str) -> dict[str, Any]: # noqa: D417
252
+ """Get current output from a background process.
253
+
254
+ Args:
255
+ process_id: Process identifier from start_process
256
+ """
257
+ manager = self.get_env(agent_ctx).process_manager
258
+ try:
259
+ output = await manager.get_output(process_id)
260
+ await agent_ctx.events.process_output(process_id, output.combined or "")
261
+ result: dict[str, Any] = {
262
+ "process_id": process_id,
263
+ "stdout": output.stdout or "",
264
+ "stderr": output.stderr or "",
265
+ "combined": output.combined or "",
266
+ "truncated": output.truncated,
267
+ }
268
+ if output.exit_code is not None:
269
+ result["exit_code"] = output.exit_code
270
+ result["status"] = "completed"
271
+ else:
272
+ result["status"] = "running"
273
+ except ValueError as e:
274
+ return {"error": str(e)}
275
+ except Exception as e: # noqa: BLE001
276
+ return {"error": f"Error getting process output: {e}"}
277
+ else:
278
+ return result
279
+
280
+ async def wait_for_process(self, agent_ctx: AgentContext, process_id: str) -> dict[str, Any]: # noqa: D417
281
+ """Wait for background process to complete and return final output.
282
+
283
+ Args:
284
+ process_id: Process identifier from start_process
285
+ """
286
+ manager = self.get_env(agent_ctx).process_manager
287
+ try:
288
+ exit_code = await manager.wait_for_exit(process_id)
289
+ output = await manager.get_output(process_id)
290
+ await agent_ctx.events.process_exit(process_id, exit_code, final_output=output.combined)
291
+
292
+ except ValueError as e:
293
+ return {"error": str(e)}
294
+ except Exception as e: # noqa: BLE001
295
+ return {"error": f"Error waiting for process: {e}"}
296
+ else:
297
+ return {
298
+ "process_id": process_id,
299
+ "exit_code": exit_code,
300
+ "status": "completed",
301
+ "stdout": output.stdout or "",
302
+ "stderr": output.stderr or "",
303
+ "combined": output.combined or "",
304
+ "truncated": output.truncated,
305
+ }
306
+
307
+ async def kill_process(self, agent_ctx: AgentContext, process_id: str) -> dict[str, Any]: # noqa: D417
308
+ """Terminate a background process.
309
+
310
+ Args:
311
+ process_id: Process identifier from start_process
312
+ """
313
+ try:
314
+ await self.get_env(agent_ctx).process_manager.kill_process(process_id)
315
+ await agent_ctx.events.process_killed(process_id=process_id, success=True)
316
+ except ValueError as e:
317
+ await agent_ctx.events.process_killed(process_id, success=False, error=str(e))
318
+ return {"error": str(e)}
319
+ except Exception as e: # noqa: BLE001
320
+ await agent_ctx.events.process_killed(process_id, success=False, error=str(e))
321
+ return {"error": f"Error killing process: {e}"}
322
+ else:
323
+ return {
324
+ "process_id": process_id,
325
+ "status": "killed",
326
+ "message": f"Process {process_id} has been terminated",
327
+ }
328
+
329
+ async def release_process(self, agent_ctx: AgentContext, process_id: str) -> dict[str, Any]: # noqa: D417
330
+ """Release resources for a background process.
331
+
332
+ Args:
333
+ process_id: Process identifier from start_process
334
+ """
335
+ try:
336
+ await self.get_env(agent_ctx).process_manager.release_process(process_id)
337
+ await agent_ctx.events.process_released(process_id=process_id, success=True)
338
+
339
+ except ValueError as e:
340
+ await agent_ctx.events.process_released(process_id, success=False, error=str(e))
341
+ return {"error": str(e)}
342
+ except Exception as e: # noqa: BLE001
343
+ await agent_ctx.events.process_released(process_id, success=False, error=str(e))
344
+ return {"error": f"Error releasing process: {e}"}
345
+ else:
346
+ return {
347
+ "process_id": process_id,
348
+ "status": "released",
349
+ "message": f"Process {process_id} resources have been released",
350
+ }
351
+
352
+ async def list_processes(self, agent_ctx: AgentContext) -> dict[str, Any]:
353
+ """List all active background processes."""
354
+ env = self.get_env(agent_ctx)
355
+ try:
356
+ process_ids = await env.process_manager.list_processes()
357
+ if not process_ids:
358
+ return {"processes": [], "count": 0, "message": "No active processes"}
359
+
360
+ processes = []
361
+ for process_id in process_ids:
362
+ try:
363
+ info = await env.process_manager.get_process_info(process_id)
364
+ processes.append({
365
+ "process_id": process_id,
366
+ "command": info["command"],
367
+ "args": info.get("args", []),
368
+ "cwd": info.get("cwd"),
369
+ "is_running": info.get("is_running", False),
370
+ "exit_code": info.get("exit_code"),
371
+ "created_at": info.get("created_at"),
372
+ })
373
+ except Exception as e: # noqa: BLE001
374
+ processes.append({
375
+ "process_id": process_id,
376
+ "error": f"Error getting info: {e}",
377
+ })
378
+
379
+ return {"processes": processes, "count": len(processes)}
380
+ except Exception as e: # noqa: BLE001
381
+ return {"error": f"Error listing processes: {e}"}
@@ -0,0 +1,11 @@
1
+ """File edit AI tools."""
2
+
3
+ from .file_edit import EditParams, edit_file_tool, edit_tool, replace_content
4
+
5
+
6
+ __all__ = [
7
+ "EditParams",
8
+ "edit_file_tool",
9
+ "edit_tool",
10
+ "replace_content",
11
+ ]