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
acp/filesystem.py ADDED
@@ -0,0 +1,524 @@
1
+ """Filesystem implementation for ACP (Agent Communication Protocol) sessions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import logging
6
+ from pathlib import Path
7
+ from typing import TYPE_CHECKING, Any, Literal, Required, overload
8
+
9
+ from anyenv import get_os_command_provider
10
+ from fsspec.asyn import sync_wrapper
11
+ from fsspec.spec import AbstractBufferedFile
12
+ from upathtools.filesystems.base import BaseAsyncFileSystem, BaseUPath, FileInfo
13
+
14
+ from acp.acp_requests import ACPRequests
15
+ from acp.notifications import ACPNotifications
16
+ from agentpool.mime_utils import guess_type, is_text_mime
17
+
18
+
19
+ class AcpInfo(FileInfo, total=False):
20
+ """Info dict for ACP filesystem paths."""
21
+
22
+ islink: bool
23
+ timestamp: str | None
24
+ permissions: str | None
25
+ size: Required[int]
26
+
27
+
28
+ if TYPE_CHECKING:
29
+ from acp.client.protocol import Client
30
+
31
+
32
+ logger = logging.getLogger(__name__)
33
+
34
+
35
+ class ACPFile(AbstractBufferedFile): # type: ignore[misc]
36
+ """File-like object for ACP filesystem operations."""
37
+
38
+ def __init__(self, fs: ACPFileSystem, path: str, mode: str = "rb", **kwargs: Any) -> None:
39
+ """Initialize ACP file handle."""
40
+ super().__init__(fs, path, mode, **kwargs)
41
+ self._content: bytes | None = None
42
+ self.forced = False
43
+ self.fs = fs # assign again here just for typing
44
+
45
+ def _fetch_range(self, start: int | None, end: int | None) -> bytes:
46
+ """Fetch byte range from file (sync wrapper)."""
47
+ if self._content is None:
48
+ # Run the async operation in the event loop
49
+ self._content = self.fs.cat_file(self.path) # pyright: ignore[reportAttributeAccessIssue]
50
+ assert self._content
51
+
52
+ if start is None and end is None:
53
+ return self._content
54
+ return self._content[start:end]
55
+
56
+ def _upload_chunk(self, final: bool = False) -> bool:
57
+ """Upload buffered data to file (sync wrapper)."""
58
+ if final and self.buffer:
59
+ content = self.buffer.getvalue()
60
+ if isinstance(content, bytes):
61
+ content = content.decode("utf-8")
62
+ # Run the async operation in the event loop
63
+ self.fs.put_file(self.path, content)
64
+ return True
65
+
66
+
67
+ class ACPPath(BaseUPath[AcpInfo]):
68
+ """Path for ACP filesystem."""
69
+
70
+ __slots__ = ()
71
+
72
+
73
+ class ACPFileSystem(BaseAsyncFileSystem[ACPPath, AcpInfo]):
74
+ """Async filesystem for ACP sessions."""
75
+
76
+ protocol = "acp"
77
+ sep = "/"
78
+ upath_cls = ACPPath
79
+
80
+ def __init__(
81
+ self,
82
+ client: Client,
83
+ session_id: str,
84
+ *,
85
+ use_cli_find: bool = True,
86
+ **kwargs: Any,
87
+ ) -> None:
88
+ """Initialize ACP filesystem.
89
+
90
+ Args:
91
+ client: ACP client for operations
92
+ session_id: Session identifier
93
+ use_cli_find: Use CLI find command for _find/_glob operations.
94
+ When True (default), uses a single `find` command for recursive
95
+ file discovery, which is much more efficient over the protocol
96
+ barrier than walking the tree with multiple ls calls.
97
+ **kwargs: Additional filesystem options
98
+ """
99
+ super().__init__(**kwargs)
100
+ self.client = client
101
+ self.session_id = session_id
102
+ self.requests = ACPRequests(client, session_id)
103
+ self.notifications = ACPNotifications(client, session_id)
104
+ self.command_provider = get_os_command_provider()
105
+ self.use_cli_find = use_cli_find
106
+
107
+ async def _cat_file(
108
+ self, path: str, start: int | None = None, end: int | None = None, **kwargs: Any
109
+ ) -> bytes:
110
+ """Read file content via ACP session.
111
+
112
+ Args:
113
+ path: File path to read
114
+ start: Start byte position (not supported by ACP)
115
+ end: End byte position (not supported by ACP)
116
+ **kwargs: Additional options
117
+
118
+ Returns:
119
+ File content as bytes
120
+
121
+ Raises:
122
+ NotImplementedError: If byte range is requested (ACP doesn't support
123
+ partial reads)
124
+ """
125
+ if start is not None or end is not None:
126
+ msg = "ACP filesystem does not support byte range reads"
127
+ raise NotImplementedError(msg)
128
+
129
+ mime_type = guess_type(path)
130
+
131
+ if is_text_mime(mime_type):
132
+ # Text file - use read_text_file directly
133
+ try:
134
+ content = await self.requests.read_text_file(path)
135
+ return content.encode("utf-8")
136
+ except Exception as e:
137
+ raise FileNotFoundError(f"Could not read file {path}: {e}") from e
138
+
139
+ # Binary file - use base64 encoding via terminal command
140
+ try:
141
+ b64_cmd = self.command_provider.get_command("base64_encode")
142
+ cmd_str = b64_cmd.create_command(path)
143
+ output, exit_code = await self.requests.run_command(cmd_str, timeout_seconds=30)
144
+
145
+ if exit_code != 0:
146
+ msg = f"Could not read binary file {path}: {output}"
147
+ raise FileNotFoundError(msg) # noqa: TRY301
148
+
149
+ return b64_cmd.parse_command(output)
150
+ except Exception as e:
151
+ msg = f"Could not read file {path}: {e}"
152
+ raise FileNotFoundError(msg) from e
153
+
154
+ cat_file = sync_wrapper(_cat_file) # pyright: ignore[reportAssignmentType]
155
+
156
+ async def _put_file(self, path: str, content: str | bytes, **kwargs: Any) -> None:
157
+ """Write file content via ACP session.
158
+
159
+ Args:
160
+ path: File path to write
161
+ content: Content to write (string or bytes)
162
+ **kwargs: Additional options
163
+ """
164
+ if isinstance(content, bytes):
165
+ content = content.decode("utf-8")
166
+
167
+ try:
168
+ await self.requests.write_text_file(path, content)
169
+ except Exception as e:
170
+ msg = f"Could not write file {path}: {e}"
171
+ raise OSError(msg) from e
172
+
173
+ put_file = sync_wrapper(_put_file)
174
+
175
+ async def _pipe_file(self, path: str, data: bytes, **kwargs: Any) -> None:
176
+ """Write bytes directly to a file path.
177
+
178
+ This is the fsspec standard method for writing data to a file.
179
+ Wraps _put_file for compatibility.
180
+
181
+ Args:
182
+ path: File path to write
183
+ data: Bytes to write
184
+ **kwargs: Additional options
185
+ """
186
+ await self._put_file(path, data, **kwargs)
187
+
188
+ pipe_file = sync_wrapper(_pipe_file)
189
+
190
+ @overload
191
+ async def _ls(self, path: str, detail: Literal[True] = ..., **kwargs: Any) -> list[AcpInfo]: ...
192
+
193
+ @overload
194
+ async def _ls(self, path: str, detail: Literal[False], **kwargs: Any) -> list[str]: ...
195
+
196
+ async def _ls(self, path: str, detail: bool = True, **kwargs: Any) -> list[AcpInfo] | list[str]:
197
+ """List directory contents via terminal command.
198
+
199
+ Uses 'ls -la' command through ACP terminal to get directory listings.
200
+
201
+ Args:
202
+ path: Directory path to list
203
+ detail: Whether to return detailed file information
204
+ **kwargs: Additional options
205
+
206
+ Returns:
207
+ List of file information dictionaries or file names
208
+ """
209
+ # Use OS-specific command to list directory contents
210
+ list_cmd = self.command_provider.get_command("list_directory")
211
+ ls_cmd = list_cmd.create_command(path)
212
+
213
+ try:
214
+ output, exit_code = await self.requests.run_command(ls_cmd, timeout_seconds=10)
215
+
216
+ if exit_code != 0:
217
+ msg = f"Error listing directory {path!r}: {output}"
218
+ raise FileNotFoundError(msg) # noqa: TRY301
219
+
220
+ result = list_cmd.parse_command(output, path)
221
+ if detail:
222
+ return [
223
+ AcpInfo(
224
+ name=item.path, # fsspec expects full path in 'name'
225
+ type="file" if item.type == "link" else item.type,
226
+ size=item.size,
227
+ islink=item.type == "link",
228
+ timestamp=item.timestamp,
229
+ permissions=item.permissions,
230
+ )
231
+ for item in result
232
+ ]
233
+ return [item.path for item in result] # Return full paths for consistency
234
+
235
+ except Exception as e:
236
+ msg = f"Could not list directory {path}: {e}"
237
+ raise FileNotFoundError(msg) from e
238
+
239
+ ls = sync_wrapper(_ls)
240
+
241
+ async def _info(self, path: str, **kwargs: Any) -> AcpInfo:
242
+ """Get file information via stat command.
243
+
244
+ Args:
245
+ path: File path to get info for
246
+ **kwargs: Additional options
247
+
248
+ Returns:
249
+ File information dictionary
250
+ """
251
+ info_cmd = self.command_provider.get_command("file_info")
252
+ stat_cmd = info_cmd.create_command(path)
253
+
254
+ try:
255
+ output, exit_code = await self.requests.run_command(stat_cmd, timeout_seconds=5)
256
+
257
+ if exit_code != 0:
258
+ raise FileNotFoundError(f"File not found: {path}")
259
+ file_info = info_cmd.parse_command(output.strip(), path)
260
+ return AcpInfo(
261
+ name=file_info.path,
262
+ type="file" if file_info.type == "link" else file_info.type,
263
+ size=file_info.size,
264
+ islink=file_info.type == "link",
265
+ timestamp=file_info.timestamp,
266
+ permissions=file_info.permissions,
267
+ )
268
+
269
+ except (OSError, ValueError) as e:
270
+ # Fallback: try to get basic info from ls
271
+ try:
272
+ ls_result = await self._ls(str(Path(path).parent), detail=True)
273
+ filename = Path(path).name
274
+
275
+ for item in ls_result:
276
+ if Path(item["name"]).name == filename:
277
+ return AcpInfo(
278
+ name=path, # fsspec expects full path in 'name'
279
+ type=item["type"],
280
+ size=item["size"],
281
+ islink=item.get("islink", False),
282
+ timestamp=item.get("timestamp"),
283
+ permissions=item.get("permissions"),
284
+ )
285
+
286
+ raise FileNotFoundError(f"File not found: {path}")
287
+ except (OSError, ValueError):
288
+ msg = f"Could not get file info for {path}: {e}"
289
+ raise FileNotFoundError(msg) from e
290
+
291
+ info = sync_wrapper(_info)
292
+
293
+ async def _exists(self, path: str, **kwargs: Any) -> bool:
294
+ """Check if file exists via test command.
295
+
296
+ Args:
297
+ path: File path to check
298
+ **kwargs: Additional options
299
+
300
+ Returns:
301
+ True if file exists, False otherwise
302
+ """
303
+ exists_cmd = self.command_provider.get_command("exists")
304
+ test_cmd = exists_cmd.create_command(path)
305
+
306
+ try:
307
+ output, exit_code = await self.requests.run_command(test_cmd, timeout_seconds=5)
308
+ except (OSError, ValueError):
309
+ return False
310
+ else:
311
+ return exists_cmd.parse_command(output, exit_code if exit_code is not None else 1)
312
+
313
+ exists = sync_wrapper(_exists) # pyright: ignore[reportAssignmentType]
314
+
315
+ async def _isdir(self, path: str, **kwargs: Any) -> bool:
316
+ """Check if path is a directory via test command.
317
+
318
+ Args:
319
+ path: Path to check
320
+ **kwargs: Additional options
321
+
322
+ Returns:
323
+ True if path is a directory, False otherwise
324
+ """
325
+ isdir_cmd = self.command_provider.get_command("is_directory")
326
+ test_cmd = isdir_cmd.create_command(path)
327
+
328
+ try:
329
+ output, exit_code = await self.requests.run_command(test_cmd, timeout_seconds=5)
330
+ except (OSError, ValueError):
331
+ return False
332
+ else:
333
+ return isdir_cmd.parse_command(output, exit_code if exit_code is not None else 1)
334
+
335
+ isdir = sync_wrapper(_isdir)
336
+
337
+ async def _isfile(self, path: str, **kwargs: Any) -> bool:
338
+ """Check if path is a file via test command.
339
+
340
+ Args:
341
+ path: Path to check
342
+ **kwargs: Additional options
343
+
344
+ Returns:
345
+ True if path is a file, False otherwise
346
+ """
347
+ isfile_cmd = self.command_provider.get_command("is_file")
348
+ test_cmd = isfile_cmd.create_command(path)
349
+
350
+ try:
351
+ output, exit_code = await self.requests.run_command(test_cmd, timeout_seconds=5)
352
+ except (OSError, ValueError):
353
+ return False
354
+ else:
355
+ return isfile_cmd.parse_command(output, exit_code if exit_code is not None else 1)
356
+
357
+ isfile = sync_wrapper(_isfile)
358
+
359
+ async def _makedirs(self, path: str, exist_ok: bool = False, **kwargs: Any) -> None:
360
+ """Create directories via mkdir command.
361
+
362
+ Args:
363
+ path: Directory path to create
364
+ exist_ok: Don't raise error if directory already exists
365
+ **kwargs: Additional options
366
+ """
367
+ create_cmd = self.command_provider.get_command("create_directory")
368
+ mkdir_cmd = create_cmd.create_command(path, parents=exist_ok)
369
+
370
+ try:
371
+ output, exit_code = await self.requests.run_command(mkdir_cmd, timeout_seconds=5)
372
+ success = create_cmd.parse_command(output, exit_code if exit_code is not None else 1)
373
+ if not success:
374
+ msg = f"Error creating directory {path}: {output}"
375
+ raise OSError(msg) # noqa: TRY301
376
+ except Exception as e:
377
+ msg = f"Could not create directory {path}: {e}"
378
+ raise OSError(msg) from e
379
+
380
+ makedirs = sync_wrapper(_makedirs)
381
+
382
+ async def _cp_file(self, path1: str, path2: str, **kwargs: Any) -> None:
383
+ """Copy a file from path1 to path2.
384
+
385
+ Uses CLI cp/copy command for efficiency - single round-trip and
386
+ native binary file support without base64 encoding overhead.
387
+
388
+ Args:
389
+ path1: Source file path
390
+ path2: Destination file path
391
+ **kwargs: Additional options
392
+ """
393
+ copy_cmd = self.command_provider.get_command("copy_path")
394
+ cmd_str = copy_cmd.create_command(path1, path2, recursive=False)
395
+
396
+ try:
397
+ output, exit_code = await self.requests.run_command(cmd_str, timeout_seconds=30)
398
+ success = copy_cmd.parse_command(output, exit_code if exit_code is not None else 1)
399
+ if not success:
400
+ msg = f"Error copying {path1} to {path2}: {output}"
401
+ raise OSError(msg) # noqa: TRY301
402
+ except Exception as e:
403
+ msg = f"Could not copy {path1} to {path2}: {e}"
404
+ raise OSError(msg) from e
405
+
406
+ cp_file = sync_wrapper(_cp_file)
407
+
408
+ async def _rm(self, path: str, recursive: bool = False, **kwargs: Any) -> None:
409
+ """Remove file or directory via rm command.
410
+
411
+ Args:
412
+ path: Path to remove
413
+ recursive: Remove directories recursively
414
+ **kwargs: Additional options
415
+ """
416
+ remove_cmd = self.command_provider.get_command("remove_path")
417
+ rm_cmd = remove_cmd.create_command(path, recursive=recursive)
418
+
419
+ try:
420
+ output, exit_code = await self.requests.run_command(rm_cmd, timeout_seconds=10)
421
+ success = remove_cmd.parse_command(output, exit_code if exit_code is not None else 1)
422
+ if not success:
423
+ msg = f"Error removing {path}: {output}"
424
+ raise OSError(msg) # noqa: TRY301
425
+ except Exception as e:
426
+ msg = f"Could not remove {path}: {e}"
427
+ raise OSError(msg) from e
428
+
429
+ rm = sync_wrapper(_rm)
430
+
431
+ async def _find(
432
+ self,
433
+ path: str,
434
+ maxdepth: int | None = None,
435
+ withdirs: bool = False,
436
+ **kwargs: Any,
437
+ ) -> list[str] | dict[str, AcpInfo]:
438
+ """Find files recursively.
439
+
440
+ When use_cli_find is enabled, uses a single CLI find command instead of
441
+ walking the directory tree with multiple ls calls. This is much more
442
+ efficient over the protocol barrier.
443
+
444
+ Args:
445
+ path: Root path to search from
446
+ maxdepth: Maximum depth to descend (None for unlimited)
447
+ withdirs: Include directories in results
448
+ **kwargs: Additional options (detail=True returns dict with info)
449
+
450
+ Returns:
451
+ List of paths, or dict mapping paths to info if detail=True
452
+ """
453
+ if not self.use_cli_find:
454
+ # Fall back to default fsspec implementation (walks tree with _ls)
455
+ return await super()._find(path, maxdepth=maxdepth, withdirs=withdirs, **kwargs) # type: ignore[no-any-return]
456
+
457
+ detail = kwargs.pop("detail", False)
458
+ stripped = self._strip_protocol(path)
459
+ search_path = stripped if isinstance(stripped, str) else stripped[0]
460
+
461
+ # Determine file_type filter
462
+ file_type: Literal["file", "directory", "all"] = "all" if withdirs else "file"
463
+
464
+ # Use anyenv find command
465
+ find_cmd = self.command_provider.get_command("find")
466
+ cmd_str = find_cmd.create_command(
467
+ search_path, maxdepth=maxdepth, file_type=file_type, with_stats=detail
468
+ )
469
+
470
+ try:
471
+ output, exit_code = await self.requests.run_command(cmd_str, timeout_seconds=60)
472
+
473
+ if exit_code != 0:
474
+ # If find fails, fall back to default implementation
475
+ logger.warning("CLI find failed, falling back to walk: %s", output)
476
+ return await super()._find(path, maxdepth=maxdepth, withdirs=withdirs, **kwargs) # type: ignore[no-any-return]
477
+
478
+ entries = find_cmd.parse_command(output, search_path)
479
+
480
+ if detail:
481
+ # Return dict with info from find output
482
+ return {
483
+ entry.path: AcpInfo(
484
+ name=entry.path,
485
+ type="file" if entry.type == "link" else entry.type,
486
+ size=entry.size,
487
+ islink=entry.type == "link",
488
+ timestamp=entry.timestamp,
489
+ permissions=entry.permissions,
490
+ )
491
+ for entry in entries
492
+ if entry.name not in (".", "..")
493
+ }
494
+ return [entry.path for entry in entries if entry.name not in (".", "..")]
495
+
496
+ except Exception as e: # noqa: BLE001
497
+ logger.warning("CLI find error, falling back to walk: %s", e)
498
+ return await super()._find(path, maxdepth=maxdepth, withdirs=withdirs, **kwargs) # type: ignore[no-any-return]
499
+
500
+ find = sync_wrapper(_find) # pyright: ignore[reportAssignmentType]
501
+
502
+ def open(self, path: str, mode: str = "rb", **kwargs: Any) -> ACPFile:
503
+ """Open file for reading or writing.
504
+
505
+ Args:
506
+ path: File path to open
507
+ mode: File mode ('rb', 'wb', 'ab', 'xb')
508
+ **kwargs: Additional options
509
+
510
+ Returns:
511
+ File-like object
512
+ """
513
+ # Convert text modes to binary modes for fsspec compatibility
514
+ match mode:
515
+ case "r":
516
+ mode = "rb"
517
+ case "w":
518
+ mode = "wb"
519
+ case "a":
520
+ mode = "ab"
521
+ case "x":
522
+ mode = "xb"
523
+
524
+ return ACPFile(self, path, mode, **kwargs)