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,199 @@
|
|
|
1
|
+
"""Stateful tool call progress reporter for ACP."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Self
|
|
6
|
+
|
|
7
|
+
from acp.schema.tool_call import ToolCallLocation
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from collections.abc import Sequence
|
|
12
|
+
import types
|
|
13
|
+
|
|
14
|
+
from acp.notifications import ACPNotifications
|
|
15
|
+
from acp.schema.tool_call import (
|
|
16
|
+
ToolCallContent,
|
|
17
|
+
ToolCallKind,
|
|
18
|
+
ToolCallStatus,
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ToolCallReporter:
|
|
23
|
+
"""Stateful reporter for tool call progress.
|
|
24
|
+
|
|
25
|
+
Maintains the current state of a tool call and sends updates
|
|
26
|
+
when fields are modified. This avoids having to repeat unchanged
|
|
27
|
+
fields on every progress update.
|
|
28
|
+
|
|
29
|
+
Example:
|
|
30
|
+
```python
|
|
31
|
+
reporter = await notifications.create_tool_reporter(
|
|
32
|
+
tool_call_id="abc123",
|
|
33
|
+
title="Reading file",
|
|
34
|
+
kind="read",
|
|
35
|
+
)
|
|
36
|
+
await reporter.update(status="in_progress", message="Opening file...")
|
|
37
|
+
await reporter.update(progress=0.5)
|
|
38
|
+
await reporter.update(status="completed", message="Done!")
|
|
39
|
+
```
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
def __init__(
|
|
43
|
+
self,
|
|
44
|
+
notifications: ACPNotifications,
|
|
45
|
+
tool_call_id: str,
|
|
46
|
+
title: str,
|
|
47
|
+
*,
|
|
48
|
+
kind: ToolCallKind | None = None,
|
|
49
|
+
status: ToolCallStatus = "pending",
|
|
50
|
+
locations: Sequence[ToolCallLocation] | None = None,
|
|
51
|
+
content: Sequence[ToolCallContent] | None = None,
|
|
52
|
+
raw_input: Any | None = None,
|
|
53
|
+
raw_output: Any | None = None,
|
|
54
|
+
) -> None:
|
|
55
|
+
"""Initialize the reporter with initial state.
|
|
56
|
+
|
|
57
|
+
Args:
|
|
58
|
+
notifications: The ACPNotifications instance to send updates through
|
|
59
|
+
tool_call_id: Unique identifier for this tool call
|
|
60
|
+
title: Human-readable title describing the tool action
|
|
61
|
+
kind: Category of tool being invoked
|
|
62
|
+
status: Initial execution status
|
|
63
|
+
locations: File locations affected by this tool call
|
|
64
|
+
content: Content produced by the tool call
|
|
65
|
+
raw_input: Raw input parameters sent to the tool
|
|
66
|
+
raw_output: Raw output returned by the tool
|
|
67
|
+
"""
|
|
68
|
+
self._notifications = notifications
|
|
69
|
+
self.tool_call_id = tool_call_id
|
|
70
|
+
self.title = title
|
|
71
|
+
self.kind: ToolCallKind | None = kind
|
|
72
|
+
self.status: ToolCallStatus = status
|
|
73
|
+
self.locations: list[ToolCallLocation] = list(locations) if locations else []
|
|
74
|
+
self.content: list[ToolCallContent] = list(content) if content else []
|
|
75
|
+
self.raw_input = raw_input
|
|
76
|
+
self.raw_output = raw_output
|
|
77
|
+
self._started = False
|
|
78
|
+
|
|
79
|
+
async def start(self) -> None:
|
|
80
|
+
"""Send the initial tool_call notification.
|
|
81
|
+
|
|
82
|
+
This is called automatically if you use `create_tool_reporter`,
|
|
83
|
+
but can be called manually if constructing the reporter directly.
|
|
84
|
+
"""
|
|
85
|
+
if self._started:
|
|
86
|
+
return
|
|
87
|
+
|
|
88
|
+
await self._notifications.tool_call_start(
|
|
89
|
+
tool_call_id=self.tool_call_id,
|
|
90
|
+
title=self.title,
|
|
91
|
+
kind=self.kind,
|
|
92
|
+
locations=self.locations or None,
|
|
93
|
+
content=self.content or None,
|
|
94
|
+
raw_input=self.raw_input,
|
|
95
|
+
)
|
|
96
|
+
self._started = True
|
|
97
|
+
|
|
98
|
+
async def update(
|
|
99
|
+
self,
|
|
100
|
+
*,
|
|
101
|
+
title: str | None = None,
|
|
102
|
+
status: ToolCallStatus | None = None,
|
|
103
|
+
kind: ToolCallKind | None = None,
|
|
104
|
+
message: str | None = None,
|
|
105
|
+
raw_output: Any | None = None,
|
|
106
|
+
locations: Sequence[ToolCallLocation | str] | None = None,
|
|
107
|
+
content: Sequence[ToolCallContent | str] | None = None,
|
|
108
|
+
replace: bool = False,
|
|
109
|
+
) -> None:
|
|
110
|
+
"""Update one or more fields and send the updated state.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
title: Update the human-readable title
|
|
114
|
+
status: Update the execution status
|
|
115
|
+
kind: Update the tool kind
|
|
116
|
+
message: Convenience for adding a text content block
|
|
117
|
+
raw_output: Update the raw output
|
|
118
|
+
locations: Locations to add or replace (path strings or ToolCallLocation)
|
|
119
|
+
content: Content blocks to add or replace
|
|
120
|
+
replace: If True, replace all content/locations; if False, append
|
|
121
|
+
"""
|
|
122
|
+
if not self._started:
|
|
123
|
+
await self.start()
|
|
124
|
+
|
|
125
|
+
# Update stored state
|
|
126
|
+
if title is not None:
|
|
127
|
+
self.title = title
|
|
128
|
+
if status is not None:
|
|
129
|
+
self.status = status
|
|
130
|
+
if kind is not None:
|
|
131
|
+
self.kind = kind
|
|
132
|
+
if raw_output is not None:
|
|
133
|
+
self.raw_output = raw_output
|
|
134
|
+
|
|
135
|
+
# Handle locations
|
|
136
|
+
if locations is not None:
|
|
137
|
+
normalized = [
|
|
138
|
+
ToolCallLocation(path=loc) if isinstance(loc, str) else loc for loc in locations
|
|
139
|
+
]
|
|
140
|
+
if replace:
|
|
141
|
+
self.locations = normalized
|
|
142
|
+
else:
|
|
143
|
+
self.locations.extend(normalized)
|
|
144
|
+
|
|
145
|
+
# Handle content (strings will be converted by tool_call_progress)
|
|
146
|
+
if content is not None:
|
|
147
|
+
content_list: list[ToolCallContent | str] = list(content)
|
|
148
|
+
if replace:
|
|
149
|
+
self.content = content_list # type: ignore[assignment]
|
|
150
|
+
else:
|
|
151
|
+
self.content.extend(content_list) # type: ignore[arg-type]
|
|
152
|
+
|
|
153
|
+
if message is not None:
|
|
154
|
+
self.content.append(message) # type: ignore[arg-type]
|
|
155
|
+
|
|
156
|
+
await self._notifications.tool_call_progress(
|
|
157
|
+
tool_call_id=self.tool_call_id,
|
|
158
|
+
status=self.status,
|
|
159
|
+
title=self.title,
|
|
160
|
+
kind=self.kind,
|
|
161
|
+
locations=self.locations or None,
|
|
162
|
+
content=self.content or None,
|
|
163
|
+
raw_output=self.raw_output,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
async def complete(self, *, message: str | None = None, raw_output: Any | None = None) -> None:
|
|
167
|
+
"""Mark the tool call as completed.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
message: Optional final message to add
|
|
171
|
+
raw_output: Optional final output
|
|
172
|
+
"""
|
|
173
|
+
await self.update(status="completed", message=message, raw_output=raw_output)
|
|
174
|
+
|
|
175
|
+
async def fail(self, *, error: str | None = None, raw_output: Any | None = None) -> None:
|
|
176
|
+
"""Mark the tool call as failed.
|
|
177
|
+
|
|
178
|
+
Args:
|
|
179
|
+
error: Optional error message to add
|
|
180
|
+
raw_output: Optional output (e.g., error details)
|
|
181
|
+
"""
|
|
182
|
+
await self.update(status="failed", message=error, raw_output=raw_output)
|
|
183
|
+
|
|
184
|
+
async def __aenter__(self) -> Self:
|
|
185
|
+
"""Enter async context, starting the tool call."""
|
|
186
|
+
await self.start()
|
|
187
|
+
return self
|
|
188
|
+
|
|
189
|
+
async def __aexit__(
|
|
190
|
+
self,
|
|
191
|
+
exc_type: type[BaseException] | None,
|
|
192
|
+
exc_val: BaseException | None,
|
|
193
|
+
exc_tb: types.TracebackType | None,
|
|
194
|
+
) -> None:
|
|
195
|
+
"""Exit async context, marking complete or failed based on exception."""
|
|
196
|
+
if exc_type is not None:
|
|
197
|
+
await self.fail(error=str(exc_val) if exc_val else "Unknown error")
|
|
198
|
+
elif self.status not in ("completed", "failed"):
|
|
199
|
+
await self.complete()
|
acp/tool_call_state.py
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""Stateful tool call tracker for ACP.
|
|
2
|
+
|
|
3
|
+
This module provides a simple state tracker for tool calls that sends
|
|
4
|
+
only changed fields in updates, following the ACP protocol spec.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import TYPE_CHECKING, Any
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import Sequence
|
|
14
|
+
|
|
15
|
+
from acp.notifications import ACPNotifications
|
|
16
|
+
from acp.schema.tool_call import ToolCallContent, ToolCallKind, ToolCallLocation, ToolCallStatus
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ToolCallState:
|
|
20
|
+
"""Tracks tool call state and sends delta updates.
|
|
21
|
+
|
|
22
|
+
Instead of accumulating all state and sending everything on each update,
|
|
23
|
+
this class tracks whether we've started and sends only the fields that
|
|
24
|
+
are explicitly provided in each update call.
|
|
25
|
+
|
|
26
|
+
The ACP protocol spec states:
|
|
27
|
+
"All fields except toolCallId are optional in updates.
|
|
28
|
+
Only the fields being changed need to be included."
|
|
29
|
+
|
|
30
|
+
Example flow:
|
|
31
|
+
1. Tool call starts → state.start() sends initial notification
|
|
32
|
+
2. Progress event → state.update(title="Running...") sends just title
|
|
33
|
+
3. More progress → state.update(content=[...]) sends just content
|
|
34
|
+
4. Tool completes → state.complete(raw_output=result) sends status + output
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
notifications: ACPNotifications,
|
|
40
|
+
tool_call_id: str,
|
|
41
|
+
tool_name: str,
|
|
42
|
+
title: str,
|
|
43
|
+
kind: ToolCallKind,
|
|
44
|
+
raw_input: dict[str, Any],
|
|
45
|
+
) -> None:
|
|
46
|
+
"""Initialize tool call state.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
notifications: ACPNotifications instance for sending updates
|
|
50
|
+
tool_call_id: Unique identifier for this tool call
|
|
51
|
+
tool_name: Name of the tool being called
|
|
52
|
+
title: Initial human-readable title
|
|
53
|
+
kind: Category of tool (read, edit, execute, etc.)
|
|
54
|
+
raw_input: Input parameters passed to the tool
|
|
55
|
+
"""
|
|
56
|
+
self._notifications = notifications
|
|
57
|
+
self.tool_call_id = tool_call_id
|
|
58
|
+
self.tool_name = tool_name
|
|
59
|
+
self._initial_title = title
|
|
60
|
+
self._initial_kind: ToolCallKind = kind
|
|
61
|
+
self._raw_input = raw_input
|
|
62
|
+
self._started = False
|
|
63
|
+
self._has_content = False # Track if content has been sent
|
|
64
|
+
|
|
65
|
+
@property
|
|
66
|
+
def has_content(self) -> bool:
|
|
67
|
+
"""Whether content has been sent for this tool call."""
|
|
68
|
+
return self._has_content
|
|
69
|
+
|
|
70
|
+
async def start(self) -> None:
|
|
71
|
+
"""Send initial tool_call notification.
|
|
72
|
+
|
|
73
|
+
This creates the tool call entry in the client UI. Subsequent calls
|
|
74
|
+
to update() will send tool_call_update notifications with only
|
|
75
|
+
the changed fields.
|
|
76
|
+
"""
|
|
77
|
+
if self._started:
|
|
78
|
+
return
|
|
79
|
+
|
|
80
|
+
await self._notifications.tool_call_start(
|
|
81
|
+
tool_call_id=self.tool_call_id,
|
|
82
|
+
title=self._initial_title,
|
|
83
|
+
kind=self._initial_kind,
|
|
84
|
+
raw_input=self._raw_input,
|
|
85
|
+
)
|
|
86
|
+
self._started = True
|
|
87
|
+
|
|
88
|
+
async def update(
|
|
89
|
+
self,
|
|
90
|
+
*,
|
|
91
|
+
title: str | None = None,
|
|
92
|
+
status: ToolCallStatus | None = None,
|
|
93
|
+
kind: ToolCallKind | None = None,
|
|
94
|
+
content: Sequence[ToolCallContent] | None = None,
|
|
95
|
+
locations: Sequence[ToolCallLocation | str] | None = None,
|
|
96
|
+
raw_output: Any = None,
|
|
97
|
+
) -> None:
|
|
98
|
+
"""Send an update with only the provided fields.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
title: Update the human-readable title
|
|
102
|
+
status: Update execution status
|
|
103
|
+
kind: Update tool kind
|
|
104
|
+
content: Content items (terminals, diffs, text) - replaces previous
|
|
105
|
+
locations: File locations - replaces previous
|
|
106
|
+
raw_output: Update raw output data
|
|
107
|
+
|
|
108
|
+
Note:
|
|
109
|
+
Only fields that are truthy (not None/empty) will be included
|
|
110
|
+
in the notification. This follows the ACP spec which states
|
|
111
|
+
that only changed fields need to be sent.
|
|
112
|
+
"""
|
|
113
|
+
from acp.schema.tool_call import ToolCallLocation
|
|
114
|
+
|
|
115
|
+
if not self._started:
|
|
116
|
+
await self.start()
|
|
117
|
+
# Build kwargs with only the provided fields
|
|
118
|
+
kwargs: dict[str, Any] = {}
|
|
119
|
+
if title is not None:
|
|
120
|
+
kwargs["title"] = title
|
|
121
|
+
if status is not None:
|
|
122
|
+
kwargs["status"] = status
|
|
123
|
+
if kind is not None:
|
|
124
|
+
kwargs["kind"] = kind
|
|
125
|
+
if content:
|
|
126
|
+
kwargs["content"] = content
|
|
127
|
+
self._has_content = True
|
|
128
|
+
if locations:
|
|
129
|
+
# Normalize string paths to ToolCallLocation
|
|
130
|
+
kwargs["locations"] = [
|
|
131
|
+
ToolCallLocation(path=loc) if isinstance(loc, str) else loc for loc in locations
|
|
132
|
+
]
|
|
133
|
+
if raw_output is not None:
|
|
134
|
+
kwargs["raw_output"] = raw_output
|
|
135
|
+
|
|
136
|
+
# Only send if there's something to update
|
|
137
|
+
if kwargs:
|
|
138
|
+
await self._notifications.tool_call_update(
|
|
139
|
+
tool_call_id=self.tool_call_id,
|
|
140
|
+
**kwargs,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
async def complete(
|
|
144
|
+
self,
|
|
145
|
+
raw_output: Any = None,
|
|
146
|
+
*,
|
|
147
|
+
content: Sequence[ToolCallContent] | None = None,
|
|
148
|
+
title: str | None = None,
|
|
149
|
+
) -> None:
|
|
150
|
+
"""Mark tool call as completed.
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
raw_output: Final output data
|
|
154
|
+
content: Optional final content
|
|
155
|
+
title: Optional final title
|
|
156
|
+
"""
|
|
157
|
+
await self.update(
|
|
158
|
+
status="completed",
|
|
159
|
+
raw_output=raw_output,
|
|
160
|
+
content=content,
|
|
161
|
+
title=title,
|
|
162
|
+
)
|
|
163
|
+
|
|
164
|
+
async def fail(self, error: str | None = None, *, raw_output: Any = None) -> None:
|
|
165
|
+
"""Mark tool call as failed.
|
|
166
|
+
|
|
167
|
+
Args:
|
|
168
|
+
error: Error message to display
|
|
169
|
+
raw_output: Optional error details
|
|
170
|
+
"""
|
|
171
|
+
from acp.schema import ContentToolCallContent
|
|
172
|
+
|
|
173
|
+
content = None
|
|
174
|
+
if error:
|
|
175
|
+
error_content = ContentToolCallContent.text(text=f"Error: {error}")
|
|
176
|
+
content = [error_content]
|
|
177
|
+
|
|
178
|
+
await self.update(status="failed", content=content, raw_output=raw_output)
|
acp/transports.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import contextlib
|
|
4
|
+
from contextlib import asynccontextmanager
|
|
5
|
+
import os
|
|
6
|
+
import subprocess
|
|
7
|
+
from typing import TYPE_CHECKING
|
|
8
|
+
|
|
9
|
+
import anyio
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from collections.abc import AsyncIterator, Mapping
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from anyio.abc import ByteReceiveStream, ByteSendStream, Process
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
DEFAULT_INHERITED_ENV_VARS = (
|
|
20
|
+
[
|
|
21
|
+
"APPDATA",
|
|
22
|
+
"HOMEDRIVE",
|
|
23
|
+
"HOMEPATH",
|
|
24
|
+
"LOCALAPPDATA",
|
|
25
|
+
"PATH",
|
|
26
|
+
"PATHEXT",
|
|
27
|
+
"PROCESSOR_ARCHITECTURE",
|
|
28
|
+
"SYSTEMDRIVE",
|
|
29
|
+
"SYSTEMROOT",
|
|
30
|
+
"TEMP",
|
|
31
|
+
"USERNAME",
|
|
32
|
+
"USERPROFILE",
|
|
33
|
+
]
|
|
34
|
+
if os.name == "nt"
|
|
35
|
+
else ["HOME", "LOGNAME", "PATH", "SHELL", "TERM", "USER"]
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def default_environment() -> dict[str, str]:
|
|
40
|
+
"""Return a trimmed environment based on MCP best practices."""
|
|
41
|
+
env: dict[str, str] = {}
|
|
42
|
+
for key in DEFAULT_INHERITED_ENV_VARS:
|
|
43
|
+
value = os.environ.get(key)
|
|
44
|
+
if value is None:
|
|
45
|
+
continue
|
|
46
|
+
# Skip function-style env vars on some shells (see MCP reference)
|
|
47
|
+
if value.startswith("()"):
|
|
48
|
+
continue
|
|
49
|
+
env[key] = value
|
|
50
|
+
return env
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@asynccontextmanager
|
|
54
|
+
async def spawn_stdio_transport(
|
|
55
|
+
command: str,
|
|
56
|
+
*args: str,
|
|
57
|
+
env: Mapping[str, str] | None = None,
|
|
58
|
+
cwd: str | Path | None = None,
|
|
59
|
+
stderr: int | None = subprocess.PIPE,
|
|
60
|
+
shutdown_timeout: float = 2.0,
|
|
61
|
+
) -> AsyncIterator[tuple[ByteReceiveStream, ByteSendStream, Process]]:
|
|
62
|
+
"""Launch a subprocess and expose its stdio streams as anyio streams.
|
|
63
|
+
|
|
64
|
+
This mirrors the defensive shutdown behaviour used by the MCP Python SDK:
|
|
65
|
+
close stdin first, wait for graceful exit, then escalate to terminate/kill.
|
|
66
|
+
"""
|
|
67
|
+
merged_env = default_environment()
|
|
68
|
+
if env:
|
|
69
|
+
merged_env.update(env)
|
|
70
|
+
|
|
71
|
+
process = await anyio.open_process(
|
|
72
|
+
[command, *args],
|
|
73
|
+
stdin=subprocess.PIPE,
|
|
74
|
+
stdout=subprocess.PIPE,
|
|
75
|
+
stderr=stderr,
|
|
76
|
+
env=merged_env,
|
|
77
|
+
cwd=str(cwd) if cwd is not None else None,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
if process.stdout is None or process.stdin is None:
|
|
81
|
+
process.kill()
|
|
82
|
+
await process.wait()
|
|
83
|
+
msg = "spawn_stdio_transport requires stdout/stdin pipes"
|
|
84
|
+
raise RuntimeError(msg)
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
yield process.stdout, process.stdin, process
|
|
88
|
+
finally:
|
|
89
|
+
# Attempt graceful stdin shutdown first
|
|
90
|
+
if process.stdin is not None:
|
|
91
|
+
with contextlib.suppress(Exception):
|
|
92
|
+
await process.stdin.aclose()
|
|
93
|
+
|
|
94
|
+
try:
|
|
95
|
+
with anyio.fail_after(shutdown_timeout):
|
|
96
|
+
await process.wait()
|
|
97
|
+
except TimeoutError:
|
|
98
|
+
process.terminate()
|
|
99
|
+
try:
|
|
100
|
+
with anyio.fail_after(shutdown_timeout):
|
|
101
|
+
await process.wait()
|
|
102
|
+
except TimeoutError:
|
|
103
|
+
process.kill()
|
|
104
|
+
await process.wait()
|