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,164 @@
|
|
|
1
|
+
"""Base class for HTTP-based servers.
|
|
2
|
+
|
|
3
|
+
This module provides a base class for servers that expose HTTP routes via Starlette.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
|
|
8
|
+
from abc import abstractmethod
|
|
9
|
+
from typing import TYPE_CHECKING, Self
|
|
10
|
+
|
|
11
|
+
from agentpool.log import get_logger
|
|
12
|
+
from agentpool_server.base import BaseServer
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
if TYPE_CHECKING:
|
|
16
|
+
from starlette.applications import Starlette
|
|
17
|
+
from starlette.routing import Route
|
|
18
|
+
from upathtools import JoinablePathLike
|
|
19
|
+
|
|
20
|
+
from agentpool import AgentPool
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
logger = get_logger(__name__)
|
|
24
|
+
|
|
25
|
+
DEFAULT_HTTP_PORT = 8000
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class HTTPServer(BaseServer):
|
|
29
|
+
"""Base class for HTTP-based servers.
|
|
30
|
+
|
|
31
|
+
Provides common infrastructure for servers that expose HTTP routes via Starlette.
|
|
32
|
+
|
|
33
|
+
Subclasses must implement:
|
|
34
|
+
- `get_routes()`: Return list of Starlette Route objects
|
|
35
|
+
|
|
36
|
+
Example:
|
|
37
|
+
```python
|
|
38
|
+
class MyHTTPServer(HTTPServer):
|
|
39
|
+
async def get_routes(self) -> list[Route]:
|
|
40
|
+
return [
|
|
41
|
+
Route("/hello", self.hello_handler, methods=["GET"]),
|
|
42
|
+
Route("/world", self.world_handler, methods=["POST"]),
|
|
43
|
+
]
|
|
44
|
+
```
|
|
45
|
+
"""
|
|
46
|
+
|
|
47
|
+
def __init__(
|
|
48
|
+
self,
|
|
49
|
+
pool: AgentPool,
|
|
50
|
+
*,
|
|
51
|
+
name: str | None = None,
|
|
52
|
+
host: str = "localhost",
|
|
53
|
+
port: int = DEFAULT_HTTP_PORT,
|
|
54
|
+
raise_exceptions: bool = False,
|
|
55
|
+
) -> None:
|
|
56
|
+
"""Initialize HTTP server.
|
|
57
|
+
|
|
58
|
+
Args:
|
|
59
|
+
pool: AgentPool containing available agents
|
|
60
|
+
name: Optional server name (auto-generated if None)
|
|
61
|
+
host: Host to bind server to
|
|
62
|
+
port: Port to bind server to
|
|
63
|
+
raise_exceptions: Whether to raise exceptions during server start
|
|
64
|
+
"""
|
|
65
|
+
super().__init__(pool, name=name, raise_exceptions=raise_exceptions)
|
|
66
|
+
self.host = host
|
|
67
|
+
self.port = port
|
|
68
|
+
|
|
69
|
+
@abstractmethod
|
|
70
|
+
async def get_routes(self) -> list[Route]:
|
|
71
|
+
"""Get Starlette routes for this server.
|
|
72
|
+
|
|
73
|
+
Subclasses must implement this method to provide their HTTP routes.
|
|
74
|
+
|
|
75
|
+
Returns:
|
|
76
|
+
List of Starlette Route objects
|
|
77
|
+
"""
|
|
78
|
+
...
|
|
79
|
+
|
|
80
|
+
async def create_app(self) -> Starlette:
|
|
81
|
+
"""Create Starlette application with this server's routes.
|
|
82
|
+
|
|
83
|
+
Returns:
|
|
84
|
+
Starlette application instance
|
|
85
|
+
"""
|
|
86
|
+
from starlette.applications import Starlette
|
|
87
|
+
|
|
88
|
+
routes = await self.get_routes()
|
|
89
|
+
app = Starlette(debug=False, routes=routes)
|
|
90
|
+
self.log.info(
|
|
91
|
+
"Created HTTP app",
|
|
92
|
+
route_count=len(routes),
|
|
93
|
+
host=self.host,
|
|
94
|
+
port=self.port,
|
|
95
|
+
)
|
|
96
|
+
return app
|
|
97
|
+
|
|
98
|
+
async def _start_async(self) -> None:
|
|
99
|
+
"""Start the HTTP server (blocking async - runs until stopped)."""
|
|
100
|
+
try:
|
|
101
|
+
import uvicorn
|
|
102
|
+
except ImportError as e:
|
|
103
|
+
msg = "Please install 'uvicorn' to use HTTPServer. You can use: uv add uvicorn"
|
|
104
|
+
raise ImportError(msg) from e
|
|
105
|
+
|
|
106
|
+
self.log.info(
|
|
107
|
+
"Starting HTTP server",
|
|
108
|
+
host=self.host,
|
|
109
|
+
port=self.port,
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
app = await self.create_app()
|
|
113
|
+
|
|
114
|
+
config = uvicorn.Config(
|
|
115
|
+
app=app,
|
|
116
|
+
host=self.host,
|
|
117
|
+
port=self.port,
|
|
118
|
+
log_level="info",
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
server = uvicorn.Server(config)
|
|
122
|
+
|
|
123
|
+
try:
|
|
124
|
+
await server.serve()
|
|
125
|
+
except Exception:
|
|
126
|
+
self.log.exception("HTTP server error")
|
|
127
|
+
raise
|
|
128
|
+
finally:
|
|
129
|
+
self.log.info("HTTP server stopped")
|
|
130
|
+
|
|
131
|
+
@classmethod
|
|
132
|
+
def from_config(
|
|
133
|
+
cls,
|
|
134
|
+
config_path: JoinablePathLike,
|
|
135
|
+
*,
|
|
136
|
+
host: str = "localhost",
|
|
137
|
+
port: int = DEFAULT_HTTP_PORT,
|
|
138
|
+
raise_exceptions: bool = False,
|
|
139
|
+
) -> Self:
|
|
140
|
+
"""Create HTTP server from configuration file.
|
|
141
|
+
|
|
142
|
+
Args:
|
|
143
|
+
config_path: Path to agentpool YAML config file
|
|
144
|
+
host: Host to bind server to
|
|
145
|
+
port: Port to bind server to
|
|
146
|
+
raise_exceptions: Whether to raise exceptions during server start
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
Configured server instance with agent pool from config
|
|
150
|
+
"""
|
|
151
|
+
from agentpool import AgentPool
|
|
152
|
+
from agentpool.models.manifest import AgentsManifest
|
|
153
|
+
|
|
154
|
+
manifest = AgentsManifest.from_file(config_path)
|
|
155
|
+
pool = AgentPool(manifest=manifest)
|
|
156
|
+
server = cls(pool, host=host, port=port, raise_exceptions=raise_exceptions)
|
|
157
|
+
agent_names = list(server.pool.agents.keys())
|
|
158
|
+
server.log.info("Created HTTP server from config", agent_names=agent_names)
|
|
159
|
+
return server
|
|
160
|
+
|
|
161
|
+
@property
|
|
162
|
+
def base_url(self) -> str:
|
|
163
|
+
"""Get the base URL for the server."""
|
|
164
|
+
return f"http://{self.host}:{self.port}"
|
|
@@ -0,0 +1,314 @@
|
|
|
1
|
+
"""MCP protocol server implementation using FastMCP decorators."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from collections import defaultdict
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
from fastmcp import FastMCP
|
|
9
|
+
from fastmcp.server.middleware.caching import ResponseCachingMiddleware
|
|
10
|
+
from key_value.aio.stores.disk import DiskStore
|
|
11
|
+
import mcp
|
|
12
|
+
from mcp import types
|
|
13
|
+
import platformdirs
|
|
14
|
+
|
|
15
|
+
import agentpool
|
|
16
|
+
from agentpool.log import get_logger
|
|
17
|
+
from agentpool.mcp_server import constants
|
|
18
|
+
from agentpool_server import BaseServer
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
if TYPE_CHECKING:
|
|
22
|
+
from collections.abc import Awaitable, Callable
|
|
23
|
+
from contextlib import AbstractAsyncContextManager
|
|
24
|
+
|
|
25
|
+
from mcp.server.lowlevel.server import LifespanResultT
|
|
26
|
+
from pydantic import AnyUrl
|
|
27
|
+
|
|
28
|
+
from agentpool import AgentPool
|
|
29
|
+
from agentpool.prompts.prompts import BasePrompt
|
|
30
|
+
from agentpool.tools import Tool
|
|
31
|
+
from agentpool_config.pool_server import MCPPoolServerConfig
|
|
32
|
+
|
|
33
|
+
LifespanHandler = Callable[
|
|
34
|
+
[FastMCP[LifespanResultT]],
|
|
35
|
+
AbstractAsyncContextManager[LifespanResultT],
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
logger = get_logger(__name__)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
agentpool_dir = platformdirs.user_config_dir("agentpool")
|
|
42
|
+
|
|
43
|
+
store = DiskStore(directory=agentpool_dir)
|
|
44
|
+
middleware = ResponseCachingMiddleware(cache_storage=store)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
class MCPServer(BaseServer):
|
|
48
|
+
"""MCP protocol server implementation using FastMCP decorators.
|
|
49
|
+
|
|
50
|
+
This server uses FastMCP's native @tool and @prompt decorators for
|
|
51
|
+
cleaner, more maintainable code. Tools and prompts from the pool are
|
|
52
|
+
registered dynamically using the same decorator pattern.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
def __init__(
|
|
56
|
+
self,
|
|
57
|
+
pool: AgentPool[Any],
|
|
58
|
+
config: MCPPoolServerConfig,
|
|
59
|
+
lifespan: LifespanHandler | None = None,
|
|
60
|
+
instructions: str | None = None,
|
|
61
|
+
name: str = "agentpool-server",
|
|
62
|
+
raise_exceptions: bool = False,
|
|
63
|
+
) -> None:
|
|
64
|
+
"""Initialize server with agent pool.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
pool: AgentPool to expose through MCP
|
|
68
|
+
config: Server configuration
|
|
69
|
+
name: Server name for MCP protocol
|
|
70
|
+
lifespan: Lifespan context manager
|
|
71
|
+
instructions: Instructions for server usage
|
|
72
|
+
raise_exceptions: Whether to raise exceptions during server start
|
|
73
|
+
"""
|
|
74
|
+
from agentpool.resource_providers.pool import PoolResourceProvider
|
|
75
|
+
|
|
76
|
+
super().__init__(pool, name=name, raise_exceptions=raise_exceptions)
|
|
77
|
+
self.provider = PoolResourceProvider(pool, zed_mode=config.zed_mode)
|
|
78
|
+
self.config = config
|
|
79
|
+
|
|
80
|
+
self._subscriptions: defaultdict[str, set[mcp.ServerSession]] = defaultdict(set)
|
|
81
|
+
self._tools_registered = False
|
|
82
|
+
self._prompts_registered = False
|
|
83
|
+
|
|
84
|
+
# Create FastMCP instance
|
|
85
|
+
self.fastmcp = FastMCP(
|
|
86
|
+
instructions=instructions,
|
|
87
|
+
lifespan=lifespan,
|
|
88
|
+
version=agentpool.__version__,
|
|
89
|
+
middleware=[middleware],
|
|
90
|
+
)
|
|
91
|
+
self.server = self.fastmcp._mcp_server
|
|
92
|
+
|
|
93
|
+
# Register static handlers
|
|
94
|
+
self._register_logging_handlers()
|
|
95
|
+
self._register_resource_handlers()
|
|
96
|
+
|
|
97
|
+
async def _register_pool_tools(self) -> None:
|
|
98
|
+
"""Register all pool tools using FastMCP's @tool decorator."""
|
|
99
|
+
if self._tools_registered:
|
|
100
|
+
return
|
|
101
|
+
|
|
102
|
+
tools = await self.provider.get_tools()
|
|
103
|
+
|
|
104
|
+
for tool in tools:
|
|
105
|
+
# Create handler with closure to capture tool instance
|
|
106
|
+
def make_handler(tool_instance: Tool) -> Callable[..., Awaitable[str]]:
|
|
107
|
+
async def handler(**kwargs: Any) -> str:
|
|
108
|
+
"""Dynamically generated tool handler."""
|
|
109
|
+
# Filter out _meta arguments
|
|
110
|
+
args = {k: v for k, v in kwargs.items() if not k.startswith("_")}
|
|
111
|
+
try:
|
|
112
|
+
result = await tool_instance.execute(**args)
|
|
113
|
+
return str(result)
|
|
114
|
+
except Exception as exc:
|
|
115
|
+
logger.exception("Tool execution failed", name=tool_instance.name)
|
|
116
|
+
return f"Tool execution failed: {exc}"
|
|
117
|
+
|
|
118
|
+
# Set proper function metadata for FastMCP
|
|
119
|
+
handler.__name__ = tool_instance.name
|
|
120
|
+
handler.__doc__ = tool_instance.description or f"Execute {tool_instance.name}"
|
|
121
|
+
return handler
|
|
122
|
+
|
|
123
|
+
# Register using FastMCP's tool decorator
|
|
124
|
+
tool_handler = make_handler(tool)
|
|
125
|
+
tool_annotations = types.ToolAnnotations(
|
|
126
|
+
title=tool.name,
|
|
127
|
+
readOnlyHint=tool.hints.read_only,
|
|
128
|
+
destructiveHint=tool.hints.destructive,
|
|
129
|
+
idempotentHint=tool.hints.idempotent,
|
|
130
|
+
openWorldHint=tool.hints.open_world,
|
|
131
|
+
)
|
|
132
|
+
self.fastmcp.tool(annotations=tool_annotations, task=True)(tool_handler)
|
|
133
|
+
|
|
134
|
+
self._tools_registered = True
|
|
135
|
+
logger.info("Registered MCP tools", count=len(tools))
|
|
136
|
+
|
|
137
|
+
async def _register_pool_prompts(self) -> None:
|
|
138
|
+
"""Register all pool prompts using FastMCP's @prompt decorator."""
|
|
139
|
+
if self._prompts_registered:
|
|
140
|
+
return
|
|
141
|
+
|
|
142
|
+
prompts = await self.provider.get_prompts()
|
|
143
|
+
|
|
144
|
+
for prompt in prompts:
|
|
145
|
+
# Create handler with closure to capture prompt instance
|
|
146
|
+
def make_handler(prompt_instance: BasePrompt) -> Callable[..., Awaitable[str]]:
|
|
147
|
+
async def handler(**kwargs: Any) -> str:
|
|
148
|
+
"""Dynamically generated prompt handler."""
|
|
149
|
+
from agentpool.mcp_server import conversions
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
assert prompt_instance.name
|
|
153
|
+
parts = await self.provider.get_request_parts(
|
|
154
|
+
prompt_instance.name, kwargs or {}
|
|
155
|
+
)
|
|
156
|
+
messages = [msg for p in parts for msg in conversions.to_mcp_messages(p)]
|
|
157
|
+
|
|
158
|
+
# Format messages as text
|
|
159
|
+
result_lines = []
|
|
160
|
+
for msg in messages:
|
|
161
|
+
if isinstance(msg.content, types.TextContent):
|
|
162
|
+
result_lines.append(f"{msg.role}: {msg.content.text}")
|
|
163
|
+
else:
|
|
164
|
+
result_lines.append(f"{msg.role}: {msg.content}")
|
|
165
|
+
|
|
166
|
+
return "\n".join(result_lines)
|
|
167
|
+
except Exception as exc:
|
|
168
|
+
logger.exception("Prompt execution failed", name=prompt_instance.name)
|
|
169
|
+
return f"Prompt execution failed: {exc}"
|
|
170
|
+
|
|
171
|
+
# Set proper function metadata for FastMCP
|
|
172
|
+
assert prompt_instance.name
|
|
173
|
+
handler.__name__ = prompt_instance.name
|
|
174
|
+
handler.__doc__ = (
|
|
175
|
+
prompt_instance.description or f"Get prompt {prompt_instance.name}"
|
|
176
|
+
)
|
|
177
|
+
return handler
|
|
178
|
+
|
|
179
|
+
# Register using FastMCP's prompt decorator
|
|
180
|
+
prompt_handler = make_handler(prompt)
|
|
181
|
+
self.fastmcp.prompt()(prompt_handler)
|
|
182
|
+
|
|
183
|
+
self._prompts_registered = True
|
|
184
|
+
logger.info("Registered MCP prompts", count=len(prompts))
|
|
185
|
+
|
|
186
|
+
def _register_resource_handlers(self) -> None:
|
|
187
|
+
"""Register resource subscription handlers."""
|
|
188
|
+
|
|
189
|
+
@self.server.subscribe_resource() # type: ignore[no-untyped-call, untyped-decorator]
|
|
190
|
+
async def handle_subscribe(uri: AnyUrl) -> None:
|
|
191
|
+
"""Subscribe to resource updates."""
|
|
192
|
+
uri_str = str(uri)
|
|
193
|
+
self._subscriptions[uri_str].add(self.current_session)
|
|
194
|
+
logger.debug("Added subscription", uri=uri)
|
|
195
|
+
|
|
196
|
+
@self.server.unsubscribe_resource() # type: ignore[no-untyped-call, untyped-decorator]
|
|
197
|
+
async def handle_unsubscribe(uri: AnyUrl) -> None:
|
|
198
|
+
"""Unsubscribe from resource updates."""
|
|
199
|
+
if (uri_str := str(uri)) in self._subscriptions:
|
|
200
|
+
self._subscriptions[uri_str].discard(self.current_session)
|
|
201
|
+
if not self._subscriptions[uri_str]:
|
|
202
|
+
del self._subscriptions[uri_str]
|
|
203
|
+
logger.debug("Removed subscription", uri=uri)
|
|
204
|
+
|
|
205
|
+
def _register_logging_handlers(self) -> None:
|
|
206
|
+
"""Register logging-related handlers."""
|
|
207
|
+
|
|
208
|
+
@self.server.set_logging_level() # type: ignore[no-untyped-call, untyped-decorator]
|
|
209
|
+
async def handle_set_level(level: mcp.LoggingLevel) -> None:
|
|
210
|
+
"""Handle logging level changes."""
|
|
211
|
+
try:
|
|
212
|
+
python_level = constants.MCP_TO_LOGGING[level]
|
|
213
|
+
logger.setLevel(python_level)
|
|
214
|
+
data = f"Log level set to {level}"
|
|
215
|
+
await self.current_session.send_log_message(level, data, logger=self.name)
|
|
216
|
+
except Exception as exc:
|
|
217
|
+
error_data = mcp.ErrorData(
|
|
218
|
+
message="Error setting log level",
|
|
219
|
+
code=types.INTERNAL_ERROR,
|
|
220
|
+
data=str(exc),
|
|
221
|
+
)
|
|
222
|
+
raise mcp.McpError(error_data) from exc
|
|
223
|
+
|
|
224
|
+
@self.server.progress_notification() # type: ignore[no-untyped-call, untyped-decorator]
|
|
225
|
+
async def handle_progress(
|
|
226
|
+
token: str | int,
|
|
227
|
+
progress: float,
|
|
228
|
+
total: float | None,
|
|
229
|
+
message: str | None = None,
|
|
230
|
+
) -> None:
|
|
231
|
+
"""Handle progress notifications from client."""
|
|
232
|
+
logger.debug(
|
|
233
|
+
"Progress notification",
|
|
234
|
+
token=token,
|
|
235
|
+
progress=progress,
|
|
236
|
+
total=total,
|
|
237
|
+
message=message,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
async def _start_async(self) -> None:
|
|
241
|
+
"""Start the server (blocking async - runs until stopped)."""
|
|
242
|
+
# Register pool tools and prompts before starting
|
|
243
|
+
await self._register_pool_tools()
|
|
244
|
+
await self._register_pool_prompts()
|
|
245
|
+
|
|
246
|
+
# Start FastMCP server
|
|
247
|
+
if self.config.transport == "stdio":
|
|
248
|
+
await self.fastmcp.run_async(transport=self.config.transport)
|
|
249
|
+
else:
|
|
250
|
+
await self.fastmcp.run_async(
|
|
251
|
+
transport=self.config.transport,
|
|
252
|
+
host=self.config.host,
|
|
253
|
+
port=self.config.port,
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
@property
|
|
257
|
+
def current_session(self) -> mcp.ServerSession:
|
|
258
|
+
"""Get current session from request context."""
|
|
259
|
+
try:
|
|
260
|
+
return self.server.request_context.session
|
|
261
|
+
except LookupError as exc:
|
|
262
|
+
msg = "No active request context"
|
|
263
|
+
raise RuntimeError(msg) from exc
|
|
264
|
+
|
|
265
|
+
async def report_progress(
|
|
266
|
+
self,
|
|
267
|
+
progress: float,
|
|
268
|
+
total: float | None = None,
|
|
269
|
+
message: str | None = None,
|
|
270
|
+
related_request_id: str | None = None,
|
|
271
|
+
) -> None:
|
|
272
|
+
"""Report progress for the current operation."""
|
|
273
|
+
progress_token = (
|
|
274
|
+
self.server.request_context.meta.progressToken
|
|
275
|
+
if self.server.request_context.meta
|
|
276
|
+
else None
|
|
277
|
+
)
|
|
278
|
+
|
|
279
|
+
if progress_token is None:
|
|
280
|
+
return
|
|
281
|
+
|
|
282
|
+
await self.server.request_context.session.send_progress_notification(
|
|
283
|
+
progress_token=progress_token,
|
|
284
|
+
progress=progress,
|
|
285
|
+
total=total,
|
|
286
|
+
message=message,
|
|
287
|
+
related_request_id=related_request_id,
|
|
288
|
+
)
|
|
289
|
+
|
|
290
|
+
@property
|
|
291
|
+
def client_info(self) -> mcp.Implementation | None:
|
|
292
|
+
"""Get client info from current session."""
|
|
293
|
+
session = self.current_session
|
|
294
|
+
if not session.client_params:
|
|
295
|
+
return None
|
|
296
|
+
return session.client_params.clientInfo
|
|
297
|
+
|
|
298
|
+
async def notify_tool_list_changed(self) -> None:
|
|
299
|
+
"""Notify clients about tool list changes."""
|
|
300
|
+
try:
|
|
301
|
+
self.task_manager.create_task(self.current_session.send_tool_list_changed())
|
|
302
|
+
except RuntimeError:
|
|
303
|
+
self.log.debug("No active session for notification")
|
|
304
|
+
except Exception:
|
|
305
|
+
self.log.exception("Failed to send tool list change notification")
|
|
306
|
+
|
|
307
|
+
async def notify_prompt_list_changed(self) -> None:
|
|
308
|
+
"""Notify clients about prompt list changes."""
|
|
309
|
+
try:
|
|
310
|
+
self.task_manager.create_task(self.current_session.send_prompt_list_changed())
|
|
311
|
+
except RuntimeError:
|
|
312
|
+
self.log.debug("No active session for notification")
|
|
313
|
+
except Exception:
|
|
314
|
+
self.log.exception("Failed to send prompt list change notification")
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"""Function parameter encoding utils for Zed compatibility."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from functools import wraps
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
from agentpool.log import get_logger
|
|
9
|
+
from agentpool.prompts.prompts import DynamicPrompt
|
|
10
|
+
from agentpool.utils.importing import import_callable
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from collections.abc import Sequence
|
|
15
|
+
|
|
16
|
+
from agentpool.prompts.prompts import BasePrompt
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
logger = get_logger(__name__)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def decode_zed_args(input_str: str) -> dict[str, Any]:
|
|
23
|
+
"""Decode Zed-style input string into kwargs dict."""
|
|
24
|
+
if " :: " not in input_str:
|
|
25
|
+
# Single argument case - use as first argument
|
|
26
|
+
return {"main_arg": input_str}
|
|
27
|
+
|
|
28
|
+
# Multiple arguments case
|
|
29
|
+
parts = input_str.split(" :: ", 1)
|
|
30
|
+
result: dict[str, Any] = {"main_arg": parts[0]}
|
|
31
|
+
|
|
32
|
+
if len(parts) > 1:
|
|
33
|
+
for pair in parts[1].split(" | "):
|
|
34
|
+
if not pair:
|
|
35
|
+
continue
|
|
36
|
+
key, value = pair.split("=", 1)
|
|
37
|
+
# Convert value types
|
|
38
|
+
match value.lower():
|
|
39
|
+
case "true":
|
|
40
|
+
result[key] = True
|
|
41
|
+
case "false":
|
|
42
|
+
result[key] = False
|
|
43
|
+
case "null":
|
|
44
|
+
result[key] = None
|
|
45
|
+
case _:
|
|
46
|
+
try:
|
|
47
|
+
if "." in value:
|
|
48
|
+
result[key] = float(value)
|
|
49
|
+
else:
|
|
50
|
+
result[key] = int(value)
|
|
51
|
+
except ValueError:
|
|
52
|
+
result[key] = value
|
|
53
|
+
|
|
54
|
+
return result
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def create_zed_wrapper(func: Any) -> Any:
|
|
58
|
+
"""Create a wrapper that accepts Zed-style input."""
|
|
59
|
+
|
|
60
|
+
@wraps(func)
|
|
61
|
+
def wrapper(input: str, **_kwargs: Any) -> Any: # noqa: A002
|
|
62
|
+
kwargs = decode_zed_args(input)
|
|
63
|
+
return func(**kwargs)
|
|
64
|
+
|
|
65
|
+
# Copy over metadata
|
|
66
|
+
wrapper.__module__ = func.__module__
|
|
67
|
+
wrapper.__qualname__ = f"zed_wrapped_{func.__qualname__}"
|
|
68
|
+
return wrapper
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def prepare_prompts_for_zed(prompts: Sequence[BasePrompt]) -> list[BasePrompt]:
|
|
72
|
+
"""Prepare prompts for Zed compatibility."""
|
|
73
|
+
result: list[BasePrompt] = []
|
|
74
|
+
|
|
75
|
+
for prompt in prompts:
|
|
76
|
+
# Only process DynamicPrompts
|
|
77
|
+
if not isinstance(prompt, DynamicPrompt):
|
|
78
|
+
result.append(prompt)
|
|
79
|
+
continue
|
|
80
|
+
|
|
81
|
+
# Skip if only one or zero parameters
|
|
82
|
+
# if len(prompt.arguments) <= 1:
|
|
83
|
+
# result.append(prompt)
|
|
84
|
+
# continue
|
|
85
|
+
|
|
86
|
+
try:
|
|
87
|
+
# Get and wrap the original function
|
|
88
|
+
original_func = (
|
|
89
|
+
import_callable(prompt.import_path)
|
|
90
|
+
if isinstance(prompt.import_path, str)
|
|
91
|
+
else prompt.import_path
|
|
92
|
+
)
|
|
93
|
+
wrapped_func = create_zed_wrapper(original_func)
|
|
94
|
+
|
|
95
|
+
# Create new prompt with single input parameter
|
|
96
|
+
new_prompt = DynamicPrompt(
|
|
97
|
+
name=prompt.name,
|
|
98
|
+
description=prompt.description,
|
|
99
|
+
import_path=f"{wrapped_func.__module__}.{wrapped_func.__qualname__}",
|
|
100
|
+
template=prompt.template,
|
|
101
|
+
completions=prompt.completions,
|
|
102
|
+
)
|
|
103
|
+
result.append(new_prompt)
|
|
104
|
+
logger.debug("Wrapped prompt for Zed mode", name=prompt.name)
|
|
105
|
+
|
|
106
|
+
except Exception:
|
|
107
|
+
logger.exception("Failed to wrap function for prompt", name=prompt.name)
|
|
108
|
+
result.append(prompt)
|
|
109
|
+
|
|
110
|
+
return result
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Completions API."""
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"""Helpers for OpenAI-compatible API server."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import time
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
7
|
+
|
|
8
|
+
import anyenv
|
|
9
|
+
from pydantic_ai import PartDeltaEvent, TextPartDelta
|
|
10
|
+
|
|
11
|
+
from agentpool.log import get_logger
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if TYPE_CHECKING:
|
|
15
|
+
from collections.abc import AsyncGenerator
|
|
16
|
+
|
|
17
|
+
from agentpool.common_types import SupportsRunStream
|
|
18
|
+
from agentpool_server.openai_api_server.completions.models import ChatCompletionRequest
|
|
19
|
+
|
|
20
|
+
logger = get_logger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
async def stream_response(
|
|
24
|
+
agent: SupportsRunStream[Any],
|
|
25
|
+
content: str,
|
|
26
|
+
request: ChatCompletionRequest,
|
|
27
|
+
) -> AsyncGenerator[str]:
|
|
28
|
+
"""Generate streaming response chunks."""
|
|
29
|
+
response_id = f"chatcmpl-{int(time.time() * 1000)}"
|
|
30
|
+
created = int(time.time())
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
# First chunk with role
|
|
34
|
+
choice = {"index": 0, "delta": {"role": "assistant"}, "finish_reason": None}
|
|
35
|
+
first_chunk = {
|
|
36
|
+
"id": response_id,
|
|
37
|
+
"object": "chat.completion.chunk",
|
|
38
|
+
"created": created,
|
|
39
|
+
"model": request.model,
|
|
40
|
+
"choices": [choice],
|
|
41
|
+
}
|
|
42
|
+
yield f"data: {anyenv.dump_json(first_chunk)}\n\n"
|
|
43
|
+
async for event in agent.run_stream(content):
|
|
44
|
+
match event:
|
|
45
|
+
case PartDeltaEvent(delta=TextPartDelta(content_delta=chunk)):
|
|
46
|
+
# Skip empty chunks
|
|
47
|
+
if not chunk:
|
|
48
|
+
continue
|
|
49
|
+
delta = {"content": chunk}
|
|
50
|
+
choice = {"index": 0, "delta": delta, "finish_reason": None}
|
|
51
|
+
chunk_data = {
|
|
52
|
+
"id": response_id,
|
|
53
|
+
"object": "chat.completion.chunk",
|
|
54
|
+
"created": created,
|
|
55
|
+
"model": request.model,
|
|
56
|
+
"choices": [choice],
|
|
57
|
+
}
|
|
58
|
+
yield f"data: {anyenv.dump_json(chunk_data)}\n\n"
|
|
59
|
+
final_chunk = {
|
|
60
|
+
"id": response_id,
|
|
61
|
+
"object": "chat.completion.chunk",
|
|
62
|
+
"created": created,
|
|
63
|
+
"model": request.model,
|
|
64
|
+
"choices": [{"index": 0, "delta": {}, "finish_reason": "stop"}],
|
|
65
|
+
}
|
|
66
|
+
yield f"data: {anyenv.dump_json(final_chunk)}\n\n"
|
|
67
|
+
yield "data: [DONE]\n\n"
|
|
68
|
+
|
|
69
|
+
except Exception as e:
|
|
70
|
+
logger.exception("Error during streaming response")
|
|
71
|
+
delta = {"content": f"Error: {e!s}"}
|
|
72
|
+
choice = {"index": 0, "delta": delta, "finish_reason": "error"}
|
|
73
|
+
error_chunk = {
|
|
74
|
+
"id": response_id,
|
|
75
|
+
"object": "chat.completion.chunk",
|
|
76
|
+
"created": created,
|
|
77
|
+
"model": request.model,
|
|
78
|
+
"choices": [choice],
|
|
79
|
+
}
|
|
80
|
+
yield f"data: {anyenv.dump_json(error_chunk)}\n\n"
|
|
81
|
+
yield "data: [DONE]\n\n"
|