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,496 @@
|
|
|
1
|
+
"""Debug server combining ACP protocol with FastAPI for manual testing.
|
|
2
|
+
|
|
3
|
+
This module provides a debug server that runs both:
|
|
4
|
+
1. An ACP (Agent Client Protocol) server for testing client integration
|
|
5
|
+
2. A FastAPI web server for manually triggering all notification types
|
|
6
|
+
|
|
7
|
+
The server allows developers to test ACP client implementations by providing
|
|
8
|
+
mock responses and the ability to manually send any notification type from
|
|
9
|
+
the ACP schema through a web interface.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
from contextlib import asynccontextmanager
|
|
15
|
+
from dataclasses import dataclass, field
|
|
16
|
+
import logging
|
|
17
|
+
from pathlib import Path
|
|
18
|
+
import sys
|
|
19
|
+
import threading
|
|
20
|
+
import time
|
|
21
|
+
from typing import TYPE_CHECKING, Any
|
|
22
|
+
import uuid
|
|
23
|
+
|
|
24
|
+
import anyio
|
|
25
|
+
from fastapi import FastAPI, HTTPException
|
|
26
|
+
from fastapi.responses import HTMLResponse
|
|
27
|
+
from pydantic import BaseModel, Field
|
|
28
|
+
import uvicorn
|
|
29
|
+
|
|
30
|
+
from acp import AgentSideConnection
|
|
31
|
+
from acp.agent.protocol import Agent
|
|
32
|
+
from acp.schema import (
|
|
33
|
+
AgentMessageChunk,
|
|
34
|
+
AgentPlanUpdate,
|
|
35
|
+
AgentThoughtChunk,
|
|
36
|
+
AuthenticateResponse,
|
|
37
|
+
AvailableCommand,
|
|
38
|
+
AvailableCommandsUpdate,
|
|
39
|
+
ContentToolCallContent,
|
|
40
|
+
CreateTerminalResponse,
|
|
41
|
+
# CurrentModelUpdate,
|
|
42
|
+
CurrentModeUpdate,
|
|
43
|
+
ForkSessionResponse,
|
|
44
|
+
InitializeResponse,
|
|
45
|
+
ListSessionsResponse,
|
|
46
|
+
LoadSessionResponse,
|
|
47
|
+
NewSessionResponse,
|
|
48
|
+
PlanEntry,
|
|
49
|
+
PromptResponse,
|
|
50
|
+
ReadTextFileResponse,
|
|
51
|
+
ResumeSessionResponse,
|
|
52
|
+
SessionInfo,
|
|
53
|
+
SessionNotification,
|
|
54
|
+
ToolCallProgress,
|
|
55
|
+
ToolCallStart,
|
|
56
|
+
UserMessageChunk,
|
|
57
|
+
WriteTextFileResponse,
|
|
58
|
+
)
|
|
59
|
+
from acp.stdio import stdio_streams
|
|
60
|
+
from agentpool.log import get_logger
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
if TYPE_CHECKING:
|
|
64
|
+
from collections.abc import AsyncIterator
|
|
65
|
+
|
|
66
|
+
from acp import SetSessionModelRequest, SetSessionModeRequest
|
|
67
|
+
from acp.schema import (
|
|
68
|
+
AuthenticateRequest,
|
|
69
|
+
CancelNotification,
|
|
70
|
+
CreateTerminalRequest,
|
|
71
|
+
ForkSessionRequest,
|
|
72
|
+
InitializeRequest,
|
|
73
|
+
ListSessionsRequest,
|
|
74
|
+
LoadSessionRequest,
|
|
75
|
+
NewSessionRequest,
|
|
76
|
+
PromptRequest,
|
|
77
|
+
ReadTextFileRequest,
|
|
78
|
+
ResumeSessionRequest,
|
|
79
|
+
SessionUpdate,
|
|
80
|
+
WriteTextFileRequest,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
logger = get_logger(__name__)
|
|
85
|
+
MOCK_FILE = """\
|
|
86
|
+
# Mock file: {path}
|
|
87
|
+
# Generated by ACP Debug Server
|
|
88
|
+
|
|
89
|
+
def example_function():
|
|
90
|
+
return "This is mock content for testing"
|
|
91
|
+
|
|
92
|
+
# Line count: 10 lines
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
@dataclass
|
|
97
|
+
class DebugSession:
|
|
98
|
+
"""Debug session data."""
|
|
99
|
+
|
|
100
|
+
session_id: str
|
|
101
|
+
created_at: float
|
|
102
|
+
cwd: str
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
@dataclass
|
|
106
|
+
class NotificationRecord:
|
|
107
|
+
"""Record of a sent notification."""
|
|
108
|
+
|
|
109
|
+
notification_type: str
|
|
110
|
+
session_id: str
|
|
111
|
+
timestamp: float
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
@dataclass
|
|
115
|
+
class DebugState:
|
|
116
|
+
"""Type-safe debug server state."""
|
|
117
|
+
|
|
118
|
+
sessions: dict[str, DebugSession] = field(default_factory=dict)
|
|
119
|
+
active_session_id: str | None = None
|
|
120
|
+
notifications_sent: list[NotificationRecord] = field(default_factory=list)
|
|
121
|
+
client_connection: Any = None
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
class MockAgent(Agent):
|
|
125
|
+
"""Mock ACP agent for debug server."""
|
|
126
|
+
|
|
127
|
+
def __init__(self, debug_state: DebugState) -> None:
|
|
128
|
+
"""Initialize with debug state."""
|
|
129
|
+
self.debug_state = debug_state
|
|
130
|
+
|
|
131
|
+
async def initialize(self, params: InitializeRequest) -> InitializeResponse:
|
|
132
|
+
"""Handle initialize request with mock capabilities."""
|
|
133
|
+
return InitializeResponse.create(
|
|
134
|
+
title="MockAgent",
|
|
135
|
+
name="MockAgent",
|
|
136
|
+
version="1.0",
|
|
137
|
+
protocol_version=1,
|
|
138
|
+
load_session=True,
|
|
139
|
+
)
|
|
140
|
+
|
|
141
|
+
async def new_session(self, params: NewSessionRequest) -> NewSessionResponse:
|
|
142
|
+
"""Create new debug session."""
|
|
143
|
+
session_id = str(uuid.uuid4())
|
|
144
|
+
created = time.perf_counter()
|
|
145
|
+
session = DebugSession(session_id=session_id, created_at=created, cwd=params.cwd)
|
|
146
|
+
self.debug_state.sessions[session_id] = session
|
|
147
|
+
self.debug_state.active_session_id = session_id
|
|
148
|
+
return NewSessionResponse(session_id=session_id)
|
|
149
|
+
|
|
150
|
+
async def load_session(self, params: LoadSessionRequest) -> LoadSessionResponse:
|
|
151
|
+
"""Load existing debug session."""
|
|
152
|
+
if params.session_id in self.debug_state.sessions:
|
|
153
|
+
self.debug_state.active_session_id = params.session_id
|
|
154
|
+
return LoadSessionResponse()
|
|
155
|
+
raise HTTPException(status_code=404, detail="Session not found")
|
|
156
|
+
|
|
157
|
+
async def prompt(self, params: PromptRequest) -> PromptResponse:
|
|
158
|
+
"""Handle prompt with mock response."""
|
|
159
|
+
logger.info("Received prompt", session_id=params.session_id)
|
|
160
|
+
return PromptResponse(stop_reason="end_turn")
|
|
161
|
+
|
|
162
|
+
async def cancel(self, params: CancelNotification) -> None:
|
|
163
|
+
"""Handle cancellation."""
|
|
164
|
+
logger.info("Received cancellation request")
|
|
165
|
+
|
|
166
|
+
async def authenticate(self, params: AuthenticateRequest) -> AuthenticateResponse | None:
|
|
167
|
+
"""Mock authentication - always succeeds."""
|
|
168
|
+
return AuthenticateResponse()
|
|
169
|
+
|
|
170
|
+
async def read_text_file(self, params: ReadTextFileRequest) -> ReadTextFileResponse:
|
|
171
|
+
"""Mock file reading."""
|
|
172
|
+
mock_content = MOCK_FILE.format(path=params.path)
|
|
173
|
+
return ReadTextFileResponse(content=mock_content)
|
|
174
|
+
|
|
175
|
+
async def write_text_file(self, params: WriteTextFileRequest) -> WriteTextFileResponse:
|
|
176
|
+
"""Mock file writing."""
|
|
177
|
+
logger.info("Mock write", path=params.path, content_length=len(params.content))
|
|
178
|
+
return WriteTextFileResponse()
|
|
179
|
+
|
|
180
|
+
async def create_terminal(self, params: CreateTerminalRequest) -> CreateTerminalResponse:
|
|
181
|
+
"""Mock terminal creation."""
|
|
182
|
+
terminal_id = str(uuid.uuid4())
|
|
183
|
+
return CreateTerminalResponse(terminal_id=terminal_id)
|
|
184
|
+
|
|
185
|
+
async def set_session_mode(self, params: SetSessionModeRequest) -> None:
|
|
186
|
+
"""Mock session mode change."""
|
|
187
|
+
logger.info("Mock session mode change")
|
|
188
|
+
|
|
189
|
+
async def set_session_model(self, params: SetSessionModelRequest) -> None:
|
|
190
|
+
"""Mock session model change."""
|
|
191
|
+
logger.info("Mock session model change")
|
|
192
|
+
|
|
193
|
+
async def ext_notification(self, method: str, params: dict[str, Any]) -> None:
|
|
194
|
+
"""Mock extensibility notification."""
|
|
195
|
+
logger.info("Mock ext notification", method=method)
|
|
196
|
+
|
|
197
|
+
async def ext_method(self, method: str, params: dict[str, Any]) -> Any:
|
|
198
|
+
"""Mock extensibility method."""
|
|
199
|
+
logger.info("Mock ext method", method=method)
|
|
200
|
+
return {"result": "mock response"}
|
|
201
|
+
|
|
202
|
+
async def list_sessions(self, params: ListSessionsRequest) -> ListSessionsResponse:
|
|
203
|
+
"""Mock list sessions."""
|
|
204
|
+
session_ids = list(self.debug_state.sessions.keys())
|
|
205
|
+
sessions = [SessionInfo(session_id=sid, cwd="/mock/cwd") for sid in session_ids]
|
|
206
|
+
return ListSessionsResponse(sessions=sessions)
|
|
207
|
+
|
|
208
|
+
async def fork_session(self, params: ForkSessionRequest) -> ForkSessionResponse:
|
|
209
|
+
"""Mock fork session."""
|
|
210
|
+
new_session_id = str(uuid.uuid4())
|
|
211
|
+
if params.session_id in self.debug_state.sessions:
|
|
212
|
+
old_session = self.debug_state.sessions[params.session_id]
|
|
213
|
+
new_session = DebugSession(
|
|
214
|
+
session_id=new_session_id,
|
|
215
|
+
created_at=time.perf_counter(),
|
|
216
|
+
cwd=old_session.cwd,
|
|
217
|
+
)
|
|
218
|
+
self.debug_state.sessions[new_session_id] = new_session
|
|
219
|
+
return ForkSessionResponse(session_id=new_session_id)
|
|
220
|
+
|
|
221
|
+
async def resume_session(self, params: ResumeSessionRequest) -> ResumeSessionResponse:
|
|
222
|
+
"""Mock resume session."""
|
|
223
|
+
if params.session_id in self.debug_state.sessions:
|
|
224
|
+
self.debug_state.active_session_id = params.session_id
|
|
225
|
+
return ResumeSessionResponse()
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
# FastAPI models for web interface
|
|
229
|
+
class NotificationRequest(BaseModel):
|
|
230
|
+
"""Request to send a notification."""
|
|
231
|
+
|
|
232
|
+
session_id: str = Field(description="Target session ID")
|
|
233
|
+
notification_type: str = Field(description="Type of notification to send")
|
|
234
|
+
data: dict[str, Any] = Field(default_factory=dict, description="Notification data")
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
class DebugStatus(BaseModel):
|
|
238
|
+
"""Current debug server status."""
|
|
239
|
+
|
|
240
|
+
active_sessions: list[str]
|
|
241
|
+
current_session: str | None
|
|
242
|
+
notifications_sent: int
|
|
243
|
+
acp_connected: bool
|
|
244
|
+
|
|
245
|
+
|
|
246
|
+
@asynccontextmanager
|
|
247
|
+
async def lifespan(app: FastAPI) -> AsyncIterator[None]:
|
|
248
|
+
"""FastAPI lifespan manager."""
|
|
249
|
+
logger.info("Debug server FastAPI starting up")
|
|
250
|
+
yield
|
|
251
|
+
logger.info("Debug server FastAPI shutting down")
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
# Create FastAPI app
|
|
255
|
+
app = FastAPI(
|
|
256
|
+
title="ACP Debug Server",
|
|
257
|
+
description="Debug interface for Agent Client Protocol testing",
|
|
258
|
+
version="1.0.0",
|
|
259
|
+
lifespan=lifespan,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
@app.get("/", response_class=HTMLResponse)
|
|
264
|
+
async def debug_interface() -> HTMLResponse:
|
|
265
|
+
"""Serve debug interface HTML."""
|
|
266
|
+
content = Path(__file__).parent / "debug.html"
|
|
267
|
+
return HTMLResponse(content.read_text("utf-8"))
|
|
268
|
+
|
|
269
|
+
|
|
270
|
+
@app.get("/status")
|
|
271
|
+
async def get_status() -> DebugStatus:
|
|
272
|
+
"""Get current debug server status."""
|
|
273
|
+
state = _get_debug_state()
|
|
274
|
+
return DebugStatus(
|
|
275
|
+
active_sessions=list(state.sessions.keys()),
|
|
276
|
+
current_session=state.active_session_id,
|
|
277
|
+
notifications_sent=len(state.notifications_sent),
|
|
278
|
+
acp_connected=state.client_connection is not None,
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
@app.post("/send-notification")
|
|
283
|
+
async def send_notification(request: NotificationRequest) -> dict[str, Any]:
|
|
284
|
+
"""Send a notification through ACP."""
|
|
285
|
+
state = _get_debug_state()
|
|
286
|
+
|
|
287
|
+
if not state.client_connection:
|
|
288
|
+
raise HTTPException(status_code=503, detail="ACP client not connected")
|
|
289
|
+
|
|
290
|
+
if request.session_id not in state.sessions:
|
|
291
|
+
raise HTTPException(status_code=404, detail="Session not found")
|
|
292
|
+
|
|
293
|
+
try:
|
|
294
|
+
update = await _create_notification_update(request.notification_type, request.data)
|
|
295
|
+
notification = SessionNotification(session_id=request.session_id, update=update)
|
|
296
|
+
await state.client_connection.session_update(notification)
|
|
297
|
+
record = NotificationRecord(
|
|
298
|
+
notification_type=request.notification_type,
|
|
299
|
+
session_id=request.session_id,
|
|
300
|
+
timestamp=time.perf_counter(),
|
|
301
|
+
)
|
|
302
|
+
state.notifications_sent.append(record)
|
|
303
|
+
logger.info(
|
|
304
|
+
"Sent notification to session",
|
|
305
|
+
notification_type=request.notification_type,
|
|
306
|
+
session_id=request.session_id,
|
|
307
|
+
)
|
|
308
|
+
except Exception as e:
|
|
309
|
+
logger.exception("Failed to send notification")
|
|
310
|
+
raise HTTPException(status_code=500, detail=str(e)) from e
|
|
311
|
+
else:
|
|
312
|
+
return {"success": True, "message": "Notification sent"}
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
async def _create_notification_update( # noqa: PLR0911
|
|
316
|
+
notification_type: str, data: dict[str, Any]
|
|
317
|
+
) -> SessionUpdate:
|
|
318
|
+
"""Create appropriate notification update object."""
|
|
319
|
+
match notification_type:
|
|
320
|
+
case "agent_message":
|
|
321
|
+
return AgentMessageChunk.text(text=data.get("text", "Mock agent message"))
|
|
322
|
+
case "user_message":
|
|
323
|
+
return UserMessageChunk.text(text=data.get("text", "Mock user message"))
|
|
324
|
+
case "agent_thought":
|
|
325
|
+
return AgentThoughtChunk.text(text=data.get("text", "Mock agent thought"))
|
|
326
|
+
case "tool_call_start":
|
|
327
|
+
return ToolCallStart(
|
|
328
|
+
tool_call_id=data.get("tool_call_id", f"tool-{uuid.uuid4()}"),
|
|
329
|
+
title=data.get("title", "Mock Tool Call"),
|
|
330
|
+
status="pending",
|
|
331
|
+
kind=data.get("kind", "other"),
|
|
332
|
+
)
|
|
333
|
+
case "tool_call_progress":
|
|
334
|
+
return ToolCallProgress(
|
|
335
|
+
tool_call_id=data.get("tool_call_id", "tool-123"),
|
|
336
|
+
status=data.get("status", "completed"),
|
|
337
|
+
raw_output=data.get("output"),
|
|
338
|
+
content=[ContentToolCallContent.text(text=data.get("output", "Tool completed"))]
|
|
339
|
+
if data.get("output")
|
|
340
|
+
else None,
|
|
341
|
+
)
|
|
342
|
+
case "plan_update":
|
|
343
|
+
entries = [
|
|
344
|
+
PlanEntry(content="Mock Plan Entry 1", priority="high", status="completed"),
|
|
345
|
+
PlanEntry(content="Mock Plan Entry 2", priority="medium", status="in_progress"),
|
|
346
|
+
]
|
|
347
|
+
return AgentPlanUpdate(entries=entries)
|
|
348
|
+
case "commands_update":
|
|
349
|
+
commands = [
|
|
350
|
+
AvailableCommand(name="mock-command", description="A mock command for testing"),
|
|
351
|
+
]
|
|
352
|
+
return AvailableCommandsUpdate(available_commands=commands)
|
|
353
|
+
case "mode_update":
|
|
354
|
+
return CurrentModeUpdate(current_mode_id=data.get("mode_id", "debug"))
|
|
355
|
+
# case "model_update":
|
|
356
|
+
# return CurrentModelUpdate(current_model_id=data.get("model_id", "None"))
|
|
357
|
+
case _:
|
|
358
|
+
raise ValueError(f"Unknown notification type: {notification_type}")
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
# Global state reference for FastAPI endpoints (unavoidable with FastAPI)
|
|
362
|
+
_global_debug_state: DebugState | None = None
|
|
363
|
+
|
|
364
|
+
|
|
365
|
+
def _set_debug_state(state: DebugState) -> None:
|
|
366
|
+
"""Set global debug state reference."""
|
|
367
|
+
global _global_debug_state # noqa: PLW0603
|
|
368
|
+
_global_debug_state = state
|
|
369
|
+
|
|
370
|
+
|
|
371
|
+
def _get_debug_state() -> DebugState:
|
|
372
|
+
"""Get global debug state reference."""
|
|
373
|
+
if _global_debug_state is None:
|
|
374
|
+
raise RuntimeError("Debug state not initialized")
|
|
375
|
+
return _global_debug_state
|
|
376
|
+
|
|
377
|
+
|
|
378
|
+
class ACPDebugServer:
|
|
379
|
+
"""Combined ACP and FastAPI debug server."""
|
|
380
|
+
|
|
381
|
+
def __init__(self, *, fastapi_port: int = 8000, fastapi_host: str = "127.0.0.1") -> None:
|
|
382
|
+
"""Initialize the debug server.
|
|
383
|
+
|
|
384
|
+
Args:
|
|
385
|
+
fastapi_port: Port for FastAPI web interface
|
|
386
|
+
fastapi_host: Host for FastAPI web interface
|
|
387
|
+
"""
|
|
388
|
+
self.fastapi_port = fastapi_port
|
|
389
|
+
self.fastapi_host = fastapi_host
|
|
390
|
+
self.debug_state = DebugState()
|
|
391
|
+
self.agent = MockAgent(self.debug_state)
|
|
392
|
+
self._running = False
|
|
393
|
+
self._shutdown_event: anyio.Event | None = None
|
|
394
|
+
self._fastapi_thread: threading.Thread | None = None
|
|
395
|
+
# Set global reference for FastAPI endpoints
|
|
396
|
+
_set_debug_state(self.debug_state)
|
|
397
|
+
|
|
398
|
+
async def run(self) -> None:
|
|
399
|
+
"""Run both ACP server (stdio) and FastAPI server."""
|
|
400
|
+
if self._running:
|
|
401
|
+
raise RuntimeError("Server already running")
|
|
402
|
+
|
|
403
|
+
self._running = True
|
|
404
|
+
self._shutdown_event = anyio.Event()
|
|
405
|
+
logger.info("Starting ACP Debug Server")
|
|
406
|
+
|
|
407
|
+
try:
|
|
408
|
+
self._start_fastapi() # Start FastAPI server in background thread
|
|
409
|
+
await self._run_acp_server() # Start ACP server on stdio
|
|
410
|
+
except Exception:
|
|
411
|
+
logger.exception("Error running debug server")
|
|
412
|
+
raise
|
|
413
|
+
finally:
|
|
414
|
+
await self.shutdown()
|
|
415
|
+
|
|
416
|
+
def _start_fastapi(self) -> None:
|
|
417
|
+
"""Start FastAPI server in a separate thread."""
|
|
418
|
+
|
|
419
|
+
def run_fastapi() -> None:
|
|
420
|
+
uvicorn.run(app, host=self.fastapi_host, port=self.fastapi_port, log_level="info")
|
|
421
|
+
|
|
422
|
+
self._fastapi_thread = threading.Thread(target=run_fastapi, daemon=True)
|
|
423
|
+
self._fastapi_thread.start()
|
|
424
|
+
url = f"http://{self.fastapi_host}:{self.fastapi_port}"
|
|
425
|
+
logger.info("FastAPI debug interface started", url=url)
|
|
426
|
+
|
|
427
|
+
async def _run_acp_server(self) -> None:
|
|
428
|
+
"""Run ACP server on stdio."""
|
|
429
|
+
try:
|
|
430
|
+
logger.info("Starting ACP server on stdio")
|
|
431
|
+
reader, writer = await stdio_streams()
|
|
432
|
+
|
|
433
|
+
# Create ACP connection
|
|
434
|
+
def agent_factory(connection: AgentSideConnection) -> Agent:
|
|
435
|
+
return self.agent
|
|
436
|
+
|
|
437
|
+
filename = "acp-debug-server.jsonl"
|
|
438
|
+
conn = AgentSideConnection(agent_factory, writer, reader, debug_file=filename)
|
|
439
|
+
# Store connection for FastAPI endpoints
|
|
440
|
+
self.debug_state.client_connection = conn
|
|
441
|
+
logger.info("ACP Debug Server ready - connect your client!")
|
|
442
|
+
url = f"http://{self.fastapi_host}:{self.fastapi_port}"
|
|
443
|
+
logger.info("Web interface", url=url)
|
|
444
|
+
assert self._shutdown_event is not None
|
|
445
|
+
await self._shutdown_event.wait()
|
|
446
|
+
except Exception:
|
|
447
|
+
logger.exception("ACP server error")
|
|
448
|
+
raise
|
|
449
|
+
|
|
450
|
+
async def shutdown(self) -> None:
|
|
451
|
+
"""Shutdown the debug server."""
|
|
452
|
+
if not self._running:
|
|
453
|
+
raise RuntimeError("Server is not running")
|
|
454
|
+
|
|
455
|
+
self._running = False
|
|
456
|
+
if self._shutdown_event:
|
|
457
|
+
self._shutdown_event.set()
|
|
458
|
+
logger.info("Shutting down ACP Debug Server")
|
|
459
|
+
# Clean up connection
|
|
460
|
+
if self.debug_state.client_connection:
|
|
461
|
+
try:
|
|
462
|
+
await self.debug_state.client_connection.close()
|
|
463
|
+
except Exception as e: # noqa: BLE001
|
|
464
|
+
logger.warning("Error closing ACP connection", error=e)
|
|
465
|
+
finally:
|
|
466
|
+
self.debug_state.client_connection = None
|
|
467
|
+
|
|
468
|
+
|
|
469
|
+
async def main() -> None:
|
|
470
|
+
"""Entry point for debug server."""
|
|
471
|
+
import argparse
|
|
472
|
+
|
|
473
|
+
parser = argparse.ArgumentParser(description="ACP Debug Server")
|
|
474
|
+
parser.add_argument("--port", type=int, default=7777, help="FastAPI port")
|
|
475
|
+
parser.add_argument("--host", default="127.0.0.1", help="FastAPI host")
|
|
476
|
+
parser.add_argument("--log-level", default="info", help="Logging level")
|
|
477
|
+
args = parser.parse_args()
|
|
478
|
+
# Configure logging
|
|
479
|
+
level = getattr(logging, args.log_level.upper())
|
|
480
|
+
logging.basicConfig(
|
|
481
|
+
level=level,
|
|
482
|
+
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
483
|
+
)
|
|
484
|
+
|
|
485
|
+
server = ACPDebugServer(fastapi_port=args.port, fastapi_host=args.host)
|
|
486
|
+
try:
|
|
487
|
+
await server.run()
|
|
488
|
+
except KeyboardInterrupt:
|
|
489
|
+
logger.info("Debug server interrupted")
|
|
490
|
+
except Exception:
|
|
491
|
+
logger.exception("Debug server error")
|
|
492
|
+
sys.exit(1)
|
|
493
|
+
|
|
494
|
+
|
|
495
|
+
if __name__ == "__main__":
|
|
496
|
+
anyio.run(main)
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"""Test fixtures for ACP tests."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any
|
|
6
|
+
|
|
7
|
+
from acp import (
|
|
8
|
+
Agent,
|
|
9
|
+
Implementation,
|
|
10
|
+
InitializeResponse,
|
|
11
|
+
LoadSessionResponse,
|
|
12
|
+
NewSessionResponse,
|
|
13
|
+
PromptResponse,
|
|
14
|
+
)
|
|
15
|
+
from acp.schema import (
|
|
16
|
+
AuthenticateResponse,
|
|
17
|
+
ForkSessionResponse,
|
|
18
|
+
ListSessionsResponse,
|
|
19
|
+
ResumeSessionResponse,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from acp import SetSessionModeRequest
|
|
25
|
+
from acp.schema import (
|
|
26
|
+
AuthenticateRequest,
|
|
27
|
+
CancelNotification,
|
|
28
|
+
ForkSessionRequest,
|
|
29
|
+
InitializeRequest,
|
|
30
|
+
ListSessionsRequest,
|
|
31
|
+
LoadSessionRequest,
|
|
32
|
+
NewSessionRequest,
|
|
33
|
+
PromptRequest,
|
|
34
|
+
ResumeSessionRequest,
|
|
35
|
+
SetSessionModelRequest,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class TestAgent(Agent):
|
|
40
|
+
"""Test agent implementation for ACP testing."""
|
|
41
|
+
|
|
42
|
+
def __init__(self) -> None:
|
|
43
|
+
self.prompts: list[PromptRequest] = []
|
|
44
|
+
self.cancellations: list[str] = []
|
|
45
|
+
self.ext_calls: list[tuple[str, dict[str, Any]]] = []
|
|
46
|
+
self.ext_notes: list[tuple[str, dict[str, Any]]] = []
|
|
47
|
+
|
|
48
|
+
async def initialize(self, params: InitializeRequest) -> InitializeResponse:
|
|
49
|
+
return InitializeResponse(
|
|
50
|
+
protocol_version=params.protocol_version,
|
|
51
|
+
agent_capabilities=None,
|
|
52
|
+
agent_info=Implementation(name="test-agent", version="1.0"),
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
async def new_session(self, params: NewSessionRequest) -> NewSessionResponse:
|
|
56
|
+
return NewSessionResponse(session_id="test-session-123")
|
|
57
|
+
|
|
58
|
+
async def load_session(self, params: LoadSessionRequest) -> LoadSessionResponse:
|
|
59
|
+
return LoadSessionResponse()
|
|
60
|
+
|
|
61
|
+
async def authenticate(self, params: AuthenticateRequest) -> AuthenticateResponse | None:
|
|
62
|
+
return AuthenticateResponse()
|
|
63
|
+
|
|
64
|
+
async def prompt(self, params: PromptRequest) -> PromptResponse:
|
|
65
|
+
self.prompts.append(params)
|
|
66
|
+
return PromptResponse(stop_reason="end_turn")
|
|
67
|
+
|
|
68
|
+
async def cancel(self, params: CancelNotification) -> None:
|
|
69
|
+
self.cancellations.append(params.session_id)
|
|
70
|
+
|
|
71
|
+
async def set_session_mode(self, params: SetSessionModeRequest) -> None:
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
async def set_session_model(self, params: SetSessionModelRequest) -> None:
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
async def ext_method(self, method: str, params: dict[str, Any]) -> dict[str, Any]:
|
|
78
|
+
self.ext_calls.append((method, params))
|
|
79
|
+
return {"ok": True, "method": method}
|
|
80
|
+
|
|
81
|
+
async def ext_notification(self, method: str, params: dict[str, Any]) -> None:
|
|
82
|
+
self.ext_notes.append((method, params))
|
|
83
|
+
|
|
84
|
+
async def list_sessions(self, params: ListSessionsRequest) -> ListSessionsResponse:
|
|
85
|
+
return ListSessionsResponse(sessions=[])
|
|
86
|
+
|
|
87
|
+
async def fork_session(self, params: ForkSessionRequest) -> ForkSessionResponse:
|
|
88
|
+
return ForkSessionResponse(session_id="test-session-123")
|
|
89
|
+
|
|
90
|
+
async def resume_session(self, params: ResumeSessionRequest) -> ResumeSessionResponse:
|
|
91
|
+
return ResumeSessionResponse()
|
acp/agent/protocol.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Client ACP Connection."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Protocol
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
if TYPE_CHECKING:
|
|
9
|
+
from acp.schema import (
|
|
10
|
+
AuthenticateRequest,
|
|
11
|
+
AuthenticateResponse,
|
|
12
|
+
CancelNotification,
|
|
13
|
+
ForkSessionRequest,
|
|
14
|
+
ForkSessionResponse,
|
|
15
|
+
InitializeRequest,
|
|
16
|
+
InitializeResponse,
|
|
17
|
+
ListSessionsRequest,
|
|
18
|
+
ListSessionsResponse,
|
|
19
|
+
LoadSessionRequest,
|
|
20
|
+
LoadSessionResponse,
|
|
21
|
+
NewSessionRequest,
|
|
22
|
+
NewSessionResponse,
|
|
23
|
+
PromptRequest,
|
|
24
|
+
PromptResponse,
|
|
25
|
+
ResumeSessionRequest,
|
|
26
|
+
ResumeSessionResponse,
|
|
27
|
+
SetSessionModelRequest,
|
|
28
|
+
SetSessionModelResponse,
|
|
29
|
+
SetSessionModeRequest,
|
|
30
|
+
SetSessionModeResponse,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class Agent(Protocol):
|
|
35
|
+
"""Base agent interface for ACP."""
|
|
36
|
+
|
|
37
|
+
async def initialize(self, params: InitializeRequest) -> InitializeResponse: ...
|
|
38
|
+
|
|
39
|
+
async def new_session(self, params: NewSessionRequest) -> NewSessionResponse: ...
|
|
40
|
+
|
|
41
|
+
async def prompt(self, params: PromptRequest) -> PromptResponse: ...
|
|
42
|
+
|
|
43
|
+
async def cancel(self, params: CancelNotification) -> None: ...
|
|
44
|
+
|
|
45
|
+
async def load_session(self, params: LoadSessionRequest) -> LoadSessionResponse: ...
|
|
46
|
+
|
|
47
|
+
async def list_sessions(self, params: ListSessionsRequest) -> ListSessionsResponse: ...
|
|
48
|
+
|
|
49
|
+
async def fork_session(self, params: ForkSessionRequest) -> ForkSessionResponse: ...
|
|
50
|
+
|
|
51
|
+
async def resume_session(self, params: ResumeSessionRequest) -> ResumeSessionResponse: ...
|
|
52
|
+
|
|
53
|
+
async def authenticate(self, params: AuthenticateRequest) -> AuthenticateResponse | None: ...
|
|
54
|
+
|
|
55
|
+
async def set_session_mode(
|
|
56
|
+
self, params: SetSessionModeRequest
|
|
57
|
+
) -> SetSessionModeResponse | None: ...
|
|
58
|
+
|
|
59
|
+
async def set_session_model(
|
|
60
|
+
self, params: SetSessionModelRequest
|
|
61
|
+
) -> SetSessionModelResponse | None: ...
|
|
62
|
+
|
|
63
|
+
async def ext_method(self, method: str, params: dict[str, Any]) -> dict[str, Any]: ...
|
|
64
|
+
|
|
65
|
+
async def ext_notification(self, method: str, params: dict[str, Any]) -> None: ...
|