agentpool 2.2.3__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 +0 -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/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 +18 -49
- 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/task/supervisor.py +2 -2
- acp/utils.py +2 -2
- agentpool/__init__.py +2 -0
- agentpool/agents/acp_agent/acp_agent.py +278 -263
- agentpool/agents/acp_agent/acp_converters.py +150 -17
- agentpool/agents/acp_agent/client_handler.py +35 -24
- agentpool/agents/acp_agent/session_state.py +14 -6
- agentpool/agents/agent.py +471 -643
- agentpool/agents/agui_agent/agui_agent.py +104 -107
- agentpool/agents/agui_agent/helpers.py +3 -4
- agentpool/agents/base_agent.py +485 -32
- 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 +654 -334
- agentpool/agents/claude_code_agent/converters.py +4 -141
- 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/events/__init__.py +22 -0
- agentpool/agents/events/builtin_handlers.py +65 -0
- agentpool/agents/events/event_emitter.py +3 -0
- agentpool/agents/events/events.py +84 -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 +13 -0
- agentpool/agents/slashed_agent.py +5 -4
- agentpool/agents/tool_wrapping.py +18 -6
- agentpool/common_types.py +35 -21
- 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 +9 -8
- agentpool/config_resources/external_acp_agents.yml +2 -1
- agentpool/delegation/base_team.py +4 -30
- agentpool/delegation/pool.py +104 -265
- agentpool/delegation/team.py +57 -57
- agentpool/delegation/teamrun.py +50 -55
- agentpool/functional/run.py +10 -4
- agentpool/mcp_server/client.py +73 -38
- agentpool/mcp_server/conversions.py +54 -13
- agentpool/mcp_server/manager.py +9 -23
- agentpool/mcp_server/registries/official_registry_client.py +10 -1
- agentpool/mcp_server/tool_bridge.py +114 -79
- 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 +87 -8
- agentpool/messaging/messagenode.py +52 -14
- agentpool/messaging/messages.py +2 -26
- agentpool/messaging/processing.py +10 -22
- agentpool/models/__init__.py +1 -1
- agentpool/models/acp_agents/base.py +6 -2
- agentpool/models/acp_agents/mcp_capable.py +124 -15
- agentpool/models/acp_agents/non_mcp.py +0 -23
- agentpool/models/agents.py +66 -66
- agentpool/models/agui_agents.py +1 -1
- agentpool/models/claude_code_agents.py +111 -17
- agentpool/models/file_parsing.py +0 -1
- agentpool/models/manifest.py +70 -50
- agentpool/prompts/conversion_manager.py +1 -1
- agentpool/prompts/prompts.py +5 -2
- agentpool/resource_providers/__init__.py +2 -0
- agentpool/resource_providers/aggregating.py +4 -2
- agentpool/resource_providers/base.py +13 -3
- 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 +66 -12
- agentpool/resource_providers/plan_provider.py +111 -18
- agentpool/resource_providers/pool.py +5 -3
- agentpool/resource_providers/resource_info.py +111 -0
- agentpool/resource_providers/static.py +2 -2
- agentpool/sessions/__init__.py +2 -0
- agentpool/sessions/manager.py +2 -3
- agentpool/sessions/models.py +9 -6
- agentpool/sessions/protocol.py +28 -0
- agentpool/sessions/session.py +11 -55
- agentpool/storage/manager.py +361 -54
- agentpool/talk/registry.py +4 -4
- agentpool/talk/talk.py +9 -10
- agentpool/testing.py +1 -1
- 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/streams.py +21 -96
- agentpool/vfs_registry.py +7 -2
- {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/METADATA +16 -22
- {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/RECORD +242 -195
- {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/WHEEL +1 -1
- agentpool_cli/__main__.py +20 -0
- agentpool_cli/create.py +1 -1
- agentpool_cli/serve_acp.py +59 -1
- agentpool_cli/serve_opencode.py +1 -1
- agentpool_cli/ui.py +557 -0
- agentpool_commands/__init__.py +12 -5
- agentpool_commands/agents.py +1 -1
- 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/utils.py +31 -32
- agentpool_config/__init__.py +30 -2
- agentpool_config/agentpool_tools.py +498 -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 +1 -5
- agentpool_config/nodes.py +1 -1
- agentpool_config/observability.py +44 -0
- agentpool_config/session.py +0 -3
- agentpool_config/storage.py +38 -39
- agentpool_config/task.py +3 -3
- agentpool_config/tools.py +11 -28
- agentpool_config/toolsets.py +22 -90
- agentpool_server/a2a_server/agent_worker.py +307 -0
- agentpool_server/a2a_server/server.py +23 -18
- agentpool_server/acp_server/acp_agent.py +125 -56
- agentpool_server/acp_server/commands/acp_commands.py +46 -216
- agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +8 -7
- agentpool_server/acp_server/event_converter.py +651 -0
- agentpool_server/acp_server/input_provider.py +53 -10
- agentpool_server/acp_server/server.py +1 -11
- agentpool_server/acp_server/session.py +90 -410
- 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/ENDPOINTS.md +53 -14
- agentpool_server/opencode_server/OPENCODE_UI_TOOLS_COMPLETE.md +202 -0
- agentpool_server/opencode_server/__init__.py +0 -8
- agentpool_server/opencode_server/converters.py +132 -26
- agentpool_server/opencode_server/input_provider.py +160 -8
- agentpool_server/opencode_server/models/__init__.py +42 -20
- agentpool_server/opencode_server/models/app.py +12 -0
- agentpool_server/opencode_server/models/events.py +203 -29
- agentpool_server/opencode_server/models/mcp.py +19 -0
- agentpool_server/opencode_server/models/message.py +18 -1
- agentpool_server/opencode_server/models/parts.py +134 -1
- agentpool_server/opencode_server/models/question.py +56 -0
- agentpool_server/opencode_server/models/session.py +13 -1
- agentpool_server/opencode_server/routes/__init__.py +4 -0
- agentpool_server/opencode_server/routes/agent_routes.py +33 -2
- agentpool_server/opencode_server/routes/app_routes.py +66 -3
- agentpool_server/opencode_server/routes/config_routes.py +66 -5
- agentpool_server/opencode_server/routes/file_routes.py +184 -5
- agentpool_server/opencode_server/routes/global_routes.py +1 -1
- agentpool_server/opencode_server/routes/lsp_routes.py +1 -1
- agentpool_server/opencode_server/routes/message_routes.py +122 -66
- agentpool_server/opencode_server/routes/permission_routes.py +63 -0
- agentpool_server/opencode_server/routes/pty_routes.py +23 -22
- agentpool_server/opencode_server/routes/question_routes.py +128 -0
- agentpool_server/opencode_server/routes/session_routes.py +139 -68
- agentpool_server/opencode_server/routes/tui_routes.py +1 -1
- agentpool_server/opencode_server/server.py +47 -2
- agentpool_server/opencode_server/state.py +30 -0
- agentpool_storage/__init__.py +0 -4
- agentpool_storage/base.py +81 -2
- agentpool_storage/claude_provider/ARCHITECTURE.md +433 -0
- agentpool_storage/claude_provider/__init__.py +42 -0
- agentpool_storage/{claude_provider.py → claude_provider/provider.py} +190 -8
- agentpool_storage/file_provider.py +149 -15
- agentpool_storage/memory_provider.py +132 -12
- 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/session_store.py +20 -6
- agentpool_storage/sql_provider/sql_provider.py +135 -2
- agentpool_storage/sql_provider/utils.py +2 -12
- 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 -4
- agentpool_toolsets/builtin/code.py +4 -4
- agentpool_toolsets/builtin/debug.py +115 -40
- agentpool_toolsets/builtin/execution_environment.py +54 -165
- agentpool_toolsets/builtin/skills.py +0 -77
- 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/grep.py +25 -5
- agentpool_toolsets/fsspec_toolset/helpers.py +3 -2
- agentpool_toolsets/fsspec_toolset/toolset.py +350 -66
- agentpool_toolsets/mcp_discovery/data/mcp_servers.parquet +0 -0
- agentpool_toolsets/mcp_discovery/toolset.py +74 -17
- agentpool_toolsets/mcp_run_toolset.py +8 -11
- agentpool_toolsets/notifications.py +33 -33
- agentpool_toolsets/openapi.py +3 -1
- agentpool_toolsets/search_toolset.py +3 -1
- 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/opencode_provider.py +0 -730
- agentpool_storage/text_log_provider.py +0 -276
- agentpool_toolsets/builtin/chain.py +0 -288
- agentpool_toolsets/builtin/user_interaction.py +0 -52
- agentpool_toolsets/semantic_memory_toolset.py +0 -536
- {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/entry_points.txt +0 -0
- {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -6,10 +6,11 @@ import asyncio
|
|
|
6
6
|
from collections import deque
|
|
7
7
|
from contextlib import asynccontextmanager
|
|
8
8
|
from dataclasses import dataclass, field
|
|
9
|
+
import json
|
|
9
10
|
from typing import TYPE_CHECKING, Any, Self, assert_never
|
|
10
11
|
from uuid import UUID, uuid4
|
|
11
12
|
|
|
12
|
-
from
|
|
13
|
+
from anyenv.signals import Signal
|
|
13
14
|
from upathtools import read_path, to_upath
|
|
14
15
|
|
|
15
16
|
from agentpool.log import get_logger
|
|
@@ -24,6 +25,7 @@ if TYPE_CHECKING:
|
|
|
24
25
|
from datetime import datetime
|
|
25
26
|
from types import TracebackType
|
|
26
27
|
|
|
28
|
+
from fsspec.asyn import AsyncFileSystem
|
|
27
29
|
from pydantic_ai import UserContent
|
|
28
30
|
from toprompt import AnyPromptType
|
|
29
31
|
from upathtools import JoinablePathLike
|
|
@@ -48,7 +50,7 @@ class MessageHistory:
|
|
|
48
50
|
session_id: str
|
|
49
51
|
timestamp: datetime = field(default_factory=get_now)
|
|
50
52
|
|
|
51
|
-
history_cleared = Signal(
|
|
53
|
+
history_cleared = Signal[HistoryCleared]()
|
|
52
54
|
|
|
53
55
|
def __init__(
|
|
54
56
|
self,
|
|
@@ -94,6 +96,14 @@ class MessageHistory:
|
|
|
94
96
|
# Note: max_messages and max_tokens will be handled in add_message/get_history
|
|
95
97
|
# to maintain the rolling window during conversation
|
|
96
98
|
|
|
99
|
+
# Filesystem for message history
|
|
100
|
+
from fsspec.implementations.asyn_wrapper import AsyncFileSystemWrapper
|
|
101
|
+
from fsspec.implementations.memory import MemoryFileSystem
|
|
102
|
+
|
|
103
|
+
self._memory_fs = MemoryFileSystem()
|
|
104
|
+
self._fs = AsyncFileSystemWrapper(self._memory_fs)
|
|
105
|
+
self._fs_initialized = False
|
|
106
|
+
|
|
97
107
|
@property
|
|
98
108
|
def storage(self) -> StorageManager:
|
|
99
109
|
return self._storage
|
|
@@ -150,17 +160,20 @@ class MessageHistory:
|
|
|
150
160
|
self,
|
|
151
161
|
*,
|
|
152
162
|
max_tokens: int | None = None,
|
|
153
|
-
include_system: bool = False,
|
|
154
163
|
format_template: str | None = None,
|
|
155
|
-
num_messages: int | None = None,
|
|
164
|
+
num_messages: int | None = None,
|
|
156
165
|
) -> str:
|
|
157
166
|
"""Format conversation history as a single context message.
|
|
158
167
|
|
|
159
168
|
Args:
|
|
160
169
|
max_tokens: Optional limit to include only last N tokens
|
|
161
|
-
include_system: Whether to include system messages
|
|
162
170
|
format_template: Optional custom format (defaults to agent/message pairs)
|
|
163
171
|
num_messages: Optional limit to include only last N messages
|
|
172
|
+
|
|
173
|
+
Note:
|
|
174
|
+
System prompts are stored as metadata (ModelRequest.instructions),
|
|
175
|
+
not as separate messages with role="system". ChatMessage.role only
|
|
176
|
+
supports "user" and "assistant".
|
|
164
177
|
"""
|
|
165
178
|
template = format_template or "Agent {agent}: {content}\n"
|
|
166
179
|
messages: list[str] = []
|
|
@@ -323,14 +336,14 @@ class MessageHistory:
|
|
|
323
336
|
self.chat_messages.clear()
|
|
324
337
|
self.chat_messages.extend(history)
|
|
325
338
|
|
|
326
|
-
def clear(self) -> None:
|
|
339
|
+
async def clear(self) -> None:
|
|
327
340
|
"""Clear conversation history and prompts."""
|
|
328
341
|
from agentpool.messaging import ChatMessageList
|
|
329
342
|
|
|
330
343
|
self.chat_messages = ChatMessageList()
|
|
331
344
|
self._last_messages = []
|
|
332
345
|
event = self.HistoryCleared(session_id=str(self.id))
|
|
333
|
-
self.history_cleared.emit(event)
|
|
346
|
+
await self.history_cleared.emit(event)
|
|
334
347
|
|
|
335
348
|
@asynccontextmanager
|
|
336
349
|
async def temporary_state(
|
|
@@ -489,12 +502,78 @@ class MessageHistory:
|
|
|
489
502
|
return None
|
|
490
503
|
return self.chat_messages[-1].message_id
|
|
491
504
|
|
|
505
|
+
def _update_filesystem(self) -> None:
|
|
506
|
+
"""Update filesystem with current message history."""
|
|
507
|
+
# Clear existing files
|
|
508
|
+
self._memory_fs.store.clear()
|
|
509
|
+
self._memory_fs.pseudo_dirs.clear()
|
|
510
|
+
|
|
511
|
+
# Create directory structure
|
|
512
|
+
self._memory_fs.makedirs("messages", exist_ok=True)
|
|
513
|
+
self._memory_fs.makedirs("by_role", exist_ok=True)
|
|
514
|
+
|
|
515
|
+
for msg in self.chat_messages:
|
|
516
|
+
# Format: {timestamp}_{role}_{message_id}
|
|
517
|
+
timestamp = msg.timestamp.strftime("%Y%m%d_%H%M%S_%f")
|
|
518
|
+
base_name = f"{timestamp}_{msg.role}_{msg.message_id}"
|
|
519
|
+
|
|
520
|
+
# Write message content
|
|
521
|
+
content_path = f"messages/{base_name}.txt"
|
|
522
|
+
content = str(msg.content)
|
|
523
|
+
self._memory_fs.pipe(content_path, content.encode("utf-8"))
|
|
524
|
+
|
|
525
|
+
# Write metadata
|
|
526
|
+
metadata = {
|
|
527
|
+
"message_id": msg.message_id,
|
|
528
|
+
"role": msg.role,
|
|
529
|
+
"timestamp": msg.timestamp.isoformat(),
|
|
530
|
+
"parent_id": msg.parent_id,
|
|
531
|
+
"model_name": msg.model_name,
|
|
532
|
+
"tokens": msg.usage.total_tokens if msg.usage else None,
|
|
533
|
+
"cost": float(msg.cost_info.total_cost) if msg.cost_info else None,
|
|
534
|
+
}
|
|
535
|
+
metadata_path = f"messages/{base_name}.json"
|
|
536
|
+
self._memory_fs.pipe(metadata_path, json.dumps(metadata, indent=2).encode("utf-8"))
|
|
537
|
+
|
|
538
|
+
# Create role-based directory symlinks (by storing paths)
|
|
539
|
+
role_dir = f"by_role/{msg.role}"
|
|
540
|
+
self._memory_fs.makedirs(role_dir, exist_ok=True)
|
|
541
|
+
|
|
542
|
+
# Write summary
|
|
543
|
+
summary = {
|
|
544
|
+
"session_id": self.id,
|
|
545
|
+
"total_messages": len(self.chat_messages),
|
|
546
|
+
"total_tokens": self.get_history_tokens(),
|
|
547
|
+
"total_cost": self.chat_messages.get_total_cost(),
|
|
548
|
+
"roles": {
|
|
549
|
+
"user": len([m for m in self.chat_messages if m.role == "user"]),
|
|
550
|
+
"assistant": len([m for m in self.chat_messages if m.role == "assistant"]),
|
|
551
|
+
},
|
|
552
|
+
}
|
|
553
|
+
self._memory_fs.pipe("summary.json", json.dumps(summary, indent=2).encode("utf-8"))
|
|
554
|
+
|
|
555
|
+
self._fs_initialized = True
|
|
556
|
+
|
|
557
|
+
def get_fs(self) -> AsyncFileSystem:
|
|
558
|
+
"""Get filesystem view of message history.
|
|
559
|
+
|
|
560
|
+
Returns:
|
|
561
|
+
AsyncFileSystem containing:
|
|
562
|
+
- messages/{timestamp}_{role}_{message_id}.txt - Message content
|
|
563
|
+
- messages/{timestamp}_{role}_{message_id}.json - Message metadata
|
|
564
|
+
- by_role/{role}/ - Messages organized by role
|
|
565
|
+
- summary.json - Conversation statistics
|
|
566
|
+
"""
|
|
567
|
+
# Update filesystem on access
|
|
568
|
+
self._update_filesystem()
|
|
569
|
+
return self._fs
|
|
570
|
+
|
|
492
571
|
|
|
493
572
|
if __name__ == "__main__":
|
|
494
573
|
from agentpool import Agent
|
|
495
574
|
|
|
496
575
|
async def main() -> None:
|
|
497
|
-
async with Agent() as agent:
|
|
576
|
+
async with Agent(model="openai:gpt-5-nano") as agent:
|
|
498
577
|
await agent.conversation.add_context_from_path("E:/mcp_zed.yml")
|
|
499
578
|
print(agent.conversation.get_history())
|
|
500
579
|
|
|
@@ -5,9 +5,8 @@ from __future__ import annotations
|
|
|
5
5
|
from abc import ABC, abstractmethod
|
|
6
6
|
from collections.abc import Sequence
|
|
7
7
|
from typing import TYPE_CHECKING, Any, Literal, Self, overload
|
|
8
|
-
from uuid import uuid4
|
|
9
8
|
|
|
10
|
-
from
|
|
9
|
+
from anyenv.signals import Signal
|
|
11
10
|
|
|
12
11
|
from agentpool.log import get_logger
|
|
13
12
|
from agentpool.messaging import ChatMessage
|
|
@@ -20,8 +19,8 @@ if TYPE_CHECKING:
|
|
|
20
19
|
from datetime import timedelta
|
|
21
20
|
from types import TracebackType
|
|
22
21
|
|
|
23
|
-
from evented.configs import EventConfig
|
|
24
22
|
from evented.event_data import EventData
|
|
23
|
+
from evented_config import EventConfig
|
|
25
24
|
|
|
26
25
|
from agentpool.common_types import (
|
|
27
26
|
AnyTransformFn,
|
|
@@ -34,7 +33,7 @@ if TYPE_CHECKING:
|
|
|
34
33
|
from agentpool.storage import StorageManager
|
|
35
34
|
from agentpool.talk import Talk, TeamTalk
|
|
36
35
|
from agentpool.talk.stats import AggregatedMessageStats, MessageStats
|
|
37
|
-
from agentpool.tools.base import
|
|
36
|
+
from agentpool.tools.base import FunctionTool
|
|
38
37
|
from agentpool_config.forward_targets import ConnectionType
|
|
39
38
|
from agentpool_config.mcp_server import MCPServerConfig
|
|
40
39
|
|
|
@@ -45,10 +44,10 @@ logger = get_logger(__name__)
|
|
|
45
44
|
class MessageNode[TDeps, TResult](ABC):
|
|
46
45
|
"""Base class for all message processing nodes."""
|
|
47
46
|
|
|
48
|
-
message_received = Signal(
|
|
47
|
+
message_received = Signal[ChatMessage[Any]]()
|
|
49
48
|
"""Signal emitted when node receives a message."""
|
|
50
49
|
|
|
51
|
-
message_sent = Signal(
|
|
50
|
+
message_sent = Signal[ChatMessage[Any]]()
|
|
52
51
|
"""Signal emitted when node creates a message."""
|
|
53
52
|
|
|
54
53
|
def __init__(
|
|
@@ -86,18 +85,33 @@ class MessageNode[TDeps, TResult](ABC):
|
|
|
86
85
|
name_ = f"node_{self._name}"
|
|
87
86
|
self.mcp = MCPManager(name_, servers=mcp_servers, owner=self.name)
|
|
88
87
|
self.enable_db_logging = enable_logging
|
|
89
|
-
self.conversation_id =
|
|
90
|
-
|
|
91
|
-
# TODO: need to check this
|
|
92
|
-
# node.message_received.connect(self.log_message)
|
|
88
|
+
self.conversation_id: str | None = None
|
|
89
|
+
self.conversation_title: str | None = None
|
|
93
90
|
|
|
94
|
-
|
|
95
|
-
"""
|
|
96
|
-
|
|
91
|
+
def _set_conversation_title(self, title: str) -> None:
|
|
92
|
+
"""Callback for setting conversation title (called by storage manager)."""
|
|
93
|
+
self.conversation_title = title
|
|
94
|
+
|
|
95
|
+
async def log_conversation(self, initial_prompt: str | None = None) -> None:
|
|
96
|
+
"""Log conversation to storage if enabled.
|
|
97
|
+
|
|
98
|
+
Should be called at the start of run_stream() after conversation_id is set.
|
|
99
|
+
For native agents, generate conversation_id first with uuid4().
|
|
100
|
+
For wrapped agents (Claude Code), set conversation_id from SDK session first.
|
|
101
|
+
|
|
102
|
+
Args:
|
|
103
|
+
initial_prompt: Optional initial prompt to trigger title generation.
|
|
104
|
+
"""
|
|
105
|
+
if self.enable_db_logging and self.storage and self.conversation_id:
|
|
97
106
|
await self.storage.log_conversation(
|
|
98
107
|
conversation_id=self.conversation_id,
|
|
99
108
|
node_name=self.name,
|
|
109
|
+
initial_prompt=initial_prompt,
|
|
110
|
+
on_title_generated=self._set_conversation_title,
|
|
100
111
|
)
|
|
112
|
+
|
|
113
|
+
async def __aenter__(self) -> Self:
|
|
114
|
+
"""Initialize base message node."""
|
|
101
115
|
try:
|
|
102
116
|
await self._events.__aenter__()
|
|
103
117
|
await self.mcp.__aenter__()
|
|
@@ -161,7 +175,7 @@ class MessageNode[TDeps, TResult](ABC):
|
|
|
161
175
|
|
|
162
176
|
def to_tool(
|
|
163
177
|
self, *, name: str | None = None, description: str | None = None, **kwargs: Any
|
|
164
|
-
) ->
|
|
178
|
+
) -> FunctionTool[TResult]:
|
|
165
179
|
"""Convert node to a callable tool.
|
|
166
180
|
|
|
167
181
|
Args:
|
|
@@ -354,6 +368,30 @@ class MessageNode[TDeps, TResult](ABC):
|
|
|
354
368
|
async def run(self, *prompts: Any, **kwargs: Any) -> ChatMessage[TResult]:
|
|
355
369
|
"""Execute node with prompts. Implementation-specific run logic."""
|
|
356
370
|
|
|
371
|
+
async def run_message(
|
|
372
|
+
self,
|
|
373
|
+
message: ChatMessage[Any],
|
|
374
|
+
**kwargs: Any,
|
|
375
|
+
) -> ChatMessage[TResult]:
|
|
376
|
+
"""Run with an incoming ChatMessage (e.g., from Talk routing).
|
|
377
|
+
|
|
378
|
+
Extracts content from the message, preserves conversation_id,
|
|
379
|
+
and sets parent_id to track the message chain.
|
|
380
|
+
|
|
381
|
+
Args:
|
|
382
|
+
message: The incoming ChatMessage to process
|
|
383
|
+
**kwargs: Additional arguments passed to run()
|
|
384
|
+
|
|
385
|
+
Returns:
|
|
386
|
+
Response ChatMessage with message chain tracked via parent_id
|
|
387
|
+
"""
|
|
388
|
+
return await self.run(
|
|
389
|
+
message.content,
|
|
390
|
+
conversation_id=message.conversation_id,
|
|
391
|
+
parent_id=message.message_id,
|
|
392
|
+
**kwargs,
|
|
393
|
+
)
|
|
394
|
+
|
|
357
395
|
async def get_message_history(self, limit: int | None = None) -> list[ChatMessage[Any]]:
|
|
358
396
|
"""Get message history from storage."""
|
|
359
397
|
from agentpool_config.session import SessionQuery
|
agentpool/messaging/messages.py
CHANGED
|
@@ -72,9 +72,7 @@ Metadata:
|
|
|
72
72
|
{{ key }}: {{ value }}
|
|
73
73
|
{%- endfor %}
|
|
74
74
|
{%- endif %}
|
|
75
|
-
|
|
76
|
-
Forwarded via: {{ forwarded_from|join(' -> ') }}
|
|
77
|
-
{%- endif %}"""
|
|
75
|
+
"""
|
|
78
76
|
|
|
79
77
|
MARKDOWN_TEMPLATE = """## {{ name or role.title() }}
|
|
80
78
|
*{{ timestamp.strftime('%Y-%m-%d %H:%M:%S') }}*
|
|
@@ -98,10 +96,7 @@ MARKDOWN_TEMPLATE = """## {{ name or role.title() }}
|
|
|
98
96
|
```
|
|
99
97
|
{%- endif %}
|
|
100
98
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
*Forwarded via: {{ forwarded_from|join(' → ') }}*
|
|
104
|
-
{% endif %}"""
|
|
99
|
+
"""
|
|
105
100
|
|
|
106
101
|
MESSAGE_TEMPLATES = {
|
|
107
102
|
"simple": SIMPLE_TEMPLATE,
|
|
@@ -216,9 +211,6 @@ class ChatMessage[TContent]:
|
|
|
216
211
|
name: str | None = None
|
|
217
212
|
"""Display name for the message sender in UI."""
|
|
218
213
|
|
|
219
|
-
forwarded_from: list[str] = field(default_factory=list)
|
|
220
|
-
"""List of agent names (the chain) that forwarded this message to the sender."""
|
|
221
|
-
|
|
222
214
|
provider_details: dict[str, Any] = field(default_factory=dict)
|
|
223
215
|
"""Provider specific metadata / extra information."""
|
|
224
216
|
|
|
@@ -335,7 +327,6 @@ class ChatMessage[TContent]:
|
|
|
335
327
|
message: ModelMessage,
|
|
336
328
|
conversation_id: str | None = None,
|
|
337
329
|
name: str | None = None,
|
|
338
|
-
forwarded_from: list[str] | None = None,
|
|
339
330
|
parent_id: str | None = None,
|
|
340
331
|
) -> ChatMessage[TContentType]:
|
|
341
332
|
"""Convert a Pydantic model to a ChatMessage."""
|
|
@@ -346,8 +337,6 @@ class ChatMessage[TContent]:
|
|
|
346
337
|
content=content,
|
|
347
338
|
role="user",
|
|
348
339
|
message_id=run_id or str(uuid.uuid4()),
|
|
349
|
-
# instructions=instructions,
|
|
350
|
-
forwarded_from=forwarded_from or [],
|
|
351
340
|
name=name,
|
|
352
341
|
parent_id=parent_id,
|
|
353
342
|
)
|
|
@@ -375,7 +364,6 @@ class ChatMessage[TContent]:
|
|
|
375
364
|
finish_reason=finish_reason,
|
|
376
365
|
provider_response_id=provider_response_id,
|
|
377
366
|
name=name,
|
|
378
|
-
forwarded_from=forwarded_from or [],
|
|
379
367
|
parent_id=parent_id,
|
|
380
368
|
)
|
|
381
369
|
case _ as unreachable:
|
|
@@ -443,18 +431,6 @@ class ChatMessage[TContent]:
|
|
|
443
431
|
metadata=metadata or {},
|
|
444
432
|
)
|
|
445
433
|
|
|
446
|
-
def forwarded(self, previous_message: ChatMessage[Any]) -> Self:
|
|
447
|
-
"""Create new message showing it was forwarded from another message.
|
|
448
|
-
|
|
449
|
-
Args:
|
|
450
|
-
previous_message: The message that led to this one's creation
|
|
451
|
-
|
|
452
|
-
Returns:
|
|
453
|
-
New message with updated chain showing the path through previous message
|
|
454
|
-
"""
|
|
455
|
-
from_ = [*previous_message.forwarded_from, previous_message.name or "unknown"]
|
|
456
|
-
return replace(self, forwarded_from=from_)
|
|
457
|
-
|
|
458
434
|
@property
|
|
459
435
|
def response(self) -> ModelResponse:
|
|
460
436
|
"""Return the last response from the message history."""
|
|
@@ -17,34 +17,27 @@ if TYPE_CHECKING:
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
async def prepare_prompts(
|
|
20
|
-
*prompt: PromptCompatible
|
|
20
|
+
*prompt: PromptCompatible,
|
|
21
21
|
parent_id: str | None = None,
|
|
22
|
-
|
|
22
|
+
conversation_id: str | None = None,
|
|
23
|
+
) -> tuple[ChatMessage[Any], list[UserContent]]:
|
|
23
24
|
"""Prepare prompts for processing.
|
|
24
25
|
|
|
25
|
-
Extracted from MessageNode.pre_run logic.
|
|
26
|
-
|
|
27
26
|
Args:
|
|
28
27
|
*prompt: The prompt(s) to prepare.
|
|
29
28
|
parent_id: Optional ID of the parent message (typically the previous response).
|
|
29
|
+
conversation_id: Optional conversation ID for the user message.
|
|
30
30
|
|
|
31
31
|
Returns:
|
|
32
32
|
A tuple of:
|
|
33
|
-
-
|
|
34
|
-
on the prompt(s).
|
|
33
|
+
- A ChatMessage representing the user prompt.
|
|
35
34
|
- A list of prompts to be sent to the model.
|
|
36
|
-
- The original ChatMessage if forwarded, None otherwise
|
|
37
35
|
"""
|
|
38
|
-
if len(prompt) == 1 and isinstance(prompt[0], ChatMessage):
|
|
39
|
-
original_msg = prompt[0]
|
|
40
|
-
# Update received message's chain to show it came through its source
|
|
41
|
-
user_msg = original_msg.forwarded(original_msg).to_request()
|
|
42
|
-
prompts = await convert_prompts([user_msg.content])
|
|
43
|
-
# clear cost info to avoid double-counting
|
|
44
|
-
return user_msg, prompts, original_msg
|
|
45
36
|
prompts = await convert_prompts(prompt)
|
|
46
|
-
user_msg = ChatMessage.user_prompt(
|
|
47
|
-
|
|
37
|
+
user_msg = ChatMessage.user_prompt(
|
|
38
|
+
message=prompts, parent_id=parent_id, conversation_id=conversation_id
|
|
39
|
+
)
|
|
40
|
+
return user_msg, prompts
|
|
48
41
|
|
|
49
42
|
|
|
50
43
|
async def finalize_message(
|
|
@@ -52,7 +45,6 @@ async def finalize_message(
|
|
|
52
45
|
previous_message: ChatMessage[Any] | None,
|
|
53
46
|
node: MessageNode[Any, Any],
|
|
54
47
|
connections: ConnectionManager,
|
|
55
|
-
original_message: ChatMessage[Any] | None,
|
|
56
48
|
wait_for_connections: bool | None = None,
|
|
57
49
|
) -> ChatMessage[Any]:
|
|
58
50
|
"""Handle message finalization and routing.
|
|
@@ -62,16 +54,12 @@ async def finalize_message(
|
|
|
62
54
|
previous_message: The original user message (if any)
|
|
63
55
|
node: The message node that produced the message
|
|
64
56
|
connections: Connection manager for routing
|
|
65
|
-
original_message: The original ChatMessage if forwarded, None otherwise
|
|
66
57
|
wait_for_connections: Whether to wait for connected nodes
|
|
67
58
|
|
|
68
59
|
Returns:
|
|
69
60
|
The finalized message
|
|
70
61
|
"""
|
|
71
|
-
#
|
|
72
|
-
if original_message:
|
|
73
|
-
message = message.forwarded(original_message)
|
|
74
|
-
node.message_sent.emit(message) # Emit signals
|
|
62
|
+
await node.message_sent.emit(message) # Emit signals
|
|
75
63
|
await node.log_message(message) # Log message if enabled
|
|
76
64
|
# Route to connections
|
|
77
65
|
await connections.route_message(message, wait=wait_for_connections)
|
agentpool/models/__init__.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
from agentpool.models.acp_agents import ACPAgentConfig, ACPAgentConfigTypes, BaseACPAgentConfig
|
|
6
|
-
from agentpool.models.agents import NativeAgentConfig
|
|
6
|
+
from agentpool.models.agents import AnyToolConfig, NativeAgentConfig # noqa: F401
|
|
7
7
|
from agentpool.models.agui_agents import AGUIAgentConfig
|
|
8
8
|
from agentpool.models.claude_code_agents import ClaudeCodeAgentConfig
|
|
9
9
|
from agentpool.models.manifest import AgentsManifest, AnyAgentConfig
|
|
@@ -7,10 +7,10 @@ import os
|
|
|
7
7
|
import tempfile
|
|
8
8
|
from typing import TYPE_CHECKING, Annotated, Any, Literal
|
|
9
9
|
|
|
10
|
-
from
|
|
11
|
-
from exxec.configs import (
|
|
10
|
+
from exxec_config import (
|
|
12
11
|
E2bExecutionEnvironmentConfig,
|
|
13
12
|
ExecutionEnvironmentConfig, # noqa: TC002
|
|
13
|
+
ExecutionEnvironmentStr, # noqa: TC002
|
|
14
14
|
)
|
|
15
15
|
from pydantic import ConfigDict, Field
|
|
16
16
|
|
|
@@ -223,6 +223,8 @@ class BaseACPAgentConfig(NodeConfig):
|
|
|
223
223
|
|
|
224
224
|
def get_execution_environment(self) -> ExecutionEnvironment:
|
|
225
225
|
"""Create execution environment from config."""
|
|
226
|
+
from exxec import get_environment
|
|
227
|
+
|
|
226
228
|
if isinstance(self.execution_environment, str):
|
|
227
229
|
return get_environment(self.execution_environment)
|
|
228
230
|
return self.execution_environment.get_provider()
|
|
@@ -232,6 +234,8 @@ class BaseACPAgentConfig(NodeConfig):
|
|
|
232
234
|
|
|
233
235
|
Returns None if not configured (caller should fall back to main env).
|
|
234
236
|
"""
|
|
237
|
+
from exxec import get_environment
|
|
238
|
+
|
|
235
239
|
if self.client_execution_environment is None:
|
|
236
240
|
return None
|
|
237
241
|
if isinstance(self.client_execution_environment, str):
|
|
@@ -9,12 +9,14 @@ import anyenv
|
|
|
9
9
|
from pydantic import BaseModel, ConfigDict, Field
|
|
10
10
|
|
|
11
11
|
from agentpool.models.acp_agents.base import BaseACPAgentConfig
|
|
12
|
+
from agentpool_config import AnyToolConfig, BaseToolConfig # noqa: TC001
|
|
12
13
|
from agentpool_config.output_types import StructuredResponseConfig # noqa: TC001
|
|
13
|
-
from agentpool_config.toolsets import
|
|
14
|
+
from agentpool_config.toolsets import BaseToolsetConfig
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
if TYPE_CHECKING:
|
|
17
18
|
from agentpool.prompts.manager import PromptManager
|
|
19
|
+
from agentpool.resource_providers import ResourceProvider
|
|
18
20
|
|
|
19
21
|
|
|
20
22
|
ClaudeCodeModelName = Literal["default", "sonnet", "opus", "haiku", "sonnet[1m]", "opusplan"]
|
|
@@ -23,6 +25,7 @@ ClaudeCodeToolName = Literal[
|
|
|
23
25
|
"Bash",
|
|
24
26
|
"BashOutput",
|
|
25
27
|
"Edit",
|
|
28
|
+
"EnterPlanMode",
|
|
26
29
|
"ExitPlanMode",
|
|
27
30
|
"Glob",
|
|
28
31
|
"Grep",
|
|
@@ -47,23 +50,51 @@ class MCPCapableACPAgentConfig(BaseACPAgentConfig):
|
|
|
47
50
|
that can be exposed via an internal MCP bridge.
|
|
48
51
|
"""
|
|
49
52
|
|
|
50
|
-
|
|
53
|
+
tools: list[AnyToolConfig | str] = Field(
|
|
51
54
|
default_factory=list,
|
|
52
|
-
title="
|
|
55
|
+
title="Tools",
|
|
53
56
|
examples=[
|
|
54
57
|
[
|
|
55
58
|
{"type": "subagent"},
|
|
56
59
|
{"type": "agent_management"},
|
|
60
|
+
"webbrowser:open",
|
|
57
61
|
],
|
|
58
62
|
],
|
|
59
63
|
)
|
|
60
|
-
"""
|
|
64
|
+
"""Tools and toolsets to expose to this ACP agent via MCP bridge.
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
available to the external ACP agent.
|
|
64
|
-
internal agentpool toolsets like subagent delegation.
|
|
66
|
+
Supports both single tools and toolsets. These will be started as an
|
|
67
|
+
in-process MCP server and made available to the external ACP agent.
|
|
65
68
|
"""
|
|
66
69
|
|
|
70
|
+
def get_tool_providers(self) -> list[ResourceProvider]:
|
|
71
|
+
"""Get all resource providers for this agent's tools.
|
|
72
|
+
|
|
73
|
+
Returns:
|
|
74
|
+
List of ResourceProvider instances
|
|
75
|
+
"""
|
|
76
|
+
from agentpool.resource_providers import StaticResourceProvider
|
|
77
|
+
from agentpool.tools.base import Tool
|
|
78
|
+
|
|
79
|
+
providers: list[ResourceProvider] = []
|
|
80
|
+
static_tools: list[Tool] = []
|
|
81
|
+
|
|
82
|
+
for tool_config in self.tools:
|
|
83
|
+
try:
|
|
84
|
+
if isinstance(tool_config, BaseToolsetConfig):
|
|
85
|
+
providers.append(tool_config.get_provider())
|
|
86
|
+
elif isinstance(tool_config, str):
|
|
87
|
+
static_tools.append(Tool.from_callable(tool_config))
|
|
88
|
+
elif isinstance(tool_config, BaseToolConfig):
|
|
89
|
+
static_tools.append(tool_config.get_tool())
|
|
90
|
+
except Exception: # noqa: BLE001
|
|
91
|
+
continue
|
|
92
|
+
|
|
93
|
+
if static_tools:
|
|
94
|
+
providers.append(StaticResourceProvider(name="tools", tools=static_tools))
|
|
95
|
+
|
|
96
|
+
return providers
|
|
97
|
+
|
|
67
98
|
def build_mcp_config_json(self) -> str | None:
|
|
68
99
|
"""Convert inherited mcp_servers to standard MCP config JSON format.
|
|
69
100
|
|
|
@@ -197,12 +228,12 @@ class ClaudeACPAgentConfig(MCPCapableACPAgentConfig):
|
|
|
197
228
|
)
|
|
198
229
|
"""Additional directories to allow tool access to."""
|
|
199
230
|
|
|
200
|
-
|
|
231
|
+
builtin_tools: list[ClaudeCodeToolName | str] | None = Field(
|
|
201
232
|
default=None,
|
|
202
|
-
title="Tools",
|
|
233
|
+
title="Built-in Tools",
|
|
203
234
|
examples=[["Bash", "Edit", "Read"], []],
|
|
204
235
|
)
|
|
205
|
-
"""Available tools from built-in set. Empty list disables all tools."""
|
|
236
|
+
"""Available tools from Claude's built-in set. Empty list disables all tools."""
|
|
206
237
|
|
|
207
238
|
fallback_model: ClaudeCodeModelName | None = Field(
|
|
208
239
|
default=None,
|
|
@@ -260,9 +291,9 @@ class ClaudeACPAgentConfig(MCPCapableACPAgentConfig):
|
|
|
260
291
|
args.append("--strict-mcp-config")
|
|
261
292
|
if self.add_dir:
|
|
262
293
|
args.extend(["--add-dir", *self.add_dir])
|
|
263
|
-
if self.
|
|
264
|
-
if self.
|
|
265
|
-
args.extend(["--tools", ",".join(self.
|
|
294
|
+
if self.builtin_tools is not None:
|
|
295
|
+
if self.builtin_tools:
|
|
296
|
+
args.extend(["--tools", ",".join(self.builtin_tools)])
|
|
266
297
|
else:
|
|
267
298
|
args.extend(["--tools", ""])
|
|
268
299
|
if self.fallback_model:
|
|
@@ -307,7 +338,7 @@ class FastAgentACPAgentConfig(MCPCapableACPAgentConfig):
|
|
|
307
338
|
provider: fast-agent
|
|
308
339
|
cwd: /path/to/project
|
|
309
340
|
model: claude-3.5-sonnet-20241022
|
|
310
|
-
|
|
341
|
+
tools:
|
|
311
342
|
- type: subagent
|
|
312
343
|
- type: agent_management
|
|
313
344
|
skills_dir: ./my-skills
|
|
@@ -644,7 +675,85 @@ class KimiACPAgentConfig(MCPCapableACPAgentConfig):
|
|
|
644
675
|
return args
|
|
645
676
|
|
|
646
677
|
|
|
678
|
+
class AgentpoolACPAgentConfig(MCPCapableACPAgentConfig):
|
|
679
|
+
"""Configuration for agentpool's own ACP server.
|
|
680
|
+
|
|
681
|
+
This allows using agentpool serve-acp as an ACP agent, with MCP bridge support
|
|
682
|
+
for tool metadata preservation.
|
|
683
|
+
|
|
684
|
+
Example:
|
|
685
|
+
```yaml
|
|
686
|
+
acp_agents:
|
|
687
|
+
my_agentpool:
|
|
688
|
+
type: agentpool
|
|
689
|
+
config_path: path/to/agent_config.yml
|
|
690
|
+
agent: agent_name # Optional: specific agent to use
|
|
691
|
+
mcp_servers:
|
|
692
|
+
- type: stdio
|
|
693
|
+
command: mcp-server-filesystem
|
|
694
|
+
args: ["--root", "/workspace"]
|
|
695
|
+
```
|
|
696
|
+
"""
|
|
697
|
+
|
|
698
|
+
model_config = ConfigDict(title="Agentpool ACP Agent")
|
|
699
|
+
|
|
700
|
+
provider: Literal["agentpool"] = Field("agentpool", init=False)
|
|
701
|
+
"""Discriminator for agentpool ACP agent."""
|
|
702
|
+
|
|
703
|
+
config_path: str | None = None
|
|
704
|
+
"""Path to agentpool configuration file (optional)."""
|
|
705
|
+
|
|
706
|
+
agent: str | None = None
|
|
707
|
+
"""Specific agent name to use from config (defaults to first agent)."""
|
|
708
|
+
|
|
709
|
+
file_access: bool = True
|
|
710
|
+
"""Enable file system access for the agent."""
|
|
711
|
+
|
|
712
|
+
terminal_access: bool = True
|
|
713
|
+
"""Enable terminal access for the agent."""
|
|
714
|
+
|
|
715
|
+
load_skills: bool = True
|
|
716
|
+
"""Load client-side skills from .claude/skills directory."""
|
|
717
|
+
|
|
718
|
+
def get_command(self) -> str:
|
|
719
|
+
"""Get the command to run agentpool serve-acp."""
|
|
720
|
+
return "agentpool"
|
|
721
|
+
|
|
722
|
+
async def get_args(self, prompt_manager: PromptManager | None = None) -> list[str]:
|
|
723
|
+
"""Build command arguments for agentpool serve-acp."""
|
|
724
|
+
args = ["serve-acp"]
|
|
725
|
+
|
|
726
|
+
# Add config path if specified
|
|
727
|
+
if self.config_path:
|
|
728
|
+
args.append(self.config_path)
|
|
729
|
+
|
|
730
|
+
# Add agent selection
|
|
731
|
+
if self.agent:
|
|
732
|
+
args.extend(["--agent", self.agent])
|
|
733
|
+
|
|
734
|
+
# Add file/terminal access flags
|
|
735
|
+
if not self.file_access:
|
|
736
|
+
args.append("--no-file-access")
|
|
737
|
+
if not self.terminal_access:
|
|
738
|
+
args.append("--no-terminal-access")
|
|
739
|
+
|
|
740
|
+
# Add skills flag
|
|
741
|
+
if not self.load_skills:
|
|
742
|
+
args.append("--no-skills")
|
|
743
|
+
|
|
744
|
+
# Convert inherited mcp_servers to --mcp-config format
|
|
745
|
+
mcp_json = self.build_mcp_config_json()
|
|
746
|
+
if mcp_json:
|
|
747
|
+
args.extend(["--mcp-config", mcp_json])
|
|
748
|
+
|
|
749
|
+
return args
|
|
750
|
+
|
|
751
|
+
|
|
647
752
|
# Union of all ACP agent config types
|
|
648
753
|
MCPCapableACPAgentConfigTypes = (
|
|
649
|
-
ClaudeACPAgentConfig
|
|
754
|
+
ClaudeACPAgentConfig
|
|
755
|
+
| FastAgentACPAgentConfig
|
|
756
|
+
| AuggieACPAgentConfig
|
|
757
|
+
| KimiACPAgentConfig
|
|
758
|
+
| AgentpoolACPAgentConfig
|
|
650
759
|
)
|