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,212 @@
1
+ """Statement-by-statement execution with automatic progress tracking."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import ast
6
+ from dataclasses import dataclass
7
+ import inspect
8
+ import time
9
+ from typing import TYPE_CHECKING, Any
10
+
11
+ import anyio
12
+
13
+
14
+ if TYPE_CHECKING:
15
+ from collections.abc import AsyncIterator, Awaitable, Callable
16
+
17
+
18
+ @dataclass
19
+ class ProgressInfo:
20
+ """Information about code execution progress."""
21
+
22
+ current: float
23
+ """Current progress value."""
24
+
25
+ total: float
26
+ """Total progress value."""
27
+
28
+ message: str
29
+ """Progress message describing current operation."""
30
+
31
+
32
+ def count_statements(code: str) -> int:
33
+ """Count total statements in the code."""
34
+ try:
35
+ tree = ast.parse(code)
36
+ return len(tree.body)
37
+ except SyntaxError:
38
+ return 0
39
+
40
+
41
+ class ProgressTrackingExecutor:
42
+ """Execute Python code statement-by-statement with automatic progress reporting."""
43
+
44
+ def __init__(
45
+ self,
46
+ progress_callback: Callable[[ProgressInfo], Awaitable[Any]] | None = None,
47
+ step_delay: float = 0.01,
48
+ ) -> None:
49
+ """Initialize executor.
50
+
51
+ Args:
52
+ progress_callback: Optional callback for progress reporting
53
+ step_delay: Delay between statement executions (for async behavior)
54
+ """
55
+ self.globals: dict[str, Any] = {"__builtins__": __builtins__}
56
+ self.locals: dict[str, Any] = {}
57
+ self.progress_callback = progress_callback
58
+ self.step_delay = step_delay
59
+ self.total_statements = 0
60
+ self.current_statement = 0
61
+ self.start_time: float | None = None
62
+
63
+ def update_namespace(self, namespace: dict[str, Any]) -> None:
64
+ """Update the execution namespace with additional globals."""
65
+ self.globals.update(namespace)
66
+
67
+ async def execute_with_progress(self, code: str) -> Any:
68
+ """Execute code with automatic progress reporting.
69
+
70
+ Args:
71
+ code: Python source code to execute
72
+
73
+ Returns:
74
+ Result of code execution
75
+ """
76
+ self.total_statements = count_statements(code)
77
+ self.current_statement = 0
78
+ self.start_time = time.time()
79
+
80
+ if self.total_statements == 0:
81
+ return "No statements to execute"
82
+
83
+ try:
84
+ tree = ast.parse(code)
85
+
86
+ for i, node in enumerate(tree.body):
87
+ self.current_statement = i + 1
88
+
89
+ # Report progress if callback available
90
+ if self.progress_callback:
91
+ node_type = type(node).__name__
92
+ message = f"Executing {node_type.lower()} statement"
93
+
94
+ progress_info = ProgressInfo(
95
+ current=float(self.current_statement),
96
+ total=float(self.total_statements),
97
+ message=message,
98
+ )
99
+ await self.progress_callback(progress_info)
100
+
101
+ # Execute the statement
102
+ compiled = compile(
103
+ ast.Module(body=[node], type_ignores=[]), f"<statement_{i}>", "exec"
104
+ )
105
+ exec(compiled, self.globals, self.locals)
106
+
107
+ # Small delay for async behavior
108
+ if self.step_delay > 0:
109
+ await anyio.sleep(self.step_delay)
110
+
111
+ # Try to get result from main() function or return success
112
+ if "main" in self.locals and callable(self.locals["main"]):
113
+ result = self.locals["main"]()
114
+ if inspect.iscoroutine(result):
115
+ result = await result
116
+ return result
117
+ except Exception as e:
118
+ # Report error with current progress
119
+ if self.progress_callback:
120
+ progress_info = ProgressInfo(
121
+ current=float(self.current_statement),
122
+ total=float(self.total_statements),
123
+ message=f"Error: {str(e)[:50]}...",
124
+ )
125
+ await self.progress_callback(progress_info)
126
+ raise
127
+ else:
128
+ return "Code executed successfully"
129
+
130
+ async def execute_statements(self, code: str) -> AsyncIterator[tuple[str, dict[str, Any]]]:
131
+ """Execute code statement by statement, yielding each executed statement.
132
+
133
+ This method is useful for external progress tracking or debugging.
134
+
135
+ Yields:
136
+ (statement_source, metadata) tuples
137
+ """
138
+ self.total_statements = count_statements(code)
139
+ self.current_statement = 0
140
+ self.start_time = time.time()
141
+
142
+ if self.total_statements == 0:
143
+ return
144
+
145
+ tree = ast.parse(code)
146
+ for i, node in enumerate(tree.body):
147
+ self.current_statement = i + 1
148
+ statement_code = ast.unparse(node)
149
+ # Create metadata
150
+ elapsed_time = time.time() - (self.start_time or time.time())
151
+ metadata = {
152
+ "statement_index": i,
153
+ "total_statements": self.total_statements,
154
+ "node_type": type(node).__name__,
155
+ "elapsed_seconds": elapsed_time,
156
+ "locals_before": dict(self.locals),
157
+ }
158
+
159
+ # Execute the statement
160
+ try:
161
+ compiled = compile(
162
+ ast.Module(body=[node], type_ignores=[]), f"<statement_{i}>", "exec"
163
+ )
164
+ exec(compiled, self.globals, self.locals)
165
+ metadata["status"] = "success"
166
+ except Exception as e: # noqa: BLE001
167
+ metadata["status"] = "error"
168
+ metadata["error"] = str(e)
169
+
170
+ metadata["locals_after"] = dict(self.locals)
171
+ yield statement_code, metadata
172
+
173
+ if self.step_delay > 0:
174
+ await anyio.sleep(self.step_delay)
175
+
176
+
177
+ if __name__ == "__main__":
178
+ from pydantic_ai import RunContext # noqa: TC002
179
+
180
+ from agentpool import log
181
+ from agentpool.agents import AgentContext # noqa: TC001
182
+
183
+ log.configure_logging()
184
+ code = """
185
+ x = 10
186
+ y = 20
187
+ z = x + y
188
+ print(f"Result: {z}")
189
+ for i in range(3):
190
+ print(f"Loop: {i}")
191
+ """
192
+
193
+ async def run_me(run_context: RunContext, ctx: AgentContext) -> str:
194
+ """Test function using the unified progress system."""
195
+ executor = ProgressTrackingExecutor(step_delay=0.5)
196
+ results = []
197
+ async for x in executor.execute_statements(code):
198
+ await ctx.events.custom(x)
199
+ results.append(x[0])
200
+
201
+ return f"Code executed successfully. Executed {len(results)} statements."
202
+
203
+ async def main() -> None:
204
+ from agentpool.delegation import AgentPool
205
+
206
+ async with AgentPool() as pool:
207
+ agent = await pool.add_agent("test-agent", model="openai:gpt-5-nano", tools=[run_me])
208
+ print("🚀 Testing unified progress system...")
209
+ async for event in agent.run_stream("Run run_me and show progress."):
210
+ print(f"Event: {event}")
211
+
212
+ anyio.run(main)
@@ -0,0 +1,150 @@
1
+ """Meta-resource provider that exposes tools through Python execution."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from functools import partial
6
+ import inspect
7
+ from typing import TYPE_CHECKING, Any
8
+
9
+ from agentpool.agents.context import AgentContext # noqa: TC001
10
+ from agentpool.resource_providers import AggregatingResourceProvider
11
+ from agentpool.resource_providers.codemode.default_prompt import USAGE
12
+ from agentpool.resource_providers.codemode.helpers import (
13
+ tools_to_codegen,
14
+ validate_code,
15
+ )
16
+ from agentpool_toolsets.fsspec_toolset.toolset import FSSpecTools
17
+
18
+
19
+ if TYPE_CHECKING:
20
+ from schemez import ToolsetCodeGenerator
21
+
22
+ from agentpool.resource_providers import ResourceProvider
23
+ from agentpool.tools.base import Tool
24
+
25
+
26
+ class CodeModeResourceProvider(AggregatingResourceProvider):
27
+ """Provider that wraps tools into a single Python execution environment."""
28
+
29
+ def __init__(
30
+ self,
31
+ providers: list[ResourceProvider],
32
+ name: str = "meta_tools",
33
+ include_docstrings: bool = True,
34
+ usage_notes: str = USAGE,
35
+ ) -> None:
36
+ """Initialize meta provider.
37
+
38
+ Args:
39
+ providers: Providers whose tools to wrap
40
+ name: Provider name
41
+ include_docstrings: Include function docstrings in documentation
42
+ usage_notes: Usage notes for the codemode tool
43
+ """
44
+ super().__init__(providers=providers, name=name)
45
+ self.include_docstrings = include_docstrings
46
+ self._cached_tool: Tool | None = None
47
+ self.usage_notes = usage_notes
48
+
49
+ async def get_tools(self) -> list[Tool]:
50
+ """Return single meta-tool for Python execution with available tools."""
51
+ # Always generate fresh toolset to reflect current tools
52
+ toolset_generator = await self._get_code_generator()
53
+ desc = toolset_generator.generate_tool_description()
54
+ desc += self.usage_notes
55
+
56
+ if self._cached_tool is None:
57
+ # Create a closure that captures self but isn't a bound method
58
+ async def execute_tool(ctx: AgentContext, python_code: str) -> Any:
59
+ """These docstings are overriden by description_override."""
60
+ return await self.execute(ctx, python_code)
61
+
62
+ self._cached_tool = self.create_tool(execute_tool, description_override=desc)
63
+ else:
64
+ # Update the description on existing cached tool
65
+ self._cached_tool.description = desc
66
+
67
+ return [self._cached_tool]
68
+
69
+ async def execute(self, ctx: AgentContext, python_code: str) -> Any: # noqa: D417
70
+ """Execute Python code with all wrapped tools available as functions.
71
+
72
+ Args:
73
+ python_code: Python code to execute
74
+
75
+ Returns:
76
+ Result of the last expression or explicit return value
77
+ """
78
+ toolset_generator = await self._get_code_generator()
79
+ namespace = toolset_generator.generate_execution_namespace()
80
+
81
+ # Wrap namespace callables to inject AgentContext
82
+ for value in namespace.values():
83
+ if callable(value) and hasattr(value, "callable"):
84
+ # It's a NamespaceCallable - wrap its underlying callable with ctx
85
+ original_callable = value.callable
86
+ if "agent_ctx" in inspect.signature(original_callable).parameters:
87
+ value.callable = partial(original_callable, agent_ctx=ctx)
88
+
89
+ # async def report_progress(current: int, total: int, message: str = ""):
90
+ # """Report progress during code execution."""
91
+ # await ctx.report_progress(current, total, message)
92
+
93
+ # namespace["report_progress"] = NamespaceCallable(report_progress)
94
+
95
+ validate_code(python_code)
96
+ try:
97
+ exec(python_code, namespace)
98
+ result = await namespace["main"]()
99
+ # Handle edge cases with coroutines and return values
100
+ if inspect.iscoroutine(result):
101
+ result = await result
102
+ if not result: # in order to not confuse the model, return a success message.
103
+ return "Code executed successfully"
104
+ except Exception as e: # noqa: BLE001
105
+ return f"Error executing code: {e!s}"
106
+ else:
107
+ return result
108
+
109
+ def invalidate_cache(self) -> None:
110
+ """Invalidate cached tool when providers change."""
111
+ self._cached_tool = None
112
+ # Note: We no longer cache the toolset generator, so no need to clear it
113
+
114
+ async def _get_code_generator(self) -> ToolsetCodeGenerator:
115
+ """Get fresh toolset generator with current tools."""
116
+ tools = await super().get_tools()
117
+ return tools_to_codegen(tools=tools, include_docstrings=self.include_docstrings)
118
+
119
+
120
+ if __name__ == "__main__":
121
+ import anyio
122
+
123
+ from agentpool import Agent
124
+ from agentpool.delegation.pool import AgentPool
125
+
126
+ static_provider = FSSpecTools()
127
+ provider = CodeModeResourceProvider([static_provider])
128
+
129
+ async def main() -> None:
130
+ print("Available tools:")
131
+ for tool in await provider.get_tools():
132
+ print(f"- {tool.name}: {tool.description[:100]}...")
133
+
134
+ async with AgentPool() as pool:
135
+ agent: Agent[None, str] = Agent(
136
+ model="openai:gpt-5-nano", event_handlers=["simple"], retries=1
137
+ )
138
+ pool.register("test_agent", agent)
139
+ async with agent:
140
+ agent.tools.add_provider(provider)
141
+ prompt = (
142
+ "Call list_directory with path='.'. "
143
+ "Write: async def main(): "
144
+ "result = await list_directory(path='.'); "
145
+ "return result"
146
+ )
147
+ result = await agent.run(prompt)
148
+ print(f"Result: {result}")
149
+
150
+ anyio.run(main)
@@ -0,0 +1,143 @@
1
+ """Code execution provider with secure tool isolation via FastAPI server."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import TYPE_CHECKING, Any, Self
7
+
8
+ from agentpool.log import get_logger
9
+
10
+
11
+ if TYPE_CHECKING:
12
+ from collections.abc import Sequence
13
+ from types import TracebackType
14
+
15
+ from exxec.base import ExecutionEnvironment
16
+ from exxec.configs import ExecutionEnvironmentConfig
17
+ from schemez import ToolsetCodeGenerator
18
+
19
+ from agentpool.tools.base import Tool
20
+
21
+
22
+ logger = get_logger(__name__)
23
+
24
+
25
+ @dataclass
26
+ class RemoteMCPExecutor:
27
+ """Provides secure code execution with tool access.
28
+
29
+ Code Generation mode (ctx-zip style):
30
+ - Tool functions are generated as Python files inside sandbox
31
+ - User code imports tools directly, no HTTP server needed
32
+ - Better for cloud sandboxes (E2B, etc.) that can't reach localhost
33
+ """
34
+
35
+ toolset_generator: ToolsetCodeGenerator
36
+ """Code generator for tools."""
37
+
38
+ execution_env: ExecutionEnvironment
39
+ """Execution environment for running code."""
40
+
41
+ use_code_generation: bool = False
42
+ """If True, use code generation approach instead of HTTP server."""
43
+
44
+ @classmethod
45
+ def from_tools(
46
+ cls,
47
+ tools: Sequence[Tool],
48
+ env_config: ExecutionEnvironmentConfig,
49
+ include_docstrings: bool = True,
50
+ ) -> RemoteMCPExecutor:
51
+ """Create provider from tools and environment configuration.
52
+
53
+ Args:
54
+ tools: Tools to make available for code execution
55
+ env_config: Execution environment configuration
56
+ include_docstrings: Include function docstrings in documentation
57
+
58
+ Returns:
59
+ RemoteMCPExecutor instance
60
+ """
61
+ from agentpool.resource_providers.codemode.helpers import tools_to_codegen
62
+
63
+ toolset_gen = tools_to_codegen(tools, include_docstrings)
64
+ execution_env = env_config.get_provider()
65
+ return cls(toolset_gen, execution_env)
66
+
67
+ def get_tool_description(self) -> str:
68
+ """Get comprehensive description of available tools."""
69
+ # For code generation mode, provide import-based usage instructions
70
+ tool_names = [gen.name for gen in self.toolset_generator.generators]
71
+ desc = self.toolset_generator.generate_tool_description()
72
+ desc += "Usage:\n"
73
+ for name in tool_names:
74
+ desc += f" from tools.{name} import {name}\n"
75
+ desc += f" result = await {name}(...)\n"
76
+ return desc
77
+
78
+ async def execute_code(self, code: str) -> Any:
79
+ """Execute code with tools available.
80
+
81
+ Args:
82
+ code: Python code to execute
83
+
84
+ Returns:
85
+ Execution result from the environment
86
+ """
87
+ return await self.execution_env.execute(code)
88
+
89
+ async def __aenter__(self) -> Self:
90
+ """Async context manager entry."""
91
+ await self.execution_env.__aenter__()
92
+ return self
93
+
94
+ async def __aexit__(
95
+ self,
96
+ exc_type: type[BaseException] | None,
97
+ exc_val: BaseException | None,
98
+ exc_tb: TracebackType | None,
99
+ ) -> None:
100
+ """Async context manager exit."""
101
+ return await self.execution_env.__aexit__(exc_type, exc_val, exc_tb)
102
+
103
+
104
+ if __name__ == "__main__":
105
+ import anyio
106
+ from exxec.configs import LocalExecutionEnvironmentConfig
107
+
108
+ from agentpool.tools.base import Tool
109
+
110
+ def add_numbers(x: int, y: int) -> int:
111
+ """Add two numbers."""
112
+ return x + y
113
+
114
+ def multiply_numbers(x: int, y: int) -> int:
115
+ """Multiply two numbers."""
116
+ return x * y
117
+
118
+ async def main() -> None:
119
+ print("\n=== Code Generation Approach (ctx-zip style) ===")
120
+ tools = [Tool.from_callable(add_numbers), Tool.from_callable(multiply_numbers)]
121
+ config = LocalExecutionEnvironmentConfig() # Could be E2B, etc.
122
+ provider = RemoteMCPExecutor.from_tools(tools, config)
123
+ async with provider:
124
+ print("Tool description:")
125
+ print(provider.get_tool_description())
126
+ print("\nExecuting code with direct imports...")
127
+
128
+ # Code that imports tools directly (no HTTP calls)
129
+ code = """
130
+ from tools.add_numbers import add_numbers
131
+ from tools.multiply_numbers import multiply_numbers
132
+
133
+ # Direct function calls - no HTTP server needed!
134
+ result1 = add_numbers(5, 3)
135
+ result2 = multiply_numbers(4, 7)
136
+
137
+ _result = {"addition": result1, "multiplication": result2}
138
+ print(f"Addition: {result1}, Multiplication: {result2}")
139
+ """
140
+ result = await provider.execute_code(code)
141
+ print(f"Result: {result.result}")
142
+
143
+ anyio.run(main)
@@ -0,0 +1,171 @@
1
+ """Secure code execution provider using isolated execution environments."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import asyncio
6
+ import contextlib
7
+ from typing import TYPE_CHECKING, Any, Self
8
+
9
+ from exxec.configs import LocalExecutionEnvironmentConfig
10
+
11
+ from agentpool.agents.context import AgentContext # noqa: TC001
12
+ from agentpool.log import get_logger
13
+ from agentpool.resource_providers.codemode.code_executor import (
14
+ RemoteCodeExecutor,
15
+ )
16
+ from agentpool.resource_providers.codemode.default_prompt import USAGE
17
+ from agentpool.resource_providers.codemode.helpers import validate_code
18
+ from agentpool.resource_providers.codemode.provider import (
19
+ CodeModeResourceProvider,
20
+ )
21
+ from agentpool.tools.base import Tool
22
+
23
+
24
+ logger = get_logger(__name__)
25
+
26
+ if TYPE_CHECKING:
27
+ from types import TracebackType
28
+
29
+ from exxec.configs import ExecutionEnvironmentConfig
30
+
31
+ from agentpool.resource_providers import ResourceProvider
32
+
33
+
34
+ PROGRESS_HELPER = """
35
+ async def report_progress(current: int, total: int, message: str = "") -> None:
36
+ '''Report progress during execution'''
37
+ percentage = (current / total) * 100 if total > 0 else 0
38
+ print(f"Progress: {percentage:.1f}% ({current}/{total}) {message}")
39
+ """
40
+
41
+
42
+ class RemoteCodeModeResourceProvider(CodeModeResourceProvider):
43
+ """Provider that executes code in secure isolation with tool access via server."""
44
+
45
+ def __init__(
46
+ self,
47
+ providers: list[ResourceProvider],
48
+ execution_config: ExecutionEnvironmentConfig | None = None,
49
+ name: str = "secure_code_executor",
50
+ include_docstrings: bool = True,
51
+ usage_notes: str = USAGE,
52
+ server_host: str = "localhost",
53
+ server_port: int = 8000,
54
+ ) -> None:
55
+ """Initialize secure code execution provider.
56
+
57
+ Args:
58
+ providers: Providers whose tools to expose
59
+ execution_config: Execution environment configuration
60
+ name: Provider name
61
+ include_docstrings: Include function docstrings in documentation
62
+ usage_notes: Usage notes for the provider
63
+ server_host: Host for tool server
64
+ server_port: Port for tool server
65
+ """
66
+ super().__init__(
67
+ providers=providers,
68
+ name=name,
69
+ include_docstrings=include_docstrings,
70
+ usage_notes=usage_notes,
71
+ )
72
+ self.execution_config = execution_config or LocalExecutionEnvironmentConfig()
73
+ self.server_host = server_host
74
+ self.server_port = server_port
75
+ self._code_executor: RemoteCodeExecutor | None = None
76
+ self._provider_lock = asyncio.Lock()
77
+
78
+ async def execute(self, ctx: AgentContext, python_code: str) -> Any: # noqa: D417
79
+ """Execute Python code in secure environment with tools available via HTTP.
80
+
81
+ Args:
82
+ python_code: Python code to execute
83
+
84
+ Returns:
85
+ Result of the code execution
86
+ """
87
+ code_provider = await self._get_code_executor()
88
+ logger.info("Validating code", code=python_code)
89
+ validate_code(python_code)
90
+ full_code = f"{PROGRESS_HELPER}\n\n{python_code}"
91
+ logger.info("Complete code", code=full_code)
92
+ try:
93
+ result = await code_provider.execution_env.execute(full_code)
94
+ if result.success:
95
+ logger.info("Code executed successfully")
96
+ if result.result is None:
97
+ return "Code executed successfully"
98
+ return result.result
99
+ except Exception as e: # noqa: BLE001
100
+ return f"Error in secure execution: {e!s}"
101
+ else:
102
+ return f"Error executing code: {result.error}"
103
+
104
+ async def _get_code_executor(self) -> RemoteCodeExecutor:
105
+ """Get cached code execution provider with thread-safe initialization."""
106
+ async with self._provider_lock:
107
+ if self._code_executor is None:
108
+ all_tools = await super().get_tools()
109
+ self._code_executor = RemoteCodeExecutor.from_tools(
110
+ all_tools,
111
+ self.execution_config,
112
+ server_host=self.server_host,
113
+ server_port=self.server_port,
114
+ include_docstrings=self.include_docstrings,
115
+ )
116
+ # Initialize the provider and start server
117
+ await self._code_executor.__aenter__()
118
+
119
+ return self._code_executor
120
+
121
+ async def __aenter__(self) -> Self:
122
+ """Async context manager entry."""
123
+ return self
124
+
125
+ async def __aexit__(
126
+ self,
127
+ exc_type: type[BaseException] | None,
128
+ exc_val: BaseException | None,
129
+ exc_tb: TracebackType | None,
130
+ ) -> None:
131
+ """Async context manager exit."""
132
+ if self._code_executor is not None:
133
+ with contextlib.suppress(Exception):
134
+ await self._code_executor.__aexit__(exc_type, exc_val, exc_tb)
135
+ self._code_executor = None
136
+
137
+
138
+ if __name__ == "__main__":
139
+ import webbrowser
140
+
141
+ import anyio
142
+ from exxec.configs import LocalExecutionEnvironmentConfig
143
+
144
+ from agentpool import Agent, log
145
+ from agentpool.resource_providers import StaticResourceProvider
146
+
147
+ log.configure_logging()
148
+
149
+ def open_browser(url: str) -> bool:
150
+ """Use this to open url in the default browser."""
151
+ return webbrowser.open(url)
152
+
153
+ async def main() -> None:
154
+ tools = [Tool.from_callable(open_browser)]
155
+ static_provider = StaticResourceProvider(tools=tools)
156
+ config = LocalExecutionEnvironmentConfig(timeout=30.0)
157
+ provider = RemoteCodeModeResourceProvider(
158
+ providers=[static_provider],
159
+ execution_config=config,
160
+ server_port=9999,
161
+ )
162
+ print("Available tools:")
163
+ for tool in await provider.get_tools():
164
+ print(f"- {tool.name}: {tool.description}")
165
+
166
+ async with Agent(model="anthropic:claude-haiku-4-5") as agent:
167
+ agent.tools.add_provider(provider)
168
+ result = await agent.run("open google.com in the browser.")
169
+ print(f"Result: {result}")
170
+
171
+ anyio.run(main)