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,324 @@
|
|
|
1
|
+
"""Provider for subagent interaction tools with streaming support."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
6
|
+
|
|
7
|
+
from pydantic_ai import (
|
|
8
|
+
FunctionToolCallEvent,
|
|
9
|
+
FunctionToolResultEvent,
|
|
10
|
+
ModelRetry,
|
|
11
|
+
PartDeltaEvent,
|
|
12
|
+
PartStartEvent,
|
|
13
|
+
RetryPromptPart,
|
|
14
|
+
TextPart,
|
|
15
|
+
TextPartDelta,
|
|
16
|
+
ThinkingPart,
|
|
17
|
+
ThinkingPartDelta,
|
|
18
|
+
ToolCallPartDelta,
|
|
19
|
+
ToolReturnPart,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
23
|
+
from agentpool.log import get_logger
|
|
24
|
+
from agentpool.resource_providers import StaticResourceProvider
|
|
25
|
+
from agentpool.tools.exceptions import ToolError
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from collections.abc import AsyncIterator
|
|
30
|
+
|
|
31
|
+
from agentpool.agents.events import RichAgentStreamEvent
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
logger = get_logger(__name__)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Delta type identifiers for batching
|
|
38
|
+
type _DeltaType = Literal["text", "thinking", "tool_call"] | None
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
async def batch_stream_deltas( # noqa: PLR0915
|
|
42
|
+
stream: AsyncIterator[RichAgentStreamEvent[Any]],
|
|
43
|
+
) -> AsyncIterator[RichAgentStreamEvent[Any]]:
|
|
44
|
+
"""Batch consecutive delta events, yielding when event type changes.
|
|
45
|
+
|
|
46
|
+
This reduces UI update frequency by accumulating consecutive deltas of the same
|
|
47
|
+
type and yielding them as a single event when the type changes.
|
|
48
|
+
|
|
49
|
+
Batches:
|
|
50
|
+
- TextPartDelta events (consecutive deltas combined into one)
|
|
51
|
+
- ThinkingPartDelta events (consecutive deltas combined into one)
|
|
52
|
+
- ToolCallPartDelta events (consecutive deltas combined into one)
|
|
53
|
+
|
|
54
|
+
All other events pass through immediately and flush any pending batch.
|
|
55
|
+
PartStartEvents pass through unchanged.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
stream: Async iterator of stream events from agent.run_stream()
|
|
59
|
+
|
|
60
|
+
Yields:
|
|
61
|
+
Stream events with consecutive deltas batched together
|
|
62
|
+
"""
|
|
63
|
+
pending_content: list[str] = []
|
|
64
|
+
pending_type: _DeltaType = None
|
|
65
|
+
pending_index: int = 0 # For PartDeltaEvent.index
|
|
66
|
+
|
|
67
|
+
def _make_batched_event() -> PartDeltaEvent:
|
|
68
|
+
"""Create a synthetic PartDeltaEvent from accumulated content."""
|
|
69
|
+
content = "".join(pending_content)
|
|
70
|
+
delta: TextPartDelta | ThinkingPartDelta | ToolCallPartDelta
|
|
71
|
+
match pending_type:
|
|
72
|
+
case "text":
|
|
73
|
+
delta = TextPartDelta(content_delta=content)
|
|
74
|
+
case "thinking":
|
|
75
|
+
delta = ThinkingPartDelta(content_delta=content)
|
|
76
|
+
case "tool_call":
|
|
77
|
+
delta = ToolCallPartDelta(args_delta=content)
|
|
78
|
+
case _:
|
|
79
|
+
msg = f"Unexpected pending type: {pending_type}"
|
|
80
|
+
raise ValueError(msg)
|
|
81
|
+
return PartDeltaEvent(index=pending_index, delta=delta)
|
|
82
|
+
|
|
83
|
+
async for event in stream:
|
|
84
|
+
match event:
|
|
85
|
+
case PartDeltaEvent(delta=TextPartDelta(content_delta=content), index=idx):
|
|
86
|
+
if pending_type == "text":
|
|
87
|
+
pending_content.append(content)
|
|
88
|
+
else:
|
|
89
|
+
if pending_type is not None and pending_content:
|
|
90
|
+
yield _make_batched_event()
|
|
91
|
+
pending_content = [content]
|
|
92
|
+
pending_type = "text"
|
|
93
|
+
pending_index = idx
|
|
94
|
+
|
|
95
|
+
case PartDeltaEvent(delta=ThinkingPartDelta(content_delta=content), index=idx):
|
|
96
|
+
if content is None:
|
|
97
|
+
continue
|
|
98
|
+
if pending_type == "thinking":
|
|
99
|
+
pending_content.append(content)
|
|
100
|
+
else:
|
|
101
|
+
if pending_type is not None and pending_content:
|
|
102
|
+
yield _make_batched_event()
|
|
103
|
+
pending_content = [content]
|
|
104
|
+
pending_type = "thinking"
|
|
105
|
+
pending_index = idx
|
|
106
|
+
|
|
107
|
+
case PartDeltaEvent(delta=ToolCallPartDelta(args_delta=args), index=idx) if isinstance(
|
|
108
|
+
args, str
|
|
109
|
+
):
|
|
110
|
+
if pending_type == "tool_call":
|
|
111
|
+
pending_content.append(args)
|
|
112
|
+
else:
|
|
113
|
+
if pending_type is not None and pending_content:
|
|
114
|
+
yield _make_batched_event()
|
|
115
|
+
pending_content = [args]
|
|
116
|
+
pending_type = "tool_call"
|
|
117
|
+
pending_index = idx
|
|
118
|
+
|
|
119
|
+
case _:
|
|
120
|
+
# Any other event: flush pending batch and pass through
|
|
121
|
+
if pending_type is not None and pending_content:
|
|
122
|
+
yield _make_batched_event()
|
|
123
|
+
pending_content = []
|
|
124
|
+
pending_type = None
|
|
125
|
+
yield event
|
|
126
|
+
|
|
127
|
+
# Flush any remaining batch at end of stream
|
|
128
|
+
if pending_type is not None and pending_content:
|
|
129
|
+
yield _make_batched_event()
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
async def _stream_agent_with_progress(
|
|
133
|
+
ctx: AgentContext,
|
|
134
|
+
stream: AsyncIterator[RichAgentStreamEvent[Any]],
|
|
135
|
+
*,
|
|
136
|
+
batch_deltas: bool = False,
|
|
137
|
+
) -> str:
|
|
138
|
+
"""Stream an agent's execution and emit progress events.
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
ctx: Agent context for emitting events
|
|
142
|
+
stream: Async iterator of stream events from agent.run_stream()
|
|
143
|
+
batch_deltas: If True, batch consecutive text/thinking deltas for fewer UI updates
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Aggregated content from the stream
|
|
147
|
+
"""
|
|
148
|
+
if batch_deltas:
|
|
149
|
+
stream = batch_stream_deltas(stream)
|
|
150
|
+
|
|
151
|
+
aggregated: list[str] = []
|
|
152
|
+
async for event in stream:
|
|
153
|
+
match event:
|
|
154
|
+
case (
|
|
155
|
+
PartStartEvent(part=TextPart(content=delta))
|
|
156
|
+
| PartDeltaEvent(delta=TextPartDelta(content_delta=delta))
|
|
157
|
+
):
|
|
158
|
+
aggregated.append(delta)
|
|
159
|
+
await ctx.events.tool_call_progress("".join(aggregated))
|
|
160
|
+
case (
|
|
161
|
+
PartStartEvent(part=ThinkingPart(content=delta))
|
|
162
|
+
| PartDeltaEvent(delta=ThinkingPartDelta(content_delta=delta))
|
|
163
|
+
):
|
|
164
|
+
if delta:
|
|
165
|
+
aggregated.append(f"💭 {delta}")
|
|
166
|
+
await ctx.events.tool_call_progress("".join(aggregated))
|
|
167
|
+
case FunctionToolCallEvent(part=part):
|
|
168
|
+
aggregated.append(f"\n🔧 Using tool: {part.tool_name}\n")
|
|
169
|
+
await ctx.events.tool_call_progress("".join(aggregated))
|
|
170
|
+
case FunctionToolResultEvent(
|
|
171
|
+
result=ToolReturnPart(content=content, tool_name=tool_name),
|
|
172
|
+
):
|
|
173
|
+
aggregated.append(f"✅ {tool_name}: {content}\n")
|
|
174
|
+
await ctx.events.tool_call_progress("".join(aggregated))
|
|
175
|
+
|
|
176
|
+
case FunctionToolResultEvent(result=RetryPromptPart(tool_name=tool_name) as result):
|
|
177
|
+
error_message = result.model_response()
|
|
178
|
+
aggregated.append(f"❌ {tool_name or 'unknown'}: {error_message}\n")
|
|
179
|
+
await ctx.events.tool_call_progress("".join(aggregated))
|
|
180
|
+
case _:
|
|
181
|
+
pass
|
|
182
|
+
|
|
183
|
+
return "".join(aggregated).strip()
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
class SubagentTools(StaticResourceProvider):
|
|
187
|
+
"""Provider for subagent interaction tools with streaming progress."""
|
|
188
|
+
|
|
189
|
+
def __init__(
|
|
190
|
+
self,
|
|
191
|
+
name: str = "subagent_tools",
|
|
192
|
+
*,
|
|
193
|
+
batch_stream_deltas: bool = False,
|
|
194
|
+
) -> None:
|
|
195
|
+
super().__init__(name=name)
|
|
196
|
+
self._batch_stream_deltas = batch_stream_deltas
|
|
197
|
+
for tool in [
|
|
198
|
+
self.create_tool(
|
|
199
|
+
self.list_available_nodes, category="search", read_only=True, idempotent=True
|
|
200
|
+
),
|
|
201
|
+
self.create_tool(self.delegate_to, category="other"),
|
|
202
|
+
self.create_tool(self.ask_agent, category="other"),
|
|
203
|
+
]:
|
|
204
|
+
self.add_tool(tool)
|
|
205
|
+
|
|
206
|
+
async def list_available_nodes( # noqa: D417
|
|
207
|
+
self,
|
|
208
|
+
ctx: AgentContext,
|
|
209
|
+
node_type: Literal["all", "agent", "team"] = "all",
|
|
210
|
+
only_idle: bool = False,
|
|
211
|
+
) -> str:
|
|
212
|
+
"""List available agents and/or teams in the current pool.
|
|
213
|
+
|
|
214
|
+
Args:
|
|
215
|
+
node_type: Filter by node type - "all", "agent", or "team"
|
|
216
|
+
only_idle: If True, only returns nodes that aren't currently busy
|
|
217
|
+
|
|
218
|
+
Returns:
|
|
219
|
+
List of node names that you can use with delegate_to or ask_agent
|
|
220
|
+
"""
|
|
221
|
+
from agentpool import Agent
|
|
222
|
+
|
|
223
|
+
if not ctx.pool:
|
|
224
|
+
msg = "No agent pool available"
|
|
225
|
+
raise ToolError(msg)
|
|
226
|
+
lines: list[str] = []
|
|
227
|
+
if node_type in ("all", "agent"):
|
|
228
|
+
agents = dict(ctx.pool.all_agents)
|
|
229
|
+
if only_idle:
|
|
230
|
+
agents = {
|
|
231
|
+
n: a for n, a in agents.items() if not (isinstance(a, Agent) and a.is_busy())
|
|
232
|
+
}
|
|
233
|
+
for name, agent in agents.items():
|
|
234
|
+
lines.extend([
|
|
235
|
+
f"name: {name}",
|
|
236
|
+
"type: agent",
|
|
237
|
+
f"description: {agent.description or 'No description'}",
|
|
238
|
+
"---",
|
|
239
|
+
])
|
|
240
|
+
|
|
241
|
+
if node_type in ("all", "team"): # List teams
|
|
242
|
+
teams = ctx.pool.teams
|
|
243
|
+
if only_idle:
|
|
244
|
+
teams = {name: team for name, team in teams.items() if not team.is_running}
|
|
245
|
+
for name, team in teams.items():
|
|
246
|
+
lines.extend([
|
|
247
|
+
f"name: {name}",
|
|
248
|
+
f"description: {team.description or 'No description'}",
|
|
249
|
+
"---",
|
|
250
|
+
])
|
|
251
|
+
|
|
252
|
+
return "\n".join(lines) if lines else "No nodes available"
|
|
253
|
+
|
|
254
|
+
async def delegate_to( # noqa: D417
|
|
255
|
+
self,
|
|
256
|
+
ctx: AgentContext,
|
|
257
|
+
agent_or_team_name: str,
|
|
258
|
+
prompt: str,
|
|
259
|
+
) -> str:
|
|
260
|
+
"""Delegate a task to an agent or team.
|
|
261
|
+
|
|
262
|
+
If an action requires you to delegate a task, this tool can be used to assign and
|
|
263
|
+
execute a task. Instructions can be passed via the prompt parameter.
|
|
264
|
+
|
|
265
|
+
Args:
|
|
266
|
+
agent_or_team_name: The agent or team to delegate the task to
|
|
267
|
+
prompt: Instructions for the agent or team to delegate to.
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
The result of the delegated task
|
|
271
|
+
"""
|
|
272
|
+
if not ctx.pool:
|
|
273
|
+
msg = "Agent needs to be in a pool to delegate tasks"
|
|
274
|
+
raise ToolError(msg)
|
|
275
|
+
if agent_or_team_name not in ctx.pool.nodes:
|
|
276
|
+
msg = (
|
|
277
|
+
f"No agent or team found with name: {agent_or_team_name}. "
|
|
278
|
+
f"Available nodes: {', '.join(ctx.pool.nodes.keys())}"
|
|
279
|
+
)
|
|
280
|
+
raise ModelRetry(msg)
|
|
281
|
+
|
|
282
|
+
# For teams, use simple run() - no streaming support yet
|
|
283
|
+
if agent_or_team_name in ctx.pool.teams:
|
|
284
|
+
result = await ctx.pool.teams[agent_or_team_name].run(prompt)
|
|
285
|
+
return result.format(style="detailed", show_costs=True)
|
|
286
|
+
# For agents (regular or ACP), stream with progress events
|
|
287
|
+
agent = ctx.pool.all_agents[agent_or_team_name]
|
|
288
|
+
return await _stream_agent_with_progress(
|
|
289
|
+
ctx, agent.run_stream(prompt), batch_deltas=self._batch_stream_deltas
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
async def ask_agent( # noqa: D417
|
|
293
|
+
self,
|
|
294
|
+
ctx: AgentContext,
|
|
295
|
+
agent_name: str,
|
|
296
|
+
message: str,
|
|
297
|
+
) -> str:
|
|
298
|
+
"""Send a message to a specific agent and get their response.
|
|
299
|
+
|
|
300
|
+
Args:
|
|
301
|
+
agent_name: Name of the agent to interact with
|
|
302
|
+
message: Message to send to the agent
|
|
303
|
+
|
|
304
|
+
Returns:
|
|
305
|
+
The agent's response
|
|
306
|
+
"""
|
|
307
|
+
if not ctx.pool:
|
|
308
|
+
msg = "No agent pool available"
|
|
309
|
+
raise ToolError(msg)
|
|
310
|
+
|
|
311
|
+
if agent_name not in ctx.pool.all_agents:
|
|
312
|
+
available = list(ctx.pool.all_agents.keys())
|
|
313
|
+
names = ", ".join(available)
|
|
314
|
+
raise ModelRetry(f"Agent not found: {agent_name}. Available agents: {names}")
|
|
315
|
+
|
|
316
|
+
agent = ctx.pool.all_agents[agent_name]
|
|
317
|
+
try:
|
|
318
|
+
stream = agent.run_stream(message)
|
|
319
|
+
return await _stream_agent_with_progress(
|
|
320
|
+
ctx, stream, batch_deltas=self._batch_stream_deltas
|
|
321
|
+
)
|
|
322
|
+
except Exception as e:
|
|
323
|
+
msg = f"Failed to ask agent {agent_name}: {e}"
|
|
324
|
+
raise ModelRetry(msg) from e
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
"""Provider for tool management tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any
|
|
6
|
+
|
|
7
|
+
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
8
|
+
from agentpool.resource_providers import StaticResourceProvider
|
|
9
|
+
from agentpool.tools.base import Tool
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
async def register_tool( # noqa: D417
|
|
17
|
+
ctx: AgentContext,
|
|
18
|
+
tool: str | Callable[..., Any],
|
|
19
|
+
name: str | None = None,
|
|
20
|
+
description: str | None = None,
|
|
21
|
+
enabled: bool = True,
|
|
22
|
+
) -> str:
|
|
23
|
+
"""Register a new tool from callable or import path.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
tool: Callable function or import path string to register as tool
|
|
27
|
+
name: Optional name override for the tool
|
|
28
|
+
description: Optional description override for the tool
|
|
29
|
+
enabled: Whether the tool should be enabled initially
|
|
30
|
+
|
|
31
|
+
Returns:
|
|
32
|
+
Confirmation message with registered tool name
|
|
33
|
+
"""
|
|
34
|
+
# Create tool from callable/import path
|
|
35
|
+
tool_obj = Tool.from_callable(
|
|
36
|
+
tool,
|
|
37
|
+
name_override=name,
|
|
38
|
+
description_override=description,
|
|
39
|
+
source="dynamic",
|
|
40
|
+
enabled=enabled,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# Register with the agent's tool manager
|
|
44
|
+
registered_tool = ctx.agent.tools.register_tool(tool_obj)
|
|
45
|
+
|
|
46
|
+
return f"Successfully registered tool: {registered_tool.name}"
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
async def register_code_tool( # noqa: D417
|
|
50
|
+
ctx: AgentContext,
|
|
51
|
+
code: str,
|
|
52
|
+
name: str | None = None,
|
|
53
|
+
description: str | None = None,
|
|
54
|
+
enabled: bool = True,
|
|
55
|
+
) -> str:
|
|
56
|
+
"""Register a new tool from code string.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
code: Python code string containing a callable function
|
|
60
|
+
name: Optional name override for the tool
|
|
61
|
+
description: Optional description override for the tool
|
|
62
|
+
enabled: Whether the tool should be enabled initially
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Confirmation message with registered tool name
|
|
66
|
+
"""
|
|
67
|
+
# Create tool from code
|
|
68
|
+
tool_obj = Tool.from_code(
|
|
69
|
+
code,
|
|
70
|
+
name=name,
|
|
71
|
+
description=description,
|
|
72
|
+
)
|
|
73
|
+
tool_obj.enabled = enabled
|
|
74
|
+
tool_obj.source = "dynamic"
|
|
75
|
+
|
|
76
|
+
# Register with the agent's tool manager
|
|
77
|
+
registered_tool = ctx.agent.tools.register_tool(tool_obj)
|
|
78
|
+
|
|
79
|
+
return f"Successfully registered code tool: {registered_tool.name}"
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
class ToolManagementTools(StaticResourceProvider):
|
|
83
|
+
"""Provider for tool management tools."""
|
|
84
|
+
|
|
85
|
+
def __init__(self, name: str = "tool_management") -> None:
|
|
86
|
+
super().__init__(name=name)
|
|
87
|
+
self._tools = [
|
|
88
|
+
self.create_tool(register_tool, category="other"),
|
|
89
|
+
self.create_tool(register_code_tool, category="other"),
|
|
90
|
+
]
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"""Provider for user interaction tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, assert_never
|
|
6
|
+
|
|
7
|
+
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
8
|
+
from agentpool.resource_providers import StaticResourceProvider
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
async def ask_user( # noqa: D417
|
|
12
|
+
ctx: AgentContext,
|
|
13
|
+
prompt: str,
|
|
14
|
+
response_schema: dict[str, Any] | None = None,
|
|
15
|
+
) -> str:
|
|
16
|
+
"""Allow LLM to ask user a clarifying question during processing.
|
|
17
|
+
|
|
18
|
+
This tool enables agents to ask users for additional information or clarification
|
|
19
|
+
when needed to complete a task effectively.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
prompt: Question to ask the user
|
|
23
|
+
response_schema: Optional JSON schema for structured response (defaults to string)
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
The user's response as a string
|
|
27
|
+
"""
|
|
28
|
+
from mcp.types import ElicitRequestFormParams, ElicitResult, ErrorData
|
|
29
|
+
|
|
30
|
+
schema = response_schema or {"type": "string"} # string schema if no none provided
|
|
31
|
+
params = ElicitRequestFormParams(message=prompt, requestedSchema=schema)
|
|
32
|
+
result = await ctx.handle_elicitation(params)
|
|
33
|
+
|
|
34
|
+
match result:
|
|
35
|
+
case ElicitResult(action="accept", content=content):
|
|
36
|
+
return str(content)
|
|
37
|
+
case ElicitResult(action="cancel"):
|
|
38
|
+
return "User cancelled the request"
|
|
39
|
+
case ElicitResult():
|
|
40
|
+
return "User declined to answer"
|
|
41
|
+
case ErrorData(message=message):
|
|
42
|
+
return f"Error: {message}"
|
|
43
|
+
case _ as unreachable:
|
|
44
|
+
assert_never(unreachable)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class UserInteractionTools(StaticResourceProvider):
|
|
48
|
+
"""Provider for user interaction tools."""
|
|
49
|
+
|
|
50
|
+
def __init__(self, name: str = "user_interaction") -> None:
|
|
51
|
+
super().__init__(name=name)
|
|
52
|
+
self._tools = [self.create_tool(ask_user, category="other", open_world=True)]
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""Provider for worker agent tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any
|
|
6
|
+
|
|
7
|
+
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
8
|
+
from agentpool.log import get_logger
|
|
9
|
+
from agentpool.resource_providers import ResourceProvider
|
|
10
|
+
from agentpool.tools.exceptions import ToolError
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from agentpool.tools.base import Tool
|
|
15
|
+
from agentpool_config.workers import WorkerConfig
|
|
16
|
+
|
|
17
|
+
logger = get_logger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class WorkersTools(ResourceProvider):
|
|
21
|
+
"""Provider for worker agent tools.
|
|
22
|
+
|
|
23
|
+
Creates tools for each configured worker that delegate to agents/teams in the pool.
|
|
24
|
+
Tools are created lazily when get_tools() is called, using AgentContext to access
|
|
25
|
+
the pool at call time.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, workers: list[WorkerConfig], name: str = "workers") -> None:
|
|
29
|
+
"""Initialize workers toolset.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
workers: List of worker configurations
|
|
33
|
+
name: Provider name
|
|
34
|
+
"""
|
|
35
|
+
super().__init__(name=name)
|
|
36
|
+
self.workers = workers
|
|
37
|
+
|
|
38
|
+
async def get_tools(self) -> list[Tool]:
|
|
39
|
+
"""Get tools for all configured workers."""
|
|
40
|
+
return [self._create_worker_tool(i) for i in self.workers]
|
|
41
|
+
|
|
42
|
+
def _create_worker_tool(self, worker_config: WorkerConfig) -> Tool:
|
|
43
|
+
"""Create a tool for a single worker configuration."""
|
|
44
|
+
from agentpool_config.workers import AgentWorkerConfig
|
|
45
|
+
|
|
46
|
+
worker_name = worker_config.name
|
|
47
|
+
# Regular agents get history management
|
|
48
|
+
if isinstance(worker_config, AgentWorkerConfig):
|
|
49
|
+
return self._create_agent_tool(
|
|
50
|
+
worker_name,
|
|
51
|
+
reset_history_on_run=worker_config.reset_history_on_run,
|
|
52
|
+
pass_message_history=worker_config.pass_message_history,
|
|
53
|
+
)
|
|
54
|
+
# Teams, ACP agents, AGUI agents - all handled uniformly
|
|
55
|
+
return self._create_node_tool(worker_name)
|
|
56
|
+
|
|
57
|
+
def _create_agent_tool(
|
|
58
|
+
self,
|
|
59
|
+
agent_name: str,
|
|
60
|
+
*,
|
|
61
|
+
reset_history_on_run: bool = True,
|
|
62
|
+
pass_message_history: bool = False,
|
|
63
|
+
) -> Tool:
|
|
64
|
+
"""Create tool for a regular agent worker with history management."""
|
|
65
|
+
|
|
66
|
+
async def run(ctx: AgentContext, prompt: str) -> Any:
|
|
67
|
+
if not ctx.pool:
|
|
68
|
+
msg = "No agent pool available"
|
|
69
|
+
raise ToolError(msg)
|
|
70
|
+
if agent_name not in ctx.pool.agents:
|
|
71
|
+
msg = f"Agent {agent_name!r} not found in pool"
|
|
72
|
+
raise ToolError(msg)
|
|
73
|
+
|
|
74
|
+
worker = ctx.pool.agents[agent_name]
|
|
75
|
+
old_history = None
|
|
76
|
+
|
|
77
|
+
if pass_message_history:
|
|
78
|
+
old_history = worker.conversation.get_history()
|
|
79
|
+
worker.conversation.set_history(ctx.agent.conversation.get_history())
|
|
80
|
+
elif reset_history_on_run:
|
|
81
|
+
worker.conversation.clear()
|
|
82
|
+
|
|
83
|
+
try:
|
|
84
|
+
result = await worker.run(prompt)
|
|
85
|
+
return result.data
|
|
86
|
+
finally:
|
|
87
|
+
if old_history is not None:
|
|
88
|
+
worker.conversation.set_history(old_history)
|
|
89
|
+
|
|
90
|
+
tool_name = f"ask_{agent_name}"
|
|
91
|
+
normalized_name = agent_name.replace("_", " ").title()
|
|
92
|
+
docstring = f"Get expert answer from specialized agent: {normalized_name}"
|
|
93
|
+
|
|
94
|
+
run.__name__ = tool_name
|
|
95
|
+
run.__doc__ = docstring
|
|
96
|
+
|
|
97
|
+
return self.create_tool(run, name_override=tool_name, description_override=docstring)
|
|
98
|
+
|
|
99
|
+
def _create_node_tool(self, node_name: str) -> Tool:
|
|
100
|
+
"""Create tool for non-agent nodes (teams, ACP agents, AGUI agents)."""
|
|
101
|
+
from agentpool import BaseTeam
|
|
102
|
+
|
|
103
|
+
async def run(ctx: AgentContext, prompt: str) -> str:
|
|
104
|
+
if not ctx.pool:
|
|
105
|
+
msg = "No agent pool available"
|
|
106
|
+
raise ToolError(msg)
|
|
107
|
+
if node_name not in ctx.pool.nodes:
|
|
108
|
+
msg = f"Worker {node_name!r} not found in pool"
|
|
109
|
+
raise ToolError(msg)
|
|
110
|
+
|
|
111
|
+
worker = ctx.pool.nodes[node_name]
|
|
112
|
+
result = await worker.run(prompt)
|
|
113
|
+
|
|
114
|
+
# Teams get formatted output
|
|
115
|
+
if isinstance(worker, BaseTeam):
|
|
116
|
+
return result.format(style="detailed", show_costs=True)
|
|
117
|
+
|
|
118
|
+
# Other nodes (ACP, AGUI) just return data as string
|
|
119
|
+
return str(result.data)
|
|
120
|
+
|
|
121
|
+
tool_name = f"ask_{node_name}"
|
|
122
|
+
normalized_name = node_name.replace("_", " ").title()
|
|
123
|
+
docstring = f"Delegate task to worker: {normalized_name}"
|
|
124
|
+
|
|
125
|
+
run.__name__ = tool_name
|
|
126
|
+
run.__doc__ = docstring
|
|
127
|
+
|
|
128
|
+
return self.create_tool(run, name_override=tool_name, description_override=docstring)
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"""Composio based toolset implementation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
from agentpool.log import get_logger
|
|
9
|
+
from agentpool.resource_providers import ResourceProvider
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Callable
|
|
14
|
+
|
|
15
|
+
from agentpool.tools.base import Tool
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
logger = get_logger(__name__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ComposioTools(ResourceProvider):
|
|
22
|
+
"""Provider for composio tools."""
|
|
23
|
+
|
|
24
|
+
def __init__(self, user_id: str, toolsets: list[str], api_key: str | None = None) -> None:
|
|
25
|
+
from composio import Composio
|
|
26
|
+
from composio.core.provider._openai import OpenAIProvider
|
|
27
|
+
|
|
28
|
+
super().__init__(name=f"composio_{user_id}")
|
|
29
|
+
self.user_id = user_id
|
|
30
|
+
key = api_key or os.environ.get("COMPOSIO_API_KEY")
|
|
31
|
+
if key:
|
|
32
|
+
self.composio = Composio[OpenAIProvider](api_key=key)
|
|
33
|
+
else:
|
|
34
|
+
self.composio = Composio[OpenAIProvider]()
|
|
35
|
+
self._tools: list[Tool] | None = None
|
|
36
|
+
self._toolkits = toolsets
|
|
37
|
+
|
|
38
|
+
def _create_tool_handler(self, tool_slug: str) -> Callable[..., Any]:
|
|
39
|
+
"""Create a handler function for a specific tool."""
|
|
40
|
+
|
|
41
|
+
def handle_tool_call(**kwargs: Any) -> Any:
|
|
42
|
+
try:
|
|
43
|
+
return self.composio.tools.execute(
|
|
44
|
+
slug=tool_slug,
|
|
45
|
+
arguments=kwargs,
|
|
46
|
+
user_id=self.user_id,
|
|
47
|
+
)
|
|
48
|
+
except Exception:
|
|
49
|
+
logger.exception("Error executing tool", name=tool_slug)
|
|
50
|
+
return {"error": f"Failed to execute tool {tool_slug}"}
|
|
51
|
+
|
|
52
|
+
handle_tool_call.__name__ = tool_slug
|
|
53
|
+
return handle_tool_call
|
|
54
|
+
|
|
55
|
+
async def get_tools(self) -> list[Tool]:
|
|
56
|
+
"""Get tools from composio."""
|
|
57
|
+
# Return cached tools if available
|
|
58
|
+
if self._tools is not None:
|
|
59
|
+
return self._tools
|
|
60
|
+
|
|
61
|
+
self._tools = []
|
|
62
|
+
|
|
63
|
+
try:
|
|
64
|
+
# Get tools for GitHub toolkit using v3 API
|
|
65
|
+
tools = self.composio.tools.get(self.user_id, toolkits=self._toolkits)
|
|
66
|
+
|
|
67
|
+
for tool_def in tools:
|
|
68
|
+
# In v3 SDK, tools are OpenAI formatted by default
|
|
69
|
+
if isinstance(tool_def, dict) and "function" in tool_def:
|
|
70
|
+
tool_slug = tool_def["function"].get("name", "")
|
|
71
|
+
if tool_slug:
|
|
72
|
+
fn = self._create_tool_handler(tool_slug)
|
|
73
|
+
tool = self.create_tool(fn, schema_override=tool_def["function"])
|
|
74
|
+
self._tools.append(tool)
|
|
75
|
+
|
|
76
|
+
except Exception:
|
|
77
|
+
logger.exception("Error getting Composio tools")
|
|
78
|
+
# Return empty list if there's an error
|
|
79
|
+
self._tools = []
|
|
80
|
+
|
|
81
|
+
return self._tools
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
if __name__ == "__main__":
|
|
85
|
+
import anyio
|
|
86
|
+
|
|
87
|
+
async def main() -> None:
|
|
88
|
+
from agentpool import Agent
|
|
89
|
+
|
|
90
|
+
tools = ComposioTools("user@example.com", toolsets=["github"])
|
|
91
|
+
agent = Agent(model="gpt-5-nano")
|
|
92
|
+
agent.tools.add_provider(tools)
|
|
93
|
+
result = await agent.run("tell me the tools at your disposal")
|
|
94
|
+
print(result)
|
|
95
|
+
|
|
96
|
+
anyio.run(main)
|