agentpool 2.1.9__py3-none-any.whl → 2.5.0__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.
- acp/__init__.py +13 -4
- acp/acp_requests.py +20 -77
- acp/agent/connection.py +8 -0
- acp/agent/implementations/debug_server/debug_server.py +6 -2
- acp/agent/protocol.py +6 -0
- acp/bridge/README.md +15 -2
- acp/bridge/__init__.py +3 -2
- acp/bridge/__main__.py +60 -19
- acp/bridge/ws_server.py +173 -0
- acp/bridge/ws_server_cli.py +89 -0
- acp/client/connection.py +38 -29
- acp/client/implementations/default_client.py +3 -2
- acp/client/implementations/headless_client.py +2 -2
- acp/connection.py +2 -2
- acp/notifications.py +20 -50
- acp/schema/__init__.py +2 -0
- acp/schema/agent_responses.py +21 -0
- acp/schema/client_requests.py +3 -3
- acp/schema/session_state.py +63 -29
- acp/stdio.py +39 -9
- acp/task/supervisor.py +2 -2
- acp/transports.py +362 -2
- acp/utils.py +17 -4
- agentpool/__init__.py +6 -1
- agentpool/agents/__init__.py +2 -0
- agentpool/agents/acp_agent/acp_agent.py +407 -277
- agentpool/agents/acp_agent/acp_converters.py +196 -38
- agentpool/agents/acp_agent/client_handler.py +191 -26
- agentpool/agents/acp_agent/session_state.py +17 -6
- agentpool/agents/agent.py +607 -572
- agentpool/agents/agui_agent/__init__.py +0 -2
- agentpool/agents/agui_agent/agui_agent.py +176 -110
- agentpool/agents/agui_agent/agui_converters.py +0 -131
- agentpool/agents/agui_agent/helpers.py +3 -4
- agentpool/agents/base_agent.py +632 -17
- agentpool/agents/claude_code_agent/FORKING.md +191 -0
- agentpool/agents/claude_code_agent/__init__.py +13 -1
- agentpool/agents/claude_code_agent/claude_code_agent.py +1058 -291
- agentpool/agents/claude_code_agent/converters.py +74 -143
- agentpool/agents/claude_code_agent/history.py +474 -0
- agentpool/agents/claude_code_agent/models.py +77 -0
- agentpool/agents/claude_code_agent/static_info.py +100 -0
- agentpool/agents/claude_code_agent/usage.py +242 -0
- agentpool/agents/context.py +40 -0
- agentpool/agents/events/__init__.py +24 -0
- agentpool/agents/events/builtin_handlers.py +67 -1
- agentpool/agents/events/event_emitter.py +32 -2
- agentpool/agents/events/events.py +104 -3
- agentpool/agents/events/infer_info.py +145 -0
- agentpool/agents/events/processors.py +254 -0
- agentpool/agents/interactions.py +41 -6
- agentpool/agents/modes.py +67 -0
- agentpool/agents/slashed_agent.py +5 -4
- agentpool/agents/tool_call_accumulator.py +213 -0
- agentpool/agents/tool_wrapping.py +18 -6
- agentpool/common_types.py +56 -21
- agentpool/config_resources/__init__.py +38 -1
- agentpool/config_resources/acp_assistant.yml +2 -2
- agentpool/config_resources/agents.yml +3 -0
- agentpool/config_resources/agents_template.yml +1 -0
- agentpool/config_resources/claude_code_agent.yml +10 -6
- agentpool/config_resources/external_acp_agents.yml +2 -1
- agentpool/delegation/base_team.py +4 -30
- agentpool/delegation/pool.py +136 -289
- agentpool/delegation/team.py +58 -57
- agentpool/delegation/teamrun.py +51 -55
- agentpool/diagnostics/__init__.py +53 -0
- agentpool/diagnostics/lsp_manager.py +1593 -0
- agentpool/diagnostics/lsp_proxy.py +41 -0
- agentpool/diagnostics/lsp_proxy_script.py +229 -0
- agentpool/diagnostics/models.py +398 -0
- agentpool/functional/run.py +10 -4
- agentpool/mcp_server/__init__.py +0 -2
- agentpool/mcp_server/client.py +76 -32
- agentpool/mcp_server/conversions.py +54 -13
- agentpool/mcp_server/manager.py +34 -54
- agentpool/mcp_server/registries/official_registry_client.py +35 -1
- agentpool/mcp_server/tool_bridge.py +186 -139
- agentpool/messaging/__init__.py +0 -2
- agentpool/messaging/compaction.py +72 -197
- agentpool/messaging/connection_manager.py +11 -10
- agentpool/messaging/event_manager.py +5 -5
- agentpool/messaging/message_container.py +6 -30
- agentpool/messaging/message_history.py +99 -8
- agentpool/messaging/messagenode.py +52 -14
- agentpool/messaging/messages.py +54 -35
- agentpool/messaging/processing.py +12 -22
- agentpool/models/__init__.py +1 -1
- agentpool/models/acp_agents/base.py +6 -24
- agentpool/models/acp_agents/mcp_capable.py +126 -157
- agentpool/models/acp_agents/non_mcp.py +129 -95
- agentpool/models/agents.py +98 -76
- agentpool/models/agui_agents.py +1 -1
- agentpool/models/claude_code_agents.py +144 -19
- agentpool/models/file_parsing.py +0 -1
- agentpool/models/manifest.py +113 -50
- agentpool/prompts/conversion_manager.py +1 -1
- agentpool/prompts/prompts.py +5 -2
- agentpool/repomap.py +1 -1
- agentpool/resource_providers/__init__.py +11 -1
- agentpool/resource_providers/aggregating.py +56 -5
- agentpool/resource_providers/base.py +70 -4
- agentpool/resource_providers/codemode/code_executor.py +72 -5
- agentpool/resource_providers/codemode/helpers.py +2 -2
- agentpool/resource_providers/codemode/provider.py +64 -12
- agentpool/resource_providers/codemode/remote_mcp_execution.py +2 -2
- agentpool/resource_providers/codemode/remote_provider.py +9 -12
- agentpool/resource_providers/filtering.py +3 -1
- agentpool/resource_providers/mcp_provider.py +89 -12
- agentpool/resource_providers/plan_provider.py +228 -46
- agentpool/resource_providers/pool.py +7 -3
- agentpool/resource_providers/resource_info.py +111 -0
- agentpool/resource_providers/static.py +4 -2
- agentpool/sessions/__init__.py +4 -1
- agentpool/sessions/manager.py +33 -5
- agentpool/sessions/models.py +59 -6
- agentpool/sessions/protocol.py +28 -0
- agentpool/sessions/session.py +11 -55
- agentpool/skills/registry.py +13 -8
- agentpool/storage/manager.py +572 -49
- agentpool/talk/registry.py +4 -4
- agentpool/talk/talk.py +9 -10
- agentpool/testing.py +538 -20
- agentpool/tool_impls/__init__.py +6 -0
- agentpool/tool_impls/agent_cli/__init__.py +42 -0
- agentpool/tool_impls/agent_cli/tool.py +95 -0
- agentpool/tool_impls/bash/__init__.py +64 -0
- agentpool/tool_impls/bash/helpers.py +35 -0
- agentpool/tool_impls/bash/tool.py +171 -0
- agentpool/tool_impls/delete_path/__init__.py +70 -0
- agentpool/tool_impls/delete_path/tool.py +142 -0
- agentpool/tool_impls/download_file/__init__.py +80 -0
- agentpool/tool_impls/download_file/tool.py +183 -0
- agentpool/tool_impls/execute_code/__init__.py +55 -0
- agentpool/tool_impls/execute_code/tool.py +163 -0
- agentpool/tool_impls/grep/__init__.py +80 -0
- agentpool/tool_impls/grep/tool.py +200 -0
- agentpool/tool_impls/list_directory/__init__.py +73 -0
- agentpool/tool_impls/list_directory/tool.py +197 -0
- agentpool/tool_impls/question/__init__.py +42 -0
- agentpool/tool_impls/question/tool.py +127 -0
- agentpool/tool_impls/read/__init__.py +104 -0
- agentpool/tool_impls/read/tool.py +305 -0
- agentpool/tools/__init__.py +2 -1
- agentpool/tools/base.py +114 -34
- agentpool/tools/manager.py +57 -1
- agentpool/ui/base.py +2 -2
- agentpool/ui/mock_provider.py +2 -2
- agentpool/ui/stdlib_provider.py +2 -2
- agentpool/utils/file_watcher.py +269 -0
- agentpool/utils/identifiers.py +121 -0
- agentpool/utils/pydantic_ai_helpers.py +46 -0
- agentpool/utils/streams.py +616 -2
- agentpool/utils/subprocess_utils.py +155 -0
- agentpool/utils/token_breakdown.py +461 -0
- agentpool/vfs_registry.py +7 -2
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/METADATA +41 -27
- agentpool-2.5.0.dist-info/RECORD +579 -0
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/WHEEL +1 -1
- agentpool_cli/__main__.py +24 -0
- agentpool_cli/create.py +1 -1
- agentpool_cli/serve_acp.py +100 -21
- agentpool_cli/serve_agui.py +87 -0
- agentpool_cli/serve_opencode.py +119 -0
- agentpool_cli/ui.py +557 -0
- agentpool_commands/__init__.py +42 -5
- agentpool_commands/agents.py +75 -2
- agentpool_commands/history.py +62 -0
- agentpool_commands/mcp.py +176 -0
- agentpool_commands/models.py +56 -3
- agentpool_commands/pool.py +260 -0
- agentpool_commands/session.py +1 -1
- agentpool_commands/text_sharing/__init__.py +119 -0
- agentpool_commands/text_sharing/base.py +123 -0
- agentpool_commands/text_sharing/github_gist.py +80 -0
- agentpool_commands/text_sharing/opencode.py +462 -0
- agentpool_commands/text_sharing/paste_rs.py +59 -0
- agentpool_commands/text_sharing/pastebin.py +116 -0
- agentpool_commands/text_sharing/shittycodingagent.py +112 -0
- agentpool_commands/tools.py +57 -0
- agentpool_commands/utils.py +80 -30
- agentpool_config/__init__.py +30 -2
- agentpool_config/agentpool_tools.py +498 -0
- agentpool_config/builtin_tools.py +77 -22
- agentpool_config/commands.py +24 -1
- agentpool_config/compaction.py +258 -0
- agentpool_config/converters.py +1 -1
- agentpool_config/event_handlers.py +42 -0
- agentpool_config/events.py +1 -1
- agentpool_config/forward_targets.py +1 -4
- agentpool_config/jinja.py +3 -3
- agentpool_config/mcp_server.py +132 -6
- agentpool_config/nodes.py +1 -1
- agentpool_config/observability.py +44 -0
- agentpool_config/session.py +0 -3
- agentpool_config/storage.py +82 -38
- agentpool_config/task.py +3 -3
- agentpool_config/tools.py +11 -22
- agentpool_config/toolsets.py +109 -233
- agentpool_server/a2a_server/agent_worker.py +307 -0
- agentpool_server/a2a_server/server.py +23 -18
- agentpool_server/acp_server/acp_agent.py +234 -181
- agentpool_server/acp_server/commands/acp_commands.py +151 -156
- agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +18 -17
- agentpool_server/acp_server/event_converter.py +651 -0
- agentpool_server/acp_server/input_provider.py +53 -10
- agentpool_server/acp_server/server.py +24 -90
- agentpool_server/acp_server/session.py +173 -331
- agentpool_server/acp_server/session_manager.py +8 -34
- agentpool_server/agui_server/server.py +3 -1
- agentpool_server/mcp_server/server.py +5 -2
- agentpool_server/opencode_server/.rules +95 -0
- agentpool_server/opencode_server/ENDPOINTS.md +401 -0
- agentpool_server/opencode_server/OPENCODE_UI_TOOLS_COMPLETE.md +202 -0
- agentpool_server/opencode_server/__init__.py +19 -0
- agentpool_server/opencode_server/command_validation.py +172 -0
- agentpool_server/opencode_server/converters.py +975 -0
- agentpool_server/opencode_server/dependencies.py +24 -0
- agentpool_server/opencode_server/input_provider.py +421 -0
- agentpool_server/opencode_server/models/__init__.py +250 -0
- agentpool_server/opencode_server/models/agent.py +53 -0
- agentpool_server/opencode_server/models/app.py +72 -0
- agentpool_server/opencode_server/models/base.py +26 -0
- agentpool_server/opencode_server/models/common.py +23 -0
- agentpool_server/opencode_server/models/config.py +37 -0
- agentpool_server/opencode_server/models/events.py +821 -0
- agentpool_server/opencode_server/models/file.py +88 -0
- agentpool_server/opencode_server/models/mcp.py +44 -0
- agentpool_server/opencode_server/models/message.py +179 -0
- agentpool_server/opencode_server/models/parts.py +323 -0
- agentpool_server/opencode_server/models/provider.py +81 -0
- agentpool_server/opencode_server/models/pty.py +43 -0
- agentpool_server/opencode_server/models/question.py +56 -0
- agentpool_server/opencode_server/models/session.py +111 -0
- agentpool_server/opencode_server/routes/__init__.py +29 -0
- agentpool_server/opencode_server/routes/agent_routes.py +473 -0
- agentpool_server/opencode_server/routes/app_routes.py +202 -0
- agentpool_server/opencode_server/routes/config_routes.py +302 -0
- agentpool_server/opencode_server/routes/file_routes.py +571 -0
- agentpool_server/opencode_server/routes/global_routes.py +94 -0
- agentpool_server/opencode_server/routes/lsp_routes.py +319 -0
- agentpool_server/opencode_server/routes/message_routes.py +761 -0
- agentpool_server/opencode_server/routes/permission_routes.py +63 -0
- agentpool_server/opencode_server/routes/pty_routes.py +300 -0
- agentpool_server/opencode_server/routes/question_routes.py +128 -0
- agentpool_server/opencode_server/routes/session_routes.py +1276 -0
- agentpool_server/opencode_server/routes/tui_routes.py +139 -0
- agentpool_server/opencode_server/server.py +475 -0
- agentpool_server/opencode_server/state.py +151 -0
- agentpool_server/opencode_server/time_utils.py +8 -0
- agentpool_storage/__init__.py +12 -0
- agentpool_storage/base.py +184 -2
- agentpool_storage/claude_provider/ARCHITECTURE.md +433 -0
- agentpool_storage/claude_provider/__init__.py +42 -0
- agentpool_storage/claude_provider/provider.py +1089 -0
- agentpool_storage/file_provider.py +278 -15
- agentpool_storage/memory_provider.py +193 -12
- agentpool_storage/models.py +3 -0
- agentpool_storage/opencode_provider/ARCHITECTURE.md +386 -0
- agentpool_storage/opencode_provider/__init__.py +16 -0
- agentpool_storage/opencode_provider/helpers.py +414 -0
- agentpool_storage/opencode_provider/provider.py +895 -0
- agentpool_storage/project_store.py +325 -0
- agentpool_storage/session_store.py +26 -6
- agentpool_storage/sql_provider/__init__.py +4 -2
- agentpool_storage/sql_provider/models.py +48 -0
- agentpool_storage/sql_provider/sql_provider.py +269 -3
- agentpool_storage/sql_provider/utils.py +12 -13
- agentpool_storage/zed_provider/__init__.py +16 -0
- agentpool_storage/zed_provider/helpers.py +281 -0
- agentpool_storage/zed_provider/models.py +130 -0
- agentpool_storage/zed_provider/provider.py +442 -0
- agentpool_storage/zed_provider.py +803 -0
- agentpool_toolsets/__init__.py +0 -2
- agentpool_toolsets/builtin/__init__.py +2 -12
- agentpool_toolsets/builtin/code.py +96 -57
- agentpool_toolsets/builtin/debug.py +118 -48
- agentpool_toolsets/builtin/execution_environment.py +115 -230
- agentpool_toolsets/builtin/file_edit/file_edit.py +115 -7
- agentpool_toolsets/builtin/skills.py +9 -4
- agentpool_toolsets/builtin/subagent_tools.py +64 -51
- agentpool_toolsets/builtin/workers.py +4 -2
- agentpool_toolsets/composio_toolset.py +2 -2
- agentpool_toolsets/entry_points.py +3 -1
- agentpool_toolsets/fsspec_toolset/__init__.py +13 -1
- agentpool_toolsets/fsspec_toolset/diagnostics.py +860 -73
- agentpool_toolsets/fsspec_toolset/grep.py +99 -7
- agentpool_toolsets/fsspec_toolset/helpers.py +3 -2
- agentpool_toolsets/fsspec_toolset/image_utils.py +161 -0
- agentpool_toolsets/fsspec_toolset/toolset.py +500 -95
- agentpool_toolsets/mcp_discovery/__init__.py +5 -0
- agentpool_toolsets/mcp_discovery/data/mcp_servers.parquet +0 -0
- agentpool_toolsets/mcp_discovery/toolset.py +511 -0
- agentpool_toolsets/mcp_run_toolset.py +87 -12
- agentpool_toolsets/notifications.py +33 -33
- agentpool_toolsets/openapi.py +3 -1
- agentpool_toolsets/search_toolset.py +3 -1
- agentpool-2.1.9.dist-info/RECORD +0 -474
- agentpool_config/resources.py +0 -33
- agentpool_server/acp_server/acp_tools.py +0 -43
- agentpool_server/acp_server/commands/spawn.py +0 -210
- agentpool_storage/text_log_provider.py +0 -275
- agentpool_toolsets/builtin/agent_management.py +0 -239
- agentpool_toolsets/builtin/chain.py +0 -288
- agentpool_toolsets/builtin/history.py +0 -36
- agentpool_toolsets/builtin/integration.py +0 -85
- agentpool_toolsets/builtin/tool_management.py +0 -90
- agentpool_toolsets/builtin/user_interaction.py +0 -52
- agentpool_toolsets/semantic_memory_toolset.py +0 -536
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/entry_points.txt +0 -0
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,18 +6,47 @@ from collections.abc import Sequence # noqa: TC003
|
|
|
6
6
|
from typing import TYPE_CHECKING, Literal
|
|
7
7
|
|
|
8
8
|
from pydantic import ConfigDict, Field
|
|
9
|
-
|
|
9
|
+
from tokonomics.model_names import AnthropicMaxModelName # noqa: TC002
|
|
10
|
+
|
|
11
|
+
from agentpool import log
|
|
12
|
+
from agentpool.resource_providers import StaticResourceProvider
|
|
13
|
+
from agentpool_config import (
|
|
14
|
+
AnyToolConfig, # noqa: TC001
|
|
15
|
+
BaseToolConfig,
|
|
16
|
+
)
|
|
10
17
|
from agentpool_config.nodes import BaseAgentConfig
|
|
11
18
|
from agentpool_config.output_types import StructuredResponseConfig # noqa: TC001
|
|
12
19
|
from agentpool_config.system_prompts import PromptConfig # noqa: TC001
|
|
13
|
-
from agentpool_config.toolsets import ToolsetConfig # noqa: TC001
|
|
14
20
|
|
|
15
21
|
|
|
16
22
|
if TYPE_CHECKING:
|
|
17
23
|
from agentpool.resource_providers import ResourceProvider
|
|
18
24
|
|
|
25
|
+
logger = log.get_logger(__name__)
|
|
19
26
|
|
|
20
27
|
PermissionMode = Literal["default", "acceptEdits", "plan", "bypassPermissions"]
|
|
28
|
+
SettingSource = Literal["user", "project", "local"]
|
|
29
|
+
ToolName = Literal[
|
|
30
|
+
"Task",
|
|
31
|
+
"TaskOutput",
|
|
32
|
+
"Bash",
|
|
33
|
+
"Glob",
|
|
34
|
+
"Grep",
|
|
35
|
+
"ExitPlanMode",
|
|
36
|
+
"Read",
|
|
37
|
+
"Edit",
|
|
38
|
+
"Write",
|
|
39
|
+
"NotebookEdit",
|
|
40
|
+
"WebFetch",
|
|
41
|
+
"TodoWrite",
|
|
42
|
+
"WebSearch",
|
|
43
|
+
"KillShell",
|
|
44
|
+
"AskUserQuestion",
|
|
45
|
+
"Skill",
|
|
46
|
+
"EnterPlanMode",
|
|
47
|
+
"LSP",
|
|
48
|
+
"Chrome",
|
|
49
|
+
]
|
|
21
50
|
|
|
22
51
|
|
|
23
52
|
class ClaudeCodeAgentConfig(BaseAgentConfig):
|
|
@@ -67,14 +96,14 @@ class ClaudeCodeAgentConfig(BaseAgentConfig):
|
|
|
67
96
|
)
|
|
68
97
|
"""Working directory for Claude Code operations."""
|
|
69
98
|
|
|
70
|
-
model: str | None = Field(
|
|
99
|
+
model: AnthropicMaxModelName | str | None = Field(
|
|
71
100
|
default=None,
|
|
72
101
|
title="Model",
|
|
73
102
|
examples=["claude-sonnet-4-5", "claude-opus-4", "claude-haiku-3-5"],
|
|
74
103
|
)
|
|
75
104
|
"""Model to use for this agent. Defaults to Claude's default model."""
|
|
76
105
|
|
|
77
|
-
allowed_tools: list[str] | None = Field(
|
|
106
|
+
allowed_tools: list[ToolName | str] | None = Field(
|
|
78
107
|
default=None,
|
|
79
108
|
title="Allowed Tools",
|
|
80
109
|
examples=[["Read", "Write", "Bash"], ["Read", "Grep", "Glob"]],
|
|
@@ -85,7 +114,7 @@ class ClaudeCodeAgentConfig(BaseAgentConfig):
|
|
|
85
114
|
Common tools: Read, Write, Edit, Bash, Glob, Grep, Task, WebFetch, etc.
|
|
86
115
|
"""
|
|
87
116
|
|
|
88
|
-
disallowed_tools: list[str] | None = Field(
|
|
117
|
+
disallowed_tools: list[ToolName | str] | None = Field(
|
|
89
118
|
default=None,
|
|
90
119
|
title="Disallowed Tools",
|
|
91
120
|
examples=[["Bash", "Write"], ["Task"]],
|
|
@@ -132,6 +161,17 @@ class ClaudeCodeAgentConfig(BaseAgentConfig):
|
|
|
132
161
|
)
|
|
133
162
|
"""Maximum number of conversation turns before stopping."""
|
|
134
163
|
|
|
164
|
+
max_budget_usd: float | None = Field(
|
|
165
|
+
default=None,
|
|
166
|
+
title="Max Budget (USD)",
|
|
167
|
+
ge=0.0,
|
|
168
|
+
examples=[1.0, 5.0, 10.0],
|
|
169
|
+
)
|
|
170
|
+
"""Maximum budget in USD before stopping.
|
|
171
|
+
|
|
172
|
+
When set, the agent will stop once the estimated cost exceeds this limit.
|
|
173
|
+
"""
|
|
174
|
+
|
|
135
175
|
max_thinking_tokens: int | None = Field(
|
|
136
176
|
default=None,
|
|
137
177
|
title="Max Thinking Tokens",
|
|
@@ -188,15 +228,23 @@ class ClaudeCodeAgentConfig(BaseAgentConfig):
|
|
|
188
228
|
builtin_tools: list[str] | None = Field(
|
|
189
229
|
default=None,
|
|
190
230
|
title="Built-in Tools",
|
|
191
|
-
examples=[["Bash", "Edit", "Read"], []],
|
|
231
|
+
examples=[["Bash", "Edit", "Read"], ["Read", "Write", "LSP"], ["Bash", "Chrome"]],
|
|
192
232
|
)
|
|
193
233
|
"""Available tools from Claude Code's built-in set.
|
|
194
234
|
|
|
195
235
|
Empty list disables all tools. If not specified, all tools are available.
|
|
196
236
|
Different from allowed_tools which filters an already-available set.
|
|
237
|
+
|
|
238
|
+
Special tools:
|
|
239
|
+
- "LSP": Enable Language Server Protocol support for code intelligence
|
|
240
|
+
(go to definition, find references, symbol info, etc.)
|
|
241
|
+
- "Chrome": Enable Claude in Chrome integration for browser control
|
|
242
|
+
(opens, navigates, interacts with browser tabs)
|
|
243
|
+
|
|
244
|
+
Both LSP and Chrome require additional setup in your environment.
|
|
197
245
|
"""
|
|
198
246
|
|
|
199
|
-
fallback_model: str | None = Field(
|
|
247
|
+
fallback_model: AnthropicMaxModelName | str | None = Field(
|
|
200
248
|
default=None,
|
|
201
249
|
title="Fallback Model",
|
|
202
250
|
examples=["claude-sonnet-4-5", "claude-haiku-3-5"],
|
|
@@ -209,30 +257,107 @@ class ClaudeCodeAgentConfig(BaseAgentConfig):
|
|
|
209
257
|
)
|
|
210
258
|
"""Bypass all permission checks. Only for sandboxed environments."""
|
|
211
259
|
|
|
212
|
-
|
|
260
|
+
setting_sources: list[SettingSource] | None = Field(
|
|
261
|
+
default=None,
|
|
262
|
+
title="Setting Sources",
|
|
263
|
+
examples=[["user", "project"], ["local"], ["user", "project", "local"]],
|
|
264
|
+
)
|
|
265
|
+
"""Setting sources to load configuration from.
|
|
266
|
+
|
|
267
|
+
Controls which Claude Code settings files are loaded:
|
|
268
|
+
- "user": User-level settings (~/.config/claude/settings.json)
|
|
269
|
+
- "project": Project-level settings (.claude/settings.json in project root)
|
|
270
|
+
- "local": Local settings (.claude/settings.local.json, git-ignored)
|
|
271
|
+
|
|
272
|
+
If not specified, Claude Code will load all available settings.
|
|
273
|
+
"""
|
|
274
|
+
|
|
275
|
+
use_subscription: bool = Field(
|
|
276
|
+
default=False,
|
|
277
|
+
title="Use Claude Subscription",
|
|
278
|
+
)
|
|
279
|
+
"""Force usage of Claude subscription instead of API key.
|
|
280
|
+
|
|
281
|
+
When True, sets ANTHROPIC_API_KEY to empty string, forcing Claude Code
|
|
282
|
+
to use your Claude.ai subscription for authentication instead of an API key.
|
|
283
|
+
|
|
284
|
+
This is useful when:
|
|
285
|
+
- You have a Claude Pro/Team subscription with higher rate limits
|
|
286
|
+
- You want to use subscription credits instead of API credits
|
|
287
|
+
- You're using features only available to subscribers
|
|
288
|
+
|
|
289
|
+
Note: Requires an active Claude subscription and logged-in session.
|
|
290
|
+
"""
|
|
291
|
+
|
|
292
|
+
tools: list[AnyToolConfig | str] = Field(
|
|
213
293
|
default_factory=list,
|
|
214
|
-
title="
|
|
294
|
+
title="Tools",
|
|
215
295
|
examples=[
|
|
216
296
|
[
|
|
217
297
|
{"type": "subagent"},
|
|
218
298
|
{"type": "agent_management"},
|
|
299
|
+
"webbrowser:open",
|
|
300
|
+
{
|
|
301
|
+
"type": "import",
|
|
302
|
+
"import_path": "webbrowser:open",
|
|
303
|
+
"name": "web_browser",
|
|
304
|
+
},
|
|
219
305
|
],
|
|
220
306
|
],
|
|
221
307
|
)
|
|
222
|
-
"""
|
|
308
|
+
"""Tools and toolsets to expose to this Claude Code agent via MCP bridge.
|
|
223
309
|
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
agentpool toolsets like subagent delegation, agent management, etc.
|
|
310
|
+
Supports both single tools and toolsets. These will be started as an
|
|
311
|
+
in-process MCP server and made available to Claude Code.
|
|
227
312
|
|
|
228
|
-
|
|
229
|
-
which passes the FastMCP server instance directly without HTTP overhead.
|
|
313
|
+
Docs: https://phil65.github.io/agentpool/YAML%20Configuration/tool_configuration/
|
|
230
314
|
"""
|
|
231
315
|
|
|
232
|
-
def
|
|
233
|
-
"""Get resource providers for
|
|
316
|
+
def get_tool_providers(self) -> list[ResourceProvider]:
|
|
317
|
+
"""Get all resource providers for this agent's tools.
|
|
318
|
+
|
|
319
|
+
Processes the unified tools list, separating:
|
|
320
|
+
- Toolsets: Each becomes its own ResourceProvider
|
|
321
|
+
- Single tools: Aggregated into a single StaticResourceProvider
|
|
234
322
|
|
|
235
323
|
Returns:
|
|
236
|
-
List of
|
|
324
|
+
List of ResourceProvider instances
|
|
237
325
|
"""
|
|
238
|
-
|
|
326
|
+
from agentpool.tools.base import Tool
|
|
327
|
+
from agentpool_config.toolsets import BaseToolsetConfig
|
|
328
|
+
|
|
329
|
+
providers: list[ResourceProvider] = []
|
|
330
|
+
static_tools: list[Tool] = []
|
|
331
|
+
|
|
332
|
+
for tool_config in self.tools:
|
|
333
|
+
try:
|
|
334
|
+
if isinstance(tool_config, BaseToolsetConfig):
|
|
335
|
+
providers.append(tool_config.get_provider())
|
|
336
|
+
elif isinstance(tool_config, str):
|
|
337
|
+
static_tools.append(Tool.from_callable(tool_config))
|
|
338
|
+
elif isinstance(tool_config, BaseToolConfig):
|
|
339
|
+
static_tools.append(tool_config.get_tool())
|
|
340
|
+
except Exception:
|
|
341
|
+
logger.exception("Failed to load tool", config=tool_config)
|
|
342
|
+
continue
|
|
343
|
+
|
|
344
|
+
if static_tools:
|
|
345
|
+
providers.append(StaticResourceProvider(name="tools", tools=static_tools))
|
|
346
|
+
|
|
347
|
+
return providers
|
|
348
|
+
|
|
349
|
+
# Backward compatibility
|
|
350
|
+
def get_toolset_providers(self) -> list[ResourceProvider]:
|
|
351
|
+
"""Deprecated: use get_tool_providers() instead."""
|
|
352
|
+
return [
|
|
353
|
+
p
|
|
354
|
+
for p in self.get_tool_providers()
|
|
355
|
+
if not isinstance(p, StaticResourceProvider) or p.name != "tools"
|
|
356
|
+
]
|
|
357
|
+
|
|
358
|
+
def get_tool_provider(self) -> ResourceProvider | None:
|
|
359
|
+
"""Deprecated: use get_tool_providers() instead."""
|
|
360
|
+
for p in self.get_tool_providers():
|
|
361
|
+
if isinstance(p, StaticResourceProvider) and p.name == "tools":
|
|
362
|
+
return p
|
|
363
|
+
return None
|
agentpool/models/file_parsing.py
CHANGED
agentpool/models/manifest.py
CHANGED
|
@@ -5,18 +5,20 @@ from __future__ import annotations
|
|
|
5
5
|
from functools import cached_property
|
|
6
6
|
from typing import TYPE_CHECKING, Annotated, Any, Self
|
|
7
7
|
|
|
8
|
+
from llmling_models_config import AnyModelConfig, StringModelConfig
|
|
8
9
|
from pydantic import ConfigDict, Field, model_validator
|
|
9
10
|
from schemez import Schema
|
|
10
|
-
from
|
|
11
|
-
from
|
|
11
|
+
from upathtools_config import FilesystemConfigType
|
|
12
|
+
from upathtools_config.base import URIFileSystemConfig
|
|
12
13
|
|
|
13
14
|
from agentpool import log
|
|
14
15
|
from agentpool.models.acp_agents import ACPAgentConfigTypes
|
|
15
|
-
from agentpool.models.agents import NativeAgentConfig
|
|
16
|
+
from agentpool.models.agents import AnyToolConfig, NativeAgentConfig # noqa: F401
|
|
16
17
|
from agentpool.models.agui_agents import AGUIAgentConfig
|
|
17
18
|
from agentpool.models.claude_code_agents import ClaudeCodeAgentConfig
|
|
18
19
|
from agentpool.models.file_agents import FileAgentConfig
|
|
19
20
|
from agentpool_config.commands import CommandConfig, StaticCommandConfig
|
|
21
|
+
from agentpool_config.compaction import CompactionConfig
|
|
20
22
|
from agentpool_config.converters import ConversionConfig
|
|
21
23
|
from agentpool_config.mcp_server import BaseMCPServerConfig, MCPServerConfig
|
|
22
24
|
from agentpool_config.observability import ObservabilityConfig
|
|
@@ -38,6 +40,7 @@ from agentpool_config.workers import (
|
|
|
38
40
|
if TYPE_CHECKING:
|
|
39
41
|
from upathtools import JoinablePathLike
|
|
40
42
|
|
|
43
|
+
from agentpool.messaging.compaction import CompactionPipeline
|
|
41
44
|
from agentpool.models.acp_agents import BaseACPAgentConfig
|
|
42
45
|
from agentpool.prompts.manager import PromptManager
|
|
43
46
|
from agentpool.vfs_registry import VFSRegistry
|
|
@@ -77,6 +80,12 @@ class AgentsManifest(Schema):
|
|
|
77
80
|
INHERIT: str | list[str] | None = None
|
|
78
81
|
"""Inheritance references."""
|
|
79
82
|
|
|
83
|
+
name: str | None = None
|
|
84
|
+
"""Optional name for this manifest.
|
|
85
|
+
|
|
86
|
+
Useful for identification when working with multiple configurations.
|
|
87
|
+
"""
|
|
88
|
+
|
|
80
89
|
resources: dict[str, ResourceConfig] = Field(
|
|
81
90
|
default_factory=dict,
|
|
82
91
|
examples=[
|
|
@@ -212,6 +221,52 @@ class AgentsManifest(Schema):
|
|
|
212
221
|
Docs: https://phil65.github.io/agentpool/YAML%20Configuration/response_configuration/
|
|
213
222
|
"""
|
|
214
223
|
|
|
224
|
+
model_variants: dict[str, AnyModelConfig] = Field(
|
|
225
|
+
default_factory=dict,
|
|
226
|
+
examples=[
|
|
227
|
+
{
|
|
228
|
+
"thinking_high": {
|
|
229
|
+
"type": "anthropic",
|
|
230
|
+
"model": "claude-sonnet-4-5",
|
|
231
|
+
"max_thinking_tokens": 10000,
|
|
232
|
+
},
|
|
233
|
+
"fast_gpt": {
|
|
234
|
+
"type": "string",
|
|
235
|
+
"model": "openai:gpt-4o-mini",
|
|
236
|
+
"temperature": 0.3,
|
|
237
|
+
},
|
|
238
|
+
}
|
|
239
|
+
],
|
|
240
|
+
)
|
|
241
|
+
"""Named model variants with pre-configured settings.
|
|
242
|
+
|
|
243
|
+
Define reusable model configurations that can be referenced by name
|
|
244
|
+
in agent configs. Each variant specifies a base model and its settings.
|
|
245
|
+
|
|
246
|
+
Note: Currently only applies to native agents.
|
|
247
|
+
|
|
248
|
+
Example:
|
|
249
|
+
```yaml
|
|
250
|
+
model_variants:
|
|
251
|
+
thinking_high:
|
|
252
|
+
type: anthropic
|
|
253
|
+
model: claude-sonnet-4-5
|
|
254
|
+
max_thinking_tokens: 10000
|
|
255
|
+
|
|
256
|
+
fast_gpt:
|
|
257
|
+
type: string
|
|
258
|
+
model: openai:gpt-4o-mini
|
|
259
|
+
temperature: 0.3
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Then use in agents:
|
|
263
|
+
```yaml
|
|
264
|
+
agents:
|
|
265
|
+
assistant:
|
|
266
|
+
model: thinking_high # References the variant
|
|
267
|
+
```
|
|
268
|
+
"""
|
|
269
|
+
|
|
215
270
|
jobs: dict[str, Job[Any]] = Field(default_factory=dict)
|
|
216
271
|
"""Pre-defined jobs, ready to be used by nodes."""
|
|
217
272
|
|
|
@@ -272,6 +327,30 @@ class AgentsManifest(Schema):
|
|
|
272
327
|
path: "./prompts/analysis.md"
|
|
273
328
|
"""
|
|
274
329
|
|
|
330
|
+
compaction: CompactionConfig | None = None
|
|
331
|
+
"""Compaction configuration for message history management.
|
|
332
|
+
|
|
333
|
+
Controls how conversation history is compacted/summarized to manage context size.
|
|
334
|
+
Can use a preset or define custom steps:
|
|
335
|
+
compaction:
|
|
336
|
+
preset: balanced # or: minimal, summarizing
|
|
337
|
+
|
|
338
|
+
Or custom steps:
|
|
339
|
+
compaction:
|
|
340
|
+
steps:
|
|
341
|
+
- type: filter_thinking
|
|
342
|
+
- type: summarize
|
|
343
|
+
model: openai:gpt-4o-mini
|
|
344
|
+
threshold: 15
|
|
345
|
+
"""
|
|
346
|
+
|
|
347
|
+
config_file_path: str | None = Field(default=None, exclude=True)
|
|
348
|
+
"""Path to the configuration file this manifest was loaded from.
|
|
349
|
+
|
|
350
|
+
Set automatically by `from_file()`. Used for resolving relative paths.
|
|
351
|
+
Excluded from serialization.
|
|
352
|
+
"""
|
|
353
|
+
|
|
275
354
|
model_config = ConfigDict(
|
|
276
355
|
json_schema_extra={
|
|
277
356
|
"x-icon": "octicon:file-code-16",
|
|
@@ -389,6 +468,25 @@ class AgentsManifest(Schema):
|
|
|
389
468
|
registry.register_from_config(name, config)
|
|
390
469
|
return registry
|
|
391
470
|
|
|
471
|
+
def resolve_model(self, model: AnyModelConfig | str) -> AnyModelConfig:
|
|
472
|
+
"""Resolve a model specification to a model config.
|
|
473
|
+
|
|
474
|
+
If model is a string, checks model_variants first, then wraps in StringModelConfig.
|
|
475
|
+
If model is already an AnyModelConfig, returns it unchanged.
|
|
476
|
+
|
|
477
|
+
Args:
|
|
478
|
+
model: Model identifier, variant name, or config
|
|
479
|
+
|
|
480
|
+
Returns:
|
|
481
|
+
AnyModelConfig
|
|
482
|
+
"""
|
|
483
|
+
if isinstance(model, str):
|
|
484
|
+
if model in self.model_variants:
|
|
485
|
+
return self.model_variants[model]
|
|
486
|
+
return StringModelConfig(identifier=model)
|
|
487
|
+
# Already a config
|
|
488
|
+
return model
|
|
489
|
+
|
|
392
490
|
def clone_agent_config(
|
|
393
491
|
self,
|
|
394
492
|
name: str,
|
|
@@ -437,52 +535,6 @@ class AgentsManifest(Schema):
|
|
|
437
535
|
self.agents[actual_name] = config
|
|
438
536
|
return actual_name
|
|
439
537
|
|
|
440
|
-
@model_validator(mode="before")
|
|
441
|
-
@classmethod
|
|
442
|
-
def resolve_inheritance(cls, data: dict[str, Any]) -> dict[str, Any]:
|
|
443
|
-
"""Resolve agent inheritance chains."""
|
|
444
|
-
nodes = data.get("agents", {})
|
|
445
|
-
resolved: dict[str, dict[str, Any]] = {}
|
|
446
|
-
seen: set[str] = set()
|
|
447
|
-
|
|
448
|
-
def resolve_node(name: str) -> dict[str, Any] | Any:
|
|
449
|
-
if name in resolved:
|
|
450
|
-
return resolved[name]
|
|
451
|
-
|
|
452
|
-
node = nodes[name]
|
|
453
|
-
# Skip model instances - they're already validated
|
|
454
|
-
if not isinstance(node, dict):
|
|
455
|
-
return node
|
|
456
|
-
|
|
457
|
-
if name in seen:
|
|
458
|
-
msg = f"Circular inheritance detected: {name}"
|
|
459
|
-
raise ValueError(msg)
|
|
460
|
-
|
|
461
|
-
seen.add(name)
|
|
462
|
-
config = node.copy()
|
|
463
|
-
inherit = config.get("inherits")
|
|
464
|
-
if inherit:
|
|
465
|
-
if inherit not in nodes:
|
|
466
|
-
msg = f"Parent agent {inherit} not found"
|
|
467
|
-
raise ValueError(msg)
|
|
468
|
-
|
|
469
|
-
parent = resolve_node(inherit) # Get resolved parent config
|
|
470
|
-
if isinstance(parent, dict):
|
|
471
|
-
merged = parent.copy()
|
|
472
|
-
merged.update(config)
|
|
473
|
-
config = merged
|
|
474
|
-
|
|
475
|
-
seen.remove(name)
|
|
476
|
-
resolved[name] = config
|
|
477
|
-
return config
|
|
478
|
-
|
|
479
|
-
for name in nodes:
|
|
480
|
-
resolved[name] = resolve_node(name)
|
|
481
|
-
|
|
482
|
-
# Update nodes with resolved configs
|
|
483
|
-
data["agents"] = resolved
|
|
484
|
-
return data
|
|
485
|
-
|
|
486
538
|
@cached_property
|
|
487
539
|
def _loaded_file_agents(self) -> dict[str, NativeAgentConfig]:
|
|
488
540
|
"""Load and cache file-based agent configurations.
|
|
@@ -583,6 +635,16 @@ class AgentsManifest(Schema):
|
|
|
583
635
|
|
|
584
636
|
return PromptManager(self.prompts)
|
|
585
637
|
|
|
638
|
+
def get_compaction_pipeline(self) -> CompactionPipeline | None:
|
|
639
|
+
"""Get the configured compaction pipeline, if any.
|
|
640
|
+
|
|
641
|
+
Returns:
|
|
642
|
+
CompactionPipeline instance or None if not configured
|
|
643
|
+
"""
|
|
644
|
+
if self.compaction is None:
|
|
645
|
+
return None
|
|
646
|
+
return self.compaction.build()
|
|
647
|
+
|
|
586
648
|
# @model_validator(mode="after")
|
|
587
649
|
# def validate_response_types(self) -> AgentsManifest:
|
|
588
650
|
# """Ensure all agent output_types exist in responses or are inline."""
|
|
@@ -623,6 +685,7 @@ class AgentsManifest(Schema):
|
|
|
623
685
|
|
|
624
686
|
return agent_def.model_copy(
|
|
625
687
|
update={
|
|
688
|
+
"config_file_path": path_str,
|
|
626
689
|
"agents": update_with_path(agent_def.agents),
|
|
627
690
|
"teams": update_with_path(agent_def.teams),
|
|
628
691
|
}
|
|
@@ -650,7 +713,7 @@ class AgentsManifest(Schema):
|
|
|
650
713
|
|
|
651
714
|
|
|
652
715
|
if __name__ == "__main__":
|
|
653
|
-
from
|
|
716
|
+
from llmling_models_config import InputModelConfig
|
|
654
717
|
|
|
655
718
|
model = InputModelConfig()
|
|
656
719
|
agent_cfg = NativeAgentConfig(name="test_agent", model=model)
|
agentpool/prompts/prompts.py
CHANGED
|
@@ -8,7 +8,6 @@ import inspect
|
|
|
8
8
|
import os
|
|
9
9
|
from typing import TYPE_CHECKING, Annotated, Any, Literal, Self, assert_never
|
|
10
10
|
|
|
11
|
-
from mcp.types import Prompt as MCPPrompt, PromptArgument
|
|
12
11
|
from pydantic import ConfigDict, Field
|
|
13
12
|
from pydantic_ai import BinaryContent, ImageUrl, SystemPromptPart, UserPromptPart
|
|
14
13
|
from schemez import Schema
|
|
@@ -24,9 +23,9 @@ if TYPE_CHECKING:
|
|
|
24
23
|
from collections.abc import Mapping
|
|
25
24
|
|
|
26
25
|
from fastmcp.prompts.prompt import FunctionPrompt, Prompt as FastMCPPrompt
|
|
26
|
+
from mcp.types import Prompt as MCPPrompt, PromptArgument
|
|
27
27
|
from pydantic_ai import ModelRequestPart
|
|
28
28
|
|
|
29
|
-
|
|
30
29
|
logger = get_logger(__name__)
|
|
31
30
|
|
|
32
31
|
MessageContentType = Literal["text", "resource", "image_url", "image_base64"]
|
|
@@ -421,6 +420,8 @@ class MCPClientPrompt(BasePrompt):
|
|
|
421
420
|
|
|
422
421
|
def to_mcp_prompt(self) -> MCPPrompt:
|
|
423
422
|
"""Convert to MCP Prompt."""
|
|
423
|
+
from mcp.types import Prompt as MCPPrompt, PromptArgument
|
|
424
|
+
|
|
424
425
|
args = [
|
|
425
426
|
PromptArgument(name=i["name"], description=i["description"], required=i["required"])
|
|
426
427
|
for i in self.arguments
|
|
@@ -516,6 +517,8 @@ class FilePrompt(BasePrompt):
|
|
|
516
517
|
|
|
517
518
|
def to_mcp_prompt(self) -> MCPPrompt:
|
|
518
519
|
"""Convert to MCP Prompt."""
|
|
520
|
+
from mcp.types import Prompt as MCPPrompt
|
|
521
|
+
|
|
519
522
|
return MCPPrompt(
|
|
520
523
|
name=self.name or to_upath(self.path).name,
|
|
521
524
|
description=self.description,
|
agentpool/repomap.py
CHANGED
|
@@ -1109,7 +1109,7 @@ def get_file_map_from_content( # noqa: PLR0915
|
|
|
1109
1109
|
|
|
1110
1110
|
header = (
|
|
1111
1111
|
f"# File: {filename} ({lines} lines)\n"
|
|
1112
|
-
f"# Structure map (~{tokens_approx} tokens). Use
|
|
1112
|
+
f"# Structure map (~{tokens_approx} tokens). Use read with line/limit for details.\n\n"
|
|
1113
1113
|
)
|
|
1114
1114
|
|
|
1115
1115
|
result = header + f"{filename}:\n" + tree_output
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
"""Resource provider implementations."""
|
|
2
2
|
|
|
3
|
-
from agentpool.resource_providers.base import
|
|
3
|
+
from agentpool.resource_providers.base import (
|
|
4
|
+
ProviderKind,
|
|
5
|
+
ResourceChangeEvent,
|
|
6
|
+
ResourceProvider,
|
|
7
|
+
ResourceType,
|
|
8
|
+
)
|
|
9
|
+
from agentpool.resource_providers.resource_info import ResourceInfo
|
|
4
10
|
from agentpool.resource_providers.static import StaticResourceProvider
|
|
5
11
|
from agentpool.resource_providers.filtering import FilteringResourceProvider
|
|
6
12
|
from agentpool.resource_providers.aggregating import AggregatingResourceProvider
|
|
@@ -12,6 +18,10 @@ __all__ = [
|
|
|
12
18
|
"FilteringResourceProvider",
|
|
13
19
|
"MCPResourceProvider",
|
|
14
20
|
"PlanProvider",
|
|
21
|
+
"ProviderKind",
|
|
22
|
+
"ResourceChangeEvent",
|
|
23
|
+
"ResourceInfo",
|
|
15
24
|
"ResourceProvider",
|
|
25
|
+
"ResourceType",
|
|
16
26
|
"StaticResourceProvider",
|
|
17
27
|
]
|
|
@@ -4,19 +4,29 @@ from __future__ import annotations
|
|
|
4
4
|
|
|
5
5
|
from typing import TYPE_CHECKING
|
|
6
6
|
|
|
7
|
-
from agentpool.resource_providers import ResourceProvider
|
|
7
|
+
from agentpool.resource_providers.base import ResourceChangeEvent, ResourceProvider
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
if TYPE_CHECKING:
|
|
11
|
+
from collections.abc import Sequence
|
|
12
|
+
|
|
11
13
|
from pydantic_ai import ModelRequestPart
|
|
12
14
|
|
|
13
15
|
from agentpool.prompts.prompts import BasePrompt
|
|
16
|
+
from agentpool.resource_providers.resource_info import ResourceInfo
|
|
14
17
|
from agentpool.tools.base import Tool
|
|
15
|
-
|
|
18
|
+
|
|
19
|
+
_ = ResourceChangeEvent # Used at runtime in method signatures
|
|
16
20
|
|
|
17
21
|
|
|
18
22
|
class AggregatingResourceProvider(ResourceProvider):
|
|
19
|
-
"""Provider that combines resources from multiple providers.
|
|
23
|
+
"""Provider that combines resources from multiple providers.
|
|
24
|
+
|
|
25
|
+
Automatically forwards change signals from child providers.
|
|
26
|
+
When a child emits tools_changed, this provider re-emits it.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
kind = "aggregating"
|
|
20
30
|
|
|
21
31
|
def __init__(self, providers: list[ResourceProvider], name: str = "aggregating") -> None:
|
|
22
32
|
"""Initialize provider with list of providers to aggregate.
|
|
@@ -26,10 +36,51 @@ class AggregatingResourceProvider(ResourceProvider):
|
|
|
26
36
|
name: Name for this provider
|
|
27
37
|
"""
|
|
28
38
|
super().__init__(name=name)
|
|
29
|
-
|
|
39
|
+
self._providers: list[ResourceProvider] = []
|
|
40
|
+
# Use property setter to set up signal forwarding
|
|
30
41
|
self.providers = providers
|
|
31
42
|
|
|
32
|
-
|
|
43
|
+
@property
|
|
44
|
+
def providers(self) -> list[ResourceProvider]:
|
|
45
|
+
"""Get the list of child providers."""
|
|
46
|
+
return self._providers
|
|
47
|
+
|
|
48
|
+
@providers.setter
|
|
49
|
+
def providers(self, value: list[ResourceProvider]) -> None:
|
|
50
|
+
"""Set the list of child providers and set up signal forwarding."""
|
|
51
|
+
# Disconnect from old providers
|
|
52
|
+
for provider in self._providers:
|
|
53
|
+
provider.tools_changed.disconnect(self._forward_tools_changed)
|
|
54
|
+
provider.prompts_changed.disconnect(self._forward_prompts_changed)
|
|
55
|
+
provider.resources_changed.disconnect(self._forward_resources_changed)
|
|
56
|
+
provider.skills_changed.disconnect(self._forward_skills_changed)
|
|
57
|
+
|
|
58
|
+
self._providers = value
|
|
59
|
+
|
|
60
|
+
# Connect to new providers
|
|
61
|
+
for provider in self._providers:
|
|
62
|
+
provider.tools_changed.connect(self._forward_tools_changed)
|
|
63
|
+
provider.prompts_changed.connect(self._forward_prompts_changed)
|
|
64
|
+
provider.resources_changed.connect(self._forward_resources_changed)
|
|
65
|
+
provider.skills_changed.connect(self._forward_skills_changed)
|
|
66
|
+
|
|
67
|
+
async def _forward_tools_changed(self, event: ResourceChangeEvent) -> None:
|
|
68
|
+
"""Forward tools_changed signal from child provider."""
|
|
69
|
+
await self.tools_changed.emit(event)
|
|
70
|
+
|
|
71
|
+
async def _forward_prompts_changed(self, event: ResourceChangeEvent) -> None:
|
|
72
|
+
"""Forward prompts_changed signal from child provider."""
|
|
73
|
+
await self.prompts_changed.emit(event)
|
|
74
|
+
|
|
75
|
+
async def _forward_resources_changed(self, event: ResourceChangeEvent) -> None:
|
|
76
|
+
"""Forward resources_changed signal from child provider."""
|
|
77
|
+
await self.resources_changed.emit(event)
|
|
78
|
+
|
|
79
|
+
async def _forward_skills_changed(self, event: ResourceChangeEvent) -> None:
|
|
80
|
+
"""Forward skills_changed signal from child provider."""
|
|
81
|
+
await self.skills_changed.emit(event)
|
|
82
|
+
|
|
83
|
+
async def get_tools(self) -> Sequence[Tool]:
|
|
33
84
|
"""Get tools from all providers."""
|
|
34
85
|
return [t for provider in self.providers for t in await provider.get_tools()]
|
|
35
86
|
|