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,255 @@
|
|
|
1
|
+
"""Tool management for AgentPool."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import asyncio
|
|
6
|
+
from collections.abc import Callable, Sequence
|
|
7
|
+
from contextlib import asynccontextmanager
|
|
8
|
+
from typing import TYPE_CHECKING, Literal, assert_never
|
|
9
|
+
|
|
10
|
+
from agentpool.log import get_logger
|
|
11
|
+
from agentpool.resource_providers import StaticResourceProvider
|
|
12
|
+
from agentpool.tools.base import Tool
|
|
13
|
+
from agentpool.utils.baseregistry import AgentPoolError
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from collections.abc import AsyncIterator
|
|
18
|
+
|
|
19
|
+
from agentpool.common_types import ToolType
|
|
20
|
+
from agentpool.prompts.prompts import MCPClientPrompt
|
|
21
|
+
from agentpool.resource_providers import ResourceProvider
|
|
22
|
+
from agentpool.resource_providers.codemode.provider import CodeModeResourceProvider
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
logger = get_logger(__name__)
|
|
26
|
+
|
|
27
|
+
MAX_LEN_DESCRIPTION = 2000
|
|
28
|
+
ToolState = Literal["all", "enabled", "disabled"]
|
|
29
|
+
ProviderName = str
|
|
30
|
+
OwnerType = Literal["pool", "team", "node"]
|
|
31
|
+
ToolMode = Literal["codemode"]
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class ToolError(AgentPoolError):
|
|
35
|
+
"""Base exception for tool-related errors."""
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ToolManager:
|
|
39
|
+
"""Manages tool registration, enabling/disabling and access."""
|
|
40
|
+
|
|
41
|
+
def __init__(
|
|
42
|
+
self,
|
|
43
|
+
tools: Sequence[ToolType] | None = None,
|
|
44
|
+
tool_mode: ToolMode | None = None,
|
|
45
|
+
) -> None:
|
|
46
|
+
"""Initialize tool manager.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
tools: Initial tools to register
|
|
50
|
+
tool_mode: Tool execution mode (None or "codemode")
|
|
51
|
+
"""
|
|
52
|
+
super().__init__()
|
|
53
|
+
self.external_providers: list[ResourceProvider] = []
|
|
54
|
+
self.worker_provider = StaticResourceProvider(name="workers")
|
|
55
|
+
self.builtin_provider = StaticResourceProvider(name="builtin")
|
|
56
|
+
self.tool_mode = tool_mode
|
|
57
|
+
|
|
58
|
+
# CodeModeResourceProvider gets populated with providers in providers property
|
|
59
|
+
from agentpool.resource_providers.codemode.provider import CodeModeResourceProvider
|
|
60
|
+
|
|
61
|
+
self._codemode_provider: CodeModeResourceProvider = CodeModeResourceProvider([])
|
|
62
|
+
|
|
63
|
+
# Forward to provider methods
|
|
64
|
+
self.tool = self.builtin_provider.tool
|
|
65
|
+
self.register_tool = self.builtin_provider.register_tool
|
|
66
|
+
self.register_worker = self.worker_provider.register_worker
|
|
67
|
+
|
|
68
|
+
# Register initial tools
|
|
69
|
+
for tool in tools or []:
|
|
70
|
+
t = self._validate_item(tool)
|
|
71
|
+
self.builtin_provider.add_tool(t)
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def providers(self) -> list[ResourceProvider]:
|
|
75
|
+
"""Get all providers: external + worker + builtin providers."""
|
|
76
|
+
if self.tool_mode == "codemode":
|
|
77
|
+
# Update the providers list with current providers
|
|
78
|
+
self._codemode_provider.providers[:] = [
|
|
79
|
+
*self.external_providers,
|
|
80
|
+
self.worker_provider,
|
|
81
|
+
self.builtin_provider,
|
|
82
|
+
]
|
|
83
|
+
return [self._codemode_provider]
|
|
84
|
+
|
|
85
|
+
return [*self.external_providers, self.worker_provider, self.builtin_provider]
|
|
86
|
+
|
|
87
|
+
async def __prompt__(self) -> str:
|
|
88
|
+
enabled_tools = [t.name for t in await self.get_tools() if t.enabled]
|
|
89
|
+
if not enabled_tools:
|
|
90
|
+
return "No tools available"
|
|
91
|
+
return f"Available tools: {', '.join(enabled_tools)}"
|
|
92
|
+
|
|
93
|
+
def add_provider(self, provider: ResourceProvider, owner: str | None = None) -> None:
|
|
94
|
+
"""Add an external resource provider.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
provider: ResourceProvider instance (e.g., MCP server, custom provider)
|
|
98
|
+
owner: Optional owner for the provider
|
|
99
|
+
"""
|
|
100
|
+
if owner:
|
|
101
|
+
provider.owner = owner
|
|
102
|
+
self.external_providers.append(provider)
|
|
103
|
+
|
|
104
|
+
def remove_provider(self, provider: ResourceProvider | ProviderName) -> None:
|
|
105
|
+
"""Remove an external resource provider."""
|
|
106
|
+
from agentpool.resource_providers import ResourceProvider
|
|
107
|
+
|
|
108
|
+
match provider:
|
|
109
|
+
case ResourceProvider():
|
|
110
|
+
self.external_providers.remove(provider)
|
|
111
|
+
case str():
|
|
112
|
+
for p in self.external_providers:
|
|
113
|
+
if p.name == provider:
|
|
114
|
+
self.external_providers.remove(p)
|
|
115
|
+
case _ as unreachable:
|
|
116
|
+
assert_never(unreachable)
|
|
117
|
+
|
|
118
|
+
async def reset_states(self) -> None:
|
|
119
|
+
"""Reset all tools to their default enabled states."""
|
|
120
|
+
for info in await self.get_tools():
|
|
121
|
+
info.enabled = True
|
|
122
|
+
|
|
123
|
+
def _validate_item(self, item: ToolType) -> Tool:
|
|
124
|
+
"""Validate and convert items before registration."""
|
|
125
|
+
match item:
|
|
126
|
+
case Tool():
|
|
127
|
+
return item
|
|
128
|
+
case Callable() | str():
|
|
129
|
+
return Tool.from_callable(item)
|
|
130
|
+
case _:
|
|
131
|
+
typ = type(item)
|
|
132
|
+
msg = f"Item must be Tool or callable. Got {typ}"
|
|
133
|
+
raise ToolError(msg)
|
|
134
|
+
|
|
135
|
+
async def enable_tool(self, tool_name: str) -> None:
|
|
136
|
+
"""Enable a previously disabled tool."""
|
|
137
|
+
tool_info = await self.get_tool(tool_name)
|
|
138
|
+
tool_info.enabled = True
|
|
139
|
+
logger.debug("Enabled tool", tool_name=tool_name)
|
|
140
|
+
|
|
141
|
+
async def disable_tool(self, tool_name: str) -> None:
|
|
142
|
+
"""Disable a tool."""
|
|
143
|
+
tool_info = await self.get_tool(tool_name)
|
|
144
|
+
tool_info.enabled = False
|
|
145
|
+
logger.debug("Disabled tool", tool_name=tool_name)
|
|
146
|
+
|
|
147
|
+
async def list_tools(self) -> dict[str, bool]:
|
|
148
|
+
"""Get a mapping of all tools and their enabled status."""
|
|
149
|
+
return {tool.name: tool.enabled for tool in await self.get_tools()}
|
|
150
|
+
|
|
151
|
+
async def get_tools(
|
|
152
|
+
self,
|
|
153
|
+
state: ToolState = "all",
|
|
154
|
+
names: str | list[str] | None = None,
|
|
155
|
+
) -> list[Tool]:
|
|
156
|
+
"""Get tool objects based on filters."""
|
|
157
|
+
tools: list[Tool] = []
|
|
158
|
+
# Get tools from providers concurrently
|
|
159
|
+
provider_coroutines = [provider.get_tools() for provider in self.providers]
|
|
160
|
+
results = await asyncio.gather(*provider_coroutines, return_exceptions=True)
|
|
161
|
+
for provider, result in zip(self.providers, results, strict=False):
|
|
162
|
+
if isinstance(result, BaseException):
|
|
163
|
+
msg = "Failed to get tools from provider"
|
|
164
|
+
logger.warning(msg, provider=provider, result=result)
|
|
165
|
+
continue
|
|
166
|
+
tools.extend(t for t in result if t.matches_filter(state))
|
|
167
|
+
|
|
168
|
+
match names:
|
|
169
|
+
case str():
|
|
170
|
+
tools = [t for t in tools if t.name == names]
|
|
171
|
+
case list():
|
|
172
|
+
tools = [t for t in tools if t.name in names]
|
|
173
|
+
return tools
|
|
174
|
+
|
|
175
|
+
async def get_tool(self, name: str) -> Tool:
|
|
176
|
+
"""Get a specific tool by name.
|
|
177
|
+
|
|
178
|
+
First checks local tools, then uses concurrent provider fetching.
|
|
179
|
+
"""
|
|
180
|
+
tool = next((tool for tool in await self.get_tools() if tool.name == name), None)
|
|
181
|
+
if not tool:
|
|
182
|
+
msg = f"Tool not found: {tool}"
|
|
183
|
+
raise ToolError(msg)
|
|
184
|
+
return tool
|
|
185
|
+
|
|
186
|
+
async def list_prompts(self) -> list[MCPClientPrompt]:
|
|
187
|
+
"""Get all prompts from all providers."""
|
|
188
|
+
from agentpool.mcp_server.manager import MCPManager
|
|
189
|
+
|
|
190
|
+
all_prompts: list[MCPClientPrompt] = []
|
|
191
|
+
# Get prompts from all external providers (check if they're MCP providers)
|
|
192
|
+
for provider in self.external_providers:
|
|
193
|
+
if isinstance(provider, MCPManager):
|
|
194
|
+
try:
|
|
195
|
+
# Get prompts from MCP providers via the aggregating provider
|
|
196
|
+
agg_provider = provider.get_aggregating_provider()
|
|
197
|
+
prompts = await agg_provider.get_prompts()
|
|
198
|
+
all_prompts.extend(prompts)
|
|
199
|
+
except Exception:
|
|
200
|
+
logger.exception("Failed to get prompts from provider", provider=provider)
|
|
201
|
+
|
|
202
|
+
return all_prompts
|
|
203
|
+
|
|
204
|
+
@asynccontextmanager
|
|
205
|
+
async def temporary_tools(
|
|
206
|
+
self,
|
|
207
|
+
tools: ToolType | Sequence[ToolType],
|
|
208
|
+
*,
|
|
209
|
+
exclusive: bool = False,
|
|
210
|
+
) -> AsyncIterator[list[Tool]]:
|
|
211
|
+
"""Temporarily register tools.
|
|
212
|
+
|
|
213
|
+
Args:
|
|
214
|
+
tools: Tool(s) to register
|
|
215
|
+
exclusive: Whether to temporarily disable all other tools
|
|
216
|
+
|
|
217
|
+
Yields:
|
|
218
|
+
List of registered tool infos
|
|
219
|
+
"""
|
|
220
|
+
# Normalize inputs to lists
|
|
221
|
+
tools_list: list[ToolType] = [tools] if not isinstance(tools, Sequence) else list(tools)
|
|
222
|
+
# Store original tool states if exclusive
|
|
223
|
+
tools = await self.get_tools()
|
|
224
|
+
original_states: dict[str, bool] = {}
|
|
225
|
+
if exclusive:
|
|
226
|
+
original_states = {t.name: t.enabled for t in tools}
|
|
227
|
+
# Disable all existing tools
|
|
228
|
+
for t in tools:
|
|
229
|
+
t.enabled = False
|
|
230
|
+
# Register all tools
|
|
231
|
+
registered_tools: list[Tool] = []
|
|
232
|
+
try:
|
|
233
|
+
for tool in tools_list:
|
|
234
|
+
tool_info = self.register_tool(tool)
|
|
235
|
+
registered_tools.append(tool_info)
|
|
236
|
+
yield registered_tools
|
|
237
|
+
|
|
238
|
+
finally:
|
|
239
|
+
# Remove temporary tools
|
|
240
|
+
for tool_info in registered_tools:
|
|
241
|
+
self.builtin_provider.remove_tool(tool_info.name)
|
|
242
|
+
# Restore original tool states if exclusive
|
|
243
|
+
if exclusive:
|
|
244
|
+
for name_, was_enabled in original_states.items():
|
|
245
|
+
t_ = await self.get_tool(name_)
|
|
246
|
+
t_.enabled = was_enabled
|
|
247
|
+
|
|
248
|
+
|
|
249
|
+
if __name__ == "__main__":
|
|
250
|
+
manager = ToolManager()
|
|
251
|
+
|
|
252
|
+
@manager.tool(name="custom_name", description="Custom description")
|
|
253
|
+
def with_params(query: str) -> str:
|
|
254
|
+
"""With parameters."""
|
|
255
|
+
return query.upper()
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"""Tool management for AgentPool."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from datetime import datetime
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
7
|
+
from uuid import uuid4
|
|
8
|
+
|
|
9
|
+
from pydantic import Field
|
|
10
|
+
from schemez import Schema
|
|
11
|
+
|
|
12
|
+
from agentpool.text_templates import get_tool_call_template
|
|
13
|
+
from agentpool.utils.now import get_now
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
if TYPE_CHECKING:
|
|
17
|
+
from agentpool.text_templates import FormatStyle
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class ToolCallInfo(Schema):
|
|
21
|
+
"""Information about an executed tool call."""
|
|
22
|
+
|
|
23
|
+
tool_name: str
|
|
24
|
+
"""Name of the tool that was called."""
|
|
25
|
+
|
|
26
|
+
args: dict[str, Any]
|
|
27
|
+
"""Arguments passed to the tool."""
|
|
28
|
+
|
|
29
|
+
result: Any
|
|
30
|
+
"""Result returned by the tool."""
|
|
31
|
+
|
|
32
|
+
agent_name: str
|
|
33
|
+
"""Name of the calling agent."""
|
|
34
|
+
|
|
35
|
+
tool_call_id: str = Field(default_factory=lambda: str(uuid4()))
|
|
36
|
+
"""ID provided by the model (e.g. OpenAI function call ID)."""
|
|
37
|
+
|
|
38
|
+
timestamp: datetime = Field(default_factory=get_now)
|
|
39
|
+
"""When the tool was called."""
|
|
40
|
+
|
|
41
|
+
message_id: str | None = None
|
|
42
|
+
"""ID of the message that triggered this tool call."""
|
|
43
|
+
|
|
44
|
+
error: str | None = None
|
|
45
|
+
"""Error message if the tool call failed."""
|
|
46
|
+
|
|
47
|
+
timing: float | None = None
|
|
48
|
+
"""Time taken for this specific tool call in seconds."""
|
|
49
|
+
|
|
50
|
+
agent_tool_name: str | None = None
|
|
51
|
+
"""If this tool is agent-based, the name of that agent."""
|
|
52
|
+
|
|
53
|
+
def format(
|
|
54
|
+
self,
|
|
55
|
+
style: FormatStyle | Literal["custom"] = "simple",
|
|
56
|
+
*,
|
|
57
|
+
template: str | None = None,
|
|
58
|
+
variables: dict[str, Any] | None = None,
|
|
59
|
+
show_timing: bool = True,
|
|
60
|
+
) -> str:
|
|
61
|
+
"""Format tool call information with configurable style.
|
|
62
|
+
|
|
63
|
+
Args:
|
|
64
|
+
style: Predefined style to use:
|
|
65
|
+
- simple: Compact single-line format
|
|
66
|
+
- detailed: Multi-line with all details
|
|
67
|
+
- markdown: Formatted markdown with syntax highlighting
|
|
68
|
+
template: Optional custom template (required if style="custom")
|
|
69
|
+
variables: Additional variables for template rendering
|
|
70
|
+
show_timing: Whether to include execution timing
|
|
71
|
+
|
|
72
|
+
Raises:
|
|
73
|
+
ValueError: If style is invalid or custom template is missing
|
|
74
|
+
"""
|
|
75
|
+
from jinjarope import Environment
|
|
76
|
+
|
|
77
|
+
template_str = template if style == "custom" else get_tool_call_template(style)
|
|
78
|
+
if not template_str:
|
|
79
|
+
raise ValueError("Custom template is required for style='custom'")
|
|
80
|
+
env = Environment(trim_blocks=True, lstrip_blocks=True)
|
|
81
|
+
env.filters["repr"] = repr
|
|
82
|
+
template_obj = env.from_string(template_str)
|
|
83
|
+
vars_ = self.model_dump()
|
|
84
|
+
vars_["show_timing"] = show_timing
|
|
85
|
+
if variables:
|
|
86
|
+
vars_.update(variables)
|
|
87
|
+
return template_obj.render(**vars_)
|
agentpool/ui/__init__.py
ADDED
agentpool/ui/base.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Base input provider class."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from abc import ABC, abstractmethod
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from collections.abc import Coroutine
|
|
11
|
+
|
|
12
|
+
from mcp import types
|
|
13
|
+
from pydantic import BaseModel
|
|
14
|
+
|
|
15
|
+
from agentpool.agents.context import ConfirmationResult
|
|
16
|
+
from agentpool.messaging import ChatMessage
|
|
17
|
+
from agentpool.messaging.context import NodeContext
|
|
18
|
+
from agentpool.tools.base import Tool
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class InputProvider(ABC):
|
|
22
|
+
"""Base class for handling all UI interactions."""
|
|
23
|
+
|
|
24
|
+
async def get_input(
|
|
25
|
+
self,
|
|
26
|
+
context: NodeContext,
|
|
27
|
+
prompt: str,
|
|
28
|
+
output_type: type | None = None,
|
|
29
|
+
message_history: list[ChatMessage[Any]] | None = None,
|
|
30
|
+
) -> Any:
|
|
31
|
+
"""Get normal input (used by HumanProvider).
|
|
32
|
+
|
|
33
|
+
Args:
|
|
34
|
+
context: Current agent context
|
|
35
|
+
prompt: The prompt to show to the user
|
|
36
|
+
output_type: Optional type for structured responses
|
|
37
|
+
message_history: Optional conversation history
|
|
38
|
+
"""
|
|
39
|
+
if output_type:
|
|
40
|
+
return await self.get_structured_input(context, prompt, output_type, message_history)
|
|
41
|
+
return await self.get_text_input(context, prompt, message_history)
|
|
42
|
+
|
|
43
|
+
async def get_text_input(
|
|
44
|
+
self,
|
|
45
|
+
context: NodeContext[Any],
|
|
46
|
+
prompt: str,
|
|
47
|
+
message_history: list[ChatMessage[Any]] | None = None,
|
|
48
|
+
) -> str:
|
|
49
|
+
"""Get normal text input."""
|
|
50
|
+
raise NotImplementedError
|
|
51
|
+
|
|
52
|
+
async def get_structured_input(
|
|
53
|
+
self,
|
|
54
|
+
context: NodeContext[Any],
|
|
55
|
+
prompt: str,
|
|
56
|
+
output_type: type[BaseModel],
|
|
57
|
+
message_history: list[ChatMessage[Any]] | None = None,
|
|
58
|
+
) -> BaseModel:
|
|
59
|
+
"""Get structured input."""
|
|
60
|
+
raise NotImplementedError
|
|
61
|
+
|
|
62
|
+
@abstractmethod
|
|
63
|
+
def get_tool_confirmation(
|
|
64
|
+
self,
|
|
65
|
+
context: NodeContext[Any],
|
|
66
|
+
tool: Tool,
|
|
67
|
+
args: dict[str, Any],
|
|
68
|
+
message_history: list[ChatMessage[Any]] | None = None,
|
|
69
|
+
) -> Coroutine[Any, Any, ConfirmationResult]:
|
|
70
|
+
"""Get tool execution confirmation.
|
|
71
|
+
|
|
72
|
+
Args:
|
|
73
|
+
context: Current node context
|
|
74
|
+
tool: Information about the tool to be executed
|
|
75
|
+
args: Tool arguments
|
|
76
|
+
message_history: Optional conversation history
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
@abstractmethod
|
|
80
|
+
def get_elicitation(
|
|
81
|
+
self,
|
|
82
|
+
params: types.ElicitRequestParams,
|
|
83
|
+
) -> Coroutine[Any, Any, types.ElicitResult | types.ErrorData]:
|
|
84
|
+
"""Get user response to elicitation request.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
context: Current agent context
|
|
88
|
+
params: MCP elicit request parameters
|
|
89
|
+
"""
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Mock input provider implementation."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
7
|
+
|
|
8
|
+
from agentpool.ui.base import InputProvider
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
if TYPE_CHECKING:
|
|
12
|
+
from mcp import types
|
|
13
|
+
|
|
14
|
+
from agentpool.agents.context import ConfirmationResult
|
|
15
|
+
from agentpool.messaging import ChatMessage
|
|
16
|
+
from agentpool.messaging.context import NodeContext
|
|
17
|
+
from agentpool.tools.base import Tool
|
|
18
|
+
|
|
19
|
+
InputMethod = Literal["get_input", "get_tool_confirmation", "get_elicitation"]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
@dataclass
|
|
23
|
+
class InputCall:
|
|
24
|
+
"""Record of an input provider call."""
|
|
25
|
+
|
|
26
|
+
method: InputMethod
|
|
27
|
+
args: tuple[Any, ...]
|
|
28
|
+
kwargs: dict[str, Any]
|
|
29
|
+
result: Any
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class MockInputProvider(InputProvider):
|
|
33
|
+
"""Provider that records calls and returns pre-configured responses."""
|
|
34
|
+
|
|
35
|
+
def __init__(
|
|
36
|
+
self,
|
|
37
|
+
*,
|
|
38
|
+
input_response: str = "mock response",
|
|
39
|
+
tool_confirmation: ConfirmationResult = "allow",
|
|
40
|
+
elicitation_response: dict[str, Any] | None = None,
|
|
41
|
+
) -> None:
|
|
42
|
+
self.input_response = input_response
|
|
43
|
+
self.tool_confirmation = tool_confirmation
|
|
44
|
+
self.elicitation_response = elicitation_response or {"response": "mock response"}
|
|
45
|
+
self.calls: list[InputCall] = []
|
|
46
|
+
|
|
47
|
+
async def get_input(
|
|
48
|
+
self,
|
|
49
|
+
context: NodeContext,
|
|
50
|
+
prompt: str,
|
|
51
|
+
output_type: type | None = None,
|
|
52
|
+
message_history: list[ChatMessage[Any]] | None = None,
|
|
53
|
+
) -> Any:
|
|
54
|
+
kwargs = {"output_type": output_type, "message_history": message_history}
|
|
55
|
+
call = InputCall("get_input", (context, prompt), kwargs, result=self.input_response)
|
|
56
|
+
self.calls.append(call)
|
|
57
|
+
return self.input_response
|
|
58
|
+
|
|
59
|
+
async def get_tool_confirmation(
|
|
60
|
+
self,
|
|
61
|
+
context: NodeContext,
|
|
62
|
+
tool: Tool,
|
|
63
|
+
args: dict[str, Any],
|
|
64
|
+
message_history: list[ChatMessage[Any]] | None = None,
|
|
65
|
+
) -> ConfirmationResult:
|
|
66
|
+
kwargs = {"message_history": message_history}
|
|
67
|
+
result = self.tool_confirmation
|
|
68
|
+
call = InputCall("get_tool_confirmation", (context, tool, args), kwargs, result=result)
|
|
69
|
+
self.calls.append(call)
|
|
70
|
+
return result # pyright: ignore
|
|
71
|
+
|
|
72
|
+
async def get_elicitation(
|
|
73
|
+
self,
|
|
74
|
+
params: types.ElicitRequestParams,
|
|
75
|
+
) -> types.ElicitResult | types.ErrorData:
|
|
76
|
+
from mcp import types
|
|
77
|
+
|
|
78
|
+
result = types.ElicitResult(action="accept", content=self.elicitation_response)
|
|
79
|
+
call = InputCall("get_elicitation", (params,), {}, result=result)
|
|
80
|
+
self.calls.append(call)
|
|
81
|
+
return result
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
"""Stdlib input provider."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from textwrap import dedent
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
|
+
|
|
9
|
+
import anyenv
|
|
10
|
+
from mcp import types
|
|
11
|
+
|
|
12
|
+
from agentpool.log import get_logger
|
|
13
|
+
from agentpool.tools.exceptions import ToolError
|
|
14
|
+
from agentpool.ui.base import InputProvider
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
if TYPE_CHECKING:
|
|
18
|
+
from pydantic import BaseModel
|
|
19
|
+
|
|
20
|
+
from agentpool.agents.context import ConfirmationResult
|
|
21
|
+
from agentpool.messaging import ChatMessage
|
|
22
|
+
from agentpool.messaging.context import NodeContext
|
|
23
|
+
from agentpool.tools.base import Tool
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
logger = get_logger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class StdlibInputProvider(InputProvider):
|
|
30
|
+
"""Input provider using only Python stdlib functionality."""
|
|
31
|
+
|
|
32
|
+
async def get_text_input(
|
|
33
|
+
self,
|
|
34
|
+
context: NodeContext,
|
|
35
|
+
prompt: str,
|
|
36
|
+
message_history: list[ChatMessage[Any]] | None = None,
|
|
37
|
+
) -> str:
|
|
38
|
+
print(f"{prompt}\n> ", end="", file=sys.stderr, flush=True)
|
|
39
|
+
return input()
|
|
40
|
+
|
|
41
|
+
async def get_structured_input(
|
|
42
|
+
self,
|
|
43
|
+
context: NodeContext,
|
|
44
|
+
prompt: str,
|
|
45
|
+
output_type: type[BaseModel],
|
|
46
|
+
message_history: list[ChatMessage[Any]] | None = None,
|
|
47
|
+
) -> BaseModel:
|
|
48
|
+
"""Get structured input, with promptantic and fallback handling."""
|
|
49
|
+
if result := await _get_promptantic_result(output_type):
|
|
50
|
+
return result
|
|
51
|
+
|
|
52
|
+
# Fallback: Get raw input and validate
|
|
53
|
+
prompt = f"{prompt}\n(Please provide response as {output_type.__name__})"
|
|
54
|
+
raw_input = await self.get_input(context, prompt, message_history=message_history)
|
|
55
|
+
try:
|
|
56
|
+
return output_type.model_validate_json(raw_input)
|
|
57
|
+
except Exception as e:
|
|
58
|
+
msg = f"Invalid response format: {e}"
|
|
59
|
+
raise ToolError(msg) from e
|
|
60
|
+
|
|
61
|
+
async def get_tool_confirmation(
|
|
62
|
+
self,
|
|
63
|
+
context: NodeContext,
|
|
64
|
+
tool: Tool,
|
|
65
|
+
args: dict[str, Any],
|
|
66
|
+
message_history: list[ChatMessage[Any]] | None = None,
|
|
67
|
+
) -> ConfirmationResult:
|
|
68
|
+
agent_name = context.node_name
|
|
69
|
+
prompt = dedent(f"""
|
|
70
|
+
Tool Execution Confirmation
|
|
71
|
+
-------------------------
|
|
72
|
+
Tool: {tool.name}
|
|
73
|
+
Description: {tool.description or "No description"}
|
|
74
|
+
Agent: {agent_name}
|
|
75
|
+
|
|
76
|
+
Arguments:
|
|
77
|
+
{anyenv.dump_json(args, indent=True)}
|
|
78
|
+
|
|
79
|
+
Options:
|
|
80
|
+
- y: allow execution
|
|
81
|
+
- n/skip: skip this tool
|
|
82
|
+
- abort: abort current run
|
|
83
|
+
- quit: abort entire chain
|
|
84
|
+
""").strip()
|
|
85
|
+
|
|
86
|
+
print(f"{prompt}\nChoice [y/n/abort/quit]: ", end="", file=sys.stderr, flush=True)
|
|
87
|
+
response = input().lower()
|
|
88
|
+
match response:
|
|
89
|
+
case "y" | "yes":
|
|
90
|
+
return "allow"
|
|
91
|
+
case "abort":
|
|
92
|
+
return "abort_run"
|
|
93
|
+
case "quit":
|
|
94
|
+
return "abort_chain"
|
|
95
|
+
case _:
|
|
96
|
+
return "skip"
|
|
97
|
+
|
|
98
|
+
async def get_elicitation(
|
|
99
|
+
self,
|
|
100
|
+
params: types.ElicitRequestParams,
|
|
101
|
+
) -> types.ElicitResult | types.ErrorData:
|
|
102
|
+
"""Get user response to elicitation request using stdlib input."""
|
|
103
|
+
try:
|
|
104
|
+
print(f"\n{params.message}", file=sys.stderr)
|
|
105
|
+
|
|
106
|
+
# URL mode: prompt user to open external URL
|
|
107
|
+
if isinstance(params, types.ElicitRequestURLParams):
|
|
108
|
+
print(f"URL: {params.url}", file=sys.stderr)
|
|
109
|
+
print("Open this URL? [y/n]: ", end="", file=sys.stderr, flush=True)
|
|
110
|
+
response = input().strip().lower()
|
|
111
|
+
action = (
|
|
112
|
+
"accept"
|
|
113
|
+
if response in ("y", "yes")
|
|
114
|
+
else ("decline" if response in ("n", "no") else "cancel")
|
|
115
|
+
)
|
|
116
|
+
return types.ElicitResult(action=action)
|
|
117
|
+
|
|
118
|
+
# Form mode: collect structured JSON input
|
|
119
|
+
print("Please provide response as JSON:", file=sys.stderr)
|
|
120
|
+
if params.requestedSchema:
|
|
121
|
+
schema_json = anyenv.dump_json(params.requestedSchema, indent=True)
|
|
122
|
+
print(f"Expected schema:\n{schema_json}", file=sys.stderr)
|
|
123
|
+
print("> ", end="", file=sys.stderr, flush=True)
|
|
124
|
+
response = input()
|
|
125
|
+
try:
|
|
126
|
+
content = anyenv.load_json(response, return_type=dict)
|
|
127
|
+
return types.ElicitResult(action="accept", content=content)
|
|
128
|
+
except anyenv.JsonLoadError as e:
|
|
129
|
+
return types.ErrorData(code=types.INVALID_REQUEST, message=f"Invalid JSON: {e}")
|
|
130
|
+
|
|
131
|
+
except KeyboardInterrupt:
|
|
132
|
+
return types.ElicitResult(action="cancel")
|
|
133
|
+
except Exception as e: # noqa: BLE001
|
|
134
|
+
return types.ErrorData(code=types.INVALID_REQUEST, message=f"Elicitation failed: {e}")
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
async def _get_promptantic_result(output_type: type[BaseModel]) -> BaseModel | None:
|
|
138
|
+
"""Helper to get structured input via promptantic.
|
|
139
|
+
|
|
140
|
+
Returns None if promptantic is not available or fails.
|
|
141
|
+
"""
|
|
142
|
+
try:
|
|
143
|
+
from promptantic import ModelGenerator
|
|
144
|
+
|
|
145
|
+
return await ModelGenerator().apopulate(output_type)
|
|
146
|
+
except ImportError:
|
|
147
|
+
return None
|
|
148
|
+
except Exception as e: # noqa: BLE001
|
|
149
|
+
logger.warning("Promptantic failed", error=e)
|
|
150
|
+
return None
|