agentpool 2.1.9__py3-none-any.whl → 2.2.3__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 -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/notifications.py +2 -1
- acp/stdio.py +39 -9
- acp/transports.py +362 -2
- acp/utils.py +15 -2
- agentpool/__init__.py +4 -1
- agentpool/agents/__init__.py +2 -0
- agentpool/agents/acp_agent/acp_agent.py +203 -88
- agentpool/agents/acp_agent/acp_converters.py +46 -21
- agentpool/agents/acp_agent/client_handler.py +157 -3
- agentpool/agents/acp_agent/session_state.py +4 -1
- agentpool/agents/agent.py +314 -107
- agentpool/agents/agui_agent/__init__.py +0 -2
- agentpool/agents/agui_agent/agui_agent.py +90 -21
- agentpool/agents/agui_agent/agui_converters.py +0 -131
- agentpool/agents/base_agent.py +163 -1
- agentpool/agents/claude_code_agent/claude_code_agent.py +626 -179
- agentpool/agents/claude_code_agent/converters.py +71 -3
- agentpool/agents/claude_code_agent/history.py +474 -0
- agentpool/agents/context.py +40 -0
- agentpool/agents/events/__init__.py +2 -0
- agentpool/agents/events/builtin_handlers.py +2 -1
- agentpool/agents/events/event_emitter.py +29 -2
- agentpool/agents/events/events.py +20 -0
- agentpool/agents/modes.py +54 -0
- agentpool/agents/tool_call_accumulator.py +213 -0
- agentpool/common_types.py +21 -0
- agentpool/config_resources/__init__.py +38 -1
- agentpool/config_resources/claude_code_agent.yml +3 -0
- agentpool/delegation/pool.py +37 -29
- agentpool/delegation/team.py +1 -0
- agentpool/delegation/teamrun.py +1 -0
- 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/mcp_server/__init__.py +0 -2
- agentpool/mcp_server/client.py +12 -3
- agentpool/mcp_server/manager.py +25 -31
- agentpool/mcp_server/registries/official_registry_client.py +25 -0
- agentpool/mcp_server/tool_bridge.py +78 -66
- agentpool/messaging/__init__.py +0 -2
- agentpool/messaging/compaction.py +72 -197
- agentpool/messaging/message_history.py +12 -0
- agentpool/messaging/messages.py +52 -9
- agentpool/messaging/processing.py +3 -1
- agentpool/models/acp_agents/base.py +0 -22
- agentpool/models/acp_agents/mcp_capable.py +8 -148
- agentpool/models/acp_agents/non_mcp.py +129 -72
- agentpool/models/agents.py +35 -13
- agentpool/models/claude_code_agents.py +33 -2
- agentpool/models/manifest.py +43 -0
- agentpool/repomap.py +1 -1
- agentpool/resource_providers/__init__.py +9 -1
- agentpool/resource_providers/aggregating.py +52 -3
- agentpool/resource_providers/base.py +57 -1
- agentpool/resource_providers/mcp_provider.py +23 -0
- agentpool/resource_providers/plan_provider.py +130 -41
- agentpool/resource_providers/pool.py +2 -0
- agentpool/resource_providers/static.py +2 -0
- agentpool/sessions/__init__.py +2 -1
- agentpool/sessions/manager.py +31 -2
- agentpool/sessions/models.py +50 -0
- agentpool/skills/registry.py +13 -8
- agentpool/storage/manager.py +217 -1
- agentpool/testing.py +537 -19
- 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 +690 -1
- agentpool/utils/subprocess_utils.py +155 -0
- agentpool/utils/token_breakdown.py +461 -0
- {agentpool-2.1.9.dist-info → agentpool-2.2.3.dist-info}/METADATA +27 -7
- {agentpool-2.1.9.dist-info → agentpool-2.2.3.dist-info}/RECORD +170 -112
- {agentpool-2.1.9.dist-info → agentpool-2.2.3.dist-info}/WHEEL +1 -1
- agentpool_cli/__main__.py +4 -0
- agentpool_cli/serve_acp.py +41 -20
- agentpool_cli/serve_agui.py +87 -0
- agentpool_cli/serve_opencode.py +119 -0
- agentpool_commands/__init__.py +30 -0
- agentpool_commands/agents.py +74 -1
- agentpool_commands/history.py +62 -0
- agentpool_commands/mcp.py +176 -0
- agentpool_commands/models.py +56 -3
- agentpool_commands/tools.py +57 -0
- agentpool_commands/utils.py +51 -0
- agentpool_config/builtin_tools.py +77 -22
- agentpool_config/commands.py +24 -1
- agentpool_config/compaction.py +258 -0
- agentpool_config/mcp_server.py +131 -1
- agentpool_config/storage.py +46 -1
- agentpool_config/tools.py +7 -1
- agentpool_config/toolsets.py +92 -148
- agentpool_server/acp_server/acp_agent.py +134 -150
- agentpool_server/acp_server/commands/acp_commands.py +216 -51
- agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +10 -10
- agentpool_server/acp_server/server.py +23 -79
- agentpool_server/acp_server/session.py +181 -19
- agentpool_server/opencode_server/.rules +95 -0
- agentpool_server/opencode_server/ENDPOINTS.md +362 -0
- agentpool_server/opencode_server/__init__.py +27 -0
- agentpool_server/opencode_server/command_validation.py +172 -0
- agentpool_server/opencode_server/converters.py +869 -0
- agentpool_server/opencode_server/dependencies.py +24 -0
- agentpool_server/opencode_server/input_provider.py +269 -0
- agentpool_server/opencode_server/models/__init__.py +228 -0
- agentpool_server/opencode_server/models/agent.py +53 -0
- agentpool_server/opencode_server/models/app.py +60 -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 +647 -0
- agentpool_server/opencode_server/models/file.py +88 -0
- agentpool_server/opencode_server/models/mcp.py +25 -0
- agentpool_server/opencode_server/models/message.py +162 -0
- agentpool_server/opencode_server/models/parts.py +190 -0
- agentpool_server/opencode_server/models/provider.py +81 -0
- agentpool_server/opencode_server/models/pty.py +43 -0
- agentpool_server/opencode_server/models/session.py +99 -0
- agentpool_server/opencode_server/routes/__init__.py +25 -0
- agentpool_server/opencode_server/routes/agent_routes.py +442 -0
- agentpool_server/opencode_server/routes/app_routes.py +139 -0
- agentpool_server/opencode_server/routes/config_routes.py +241 -0
- agentpool_server/opencode_server/routes/file_routes.py +392 -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 +705 -0
- agentpool_server/opencode_server/routes/pty_routes.py +299 -0
- agentpool_server/opencode_server/routes/session_routes.py +1205 -0
- agentpool_server/opencode_server/routes/tui_routes.py +139 -0
- agentpool_server/opencode_server/server.py +430 -0
- agentpool_server/opencode_server/state.py +121 -0
- agentpool_server/opencode_server/time_utils.py +8 -0
- agentpool_storage/__init__.py +16 -0
- agentpool_storage/base.py +103 -0
- agentpool_storage/claude_provider.py +907 -0
- agentpool_storage/file_provider.py +129 -0
- agentpool_storage/memory_provider.py +61 -0
- agentpool_storage/models.py +3 -0
- agentpool_storage/opencode_provider.py +730 -0
- agentpool_storage/project_store.py +325 -0
- agentpool_storage/session_store.py +6 -0
- agentpool_storage/sql_provider/__init__.py +4 -2
- agentpool_storage/sql_provider/models.py +48 -0
- agentpool_storage/sql_provider/sql_provider.py +134 -1
- agentpool_storage/sql_provider/utils.py +10 -1
- agentpool_storage/text_log_provider.py +1 -0
- agentpool_toolsets/builtin/__init__.py +0 -8
- agentpool_toolsets/builtin/code.py +95 -56
- agentpool_toolsets/builtin/debug.py +16 -21
- agentpool_toolsets/builtin/execution_environment.py +99 -103
- agentpool_toolsets/builtin/file_edit/file_edit.py +115 -7
- agentpool_toolsets/builtin/skills.py +86 -4
- agentpool_toolsets/fsspec_toolset/__init__.py +13 -1
- agentpool_toolsets/fsspec_toolset/diagnostics.py +860 -73
- agentpool_toolsets/fsspec_toolset/grep.py +74 -2
- agentpool_toolsets/fsspec_toolset/image_utils.py +161 -0
- agentpool_toolsets/fsspec_toolset/toolset.py +159 -38
- agentpool_toolsets/mcp_discovery/__init__.py +5 -0
- agentpool_toolsets/mcp_discovery/data/mcp_servers.parquet +0 -0
- agentpool_toolsets/mcp_discovery/toolset.py +454 -0
- agentpool_toolsets/mcp_run_toolset.py +84 -6
- agentpool_toolsets/builtin/agent_management.py +0 -239
- agentpool_toolsets/builtin/history.py +0 -36
- agentpool_toolsets/builtin/integration.py +0 -85
- agentpool_toolsets/builtin/tool_management.py +0 -90
- {agentpool-2.1.9.dist-info → agentpool-2.2.3.dist-info}/entry_points.txt +0 -0
- {agentpool-2.1.9.dist-info → agentpool-2.2.3.dist-info}/licenses/LICENSE +0 -0
|
@@ -17,6 +17,7 @@ from acp.schema import (
|
|
|
17
17
|
PromptResponse,
|
|
18
18
|
ResumeSessionResponse,
|
|
19
19
|
SessionInfo,
|
|
20
|
+
SessionMode,
|
|
20
21
|
SessionModelState,
|
|
21
22
|
SessionModeState,
|
|
22
23
|
SetSessionModelRequest,
|
|
@@ -24,20 +25,16 @@ from acp.schema import (
|
|
|
24
25
|
SetSessionModeRequest,
|
|
25
26
|
SetSessionModeResponse,
|
|
26
27
|
)
|
|
27
|
-
from agentpool import Agent
|
|
28
28
|
from agentpool.log import get_logger
|
|
29
29
|
from agentpool.utils.tasks import TaskManager
|
|
30
30
|
from agentpool_server.acp_server.converters import (
|
|
31
31
|
# agent_to_mode, # TODO: Re-enable when supporting agent switching via modes
|
|
32
|
-
get_confirmation_modes,
|
|
33
32
|
mode_id_to_confirmation_mode,
|
|
34
33
|
)
|
|
35
34
|
from agentpool_server.acp_server.session_manager import ACPSessionManager
|
|
36
35
|
|
|
37
36
|
|
|
38
37
|
if TYPE_CHECKING:
|
|
39
|
-
from collections.abc import Sequence
|
|
40
|
-
|
|
41
38
|
from pydantic_ai import ModelRequest, ModelResponse
|
|
42
39
|
|
|
43
40
|
from acp import AgentSideConnection, Client
|
|
@@ -63,59 +60,111 @@ if TYPE_CHECKING:
|
|
|
63
60
|
logger = get_logger(__name__)
|
|
64
61
|
|
|
65
62
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
),
|
|
73
|
-
ACPModelInfo(
|
|
74
|
-
model_id="sonnet",
|
|
75
|
-
name="Claude Sonnet",
|
|
76
|
-
description="Claude Sonnet - balanced performance and speed",
|
|
77
|
-
),
|
|
78
|
-
ACPModelInfo(
|
|
79
|
-
model_id="haiku",
|
|
80
|
-
name="Claude Haiku",
|
|
81
|
-
description="Claude Haiku - fast and cost-effective",
|
|
82
|
-
),
|
|
83
|
-
]
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
def create_claude_code_model_state(current_model: str | None = None) -> SessionModelState:
|
|
87
|
-
"""Create SessionModelState for Claude Code agents.
|
|
63
|
+
async def get_session_model_state(
|
|
64
|
+
agent: Any, current_model: str | None = None
|
|
65
|
+
) -> SessionModelState | None:
|
|
66
|
+
"""Get SessionModelState from an agent using its get_available_models() method.
|
|
67
|
+
|
|
68
|
+
Converts tokonomics ModelInfo to ACP ModelInfo format.
|
|
88
69
|
|
|
89
70
|
Args:
|
|
90
|
-
|
|
71
|
+
agent: Any agent with get_available_models() method
|
|
72
|
+
current_model: Currently active model ID (defaults to first available)
|
|
91
73
|
|
|
92
74
|
Returns:
|
|
93
|
-
SessionModelState with
|
|
75
|
+
SessionModelState with all available models, None if no models available
|
|
94
76
|
"""
|
|
95
|
-
|
|
96
|
-
current = current_model if current_model in model_ids else "sonnet"
|
|
97
|
-
return SessionModelState(available_models=CLAUDE_CODE_MODELS, current_model_id=current)
|
|
77
|
+
from agentpool.agents.base_agent import BaseAgent
|
|
98
78
|
|
|
79
|
+
if not isinstance(agent, BaseAgent):
|
|
80
|
+
return None
|
|
99
81
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
82
|
+
try:
|
|
83
|
+
toko_models = await agent.get_available_models()
|
|
84
|
+
except Exception:
|
|
85
|
+
logger.exception("Failed to get available models from agent")
|
|
86
|
+
return None
|
|
87
|
+
|
|
88
|
+
if not toko_models:
|
|
89
|
+
return None
|
|
90
|
+
|
|
91
|
+
# Convert tokonomics ModelInfo to ACP ModelInfo
|
|
92
|
+
acp_models: list[ACPModelInfo] = []
|
|
93
|
+
for toko in toko_models:
|
|
94
|
+
# Use id_override if set (e.g., "opus" for Claude Code), otherwise use id
|
|
95
|
+
model_id = toko.id_override if toko.id_override else toko.id
|
|
96
|
+
acp_models.append(
|
|
97
|
+
ACPModelInfo(
|
|
98
|
+
model_id=model_id,
|
|
99
|
+
name=toko.name,
|
|
100
|
+
description=toko.description or "",
|
|
101
|
+
)
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
if not acp_models:
|
|
105
|
+
return None
|
|
106
|
+
|
|
107
|
+
# Ensure current model is in the list
|
|
108
|
+
all_ids = [model.model_id for model in acp_models]
|
|
109
|
+
if current_model and current_model not in all_ids:
|
|
110
|
+
# Add current model to the list so the UI shows it
|
|
111
|
+
acp_models.insert(
|
|
112
|
+
0,
|
|
113
|
+
ACPModelInfo(
|
|
114
|
+
model_id=current_model,
|
|
115
|
+
name=current_model,
|
|
116
|
+
description="Currently configured model",
|
|
117
|
+
),
|
|
118
|
+
)
|
|
119
|
+
current_model_id = current_model
|
|
120
|
+
else:
|
|
121
|
+
current_model_id = current_model if current_model in all_ids else all_ids[0]
|
|
122
|
+
|
|
123
|
+
return SessionModelState(available_models=acp_models, current_model_id=current_model_id)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def get_session_mode_state(agent: Any) -> SessionModeState | None:
|
|
127
|
+
"""Get SessionModeState from an agent using its get_modes() method.
|
|
128
|
+
|
|
129
|
+
Converts agentpool ModeCategory to ACP SessionModeState format.
|
|
130
|
+
Currently uses the first mode category (ACP only supports one dropdown for now).
|
|
104
131
|
|
|
105
132
|
Args:
|
|
106
|
-
|
|
107
|
-
current_model: The currently active model (defaults to first available)
|
|
133
|
+
agent: Any agent with get_modes() method
|
|
108
134
|
|
|
109
135
|
Returns:
|
|
110
|
-
|
|
136
|
+
SessionModeState from agent's modes, None if no modes available
|
|
111
137
|
"""
|
|
112
|
-
|
|
138
|
+
from agentpool.agents.base_agent import BaseAgent
|
|
139
|
+
|
|
140
|
+
if not isinstance(agent, BaseAgent):
|
|
141
|
+
return None
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
mode_categories = agent.get_modes()
|
|
145
|
+
except Exception:
|
|
146
|
+
logger.exception("Failed to get modes from agent")
|
|
147
|
+
return None
|
|
148
|
+
|
|
149
|
+
if not mode_categories:
|
|
113
150
|
return None
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
151
|
+
|
|
152
|
+
# Use first category for now (ACP currently only supports single mode dropdown)
|
|
153
|
+
category = mode_categories[0]
|
|
154
|
+
|
|
155
|
+
# Convert ModeInfo to ACP SessionMode
|
|
156
|
+
acp_modes = [
|
|
157
|
+
SessionMode(
|
|
158
|
+
id=mode.id,
|
|
159
|
+
name=mode.name,
|
|
160
|
+
description=mode.description,
|
|
161
|
+
)
|
|
162
|
+
for mode in category.available_modes
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
return SessionModeState(
|
|
166
|
+
available_modes=acp_modes,
|
|
167
|
+
current_mode_id=category.current_mode_id,
|
|
119
168
|
)
|
|
120
169
|
|
|
121
170
|
|
|
@@ -137,9 +186,6 @@ class AgentPoolACPAgent(ACPAgent):
|
|
|
137
186
|
|
|
138
187
|
_: KW_ONLY
|
|
139
188
|
|
|
140
|
-
available_models: Sequence[ACPModelInfo] = field(default_factory=list)
|
|
141
|
-
"""List of available ACP ModelInfo objects (converted from tokonomics at startup)."""
|
|
142
|
-
|
|
143
189
|
file_access: bool = True
|
|
144
190
|
"""Whether agent can access filesystem."""
|
|
145
191
|
|
|
@@ -176,17 +222,12 @@ class AgentPoolACPAgent(ACPAgent):
|
|
|
176
222
|
|
|
177
223
|
async def initialize(self, params: InitializeRequest) -> InitializeResponse:
|
|
178
224
|
"""Initialize the agent and negotiate capabilities."""
|
|
179
|
-
logger.info("Initializing ACP agent implementation")
|
|
180
225
|
version = min(params.protocol_version, self.PROTOCOL_VERSION)
|
|
181
226
|
self.client_capabilities = params.client_capabilities
|
|
182
227
|
self.client_info = params.client_info
|
|
183
|
-
logger.info(
|
|
184
|
-
"Client capabilities",
|
|
185
|
-
capabilities=self.client_capabilities,
|
|
186
|
-
client_info=self.client_info,
|
|
187
|
-
)
|
|
228
|
+
logger.info("Client info", request=params.model_dump_json())
|
|
188
229
|
self._initialized = True
|
|
189
|
-
|
|
230
|
+
return InitializeResponse.create(
|
|
190
231
|
protocol_version=version,
|
|
191
232
|
name="agentpool",
|
|
192
233
|
title="AgentPool",
|
|
@@ -199,10 +240,8 @@ class AgentPoolACPAgent(ACPAgent):
|
|
|
199
240
|
embedded_context_prompts=True,
|
|
200
241
|
image_prompts=True,
|
|
201
242
|
)
|
|
202
|
-
logger.info("ACP agent initialized successfully", response=response)
|
|
203
|
-
return response
|
|
204
243
|
|
|
205
|
-
async def new_session(self, params: NewSessionRequest) -> NewSessionResponse:
|
|
244
|
+
async def new_session(self, params: NewSessionRequest) -> NewSessionResponse:
|
|
206
245
|
"""Create a new session."""
|
|
207
246
|
if not self._initialized:
|
|
208
247
|
raise RuntimeError("Agent not initialized")
|
|
@@ -230,48 +269,22 @@ class AgentPoolACPAgent(ACPAgent):
|
|
|
230
269
|
client_info=self.client_info,
|
|
231
270
|
)
|
|
232
271
|
|
|
233
|
-
# Get mode
|
|
272
|
+
# Get mode and model information from the agent
|
|
234
273
|
from agentpool.agents.acp_agent import ACPAgent as ACPAgentClient
|
|
235
274
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
# Pass through nested agent's modes (e.g., Claude Code's modes)
|
|
239
|
-
if session.agent._state and session.agent._state.modes:
|
|
240
|
-
state = session.agent._state.modes
|
|
241
|
-
modes = state.available_modes
|
|
242
|
-
else:
|
|
243
|
-
# Fallback to our confirmation modes if nested agent has none
|
|
244
|
-
modes = get_confirmation_modes()
|
|
245
|
-
state = SessionModeState(current_mode_id="default", available_modes=modes)
|
|
246
|
-
else:
|
|
247
|
-
# Native Agent - use our tool confirmation modes
|
|
248
|
-
modes = get_confirmation_modes()
|
|
249
|
-
state = SessionModeState(current_mode_id="default", available_modes=modes)
|
|
250
|
-
else:
|
|
251
|
-
modes = get_confirmation_modes()
|
|
252
|
-
state = SessionModeState(current_mode_id="default", available_modes=modes)
|
|
253
|
-
# TODO: Re-enable agent switching via modes when needed:
|
|
254
|
-
# modes = [agent_to_mode(agent) for agent in self.agent_pool.all_agents.values()]
|
|
255
|
-
# state = SessionModeState(current_mode_id=default_name, available_modes=modes)
|
|
275
|
+
state: SessionModeState | None = None
|
|
276
|
+
models: SessionModelState | None = None
|
|
256
277
|
|
|
257
|
-
# Get model information from the default agent
|
|
258
278
|
if session := self.session_manager.get_session(session_id):
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
# Claude Code uses simple model IDs (sonnet, opus, haiku)
|
|
263
|
-
models = create_claude_code_model_state(session.agent.model_name)
|
|
264
|
-
elif isinstance(session.agent, ACPAgentClient):
|
|
265
|
-
# Nested ACP agent - pass through its model state directly
|
|
266
|
-
if session.agent._state and session.agent._state.models:
|
|
279
|
+
if isinstance(session.agent, ACPAgentClient):
|
|
280
|
+
# Nested ACP agent - pass through its state directly
|
|
281
|
+
if session.agent._state:
|
|
267
282
|
models = session.agent._state.models
|
|
268
|
-
|
|
269
|
-
models = None
|
|
283
|
+
state = session.agent._state.modes
|
|
270
284
|
else:
|
|
271
|
-
|
|
272
|
-
models =
|
|
273
|
-
|
|
274
|
-
models = None
|
|
285
|
+
# Use unified helpers for all other agents
|
|
286
|
+
models = await get_session_model_state(session.agent, session.agent.model_name)
|
|
287
|
+
state = get_session_mode_state(session.agent)
|
|
275
288
|
except Exception:
|
|
276
289
|
logger.exception("Failed to create new session")
|
|
277
290
|
raise
|
|
@@ -285,7 +298,7 @@ class AgentPoolACPAgent(ACPAgent):
|
|
|
285
298
|
if self.load_skills:
|
|
286
299
|
coro_4 = session.init_client_skills()
|
|
287
300
|
self.tasks.create_task(coro_4, name=f"init_client_skills_{session_id}")
|
|
288
|
-
logger.info("Created session", session_id=session_id
|
|
301
|
+
logger.info("Created session", session_id=session_id)
|
|
289
302
|
return NewSessionResponse(session_id=session_id, modes=state, models=models)
|
|
290
303
|
|
|
291
304
|
async def load_session(self, params: LoadSessionRequest) -> LoadSessionResponse:
|
|
@@ -332,38 +345,22 @@ class AgentPoolACPAgent(ACPAgent):
|
|
|
332
345
|
await session.initialize_mcp_servers()
|
|
333
346
|
|
|
334
347
|
# Build response with current session state
|
|
335
|
-
# Get mode information - pass through from ACPAgent or use our confirmation modes
|
|
336
348
|
from agentpool.agents.acp_agent import ACPAgent as ACPAgentClient
|
|
337
349
|
|
|
350
|
+
mode_state: SessionModeState | None = None
|
|
351
|
+
models: SessionModelState | None = None
|
|
352
|
+
|
|
338
353
|
if isinstance(session.agent, ACPAgentClient):
|
|
339
|
-
#
|
|
340
|
-
if session.agent._state
|
|
354
|
+
# Nested ACP agent - pass through its state directly
|
|
355
|
+
if session.agent._state:
|
|
341
356
|
mode_state = session.agent._state.modes
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
357
|
+
models = session.agent._state.models
|
|
358
|
+
elif session.agent:
|
|
359
|
+
# Use unified helpers for all other agents
|
|
360
|
+
mode_state = get_session_mode_state(session.agent)
|
|
361
|
+
models = await get_session_model_state(session.agent, session.agent.model_name)
|
|
346
362
|
else:
|
|
347
|
-
|
|
348
|
-
modes = get_confirmation_modes()
|
|
349
|
-
mode_state = SessionModeState(current_mode_id="default", available_modes=modes)
|
|
350
|
-
# TODO: Re-enable agent switching via modes when needed:
|
|
351
|
-
# modes = [agent_to_mode(agent) for agent in self.agent_pool.all_agents.values()]
|
|
352
|
-
# mode_state = SessionModeState(
|
|
353
|
-
# current_mode_id=session.current_agent_name,
|
|
354
|
-
# available_modes=modes,
|
|
355
|
-
# )
|
|
356
|
-
|
|
357
|
-
# Get model information based on agent type
|
|
358
|
-
from agentpool.agents.claude_code_agent import ClaudeCodeAgent
|
|
359
|
-
|
|
360
|
-
models: SessionModelState | None
|
|
361
|
-
if session.agent and isinstance(session.agent, ClaudeCodeAgent):
|
|
362
|
-
# Claude Code uses simple model IDs (sonnet, opus, haiku)
|
|
363
|
-
models = create_claude_code_model_state(session.agent.model_name)
|
|
364
|
-
else:
|
|
365
|
-
current_model = session.agent.model_name if session.agent else None
|
|
366
|
-
models = create_session_model_state(self.available_models, current_model)
|
|
363
|
+
models = None
|
|
367
364
|
# Schedule post-load initialization tasks
|
|
368
365
|
self.tasks.create_task(session.send_available_commands_update())
|
|
369
366
|
self.tasks.create_task(session.init_project_context())
|
|
@@ -677,19 +674,15 @@ class AgentPoolACPAgent(ACPAgent):
|
|
|
677
674
|
logger.exception("Failed to set session mode", session_id=params.session_id)
|
|
678
675
|
return None
|
|
679
676
|
|
|
680
|
-
async def set_session_model(
|
|
677
|
+
async def set_session_model(
|
|
681
678
|
self, params: SetSessionModelRequest
|
|
682
679
|
) -> SetSessionModelResponse | None:
|
|
683
680
|
"""Set the session model.
|
|
684
681
|
|
|
685
682
|
Changes the model for the active agent in the session.
|
|
686
|
-
Validates that the requested model is
|
|
687
|
-
- For ClaudeCodeAgent: validates against Claude Code models (sonnet, opus, haiku)
|
|
688
|
-
- For native Agent: validates against server's available_models
|
|
689
|
-
- For ACPAgent: validates against the nested agent's model list
|
|
683
|
+
Validates that the requested model is available via agent.get_available_models().
|
|
690
684
|
"""
|
|
691
685
|
from agentpool.agents.acp_agent import ACPAgent as ACPAgentClient
|
|
692
|
-
from agentpool.agents.claude_code_agent import ClaudeCodeAgent
|
|
693
686
|
|
|
694
687
|
try:
|
|
695
688
|
session = self.session_manager.get_session(params.session_id)
|
|
@@ -698,23 +691,8 @@ class AgentPoolACPAgent(ACPAgent):
|
|
|
698
691
|
logger.warning(msg, session_id=params.session_id)
|
|
699
692
|
return None
|
|
700
693
|
|
|
701
|
-
#
|
|
702
|
-
if isinstance(session.agent, ClaudeCodeAgent):
|
|
703
|
-
# For ClaudeCodeAgent, validate against our hardcoded models
|
|
704
|
-
available_ids = [m.model_id for m in CLAUDE_CODE_MODELS]
|
|
705
|
-
if params.model_id not in available_ids:
|
|
706
|
-
logger.warning(
|
|
707
|
-
"Model not in Claude Code available models",
|
|
708
|
-
model_id=params.model_id,
|
|
709
|
-
available=available_ids,
|
|
710
|
-
)
|
|
711
|
-
return None
|
|
712
|
-
await session.agent.set_model(params.model_id)
|
|
713
|
-
logger.info("Set model", model_id=params.model_id, session_id=params.session_id)
|
|
714
|
-
return SetSessionModelResponse()
|
|
715
|
-
|
|
694
|
+
# Handle ACPAgent specially - pass through to nested agent's model state
|
|
716
695
|
if isinstance(session.agent, ACPAgentClient):
|
|
717
|
-
# For ACPAgent, validate against nested agent's model list
|
|
718
696
|
if session.agent._state and session.agent._state.models:
|
|
719
697
|
available_ids = [
|
|
720
698
|
m.model_id for m in session.agent._state.models.available_models
|
|
@@ -727,21 +705,27 @@ class AgentPoolACPAgent(ACPAgent):
|
|
|
727
705
|
)
|
|
728
706
|
return None
|
|
729
707
|
# TODO: Use ACP protocol once set_session_model stabilizes
|
|
730
|
-
# For now, we can't actually change the model on ACPAgent
|
|
731
708
|
logger.warning(
|
|
732
709
|
"Model change for ACPAgent not yet supported (ACP protocol UNSTABLE)",
|
|
733
710
|
model_id=params.model_id,
|
|
734
711
|
)
|
|
735
712
|
return None
|
|
736
713
|
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
714
|
+
# Get available models from agent and validate
|
|
715
|
+
toko_models = await session.agent.get_available_models()
|
|
716
|
+
if toko_models:
|
|
717
|
+
# Build list of valid model IDs (using id_override if set)
|
|
718
|
+
available_ids = [m.id_override if m.id_override else m.id for m in toko_models]
|
|
740
719
|
if params.model_id not in available_ids:
|
|
741
|
-
|
|
742
|
-
|
|
720
|
+
logger.warning(
|
|
721
|
+
"Model not in available models",
|
|
722
|
+
model_id=params.model_id,
|
|
723
|
+
available=available_ids,
|
|
724
|
+
)
|
|
743
725
|
return None
|
|
744
|
-
|
|
726
|
+
|
|
727
|
+
# Set the model on the agent (all agents now have async set_model)
|
|
728
|
+
await session.agent.set_model(params.model_id)
|
|
745
729
|
|
|
746
730
|
logger.info("Set model", model_id=params.model_id, session_id=params.session_id)
|
|
747
731
|
return SetSessionModelResponse()
|