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.
- acp/README.md +64 -0
- acp/__init__.py +172 -0
- acp/__main__.py +10 -0
- acp/acp_requests.py +285 -0
- acp/agent/__init__.py +6 -0
- acp/agent/connection.py +256 -0
- acp/agent/implementations/__init__.py +6 -0
- acp/agent/implementations/debug_server/__init__.py +1 -0
- acp/agent/implementations/debug_server/cli.py +79 -0
- acp/agent/implementations/debug_server/debug.html +234 -0
- acp/agent/implementations/debug_server/debug_server.py +496 -0
- acp/agent/implementations/testing.py +91 -0
- acp/agent/protocol.py +65 -0
- acp/bridge/README.md +162 -0
- acp/bridge/__init__.py +6 -0
- acp/bridge/__main__.py +91 -0
- acp/bridge/bridge.py +246 -0
- acp/bridge/py.typed +0 -0
- acp/bridge/settings.py +15 -0
- acp/client/__init__.py +7 -0
- acp/client/connection.py +251 -0
- acp/client/implementations/__init__.py +7 -0
- acp/client/implementations/default_client.py +185 -0
- acp/client/implementations/headless_client.py +266 -0
- acp/client/implementations/noop_client.py +110 -0
- acp/client/protocol.py +61 -0
- acp/connection.py +280 -0
- acp/exceptions.py +46 -0
- acp/filesystem.py +524 -0
- acp/notifications.py +832 -0
- acp/py.typed +0 -0
- acp/schema/__init__.py +265 -0
- acp/schema/agent_plan.py +30 -0
- acp/schema/agent_requests.py +126 -0
- acp/schema/agent_responses.py +256 -0
- acp/schema/base.py +39 -0
- acp/schema/capabilities.py +230 -0
- acp/schema/client_requests.py +247 -0
- acp/schema/client_responses.py +96 -0
- acp/schema/common.py +81 -0
- acp/schema/content_blocks.py +188 -0
- acp/schema/mcp.py +82 -0
- acp/schema/messages.py +171 -0
- acp/schema/notifications.py +82 -0
- acp/schema/protocol_stuff.md +3 -0
- acp/schema/session_state.py +160 -0
- acp/schema/session_updates.py +419 -0
- acp/schema/slash_commands.py +51 -0
- acp/schema/terminal.py +15 -0
- acp/schema/tool_call.py +347 -0
- acp/stdio.py +250 -0
- acp/task/__init__.py +53 -0
- acp/task/debug.py +197 -0
- acp/task/dispatcher.py +93 -0
- acp/task/queue.py +69 -0
- acp/task/sender.py +82 -0
- acp/task/state.py +87 -0
- acp/task/supervisor.py +93 -0
- acp/terminal_handle.py +30 -0
- acp/tool_call_reporter.py +199 -0
- acp/tool_call_state.py +178 -0
- acp/transports.py +104 -0
- acp/utils.py +240 -0
- agentpool/__init__.py +63 -0
- agentpool/__main__.py +7 -0
- agentpool/agents/__init__.py +30 -0
- agentpool/agents/acp_agent/__init__.py +5 -0
- agentpool/agents/acp_agent/acp_agent.py +837 -0
- agentpool/agents/acp_agent/acp_converters.py +294 -0
- agentpool/agents/acp_agent/client_handler.py +317 -0
- agentpool/agents/acp_agent/session_state.py +44 -0
- agentpool/agents/agent.py +1264 -0
- agentpool/agents/agui_agent/__init__.py +19 -0
- agentpool/agents/agui_agent/agui_agent.py +677 -0
- agentpool/agents/agui_agent/agui_converters.py +423 -0
- agentpool/agents/agui_agent/chunk_transformer.py +204 -0
- agentpool/agents/agui_agent/event_types.py +83 -0
- agentpool/agents/agui_agent/helpers.py +192 -0
- agentpool/agents/architect.py +71 -0
- agentpool/agents/base_agent.py +177 -0
- agentpool/agents/claude_code_agent/__init__.py +11 -0
- agentpool/agents/claude_code_agent/claude_code_agent.py +1021 -0
- agentpool/agents/claude_code_agent/converters.py +243 -0
- agentpool/agents/context.py +105 -0
- agentpool/agents/events/__init__.py +61 -0
- agentpool/agents/events/builtin_handlers.py +129 -0
- agentpool/agents/events/event_emitter.py +320 -0
- agentpool/agents/events/events.py +561 -0
- agentpool/agents/events/tts_handlers.py +186 -0
- agentpool/agents/interactions.py +419 -0
- agentpool/agents/slashed_agent.py +244 -0
- agentpool/agents/sys_prompts.py +178 -0
- agentpool/agents/tool_wrapping.py +184 -0
- agentpool/base_provider.py +28 -0
- agentpool/common_types.py +226 -0
- agentpool/config_resources/__init__.py +16 -0
- agentpool/config_resources/acp_assistant.yml +24 -0
- agentpool/config_resources/agents.yml +109 -0
- agentpool/config_resources/agents_template.yml +18 -0
- agentpool/config_resources/agui_test.yml +18 -0
- agentpool/config_resources/claude_code_agent.yml +16 -0
- agentpool/config_resources/claude_style_subagent.md +30 -0
- agentpool/config_resources/external_acp_agents.yml +77 -0
- agentpool/config_resources/opencode_style_subagent.md +19 -0
- agentpool/config_resources/tts_test_agents.yml +78 -0
- agentpool/delegation/__init__.py +8 -0
- agentpool/delegation/base_team.py +504 -0
- agentpool/delegation/message_flow_tracker.py +39 -0
- agentpool/delegation/pool.py +1129 -0
- agentpool/delegation/team.py +325 -0
- agentpool/delegation/teamrun.py +343 -0
- agentpool/docs/__init__.py +5 -0
- agentpool/docs/gen_examples.py +42 -0
- agentpool/docs/utils.py +370 -0
- agentpool/functional/__init__.py +20 -0
- agentpool/functional/py.typed +0 -0
- agentpool/functional/run.py +80 -0
- agentpool/functional/structure.py +136 -0
- agentpool/hooks/__init__.py +20 -0
- agentpool/hooks/agent_hooks.py +247 -0
- agentpool/hooks/base.py +119 -0
- agentpool/hooks/callable.py +140 -0
- agentpool/hooks/command.py +180 -0
- agentpool/hooks/prompt.py +122 -0
- agentpool/jinja_filters.py +132 -0
- agentpool/log.py +224 -0
- agentpool/mcp_server/__init__.py +17 -0
- agentpool/mcp_server/client.py +429 -0
- agentpool/mcp_server/constants.py +32 -0
- agentpool/mcp_server/conversions.py +172 -0
- agentpool/mcp_server/helpers.py +47 -0
- agentpool/mcp_server/manager.py +232 -0
- agentpool/mcp_server/message_handler.py +164 -0
- agentpool/mcp_server/registries/__init__.py +1 -0
- agentpool/mcp_server/registries/official_registry_client.py +345 -0
- agentpool/mcp_server/registries/pulsemcp_client.py +88 -0
- agentpool/mcp_server/tool_bridge.py +548 -0
- agentpool/messaging/__init__.py +58 -0
- agentpool/messaging/compaction.py +928 -0
- agentpool/messaging/connection_manager.py +319 -0
- agentpool/messaging/context.py +66 -0
- agentpool/messaging/event_manager.py +426 -0
- agentpool/messaging/events.py +39 -0
- agentpool/messaging/message_container.py +209 -0
- agentpool/messaging/message_history.py +491 -0
- agentpool/messaging/messagenode.py +377 -0
- agentpool/messaging/messages.py +655 -0
- agentpool/messaging/processing.py +76 -0
- agentpool/mime_utils.py +95 -0
- agentpool/models/__init__.py +21 -0
- agentpool/models/acp_agents/__init__.py +22 -0
- agentpool/models/acp_agents/base.py +308 -0
- agentpool/models/acp_agents/mcp_capable.py +790 -0
- agentpool/models/acp_agents/non_mcp.py +842 -0
- agentpool/models/agents.py +450 -0
- agentpool/models/agui_agents.py +89 -0
- agentpool/models/claude_code_agents.py +238 -0
- agentpool/models/file_agents.py +116 -0
- agentpool/models/file_parsing.py +367 -0
- agentpool/models/manifest.py +658 -0
- agentpool/observability/__init__.py +9 -0
- agentpool/observability/observability_registry.py +97 -0
- agentpool/prompts/__init__.py +1 -0
- agentpool/prompts/base.py +27 -0
- agentpool/prompts/builtin_provider.py +75 -0
- agentpool/prompts/conversion_manager.py +95 -0
- agentpool/prompts/convert.py +96 -0
- agentpool/prompts/manager.py +204 -0
- agentpool/prompts/parts/zed.md +33 -0
- agentpool/prompts/prompts.py +581 -0
- agentpool/py.typed +0 -0
- agentpool/queries/tree-sitter-language-pack/README.md +7 -0
- agentpool/queries/tree-sitter-language-pack/arduino-tags.scm +5 -0
- agentpool/queries/tree-sitter-language-pack/c-tags.scm +9 -0
- agentpool/queries/tree-sitter-language-pack/chatito-tags.scm +16 -0
- agentpool/queries/tree-sitter-language-pack/clojure-tags.scm +7 -0
- agentpool/queries/tree-sitter-language-pack/commonlisp-tags.scm +122 -0
- agentpool/queries/tree-sitter-language-pack/cpp-tags.scm +15 -0
- agentpool/queries/tree-sitter-language-pack/csharp-tags.scm +26 -0
- agentpool/queries/tree-sitter-language-pack/d-tags.scm +26 -0
- agentpool/queries/tree-sitter-language-pack/dart-tags.scm +92 -0
- agentpool/queries/tree-sitter-language-pack/elisp-tags.scm +5 -0
- agentpool/queries/tree-sitter-language-pack/elixir-tags.scm +54 -0
- agentpool/queries/tree-sitter-language-pack/elm-tags.scm +19 -0
- agentpool/queries/tree-sitter-language-pack/gleam-tags.scm +41 -0
- agentpool/queries/tree-sitter-language-pack/go-tags.scm +42 -0
- agentpool/queries/tree-sitter-language-pack/java-tags.scm +20 -0
- agentpool/queries/tree-sitter-language-pack/javascript-tags.scm +88 -0
- agentpool/queries/tree-sitter-language-pack/lua-tags.scm +34 -0
- agentpool/queries/tree-sitter-language-pack/matlab-tags.scm +10 -0
- agentpool/queries/tree-sitter-language-pack/ocaml-tags.scm +115 -0
- agentpool/queries/tree-sitter-language-pack/ocaml_interface-tags.scm +98 -0
- agentpool/queries/tree-sitter-language-pack/pony-tags.scm +39 -0
- agentpool/queries/tree-sitter-language-pack/properties-tags.scm +5 -0
- agentpool/queries/tree-sitter-language-pack/python-tags.scm +14 -0
- agentpool/queries/tree-sitter-language-pack/r-tags.scm +21 -0
- agentpool/queries/tree-sitter-language-pack/racket-tags.scm +12 -0
- agentpool/queries/tree-sitter-language-pack/ruby-tags.scm +64 -0
- agentpool/queries/tree-sitter-language-pack/rust-tags.scm +60 -0
- agentpool/queries/tree-sitter-language-pack/solidity-tags.scm +43 -0
- agentpool/queries/tree-sitter-language-pack/swift-tags.scm +51 -0
- agentpool/queries/tree-sitter-language-pack/udev-tags.scm +20 -0
- agentpool/queries/tree-sitter-languages/README.md +24 -0
- agentpool/queries/tree-sitter-languages/c-tags.scm +9 -0
- agentpool/queries/tree-sitter-languages/c_sharp-tags.scm +46 -0
- agentpool/queries/tree-sitter-languages/cpp-tags.scm +15 -0
- agentpool/queries/tree-sitter-languages/dart-tags.scm +91 -0
- agentpool/queries/tree-sitter-languages/elisp-tags.scm +8 -0
- agentpool/queries/tree-sitter-languages/elixir-tags.scm +54 -0
- agentpool/queries/tree-sitter-languages/elm-tags.scm +19 -0
- agentpool/queries/tree-sitter-languages/fortran-tags.scm +15 -0
- agentpool/queries/tree-sitter-languages/go-tags.scm +30 -0
- agentpool/queries/tree-sitter-languages/haskell-tags.scm +3 -0
- agentpool/queries/tree-sitter-languages/hcl-tags.scm +77 -0
- agentpool/queries/tree-sitter-languages/java-tags.scm +20 -0
- agentpool/queries/tree-sitter-languages/javascript-tags.scm +88 -0
- agentpool/queries/tree-sitter-languages/julia-tags.scm +60 -0
- agentpool/queries/tree-sitter-languages/kotlin-tags.scm +27 -0
- agentpool/queries/tree-sitter-languages/matlab-tags.scm +10 -0
- agentpool/queries/tree-sitter-languages/ocaml-tags.scm +115 -0
- agentpool/queries/tree-sitter-languages/ocaml_interface-tags.scm +98 -0
- agentpool/queries/tree-sitter-languages/php-tags.scm +26 -0
- agentpool/queries/tree-sitter-languages/python-tags.scm +12 -0
- agentpool/queries/tree-sitter-languages/ql-tags.scm +26 -0
- agentpool/queries/tree-sitter-languages/ruby-tags.scm +64 -0
- agentpool/queries/tree-sitter-languages/rust-tags.scm +60 -0
- agentpool/queries/tree-sitter-languages/scala-tags.scm +65 -0
- agentpool/queries/tree-sitter-languages/typescript-tags.scm +41 -0
- agentpool/queries/tree-sitter-languages/zig-tags.scm +3 -0
- agentpool/repomap.py +1231 -0
- agentpool/resource_providers/__init__.py +17 -0
- agentpool/resource_providers/aggregating.py +54 -0
- agentpool/resource_providers/base.py +172 -0
- agentpool/resource_providers/codemode/__init__.py +9 -0
- agentpool/resource_providers/codemode/code_executor.py +215 -0
- agentpool/resource_providers/codemode/default_prompt.py +19 -0
- agentpool/resource_providers/codemode/helpers.py +83 -0
- agentpool/resource_providers/codemode/progress_executor.py +212 -0
- agentpool/resource_providers/codemode/provider.py +150 -0
- agentpool/resource_providers/codemode/remote_mcp_execution.py +143 -0
- agentpool/resource_providers/codemode/remote_provider.py +171 -0
- agentpool/resource_providers/filtering.py +42 -0
- agentpool/resource_providers/mcp_provider.py +246 -0
- agentpool/resource_providers/plan_provider.py +196 -0
- agentpool/resource_providers/pool.py +69 -0
- agentpool/resource_providers/static.py +289 -0
- agentpool/running/__init__.py +20 -0
- agentpool/running/decorators.py +56 -0
- agentpool/running/discovery.py +101 -0
- agentpool/running/executor.py +284 -0
- agentpool/running/injection.py +111 -0
- agentpool/running/py.typed +0 -0
- agentpool/running/run_nodes.py +87 -0
- agentpool/server.py +122 -0
- agentpool/sessions/__init__.py +13 -0
- agentpool/sessions/manager.py +302 -0
- agentpool/sessions/models.py +71 -0
- agentpool/sessions/session.py +239 -0
- agentpool/sessions/store.py +163 -0
- agentpool/skills/__init__.py +5 -0
- agentpool/skills/manager.py +120 -0
- agentpool/skills/registry.py +210 -0
- agentpool/skills/skill.py +36 -0
- agentpool/storage/__init__.py +17 -0
- agentpool/storage/manager.py +419 -0
- agentpool/storage/serialization.py +136 -0
- agentpool/talk/__init__.py +13 -0
- agentpool/talk/registry.py +128 -0
- agentpool/talk/stats.py +159 -0
- agentpool/talk/talk.py +604 -0
- agentpool/tasks/__init__.py +20 -0
- agentpool/tasks/exceptions.py +25 -0
- agentpool/tasks/registry.py +33 -0
- agentpool/testing.py +129 -0
- agentpool/text_templates/__init__.py +39 -0
- agentpool/text_templates/system_prompt.jinja +30 -0
- agentpool/text_templates/tool_call_default.jinja +13 -0
- agentpool/text_templates/tool_call_markdown.jinja +25 -0
- agentpool/text_templates/tool_call_simple.jinja +5 -0
- agentpool/tools/__init__.py +16 -0
- agentpool/tools/base.py +269 -0
- agentpool/tools/exceptions.py +9 -0
- agentpool/tools/manager.py +255 -0
- agentpool/tools/tool_call_info.py +87 -0
- agentpool/ui/__init__.py +2 -0
- agentpool/ui/base.py +89 -0
- agentpool/ui/mock_provider.py +81 -0
- agentpool/ui/stdlib_provider.py +150 -0
- agentpool/utils/__init__.py +44 -0
- agentpool/utils/baseregistry.py +185 -0
- agentpool/utils/count_tokens.py +62 -0
- agentpool/utils/dag.py +184 -0
- agentpool/utils/importing.py +206 -0
- agentpool/utils/inspection.py +334 -0
- agentpool/utils/model_capabilities.py +25 -0
- agentpool/utils/network.py +28 -0
- agentpool/utils/now.py +22 -0
- agentpool/utils/parse_time.py +87 -0
- agentpool/utils/result_utils.py +35 -0
- agentpool/utils/signatures.py +305 -0
- agentpool/utils/streams.py +112 -0
- agentpool/utils/tasks.py +186 -0
- agentpool/vfs_registry.py +250 -0
- agentpool-2.1.9.dist-info/METADATA +336 -0
- agentpool-2.1.9.dist-info/RECORD +474 -0
- agentpool-2.1.9.dist-info/WHEEL +4 -0
- agentpool-2.1.9.dist-info/entry_points.txt +14 -0
- agentpool-2.1.9.dist-info/licenses/LICENSE +22 -0
- agentpool_cli/__init__.py +34 -0
- agentpool_cli/__main__.py +66 -0
- agentpool_cli/agent.py +175 -0
- agentpool_cli/cli_types.py +23 -0
- agentpool_cli/common.py +163 -0
- agentpool_cli/create.py +175 -0
- agentpool_cli/history.py +217 -0
- agentpool_cli/log.py +78 -0
- agentpool_cli/py.typed +0 -0
- agentpool_cli/run.py +84 -0
- agentpool_cli/serve_acp.py +177 -0
- agentpool_cli/serve_api.py +69 -0
- agentpool_cli/serve_mcp.py +74 -0
- agentpool_cli/serve_vercel.py +233 -0
- agentpool_cli/store.py +171 -0
- agentpool_cli/task.py +84 -0
- agentpool_cli/utils.py +104 -0
- agentpool_cli/watch.py +54 -0
- agentpool_commands/__init__.py +180 -0
- agentpool_commands/agents.py +199 -0
- agentpool_commands/base.py +45 -0
- agentpool_commands/commands.py +58 -0
- agentpool_commands/completers.py +110 -0
- agentpool_commands/connections.py +175 -0
- agentpool_commands/markdown_utils.py +31 -0
- agentpool_commands/models.py +62 -0
- agentpool_commands/prompts.py +78 -0
- agentpool_commands/py.typed +0 -0
- agentpool_commands/read.py +77 -0
- agentpool_commands/resources.py +210 -0
- agentpool_commands/session.py +48 -0
- agentpool_commands/tools.py +269 -0
- agentpool_commands/utils.py +189 -0
- agentpool_commands/workers.py +163 -0
- agentpool_config/__init__.py +53 -0
- agentpool_config/builtin_tools.py +265 -0
- agentpool_config/commands.py +237 -0
- agentpool_config/conditions.py +301 -0
- agentpool_config/converters.py +30 -0
- agentpool_config/durable.py +331 -0
- agentpool_config/event_handlers.py +600 -0
- agentpool_config/events.py +153 -0
- agentpool_config/forward_targets.py +251 -0
- agentpool_config/hook_conditions.py +331 -0
- agentpool_config/hooks.py +241 -0
- agentpool_config/jinja.py +206 -0
- agentpool_config/knowledge.py +41 -0
- agentpool_config/loaders.py +350 -0
- agentpool_config/mcp_server.py +243 -0
- agentpool_config/nodes.py +202 -0
- agentpool_config/observability.py +191 -0
- agentpool_config/output_types.py +55 -0
- agentpool_config/pool_server.py +267 -0
- agentpool_config/prompt_hubs.py +105 -0
- agentpool_config/prompts.py +185 -0
- agentpool_config/py.typed +0 -0
- agentpool_config/resources.py +33 -0
- agentpool_config/session.py +119 -0
- agentpool_config/skills.py +17 -0
- agentpool_config/storage.py +288 -0
- agentpool_config/system_prompts.py +190 -0
- agentpool_config/task.py +162 -0
- agentpool_config/teams.py +52 -0
- agentpool_config/tools.py +112 -0
- agentpool_config/toolsets.py +1033 -0
- agentpool_config/workers.py +86 -0
- agentpool_prompts/__init__.py +1 -0
- agentpool_prompts/braintrust_hub.py +235 -0
- agentpool_prompts/fabric.py +75 -0
- agentpool_prompts/langfuse_hub.py +79 -0
- agentpool_prompts/promptlayer_provider.py +59 -0
- agentpool_prompts/py.typed +0 -0
- agentpool_server/__init__.py +9 -0
- agentpool_server/a2a_server/__init__.py +5 -0
- agentpool_server/a2a_server/a2a_types.py +41 -0
- agentpool_server/a2a_server/server.py +190 -0
- agentpool_server/a2a_server/storage.py +81 -0
- agentpool_server/acp_server/__init__.py +22 -0
- agentpool_server/acp_server/acp_agent.py +786 -0
- agentpool_server/acp_server/acp_tools.py +43 -0
- agentpool_server/acp_server/commands/__init__.py +18 -0
- agentpool_server/acp_server/commands/acp_commands.py +594 -0
- agentpool_server/acp_server/commands/debug_commands.py +376 -0
- agentpool_server/acp_server/commands/docs_commands/__init__.py +39 -0
- agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +169 -0
- agentpool_server/acp_server/commands/docs_commands/get_schema.py +176 -0
- agentpool_server/acp_server/commands/docs_commands/get_source.py +110 -0
- agentpool_server/acp_server/commands/docs_commands/git_diff.py +111 -0
- agentpool_server/acp_server/commands/docs_commands/helpers.py +33 -0
- agentpool_server/acp_server/commands/docs_commands/url_to_markdown.py +90 -0
- agentpool_server/acp_server/commands/spawn.py +210 -0
- agentpool_server/acp_server/converters.py +235 -0
- agentpool_server/acp_server/input_provider.py +338 -0
- agentpool_server/acp_server/server.py +288 -0
- agentpool_server/acp_server/session.py +969 -0
- agentpool_server/acp_server/session_manager.py +313 -0
- agentpool_server/acp_server/syntax_detection.py +250 -0
- agentpool_server/acp_server/zed_tools.md +90 -0
- agentpool_server/aggregating_server.py +309 -0
- agentpool_server/agui_server/__init__.py +11 -0
- agentpool_server/agui_server/server.py +128 -0
- agentpool_server/base.py +189 -0
- agentpool_server/http_server.py +164 -0
- agentpool_server/mcp_server/__init__.py +6 -0
- agentpool_server/mcp_server/server.py +314 -0
- agentpool_server/mcp_server/zed_wrapper.py +110 -0
- agentpool_server/openai_api_server/__init__.py +5 -0
- agentpool_server/openai_api_server/completions/__init__.py +1 -0
- agentpool_server/openai_api_server/completions/helpers.py +81 -0
- agentpool_server/openai_api_server/completions/models.py +98 -0
- agentpool_server/openai_api_server/responses/__init__.py +1 -0
- agentpool_server/openai_api_server/responses/helpers.py +74 -0
- agentpool_server/openai_api_server/responses/models.py +96 -0
- agentpool_server/openai_api_server/server.py +242 -0
- agentpool_server/py.typed +0 -0
- agentpool_storage/__init__.py +9 -0
- agentpool_storage/base.py +310 -0
- agentpool_storage/file_provider.py +378 -0
- agentpool_storage/formatters.py +129 -0
- agentpool_storage/memory_provider.py +396 -0
- agentpool_storage/models.py +108 -0
- agentpool_storage/py.typed +0 -0
- agentpool_storage/session_store.py +262 -0
- agentpool_storage/sql_provider/__init__.py +21 -0
- agentpool_storage/sql_provider/cli.py +146 -0
- agentpool_storage/sql_provider/models.py +249 -0
- agentpool_storage/sql_provider/queries.py +15 -0
- agentpool_storage/sql_provider/sql_provider.py +444 -0
- agentpool_storage/sql_provider/utils.py +234 -0
- agentpool_storage/text_log_provider.py +275 -0
- agentpool_toolsets/__init__.py +15 -0
- agentpool_toolsets/builtin/__init__.py +33 -0
- agentpool_toolsets/builtin/agent_management.py +239 -0
- agentpool_toolsets/builtin/chain.py +288 -0
- agentpool_toolsets/builtin/code.py +398 -0
- agentpool_toolsets/builtin/debug.py +291 -0
- agentpool_toolsets/builtin/execution_environment.py +381 -0
- agentpool_toolsets/builtin/file_edit/__init__.py +11 -0
- agentpool_toolsets/builtin/file_edit/file_edit.py +747 -0
- agentpool_toolsets/builtin/file_edit/fuzzy_matcher/__init__.py +5 -0
- agentpool_toolsets/builtin/file_edit/fuzzy_matcher/example_usage.py +311 -0
- agentpool_toolsets/builtin/file_edit/fuzzy_matcher/streaming_fuzzy_matcher.py +443 -0
- agentpool_toolsets/builtin/history.py +36 -0
- agentpool_toolsets/builtin/integration.py +85 -0
- agentpool_toolsets/builtin/skills.py +77 -0
- agentpool_toolsets/builtin/subagent_tools.py +324 -0
- agentpool_toolsets/builtin/tool_management.py +90 -0
- agentpool_toolsets/builtin/user_interaction.py +52 -0
- agentpool_toolsets/builtin/workers.py +128 -0
- agentpool_toolsets/composio_toolset.py +96 -0
- agentpool_toolsets/config_creation.py +192 -0
- agentpool_toolsets/entry_points.py +47 -0
- agentpool_toolsets/fsspec_toolset/__init__.py +7 -0
- agentpool_toolsets/fsspec_toolset/diagnostics.py +115 -0
- agentpool_toolsets/fsspec_toolset/grep.py +450 -0
- agentpool_toolsets/fsspec_toolset/helpers.py +631 -0
- agentpool_toolsets/fsspec_toolset/streaming_diff_parser.py +249 -0
- agentpool_toolsets/fsspec_toolset/toolset.py +1384 -0
- agentpool_toolsets/mcp_run_toolset.py +61 -0
- agentpool_toolsets/notifications.py +146 -0
- agentpool_toolsets/openapi.py +118 -0
- agentpool_toolsets/py.typed +0 -0
- agentpool_toolsets/search_toolset.py +202 -0
- agentpool_toolsets/semantic_memory_toolset.py +536 -0
- agentpool_toolsets/streaming_tools.py +265 -0
- 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
|
+
]
|