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,443 @@
|
|
|
1
|
+
"""A streaming fuzzy matcher.
|
|
2
|
+
|
|
3
|
+
It that can process text chunks incrementally
|
|
4
|
+
and return the best match found so far at each step.
|
|
5
|
+
|
|
6
|
+
This is a Python port of Zed's streaming fuzzy matcher, designed for
|
|
7
|
+
real-time code editing and location resolution.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass, field
|
|
13
|
+
from typing import Literal
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
REPLACEMENT_COST = 1
|
|
17
|
+
INSERTION_COST = 3
|
|
18
|
+
DELETION_COST = 10
|
|
19
|
+
|
|
20
|
+
LINE_HINT_TOLERANCE = 200
|
|
21
|
+
THRESHOLD = 0.8
|
|
22
|
+
SearchDirection = Literal["up", "left", "diagonal"]
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
@dataclass(frozen=True, slots=True)
|
|
26
|
+
class Range:
|
|
27
|
+
"""Represents a text range with start and end byte offsets."""
|
|
28
|
+
|
|
29
|
+
start: int
|
|
30
|
+
end: int
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(slots=True)
|
|
34
|
+
class SearchState:
|
|
35
|
+
"""State for a cell in the dynamic programming matrix."""
|
|
36
|
+
|
|
37
|
+
cost: int
|
|
38
|
+
direction: SearchDirection
|
|
39
|
+
|
|
40
|
+
def __post_init__(self) -> None:
|
|
41
|
+
self.cost = max(self.cost, 0)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass
|
|
45
|
+
class SearchMatrix:
|
|
46
|
+
"""Dynamic programming matrix for edit distance computation."""
|
|
47
|
+
|
|
48
|
+
cols: int
|
|
49
|
+
rows: int = 0
|
|
50
|
+
data: list[SearchState] = field(default_factory=list)
|
|
51
|
+
|
|
52
|
+
def resize_rows(self, new_rows: int) -> None:
|
|
53
|
+
"""Resize matrix to accommodate more query lines."""
|
|
54
|
+
if new_rows <= self.rows:
|
|
55
|
+
return
|
|
56
|
+
|
|
57
|
+
old_size = self.rows * self.cols
|
|
58
|
+
new_size = new_rows * self.cols
|
|
59
|
+
self.data.extend([SearchState(0, "diagonal") for _ in range(new_size - old_size)])
|
|
60
|
+
self.rows = new_rows
|
|
61
|
+
|
|
62
|
+
def get(self, row: int, col: int) -> SearchState:
|
|
63
|
+
"""Get state at matrix position."""
|
|
64
|
+
if row >= self.rows or col >= self.cols or row < 0 or col < 0:
|
|
65
|
+
return SearchState(999999, "diagonal")
|
|
66
|
+
return self.data[row * self.cols + col]
|
|
67
|
+
|
|
68
|
+
def set(self, row: int, col: int, state: SearchState) -> None:
|
|
69
|
+
"""Set state at matrix position."""
|
|
70
|
+
if row < self.rows and col < self.cols and row >= 0 and col >= 0:
|
|
71
|
+
self.data[row * self.cols + col] = state
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class StreamingFuzzyMatcher:
|
|
75
|
+
"""A streaming fuzzy matcher that processes text chunks incrementally.
|
|
76
|
+
|
|
77
|
+
This matcher accumulates text chunks and performs fuzzy matching against
|
|
78
|
+
a source buffer, returning the best matches found so far.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(self, source_text: str) -> None:
|
|
82
|
+
"""Initialize matcher with source text to search against.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
source_text: The text buffer to search within
|
|
86
|
+
"""
|
|
87
|
+
self.source_lines: list[str] = source_text.splitlines()
|
|
88
|
+
self.query_lines: list[str] = []
|
|
89
|
+
self.line_hint: int | None = None
|
|
90
|
+
self.incomplete_line: str = ""
|
|
91
|
+
self.matches: list[Range] = []
|
|
92
|
+
|
|
93
|
+
# Initialize matrix with buffer line count + 1
|
|
94
|
+
buffer_line_count = len(self.source_lines)
|
|
95
|
+
self.matrix: SearchMatrix = SearchMatrix(buffer_line_count + 1)
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def query_lines_list(self) -> list[str]:
|
|
99
|
+
"""Returns the accumulated query lines."""
|
|
100
|
+
return self.query_lines.copy()
|
|
101
|
+
|
|
102
|
+
def push(self, chunk: str, line_hint: int | None = None) -> Range | None:
|
|
103
|
+
"""Push a new chunk of text and get the best match found so far.
|
|
104
|
+
|
|
105
|
+
This method accumulates text chunks and processes complete lines.
|
|
106
|
+
Partial lines are buffered internally until a newline is received.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
chunk: Text chunk to add to the query
|
|
110
|
+
line_hint: Optional line number hint for match selection
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
Range if a match has been found, None otherwise
|
|
114
|
+
"""
|
|
115
|
+
if line_hint is not None:
|
|
116
|
+
self.line_hint = line_hint
|
|
117
|
+
|
|
118
|
+
# Add chunk to incomplete line buffer
|
|
119
|
+
self.incomplete_line += chunk
|
|
120
|
+
|
|
121
|
+
# Process complete lines (everything up to the last newline)
|
|
122
|
+
if "\n" in self.incomplete_line:
|
|
123
|
+
# Find last newline position
|
|
124
|
+
last_newline = self.incomplete_line.rfind("\n")
|
|
125
|
+
complete_part = self.incomplete_line[: last_newline + 1]
|
|
126
|
+
|
|
127
|
+
# Split into lines and add to query_lines
|
|
128
|
+
new_lines = complete_part.splitlines()
|
|
129
|
+
self.query_lines.extend(new_lines)
|
|
130
|
+
|
|
131
|
+
# Keep remaining incomplete part
|
|
132
|
+
self.incomplete_line = self.incomplete_line[last_newline + 1 :]
|
|
133
|
+
|
|
134
|
+
# Update matches with new query lines
|
|
135
|
+
self.matches = self._resolve_location_fuzzy()
|
|
136
|
+
|
|
137
|
+
# Return best match
|
|
138
|
+
best_match = self.select_best_match()
|
|
139
|
+
return best_match or (self.matches[0] if self.matches else None)
|
|
140
|
+
|
|
141
|
+
def finish(self) -> list[Range]:
|
|
142
|
+
"""Finish processing and return all final matches.
|
|
143
|
+
|
|
144
|
+
This processes any remaining incomplete line before returning
|
|
145
|
+
the final match results.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
List of all found matches
|
|
149
|
+
"""
|
|
150
|
+
# Process any remaining incomplete line
|
|
151
|
+
if self.incomplete_line.strip():
|
|
152
|
+
self.query_lines.append(self.incomplete_line)
|
|
153
|
+
self.incomplete_line = ""
|
|
154
|
+
self.matches = self._resolve_location_fuzzy()
|
|
155
|
+
|
|
156
|
+
return self.matches.copy()
|
|
157
|
+
|
|
158
|
+
def select_best_match(self) -> Range | None:
|
|
159
|
+
"""Return the best match considering line hints.
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
Best match range, or None if no suitable match found
|
|
163
|
+
"""
|
|
164
|
+
if not self.matches:
|
|
165
|
+
return None
|
|
166
|
+
|
|
167
|
+
if len(self.matches) == 1:
|
|
168
|
+
return self.matches[0]
|
|
169
|
+
|
|
170
|
+
if self.line_hint is None:
|
|
171
|
+
# Multiple ambiguous matches without hint
|
|
172
|
+
return None
|
|
173
|
+
|
|
174
|
+
best_match = None
|
|
175
|
+
best_distance = float("inf")
|
|
176
|
+
|
|
177
|
+
for match_range in self.matches:
|
|
178
|
+
# Convert byte offset to approximate line number
|
|
179
|
+
start_line = self._offset_to_line(match_range.start)
|
|
180
|
+
distance = abs(start_line - self.line_hint)
|
|
181
|
+
|
|
182
|
+
if distance <= LINE_HINT_TOLERANCE and distance < best_distance:
|
|
183
|
+
best_distance = distance
|
|
184
|
+
best_match = match_range
|
|
185
|
+
|
|
186
|
+
return best_match
|
|
187
|
+
|
|
188
|
+
def _resolve_location_fuzzy(self) -> list[Range]:
|
|
189
|
+
"""Perform fuzzy matching using dynamic programming.
|
|
190
|
+
|
|
191
|
+
Returns:
|
|
192
|
+
List of match ranges found in the source text
|
|
193
|
+
"""
|
|
194
|
+
new_query_line_count = len(self.query_lines)
|
|
195
|
+
old_query_line_count = max(0, self.matrix.rows - 1)
|
|
196
|
+
|
|
197
|
+
if new_query_line_count == old_query_line_count:
|
|
198
|
+
return []
|
|
199
|
+
|
|
200
|
+
self.matrix.resize_rows(new_query_line_count + 1)
|
|
201
|
+
|
|
202
|
+
# Process only the new query lines
|
|
203
|
+
for row in range(old_query_line_count, new_query_line_count):
|
|
204
|
+
query_line = self.query_lines[row].strip()
|
|
205
|
+
leading_deletion_cost = (row + 1) * DELETION_COST
|
|
206
|
+
|
|
207
|
+
# Initialize first column
|
|
208
|
+
self.matrix.set(row + 1, 0, SearchState(leading_deletion_cost, "up"))
|
|
209
|
+
|
|
210
|
+
# Process each source line
|
|
211
|
+
for col, source_line in enumerate(self.source_lines):
|
|
212
|
+
line = source_line.strip()
|
|
213
|
+
|
|
214
|
+
# Calculate costs for each direction
|
|
215
|
+
up_cost = self.matrix.get(row, col + 1).cost + DELETION_COST
|
|
216
|
+
left_cost = self.matrix.get(row + 1, col).cost + INSERTION_COST
|
|
217
|
+
|
|
218
|
+
# Diagonal cost depends on character match
|
|
219
|
+
diagonal_cost = self.matrix.get(row, col).cost
|
|
220
|
+
if not _fuzzy_eq(query_line, line):
|
|
221
|
+
diagonal_cost += REPLACEMENT_COST
|
|
222
|
+
|
|
223
|
+
# Choose minimum cost direction
|
|
224
|
+
if diagonal_cost <= up_cost and diagonal_cost <= left_cost:
|
|
225
|
+
best_state = SearchState(diagonal_cost, "diagonal")
|
|
226
|
+
elif up_cost <= left_cost:
|
|
227
|
+
best_state = SearchState(up_cost, "up")
|
|
228
|
+
else:
|
|
229
|
+
best_state = SearchState(left_cost, "left")
|
|
230
|
+
|
|
231
|
+
self.matrix.set(row + 1, col + 1, best_state)
|
|
232
|
+
|
|
233
|
+
# Extract matches by backtracking through matrix
|
|
234
|
+
return self._extract_matches()
|
|
235
|
+
|
|
236
|
+
def _extract_matches(self) -> list[Range]:
|
|
237
|
+
"""Extract match ranges by backtracking through the DP matrix."""
|
|
238
|
+
if not self.query_lines:
|
|
239
|
+
return []
|
|
240
|
+
|
|
241
|
+
query_len = len(self.query_lines)
|
|
242
|
+
|
|
243
|
+
# Find all reasonable endpoints and score them
|
|
244
|
+
min_cost = float("inf")
|
|
245
|
+
|
|
246
|
+
for col in range(len(self.source_lines) + 1):
|
|
247
|
+
state = self.matrix.get(query_len, col)
|
|
248
|
+
min_cost = min(min_cost, state.cost)
|
|
249
|
+
|
|
250
|
+
# Accept costs within reasonable range of minimum
|
|
251
|
+
max_acceptable_cost = min(min_cost * 2, query_len * REPLACEMENT_COST * 4)
|
|
252
|
+
|
|
253
|
+
candidates: list[tuple[float, Range]] = []
|
|
254
|
+
for col in range(len(self.source_lines) + 1):
|
|
255
|
+
state = self.matrix.get(query_len, col)
|
|
256
|
+
if state.cost <= max_acceptable_cost:
|
|
257
|
+
match_range = self._backtrack_match(query_len, col)
|
|
258
|
+
if match_range:
|
|
259
|
+
# Score based on cost and match quality
|
|
260
|
+
quality_score = self._calculate_match_quality(match_range)
|
|
261
|
+
candidates.append((
|
|
262
|
+
float(state.cost) - quality_score * 10,
|
|
263
|
+
match_range,
|
|
264
|
+
))
|
|
265
|
+
|
|
266
|
+
# Sort by score and return best matches
|
|
267
|
+
candidates.sort(key=lambda x: x[0])
|
|
268
|
+
return [match for _, match in candidates[:5]] # Limit to top 5 matches
|
|
269
|
+
|
|
270
|
+
def _backtrack_match(self, end_row: int, end_col: int) -> Range | None:
|
|
271
|
+
"""Backtrack through matrix to find match boundaries."""
|
|
272
|
+
if end_row == 0 or end_col == 0:
|
|
273
|
+
return None
|
|
274
|
+
|
|
275
|
+
# Track which source lines were matched
|
|
276
|
+
matched_lines: set[int] = set()
|
|
277
|
+
row, col = end_row, end_col
|
|
278
|
+
|
|
279
|
+
# Backtrack to collect matched source lines
|
|
280
|
+
while row > 0 and col > 0:
|
|
281
|
+
state = self.matrix.get(row, col)
|
|
282
|
+
if state.direction == "diagonal":
|
|
283
|
+
# represents a match between query line (row-1) and source line (col-1)
|
|
284
|
+
matched_lines.add(col - 1)
|
|
285
|
+
row -= 1
|
|
286
|
+
col -= 1
|
|
287
|
+
elif state.direction == "up":
|
|
288
|
+
row -= 1
|
|
289
|
+
else: # LEFT
|
|
290
|
+
col -= 1
|
|
291
|
+
|
|
292
|
+
if not matched_lines:
|
|
293
|
+
return None
|
|
294
|
+
|
|
295
|
+
# Find contiguous range of matched lines
|
|
296
|
+
matched_list = sorted(matched_lines)
|
|
297
|
+
start_line: int = matched_list[0]
|
|
298
|
+
end_line: int = matched_list[-1]
|
|
299
|
+
|
|
300
|
+
# Extend range to include some context for better matches
|
|
301
|
+
context_lines = min(2, len(self.query_lines))
|
|
302
|
+
start_line = max(0, start_line - context_lines // 2)
|
|
303
|
+
end_line = min(len(self.source_lines) - 1, end_line + context_lines // 2)
|
|
304
|
+
|
|
305
|
+
start_offset = self._line_to_offset(start_line)
|
|
306
|
+
end_offset = self._line_to_offset(end_line + 1)
|
|
307
|
+
|
|
308
|
+
return Range(start_offset, end_offset)
|
|
309
|
+
|
|
310
|
+
def _calculate_match_quality(self, match_range: Range) -> float:
|
|
311
|
+
"""Calculate quality score for a match (higher is better)."""
|
|
312
|
+
if not self.query_lines:
|
|
313
|
+
return 0.0
|
|
314
|
+
|
|
315
|
+
source_text = "\n".join(self.source_lines)
|
|
316
|
+
matched_text = source_text[match_range.start : match_range.end]
|
|
317
|
+
matched_lines = matched_text.split("\n")
|
|
318
|
+
|
|
319
|
+
score = 0.0
|
|
320
|
+
query_words: set[str] = set()
|
|
321
|
+
for line in self.query_lines:
|
|
322
|
+
query_words.update(line.strip().split())
|
|
323
|
+
|
|
324
|
+
# Score based on word overlap
|
|
325
|
+
for line in matched_lines:
|
|
326
|
+
line_words = set(line.strip().split())
|
|
327
|
+
overlap = len(query_words & line_words)
|
|
328
|
+
if len(query_words) > 0:
|
|
329
|
+
score += overlap / len(query_words)
|
|
330
|
+
|
|
331
|
+
# Bonus for exact line matches
|
|
332
|
+
for query_line in self.query_lines:
|
|
333
|
+
normalized_query = " ".join(query_line.strip().split())
|
|
334
|
+
for matched_line in matched_lines:
|
|
335
|
+
normalized_matched = " ".join(matched_line.strip().split())
|
|
336
|
+
if normalized_query == normalized_matched:
|
|
337
|
+
score += 2.0
|
|
338
|
+
|
|
339
|
+
return score
|
|
340
|
+
|
|
341
|
+
def _line_to_offset(self, line_num: int) -> int:
|
|
342
|
+
"""Convert line number to byte offset."""
|
|
343
|
+
if line_num <= 0:
|
|
344
|
+
return 0
|
|
345
|
+
|
|
346
|
+
# Calculate offset by summing lengths of previous lines
|
|
347
|
+
offset = 0
|
|
348
|
+
for i in range(min(line_num, len(self.source_lines))):
|
|
349
|
+
offset += len(self.source_lines[i]) + 1 # +1 for newline
|
|
350
|
+
|
|
351
|
+
if line_num >= len(self.source_lines):
|
|
352
|
+
return offset
|
|
353
|
+
|
|
354
|
+
return max(0, offset - 1) if offset > 0 else 0
|
|
355
|
+
|
|
356
|
+
def _offset_to_line(self, offset: int) -> int:
|
|
357
|
+
"""Convert byte offset to approximate line number."""
|
|
358
|
+
if offset <= 0:
|
|
359
|
+
return 0
|
|
360
|
+
|
|
361
|
+
current_offset = 0
|
|
362
|
+
for i, line in enumerate(self.source_lines):
|
|
363
|
+
if current_offset + len(line) + 1 > offset:
|
|
364
|
+
return i
|
|
365
|
+
current_offset += len(line) + 1
|
|
366
|
+
|
|
367
|
+
return len(self.source_lines) - 1
|
|
368
|
+
|
|
369
|
+
|
|
370
|
+
def _fuzzy_eq(left: str, right: str) -> bool:
|
|
371
|
+
"""Check if two strings are fuzzy equal using normalized Levenshtein distance.
|
|
372
|
+
|
|
373
|
+
Args:
|
|
374
|
+
left: First string to compare
|
|
375
|
+
right: Second string to compare
|
|
376
|
+
|
|
377
|
+
Returns:
|
|
378
|
+
True if strings are similar enough (>= 0.8 similarity)
|
|
379
|
+
"""
|
|
380
|
+
if not left and not right:
|
|
381
|
+
return True
|
|
382
|
+
if not left or not right:
|
|
383
|
+
return False
|
|
384
|
+
|
|
385
|
+
# Normalize whitespace for better matching
|
|
386
|
+
left_normalized = " ".join(left.split())
|
|
387
|
+
right_normalized = " ".join(right.split())
|
|
388
|
+
|
|
389
|
+
# Quick exact match after normalization
|
|
390
|
+
if left_normalized == right_normalized:
|
|
391
|
+
return True
|
|
392
|
+
|
|
393
|
+
# Quick check: if length difference is too large, they can't be similar enough
|
|
394
|
+
max_len = max(len(left_normalized), len(right_normalized))
|
|
395
|
+
if max_len == 0:
|
|
396
|
+
return True
|
|
397
|
+
|
|
398
|
+
min_levenshtein = abs(len(left_normalized) - len(right_normalized))
|
|
399
|
+
min_normalized_similarity = 1.0 - (min_levenshtein / max_len)
|
|
400
|
+
|
|
401
|
+
if min_normalized_similarity < THRESHOLD:
|
|
402
|
+
return False
|
|
403
|
+
|
|
404
|
+
# Calculate actual Levenshtein distance
|
|
405
|
+
distance = _levenshtein_distance(left_normalized, right_normalized)
|
|
406
|
+
normalized_similarity = 1.0 - (distance / max_len)
|
|
407
|
+
|
|
408
|
+
return normalized_similarity >= THRESHOLD
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
def _levenshtein_distance(s1: str, s2: str) -> int:
|
|
412
|
+
"""Calculate Levenshtein distance between two strings.
|
|
413
|
+
|
|
414
|
+
Args:
|
|
415
|
+
s1: First string
|
|
416
|
+
s2: Second string
|
|
417
|
+
|
|
418
|
+
Returns:
|
|
419
|
+
Edit distance between the strings
|
|
420
|
+
"""
|
|
421
|
+
if len(s1) < len(s2):
|
|
422
|
+
return _levenshtein_distance(s2, s1)
|
|
423
|
+
|
|
424
|
+
if len(s2) == 0:
|
|
425
|
+
return len(s1)
|
|
426
|
+
|
|
427
|
+
# Create matrix
|
|
428
|
+
previous_row = list(range(len(s2) + 1))
|
|
429
|
+
|
|
430
|
+
for i, c1 in enumerate(s1):
|
|
431
|
+
current_row = [i + 1]
|
|
432
|
+
|
|
433
|
+
for j, c2 in enumerate(s2):
|
|
434
|
+
# Cost of insertions, deletions, substitutions
|
|
435
|
+
insertions = previous_row[j + 1] + 1
|
|
436
|
+
deletions = current_row[j] + 1
|
|
437
|
+
substitutions = previous_row[j] + (0 if c1 == c2 else 1)
|
|
438
|
+
|
|
439
|
+
current_row.append(min(insertions, deletions, substitutions))
|
|
440
|
+
|
|
441
|
+
previous_row = current_row
|
|
442
|
+
|
|
443
|
+
return previous_row[-1]
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Provider for history tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
6
|
+
from agentpool.resource_providers import StaticResourceProvider
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
async def search_history(
|
|
10
|
+
ctx: AgentContext,
|
|
11
|
+
query: str | None = None,
|
|
12
|
+
hours: int = 24,
|
|
13
|
+
limit: int = 5,
|
|
14
|
+
) -> str:
|
|
15
|
+
"""Search conversation history."""
|
|
16
|
+
from agentpool_storage.formatters import format_output
|
|
17
|
+
|
|
18
|
+
if not ctx.pool:
|
|
19
|
+
return "No agent pool available for history search"
|
|
20
|
+
provider = ctx.pool.storage.get_history_provider()
|
|
21
|
+
results = await provider.get_filtered_conversations(
|
|
22
|
+
query=query,
|
|
23
|
+
period=f"{hours}h",
|
|
24
|
+
limit=limit,
|
|
25
|
+
)
|
|
26
|
+
return format_output(results)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class HistoryTools(StaticResourceProvider):
|
|
30
|
+
"""Provider for history tools."""
|
|
31
|
+
|
|
32
|
+
def __init__(self, name: str = "history") -> None:
|
|
33
|
+
super().__init__(name=name)
|
|
34
|
+
self._tools = [
|
|
35
|
+
self.create_tool(search_history, category="search", read_only=True, idempotent=True),
|
|
36
|
+
]
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"""Provider for integration tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Literal
|
|
6
|
+
|
|
7
|
+
from pydantic import HttpUrl
|
|
8
|
+
|
|
9
|
+
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
10
|
+
from agentpool.resource_providers import ResourceProvider
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from agentpool.tools.base import Tool
|
|
15
|
+
from agentpool_config.mcp_server import MCPServerConfig
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
async def add_local_mcp_server( # noqa: D417
|
|
19
|
+
ctx: AgentContext,
|
|
20
|
+
name: str,
|
|
21
|
+
command: str,
|
|
22
|
+
args: list[str] | None = None,
|
|
23
|
+
env_vars: dict[str, str] | None = None,
|
|
24
|
+
) -> str:
|
|
25
|
+
"""Add a local MCP server via stdio transport.
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
name: Unique name for the MCP server
|
|
29
|
+
command: Command to execute for the server
|
|
30
|
+
args: Command arguments
|
|
31
|
+
env_vars: Environment variables to pass to the server
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Confirmation message about the added server
|
|
35
|
+
"""
|
|
36
|
+
from agentpool_config.mcp_server import StdioMCPServerConfig
|
|
37
|
+
|
|
38
|
+
env = env_vars or {}
|
|
39
|
+
config = StdioMCPServerConfig(name=name, command=command, args=args or [], env=env)
|
|
40
|
+
await ctx.agent.mcp.setup_server_runtime(config)
|
|
41
|
+
# New provider automatically available via aggregating provider
|
|
42
|
+
return f"Added local MCP server **{name}** with command: **{command}**"
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
async def add_remote_mcp_server( # noqa: D417
|
|
46
|
+
ctx: AgentContext,
|
|
47
|
+
name: str,
|
|
48
|
+
url: str,
|
|
49
|
+
transport: Literal["sse", "streamable-http"] = "streamable-http",
|
|
50
|
+
) -> str:
|
|
51
|
+
"""Add a remote MCP server via HTTP-based transport.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
name: Unique name for the MCP server
|
|
55
|
+
url: Server URL endpoint
|
|
56
|
+
transport: HTTP transport type to use (http is preferred)
|
|
57
|
+
|
|
58
|
+
Returns:
|
|
59
|
+
Confirmation message about the added server
|
|
60
|
+
"""
|
|
61
|
+
from agentpool_config.mcp_server import SSEMCPServerConfig, StreamableHTTPMCPServerConfig
|
|
62
|
+
|
|
63
|
+
match transport:
|
|
64
|
+
case "sse":
|
|
65
|
+
config: MCPServerConfig = SSEMCPServerConfig(name=name, url=HttpUrl(url))
|
|
66
|
+
case "streamable-http":
|
|
67
|
+
config = StreamableHTTPMCPServerConfig(name=name, url=HttpUrl(url))
|
|
68
|
+
|
|
69
|
+
await ctx.agent.mcp.setup_server_runtime(config)
|
|
70
|
+
# New provider automatically available via aggregating provider
|
|
71
|
+
return f"Added remote MCP server **{name}** at *{url}* using {transport} transport"
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class IntegrationTools(ResourceProvider):
|
|
75
|
+
"""Provider for integration tools."""
|
|
76
|
+
|
|
77
|
+
def __init__(self, name: str = "integrations") -> None:
|
|
78
|
+
super().__init__(name)
|
|
79
|
+
|
|
80
|
+
async def get_tools(self) -> list[Tool]:
|
|
81
|
+
"""Get integration tools."""
|
|
82
|
+
return [
|
|
83
|
+
self.create_tool(add_local_mcp_server, category="other"),
|
|
84
|
+
self.create_tool(add_remote_mcp_server, category="other", open_world=True),
|
|
85
|
+
]
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"""Provider for skills tools."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from agentpool.agents.context import AgentContext # noqa: TC001
|
|
6
|
+
from agentpool.resource_providers import StaticResourceProvider
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
BASE_DESC = """Load a Claude Code Skill and return its instructions.
|
|
10
|
+
|
|
11
|
+
This tool provides access to Claude Code Skills - specialized workflows and techniques
|
|
12
|
+
for handling specific types of tasks. When you need to use a skill, call this tool
|
|
13
|
+
with the skill name.
|
|
14
|
+
|
|
15
|
+
Available skills:"""
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
async def load_skill(ctx: AgentContext, skill_name: str) -> str:
|
|
19
|
+
"""Load a Claude Code Skill and return its instructions.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
ctx: Agent context providing access to pool and skills
|
|
23
|
+
skill_name: Name of the skill to load
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
The full skill instructions for execution
|
|
27
|
+
"""
|
|
28
|
+
if not ctx.pool:
|
|
29
|
+
return "No agent pool available - skills require pool context"
|
|
30
|
+
|
|
31
|
+
skills = ctx.pool.skills.list_skills()
|
|
32
|
+
if not skills:
|
|
33
|
+
return "No skills available."
|
|
34
|
+
skill = next((s for s in skills if s.name == skill_name), None)
|
|
35
|
+
if not skill:
|
|
36
|
+
available = ", ".join(s.name for s in skills)
|
|
37
|
+
return f"Skill {skill_name!r} not found. Available skills: {available}"
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
instructions = ctx.pool.skills.get_skill_instructions(skill_name)
|
|
41
|
+
except Exception as e: # noqa: BLE001
|
|
42
|
+
return f"Failed to load skill {skill_name!r}: {e}"
|
|
43
|
+
return f"# {skill.name}\n{instructions}\nSkill directory: {skill.skill_path}"
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
async def list_skills(ctx: AgentContext) -> str:
|
|
47
|
+
"""List all available skills.
|
|
48
|
+
|
|
49
|
+
Returns:
|
|
50
|
+
Formatted list of available skills with descriptions
|
|
51
|
+
"""
|
|
52
|
+
if not ctx.pool:
|
|
53
|
+
return "No agent pool available - skills require pool context"
|
|
54
|
+
skills = ctx.pool.skills.list_skills()
|
|
55
|
+
if not skills:
|
|
56
|
+
return "No skills available"
|
|
57
|
+
lines = ["Available skills:", ""]
|
|
58
|
+
lines.extend(f"- **{skill.name}**: {skill.description}" for skill in skills)
|
|
59
|
+
return "\n".join(lines)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
class SkillsTools(StaticResourceProvider):
|
|
63
|
+
"""Provider for Claude Code Skills tools.
|
|
64
|
+
|
|
65
|
+
Provides tools to discover and load skills from the pool's skills registry.
|
|
66
|
+
Skills are discovered from configured directories (e.g., ~/.claude/skills/,
|
|
67
|
+
.claude/skills/).
|
|
68
|
+
|
|
69
|
+
The pool manages skill discovery; this toolset just provides access to them.
|
|
70
|
+
"""
|
|
71
|
+
|
|
72
|
+
def __init__(self, name: str = "skills") -> None:
|
|
73
|
+
super().__init__(name=name)
|
|
74
|
+
self._tools = [
|
|
75
|
+
self.create_tool(load_skill, category="read", read_only=True, idempotent=True),
|
|
76
|
+
self.create_tool(list_skills, category="read", read_only=True, idempotent=True),
|
|
77
|
+
]
|