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,186 @@
1
+ """TTS event handlers for streaming text-to-speech synthesis."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from abc import abstractmethod
6
+ from typing import TYPE_CHECKING, Any, Literal
7
+
8
+ from pydantic_ai import PartDeltaEvent, PartStartEvent, TextPart, TextPartDelta
9
+
10
+
11
+ if TYPE_CHECKING:
12
+ from anyvoice import TTSStream
13
+ from pydantic_ai import RunContext
14
+
15
+ from agentpool.agents.events import RichAgentStreamEvent
16
+
17
+ TTSMode = Literal["sync_sentence", "sync_run", "async_queue", "async_cancel"]
18
+ TTSModel = Literal["tts-1", "tts-1-hd"]
19
+ TTSVoice = Literal["alloy", "echo", "fable", "onyx", "nova", "shimmer"]
20
+
21
+
22
+ class BaseTTSEventHandler:
23
+ """Base TTS event handler with shared event handling logic.
24
+
25
+ This base class handles the common pattern of:
26
+ - Managing TTS stream lifecycle (create, close)
27
+ - Translating pydantic-ai stream events to TTSStream.feed() calls
28
+ - Handling different synchronization modes
29
+
30
+ Subclasses only need to implement _create_stream() with their
31
+ specific provider and session configuration.
32
+ """
33
+
34
+ def __init__(
35
+ self,
36
+ *,
37
+ sample_rate: int = 24000,
38
+ min_text_length: int = 20,
39
+ mode: TTSMode = "sync_run",
40
+ ) -> None:
41
+ self._sample_rate = sample_rate
42
+ self._min_text_length = min_text_length
43
+ self._mode: TTSMode = mode
44
+ self._tts_stream: TTSStream | None = None
45
+
46
+ @abstractmethod
47
+ async def _create_stream(self) -> TTSStream:
48
+ """Create and return a configured TTS stream.
49
+
50
+ Subclasses implement this to create their provider-specific stream.
51
+
52
+ Returns:
53
+ Configured TTSStream instance (not yet entered).
54
+ """
55
+ raise NotImplementedError
56
+
57
+ async def _ensure_stream(self) -> TTSStream:
58
+ """Get or create the TTS stream."""
59
+ if self._tts_stream is None:
60
+ self._tts_stream = await self._create_stream()
61
+ await self._tts_stream.__aenter__()
62
+ return self._tts_stream
63
+
64
+ async def _close_stream(self) -> None:
65
+ """Close the TTS stream if open."""
66
+ if self._tts_stream is not None:
67
+ await self._tts_stream.__aexit__(None, None, None)
68
+ self._tts_stream = None
69
+
70
+ async def __call__(self, ctx: RunContext[Any], event: RichAgentStreamEvent[Any]) -> None:
71
+ """Handle stream events and trigger TTS synthesis."""
72
+ from agentpool.agents.events import RunStartedEvent, StreamCompleteEvent
73
+
74
+ match event:
75
+ case RunStartedEvent():
76
+ # For async_cancel mode, cancel any pending audio from previous run
77
+ if self._mode == "async_cancel" and self._tts_stream is not None:
78
+ await self._tts_stream.cancel()
79
+
80
+ case (
81
+ PartStartEvent(part=TextPart(content=delta))
82
+ | PartDeltaEvent(delta=TextPartDelta(content_delta=delta))
83
+ ):
84
+ stream = await self._ensure_stream()
85
+ await stream.feed(delta)
86
+
87
+ case StreamCompleteEvent():
88
+ await self._close_stream()
89
+
90
+
91
+ class OpenAITTSEventHandler(BaseTTSEventHandler):
92
+ """TTS event handler using OpenAI's Text-to-Speech API.
93
+
94
+ Translates pydantic-ai stream events to anyvoice TTSStream.feed() calls
95
+ using the OpenAI TTS provider.
96
+ """
97
+
98
+ def __init__(
99
+ self,
100
+ *,
101
+ api_key: str | None = None,
102
+ model: TTSModel = "tts-1",
103
+ voice: TTSVoice = "alloy",
104
+ speed: float = 1.0,
105
+ chunk_size: int = 1024,
106
+ sample_rate: int = 24000,
107
+ min_text_length: int = 20,
108
+ mode: TTSMode = "sync_run",
109
+ ) -> None:
110
+ super().__init__(
111
+ sample_rate=sample_rate,
112
+ min_text_length=min_text_length,
113
+ mode=mode,
114
+ )
115
+ self._api_key = api_key
116
+ self._model: TTSModel = model
117
+ self._voice: TTSVoice = voice
118
+ self._speed = speed
119
+ self._chunk_size = chunk_size
120
+
121
+ async def _create_stream(self) -> TTSStream:
122
+ """Create OpenAI TTS stream."""
123
+ from anyvoice import OpenAITTSProvider, SoundDeviceSink, TTSStream
124
+
125
+ provider = OpenAITTSProvider(api_key=self._api_key)
126
+ session = provider.session(
127
+ model=self._model,
128
+ voice=self._voice,
129
+ speed=self._speed,
130
+ chunk_size=self._chunk_size,
131
+ )
132
+ sink = SoundDeviceSink(sample_rate=self._sample_rate)
133
+ return TTSStream(
134
+ session,
135
+ sink=sink,
136
+ mode=self._mode,
137
+ min_text_length=self._min_text_length,
138
+ )
139
+
140
+
141
+ class EdgeTTSEventHandler(BaseTTSEventHandler):
142
+ """TTS event handler using Microsoft Edge's free TTS service.
143
+
144
+ Translates pydantic-ai stream events to anyvoice TTSStream.feed() calls
145
+ using the Edge TTS provider (no API key required).
146
+ """
147
+
148
+ def __init__(
149
+ self,
150
+ *,
151
+ voice: str = "en-US-AriaNeural",
152
+ rate: str = "+0%",
153
+ volume: str = "+0%",
154
+ pitch: str = "+0Hz",
155
+ sample_rate: int = 24000,
156
+ min_text_length: int = 20,
157
+ mode: TTSMode = "sync_run",
158
+ ) -> None:
159
+ super().__init__(
160
+ sample_rate=sample_rate,
161
+ min_text_length=min_text_length,
162
+ mode=mode,
163
+ )
164
+ self._voice = voice
165
+ self._rate = rate
166
+ self._volume = volume
167
+ self._pitch = pitch
168
+
169
+ async def _create_stream(self) -> TTSStream:
170
+ """Create Edge TTS stream."""
171
+ from anyvoice import EdgeTTSProvider, SoundDeviceSink, TTSStream
172
+
173
+ provider = EdgeTTSProvider(sample_rate=self._sample_rate)
174
+ session = provider.session(
175
+ voice=self._voice,
176
+ rate=self._rate,
177
+ volume=self._volume,
178
+ pitch=self._pitch,
179
+ )
180
+ sink = SoundDeviceSink(sample_rate=self._sample_rate)
181
+ return TTSStream(
182
+ session,
183
+ sink=sink,
184
+ mode=self._mode,
185
+ min_text_length=self._min_text_length,
186
+ )
@@ -0,0 +1,419 @@
1
+ """Agent interaction patterns."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable, Mapping
6
+ from typing import TYPE_CHECKING, Any, Literal, cast, overload
7
+
8
+ from schemez import Schema
9
+
10
+ from agentpool.log import get_logger
11
+ from agentpool.messaging import ChatMessage
12
+
13
+
14
+ if TYPE_CHECKING:
15
+ from collections.abc import Sequence
16
+
17
+ from toprompt import AnyPromptType
18
+
19
+ from agentpool import AgentPool, MessageNode
20
+ from agentpool.agents import Agent
21
+ from agentpool.common_types import SupportsStructuredOutput
22
+ from agentpool.delegation.base_team import BaseTeam
23
+
24
+
25
+ ExtractionMode = Literal["structured", "tool_calls"]
26
+
27
+ type EndCondition = Callable[[list[ChatMessage[Any]], ChatMessage[Any]], bool]
28
+
29
+ logger = get_logger(__name__)
30
+
31
+
32
+ class LLMPick(Schema):
33
+ """Decision format for LLM response."""
34
+
35
+ selection: str # The label/name of the selected option
36
+ reason: str
37
+
38
+
39
+ class Pick[T](Schema):
40
+ """Type-safe decision with original object."""
41
+
42
+ selection: T
43
+ reason: str
44
+
45
+
46
+ class LLMMultiPick(Schema):
47
+ """Multiple selection format for LLM response."""
48
+
49
+ selections: list[str] # Labels of selected options
50
+ reason: str
51
+
52
+
53
+ class MultiPick[T](Schema):
54
+ """Type-safe multiple selection with original objects."""
55
+
56
+ selections: list[T]
57
+ reason: str
58
+
59
+
60
+ def get_label(item: Any) -> str:
61
+ """Get label for an item to use in selection.
62
+
63
+ Args:
64
+ item: Item to get label for
65
+
66
+ Returns:
67
+ Label to use for selection
68
+
69
+ Strategy:
70
+ - strings stay as-is
71
+ - types use __name__
72
+ - others use __repr__ for unique identifiable string
73
+ """
74
+ from agentpool import MessageNode
75
+
76
+ match item:
77
+ case str():
78
+ return item
79
+ case type():
80
+ return item.__name__
81
+ case MessageNode():
82
+ return item.name or "unnamed_agent"
83
+ case _:
84
+ return repr(item)
85
+
86
+
87
+ class Interactions:
88
+ """Manages agent communication patterns."""
89
+
90
+ def __init__(self, agent: SupportsStructuredOutput) -> None:
91
+ self.agent = agent
92
+
93
+ # async def conversation(
94
+ # self,
95
+ # other: MessageNode[Any, Any],
96
+ # initial_message: AnyPromptType,
97
+ # *,
98
+ # max_rounds: int | None = None,
99
+ # end_condition: Callable[[list[ChatMessage[Any]], ChatMessage[Any]], bool] | None = None,
100
+ # ) -> AsyncIterator[ChatMessage[Any]]:
101
+ # """Maintain conversation between two agents.
102
+
103
+ # Args:
104
+ # other: Agent to converse with
105
+ # initial_message: Message to start conversation with
106
+ # max_rounds: Optional maximum number of exchanges
107
+ # end_condition: Optional predicate to check for conversation end
108
+
109
+ # Yields:
110
+ # Messages from both agents in conversation order
111
+ # """
112
+ # rounds = 0
113
+ # messages: list[ChatMessage[Any]] = []
114
+ # current_message = initial_message
115
+ # current_node: MessageNode[Any, Any] = self.agent
116
+
117
+ # while True:
118
+ # if max_rounds and rounds >= max_rounds:
119
+ # logger.debug("Conversation ended", max_rounds=max_rounds)
120
+ # return
121
+
122
+ # response = await current_node.run(current_message)
123
+ # messages.append(response)
124
+ # yield response
125
+
126
+ # if end_condition and end_condition(messages, response):
127
+ # logger.debug("Conversation ended: end condition met")
128
+ # return
129
+
130
+ # # Switch agents for next round
131
+ # current_node = other if current_node == self.agent else self.agent
132
+ # current_message = response.content
133
+ # rounds += 1
134
+
135
+ @overload
136
+ async def pick(
137
+ self,
138
+ selections: AgentPool,
139
+ task: str,
140
+ prompt: AnyPromptType | None = None,
141
+ ) -> Pick[Agent[Any, Any]]: ...
142
+
143
+ @overload
144
+ async def pick(
145
+ self,
146
+ selections: BaseTeam[Any, Any],
147
+ task: str,
148
+ prompt: AnyPromptType | None = None,
149
+ ) -> Pick[MessageNode[Any, Any]]: ...
150
+
151
+ @overload
152
+ async def pick[T: AnyPromptType](
153
+ self,
154
+ selections: Sequence[T] | Mapping[str, T],
155
+ task: str,
156
+ prompt: AnyPromptType | None = None,
157
+ ) -> Pick[T]: ...
158
+
159
+ async def pick[T](
160
+ self,
161
+ selections: Sequence[T] | Mapping[str, T] | AgentPool | BaseTeam[Any, Any],
162
+ task: str,
163
+ prompt: AnyPromptType | None = None,
164
+ ) -> Pick[T]:
165
+ """Pick from available options with reasoning.
166
+
167
+ Args:
168
+ selections: What to pick from:
169
+ - Sequence of items (auto-labeled)
170
+ - Dict mapping labels to items
171
+ - AgentPool
172
+ - Team
173
+ task: Task/decision description
174
+ prompt: Optional custom selection prompt
175
+
176
+ Returns:
177
+ Decision with selected item and reasoning
178
+
179
+ Raises:
180
+ ValueError: If no choices available or invalid selection
181
+ """
182
+ # Get items and create label mapping
183
+ from toprompt import to_prompt
184
+
185
+ from agentpool import AgentPool
186
+ from agentpool.delegation.base_team import BaseTeam
187
+
188
+ match selections:
189
+ case dict():
190
+ label_map = selections
191
+ items: list[Any] = list(selections.values())
192
+ case BaseTeam():
193
+ items = list(selections.nodes)
194
+ label_map = {get_label(item): item for item in items}
195
+ case AgentPool():
196
+ items = list(selections.agents.values())
197
+ label_map = {get_label(item): item for item in items}
198
+ case _:
199
+ items = list(selections)
200
+ label_map = {get_label(item): item for item in items}
201
+
202
+ if not items:
203
+ msg = "No choices available"
204
+ raise ValueError(msg)
205
+
206
+ # Get descriptions for all items
207
+ descriptions = []
208
+ for label, item in label_map.items():
209
+ item_desc = await to_prompt(item)
210
+ descriptions.append(f"{label}:\n{item_desc}")
211
+
212
+ default_prompt = f"""Task/Decision: {task}
213
+
214
+ Available options:
215
+ {"-" * 40}
216
+ {"\n\n".join(descriptions)}
217
+ {"-" * 40}
218
+
219
+ Select ONE option by its exact label."""
220
+
221
+ # Get LLM's string-based decision
222
+ result = await self.agent.run(prompt or default_prompt, output_type=LLMPick)
223
+
224
+ # Convert to type-safe decision
225
+ if result.content.selection not in label_map:
226
+ msg = f"Invalid selection: {result.content.selection}"
227
+ raise ValueError(msg)
228
+
229
+ selected = cast(T, label_map[result.content.selection])
230
+ return Pick(selection=selected, reason=result.content.reason)
231
+
232
+ @overload
233
+ async def pick_multiple(
234
+ self,
235
+ selections: BaseTeam[Any, Any],
236
+ task: str,
237
+ *,
238
+ min_picks: int = 1,
239
+ max_picks: int | None = None,
240
+ prompt: AnyPromptType | None = None,
241
+ ) -> MultiPick[MessageNode[Any, Any]]: ...
242
+
243
+ @overload
244
+ async def pick_multiple(
245
+ self,
246
+ selections: AgentPool,
247
+ task: str,
248
+ *,
249
+ min_picks: int = 1,
250
+ max_picks: int | None = None,
251
+ prompt: AnyPromptType | None = None,
252
+ ) -> MultiPick[Agent[Any, Any]]: ...
253
+
254
+ @overload
255
+ async def pick_multiple[T: AnyPromptType](
256
+ self,
257
+ selections: Sequence[T] | Mapping[str, T],
258
+ task: str,
259
+ *,
260
+ min_picks: int = 1,
261
+ max_picks: int | None = None,
262
+ prompt: AnyPromptType | None = None,
263
+ ) -> MultiPick[T]: ...
264
+
265
+ async def pick_multiple[T](
266
+ self,
267
+ selections: Sequence[T] | Mapping[str, T] | AgentPool | BaseTeam[Any, Any],
268
+ task: str,
269
+ *,
270
+ min_picks: int = 1,
271
+ max_picks: int | None = None,
272
+ prompt: AnyPromptType | None = None,
273
+ ) -> MultiPick[T]:
274
+ """Pick multiple options from available choices.
275
+
276
+ Args:
277
+ selections: What to pick from
278
+ task: Task/decision description
279
+ min_picks: Minimum number of selections required
280
+ max_picks: Maximum number of selections (None for unlimited)
281
+ prompt: Optional custom selection prompt
282
+ """
283
+ from toprompt import to_prompt
284
+
285
+ from agentpool import AgentPool
286
+ from agentpool.delegation.base_team import BaseTeam
287
+
288
+ match selections:
289
+ case AgentPool():
290
+ items: list[Any] = list(selections.agents.values())
291
+ label_map: Mapping[str, Any] = {get_label(item): item for item in items}
292
+ case Mapping():
293
+ label_map = selections
294
+ items = list(selections.values())
295
+ case BaseTeam():
296
+ items = list(selections.nodes)
297
+ label_map = {get_label(item): item for item in items}
298
+ case _:
299
+ items = list(selections)
300
+ label_map = {get_label(item): item for item in items}
301
+
302
+ if not items:
303
+ msg = "No choices available"
304
+ raise ValueError(msg)
305
+
306
+ if max_picks is not None and max_picks < min_picks:
307
+ msg = f"max_picks ({max_picks}) cannot be less than min_picks ({min_picks})"
308
+ raise ValueError(msg)
309
+
310
+ descriptions = []
311
+ for label, item in label_map.items():
312
+ item_desc = await to_prompt(item)
313
+ descriptions.append(f"{label}:\n{item_desc}")
314
+
315
+ picks_info = (
316
+ f"Select between {min_picks} and {max_picks}"
317
+ if max_picks is not None
318
+ else f"Select at least {min_picks}"
319
+ )
320
+
321
+ default_prompt = f"""Task/Decision: {task}
322
+
323
+ Available options:
324
+ {"-" * 40}
325
+ {"\n\n".join(descriptions)}
326
+ {"-" * 40}
327
+
328
+ {picks_info} options by their exact labels.
329
+ List your selections, one per line, followed by your reasoning."""
330
+
331
+ result = await self.agent.run(prompt or default_prompt, output_type=LLMMultiPick)
332
+
333
+ # Validate selections
334
+ invalid = [s for s in result.content.selections if s not in label_map]
335
+ if invalid:
336
+ msg = f"Invalid selections: {', '.join(invalid)}"
337
+ raise ValueError(msg)
338
+ num_picks = len(result.content.selections)
339
+ if num_picks < min_picks:
340
+ msg = f"Too few selections: got {num_picks}, need {min_picks}"
341
+ raise ValueError(msg)
342
+
343
+ if max_picks and num_picks > max_picks:
344
+ msg = f"Too many selections: got {num_picks}, max {max_picks}"
345
+ raise ValueError(msg)
346
+
347
+ selected = [cast(T, label_map[label]) for label in result.content.selections]
348
+ return MultiPick(selections=selected, reason=result.content.reason)
349
+
350
+ async def extract[T](
351
+ self,
352
+ text: str,
353
+ as_type: type[T],
354
+ *,
355
+ prompt: AnyPromptType | None = None,
356
+ ) -> T:
357
+ """Extract single instance of type from text.
358
+
359
+ Args:
360
+ text: Text to extract from
361
+ as_type: Type to extract
362
+ prompt: Optional custom prompt
363
+ """
364
+ item_model = Schema.for_class_ctor(as_type)
365
+ final_prompt = prompt or f"Extract {as_type.__name__} from: {text}"
366
+
367
+ class Extraction(Schema):
368
+ instance: item_model # type: ignore
369
+ # explanation: str | None = None
370
+
371
+ result = await self.agent.run(final_prompt, output_type=Extraction)
372
+ return as_type(**result.content.instance.model_dump())
373
+
374
+ async def extract_multiple[T](
375
+ self,
376
+ text: str,
377
+ as_type: type[T],
378
+ *,
379
+ min_items: int = 1,
380
+ max_items: int | None = None,
381
+ prompt: AnyPromptType | None = None,
382
+ ) -> list[T]:
383
+ """Extract multiple instances of type from text.
384
+
385
+ Args:
386
+ text: Text to extract from
387
+ as_type: Type to extract
388
+ min_items: Minimum number of instances to extract
389
+ max_items: Maximum number of instances (None=unlimited)
390
+ prompt: Optional custom prompt
391
+ """
392
+ item_model = Schema.for_class_ctor(as_type)
393
+ final_prompt = prompt or "\n".join([
394
+ f"Extract {as_type.__name__} instances from text.",
395
+ # "Requirements:",
396
+ # f"- Extract at least {min_items} instances",
397
+ # f"- Extract at most {max_items} instances" if max_items else "",
398
+ "\nText to analyze:",
399
+ text,
400
+ ])
401
+ # Create model for individual instance
402
+
403
+ class Extraction(Schema):
404
+ instances: list[item_model] # type: ignore
405
+ # explanation: str | None = None
406
+
407
+ result = await self.agent.run(final_prompt, output_type=Extraction)
408
+ num_instances = len(result.content.instances) # Validate counts
409
+ if len(result.content.instances) < min_items:
410
+ msg = f"Found only {num_instances} instances, need {min_items}"
411
+ raise ValueError(msg)
412
+
413
+ if max_items and num_instances > max_items:
414
+ msg = f"Found {num_instances} instances, max is {max_items}"
415
+ raise ValueError(msg)
416
+ return [
417
+ as_type(**instance.data if hasattr(instance, "data") else instance.model_dump())
418
+ for instance in result.content.instances
419
+ ]