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
|
@@ -2,8 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
|
|
5
|
+
from pydantic_ai import ModelRequest, ModelResponse # noqa: TC002
|
|
7
6
|
from slashed import CommandContext # noqa: TC002
|
|
8
7
|
|
|
9
8
|
from agentpool.messaging.context import NodeContext # noqa: TC001
|
|
@@ -12,32 +11,29 @@ from agentpool_config.session import SessionQuery
|
|
|
12
11
|
from agentpool_server.acp_server.session import ACPSession # noqa: TC001
|
|
13
12
|
|
|
14
13
|
|
|
15
|
-
if TYPE_CHECKING:
|
|
16
|
-
from pydantic_ai import ModelRequest, ModelResponse
|
|
17
|
-
|
|
18
|
-
|
|
19
14
|
class ListSessionsCommand(NodeCommand):
|
|
20
15
|
"""List all available ACP sessions.
|
|
21
16
|
|
|
22
|
-
Shows:
|
|
23
|
-
- Session ID and status (active/stored)
|
|
24
|
-
- Agent name and working directory
|
|
25
|
-
- Creation time and last activity
|
|
26
|
-
|
|
27
17
|
Options:
|
|
28
18
|
--active Show only active sessions
|
|
29
19
|
--stored Show only stored sessions
|
|
20
|
+
--detail Show detailed view (default: compact table)
|
|
21
|
+
--page Page number (1-based, default: 1)
|
|
22
|
+
--per-page Items per page (default: 20)
|
|
30
23
|
"""
|
|
31
24
|
|
|
32
25
|
name = "list-sessions"
|
|
33
26
|
category = "acp"
|
|
34
27
|
|
|
35
|
-
async def execute_command(
|
|
28
|
+
async def execute_command( # noqa: PLR0915
|
|
36
29
|
self,
|
|
37
30
|
ctx: CommandContext[NodeContext[ACPSession]],
|
|
38
31
|
*,
|
|
39
32
|
active: bool = False,
|
|
40
33
|
stored: bool = False,
|
|
34
|
+
detail: bool = False,
|
|
35
|
+
page: int = 1,
|
|
36
|
+
per_page: int = 20,
|
|
41
37
|
) -> None:
|
|
42
38
|
"""List available ACP sessions.
|
|
43
39
|
|
|
@@ -45,6 +41,9 @@ class ListSessionsCommand(NodeCommand):
|
|
|
45
41
|
ctx: Command context with ACP session
|
|
46
42
|
active: Show only active sessions
|
|
47
43
|
stored: Show only stored sessions
|
|
44
|
+
detail: Show detailed view instead of compact table
|
|
45
|
+
page: Page number (1-based)
|
|
46
|
+
per_page: Number of items per page
|
|
48
47
|
"""
|
|
49
48
|
session = ctx.context.data
|
|
50
49
|
if not session:
|
|
@@ -54,6 +53,11 @@ class ListSessionsCommand(NodeCommand):
|
|
|
54
53
|
await ctx.output.print("❌ **Session manager not available**")
|
|
55
54
|
return
|
|
56
55
|
|
|
56
|
+
# Validate pagination params
|
|
57
|
+
page = max(page, 1)
|
|
58
|
+
if per_page < 1:
|
|
59
|
+
per_page = 20
|
|
60
|
+
|
|
57
61
|
# If no filter specified, show both
|
|
58
62
|
if not active and not stored:
|
|
59
63
|
active = stored = True
|
|
@@ -61,63 +65,146 @@ class ListSessionsCommand(NodeCommand):
|
|
|
61
65
|
try:
|
|
62
66
|
output_lines = ["## 📋 ACP Sessions\n"]
|
|
63
67
|
|
|
64
|
-
#
|
|
68
|
+
# Collect all sessions to paginate
|
|
69
|
+
# (id, type, info) where info includes conversation_id for message counting
|
|
70
|
+
all_sessions: list[tuple[str, str, dict[str, str | None]]] = []
|
|
71
|
+
|
|
72
|
+
# Collect active sessions
|
|
65
73
|
if active:
|
|
66
|
-
output_lines.append("### 🟢 Active Sessions")
|
|
67
74
|
active_sessions = session.manager._active
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
output_lines.append(f" - Directory: `{cwd}`")
|
|
86
|
-
output_lines.append("")
|
|
87
|
-
|
|
88
|
-
# Show stored sessions
|
|
75
|
+
for session_id, sess in active_sessions.items():
|
|
76
|
+
session_data = await session.manager.session_manager.store.load(session_id)
|
|
77
|
+
conv_id = session_data.conversation_id if session_data else None
|
|
78
|
+
is_current = session_id == session.session_id
|
|
79
|
+
all_sessions.append((
|
|
80
|
+
session_id,
|
|
81
|
+
"active",
|
|
82
|
+
{
|
|
83
|
+
"agent_name": sess.current_agent_name,
|
|
84
|
+
"cwd": sess.cwd or "unknown",
|
|
85
|
+
"conversation_id": conv_id,
|
|
86
|
+
"is_current": "yes" if is_current else None,
|
|
87
|
+
"last_active": None,
|
|
88
|
+
},
|
|
89
|
+
))
|
|
90
|
+
|
|
91
|
+
# Collect stored sessions
|
|
89
92
|
if stored:
|
|
90
|
-
output_lines.append("### 💾 Stored Sessions")
|
|
91
|
-
|
|
92
93
|
try:
|
|
93
94
|
stored_session_ids = await session.manager.session_manager.store.list_sessions()
|
|
94
|
-
# Filter out active ones if we already
|
|
95
|
+
# Filter out active ones if we already collected them
|
|
95
96
|
if active:
|
|
96
97
|
stored_session_ids = [
|
|
97
98
|
sid for sid in stored_session_ids if sid not in session.manager._active
|
|
98
99
|
]
|
|
99
100
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
)
|
|
117
|
-
output_lines.append("")
|
|
101
|
+
for session_id in stored_session_ids:
|
|
102
|
+
session_data = await session.manager.session_manager.store.load(session_id)
|
|
103
|
+
if session_data:
|
|
104
|
+
all_sessions.append((
|
|
105
|
+
session_id,
|
|
106
|
+
"stored",
|
|
107
|
+
{
|
|
108
|
+
"agent_name": session_data.agent_name,
|
|
109
|
+
"cwd": session_data.cwd or "unknown",
|
|
110
|
+
"conversation_id": session_data.conversation_id,
|
|
111
|
+
"is_current": None,
|
|
112
|
+
"last_active": session_data.last_active.strftime(
|
|
113
|
+
"%Y-%m-%d %H:%M"
|
|
114
|
+
),
|
|
115
|
+
},
|
|
116
|
+
))
|
|
118
117
|
except Exception as e: # noqa: BLE001
|
|
119
118
|
output_lines.append(f"*Error loading stored sessions: {e}*\n")
|
|
120
119
|
|
|
120
|
+
# Get message counts and titles from storage
|
|
121
|
+
all_conv_ids = [
|
|
122
|
+
conv_id for _, _, info in all_sessions if (conv_id := info.get("conversation_id"))
|
|
123
|
+
]
|
|
124
|
+
storage = session.agent_pool.storage
|
|
125
|
+
msg_counts = await storage.get_message_counts(all_conv_ids) if storage else {}
|
|
126
|
+
titles = await storage.get_conversation_titles(all_conv_ids) if storage else {}
|
|
127
|
+
|
|
128
|
+
# Add titles to session info
|
|
129
|
+
for _, _, info in all_sessions:
|
|
130
|
+
if conv_id := info.get("conversation_id"):
|
|
131
|
+
info["title"] = titles.get(conv_id)
|
|
132
|
+
|
|
133
|
+
# Filter out sessions with 0 messages (unless showing detail view)
|
|
134
|
+
if not detail:
|
|
135
|
+
all_sessions = [
|
|
136
|
+
(sid, stype, info)
|
|
137
|
+
for sid, stype, info in all_sessions
|
|
138
|
+
if msg_counts.get(info.get("conversation_id") or "", 0) > 0
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
# Calculate pagination AFTER filtering
|
|
142
|
+
total_count = len(all_sessions)
|
|
143
|
+
total_pages = (total_count + per_page - 1) // per_page if total_count > 0 else 1
|
|
144
|
+
page = min(page, total_pages)
|
|
145
|
+
|
|
146
|
+
start_idx = (page - 1) * per_page
|
|
147
|
+
end_idx = start_idx + per_page
|
|
148
|
+
page_sessions = all_sessions[start_idx:end_idx]
|
|
149
|
+
|
|
150
|
+
if not page_sessions:
|
|
151
|
+
output_lines.append("*No sessions found*\n")
|
|
152
|
+
elif detail:
|
|
153
|
+
# Detailed view (original format)
|
|
154
|
+
active_in_page = [(s, i) for s, t, i in page_sessions if t == "active"]
|
|
155
|
+
stored_in_page = [(s, i) for s, t, i in page_sessions if t == "stored"]
|
|
156
|
+
|
|
157
|
+
if active_in_page:
|
|
158
|
+
output_lines.append("### 🟢 Active Sessions")
|
|
159
|
+
for session_id, info in active_in_page:
|
|
160
|
+
status = " *(current)*" if info["is_current"] else ""
|
|
161
|
+
title_text = f": {info['title']}" if info["title"] else ""
|
|
162
|
+
output_lines.append(f"- **{session_id}**{status}{title_text}")
|
|
163
|
+
output_lines.append(f" - Agent: `{info['agent_name']}`")
|
|
164
|
+
output_lines.append(f" - Directory: `{info['cwd']}`")
|
|
165
|
+
output_lines.append("")
|
|
166
|
+
|
|
167
|
+
if stored_in_page:
|
|
168
|
+
output_lines.append("### 💾 Stored Sessions")
|
|
169
|
+
for session_id, info in stored_in_page:
|
|
170
|
+
title_text = f": {info['title']}" if info["title"] else ""
|
|
171
|
+
output_lines.append(f"- **{session_id}**{title_text}")
|
|
172
|
+
output_lines.append(f" - Agent: `{info['agent_name']}`")
|
|
173
|
+
output_lines.append(f" - Directory: `{info['cwd']}`")
|
|
174
|
+
if info["last_active"]:
|
|
175
|
+
output_lines.append(f" - Last active: {info['last_active']}")
|
|
176
|
+
output_lines.append("")
|
|
177
|
+
else:
|
|
178
|
+
# Compact table view (default)
|
|
179
|
+
# Table with multi-line session cell (title + ID using <br>)
|
|
180
|
+
output_lines.append("| Session | Agent | Msgs | Last Active |")
|
|
181
|
+
output_lines.append("|---------|-------|------|-------------|")
|
|
182
|
+
for session_id, _session_type, info in page_sessions:
|
|
183
|
+
title = info["title"] or "(untitled)"
|
|
184
|
+
if info["is_current"]:
|
|
185
|
+
title = f"▶️ {title}"
|
|
186
|
+
agent = info["agent_name"]
|
|
187
|
+
conv_id = info.get("conversation_id") or ""
|
|
188
|
+
msg_count = msg_counts.get(conv_id, 0)
|
|
189
|
+
last_active = info["last_active"] or "-"
|
|
190
|
+
# Two lines in session cell: title and ID
|
|
191
|
+
session_cell = f"{title} `{session_id}`"
|
|
192
|
+
output_lines.append(
|
|
193
|
+
f"| {session_cell} | {agent} | {msg_count} | {last_active} |"
|
|
194
|
+
)
|
|
195
|
+
output_lines.append("")
|
|
196
|
+
|
|
197
|
+
# Add pagination info
|
|
198
|
+
output_lines.append(f"---\n*Page {page}/{total_pages} ({total_count} total sessions)*")
|
|
199
|
+
if total_pages > 1:
|
|
200
|
+
nav_hints = []
|
|
201
|
+
if page > 1:
|
|
202
|
+
nav_hints.append(f"`/list-sessions --page {page - 1}` for previous")
|
|
203
|
+
if page < total_pages:
|
|
204
|
+
nav_hints.append(f"`/list-sessions --page {page + 1}` for next")
|
|
205
|
+
if nav_hints:
|
|
206
|
+
output_lines.append(f"*{', '.join(nav_hints)}*")
|
|
207
|
+
|
|
121
208
|
await ctx.output.print("\n".join(output_lines))
|
|
122
209
|
|
|
123
210
|
except Exception as e: # noqa: BLE001
|
|
@@ -127,11 +214,6 @@ class ListSessionsCommand(NodeCommand):
|
|
|
127
214
|
class LoadSessionCommand(NodeCommand):
|
|
128
215
|
"""Load a previous ACP session with conversation replay.
|
|
129
216
|
|
|
130
|
-
This command will:
|
|
131
|
-
1. Look up the session by ID
|
|
132
|
-
2. Replay the conversation history via ACP notifications
|
|
133
|
-
3. Restore the session context (agent, working directory)
|
|
134
|
-
|
|
135
217
|
Options:
|
|
136
218
|
--preview Show session info without loading
|
|
137
219
|
--no-replay Load session without replaying conversation
|
|
@@ -190,8 +272,14 @@ class LoadSessionCommand(NodeCommand):
|
|
|
190
272
|
f"## 📋 Session Preview: `{session_id}`\n",
|
|
191
273
|
]
|
|
192
274
|
|
|
193
|
-
|
|
194
|
-
|
|
275
|
+
# Fetch title from storage
|
|
276
|
+
title = (
|
|
277
|
+
await storage.get_conversation_title(session_data.conversation_id)
|
|
278
|
+
if storage
|
|
279
|
+
else None
|
|
280
|
+
)
|
|
281
|
+
if title:
|
|
282
|
+
preview_lines.append(f"**Title:** {title}")
|
|
195
283
|
|
|
196
284
|
preview_lines.extend([
|
|
197
285
|
f"**Agent:** `{session_data.agent_name}`",
|
|
@@ -265,11 +353,6 @@ class LoadSessionCommand(NodeCommand):
|
|
|
265
353
|
class SaveSessionCommand(NodeCommand):
|
|
266
354
|
"""Save the current ACP session to persistent storage.
|
|
267
355
|
|
|
268
|
-
This will save:
|
|
269
|
-
- Current agent configuration
|
|
270
|
-
- Working directory
|
|
271
|
-
- Session metadata
|
|
272
|
-
|
|
273
356
|
Note: Conversation history is automatically saved if storage is enabled.
|
|
274
357
|
|
|
275
358
|
Options:
|
|
@@ -403,96 +486,9 @@ class DeleteSessionCommand(NodeCommand):
|
|
|
403
486
|
await ctx.output.print(f"❌ **Error deleting session:** {e}")
|
|
404
487
|
|
|
405
488
|
|
|
406
|
-
class ListPoolsCommand(NodeCommand):
|
|
407
|
-
"""List available agent pool configurations.
|
|
408
|
-
|
|
409
|
-
Shows:
|
|
410
|
-
- Stored configurations from ConfigStore (name -> path mapping)
|
|
411
|
-
- Currently active pool configuration
|
|
412
|
-
- Available agents in the current pool
|
|
413
|
-
|
|
414
|
-
Examples:
|
|
415
|
-
/list-pools
|
|
416
|
-
"""
|
|
417
|
-
|
|
418
|
-
name = "list-pools"
|
|
419
|
-
category = "acp"
|
|
420
|
-
|
|
421
|
-
async def execute_command(
|
|
422
|
-
self,
|
|
423
|
-
ctx: CommandContext[NodeContext[ACPSession]],
|
|
424
|
-
) -> None:
|
|
425
|
-
"""List available pool configurations.
|
|
426
|
-
|
|
427
|
-
Args:
|
|
428
|
-
ctx: Command context with ACP session
|
|
429
|
-
"""
|
|
430
|
-
from agentpool_cli import agent_store
|
|
431
|
-
|
|
432
|
-
session = ctx.context.data
|
|
433
|
-
if not session:
|
|
434
|
-
raise RuntimeError("Session not available in command context")
|
|
435
|
-
|
|
436
|
-
try:
|
|
437
|
-
output_lines = ["## 🏊 Agent Pool Configurations\n"]
|
|
438
|
-
|
|
439
|
-
# Show current pool info
|
|
440
|
-
output_lines.append("### 📍 Current Pool")
|
|
441
|
-
current_config = (
|
|
442
|
-
session.acp_agent.server.config_path if session.acp_agent.server else None
|
|
443
|
-
)
|
|
444
|
-
if current_config:
|
|
445
|
-
output_lines.append(f"**Config:** `{current_config}`")
|
|
446
|
-
else:
|
|
447
|
-
output_lines.append("**Config:** *(default/built-in)*")
|
|
448
|
-
|
|
449
|
-
# Show agents in current pool
|
|
450
|
-
agent_names = list(session.agent_pool.all_agents.keys())
|
|
451
|
-
output_lines.append(f"**Agents:** {', '.join(f'`{n}`' for n in agent_names)}")
|
|
452
|
-
output_lines.append(f"**Active agent:** `{session.current_agent_name}`")
|
|
453
|
-
output_lines.append("")
|
|
454
|
-
|
|
455
|
-
# Show stored configurations
|
|
456
|
-
output_lines.append("### 💾 Stored Configurations")
|
|
457
|
-
stored_configs = agent_store.list_configs()
|
|
458
|
-
active_config = agent_store.get_active()
|
|
459
|
-
|
|
460
|
-
if not stored_configs:
|
|
461
|
-
output_lines.append("*No stored configurations*")
|
|
462
|
-
output_lines.append("")
|
|
463
|
-
output_lines.append("Use `agentpool add <name> <path>` to add configurations.")
|
|
464
|
-
else:
|
|
465
|
-
# Build markdown table
|
|
466
|
-
output_lines.append("| Name | Path |")
|
|
467
|
-
output_lines.append("|------|------|")
|
|
468
|
-
for name, path in stored_configs:
|
|
469
|
-
is_active = active_config and active_config.name == name
|
|
470
|
-
is_current = current_config and path == current_config
|
|
471
|
-
markers = []
|
|
472
|
-
if is_active:
|
|
473
|
-
markers.append("default")
|
|
474
|
-
if is_current:
|
|
475
|
-
markers.append("current")
|
|
476
|
-
name_col = f"{name} ({', '.join(markers)})" if markers else name
|
|
477
|
-
output_lines.append(f"| {name_col} | `{path}` |")
|
|
478
|
-
|
|
479
|
-
output_lines.append("")
|
|
480
|
-
output_lines.append("*Use `/set-pool <name>` or `/set-pool <path>` to switch pools.*")
|
|
481
|
-
|
|
482
|
-
await ctx.output.print("\n".join(output_lines))
|
|
483
|
-
|
|
484
|
-
except Exception as e: # noqa: BLE001
|
|
485
|
-
await ctx.output.print(f"❌ **Error listing pools:** {e}")
|
|
486
|
-
|
|
487
|
-
|
|
488
489
|
class SetPoolCommand(NodeCommand):
|
|
489
490
|
"""Switch to a different agent pool configuration.
|
|
490
491
|
|
|
491
|
-
This command will:
|
|
492
|
-
1. Close all active sessions
|
|
493
|
-
2. Load the new pool configuration
|
|
494
|
-
3. Initialize the new pool with all agents
|
|
495
|
-
|
|
496
492
|
The configuration can be specified as:
|
|
497
493
|
- A stored config name (from `agentpool add`)
|
|
498
494
|
- A direct path to a configuration file
|
|
@@ -589,6 +585,5 @@ def get_acp_commands() -> list[type[NodeCommand]]:
|
|
|
589
585
|
LoadSessionCommand,
|
|
590
586
|
SaveSessionCommand,
|
|
591
587
|
DeleteSessionCommand,
|
|
592
|
-
ListPoolsCommand,
|
|
593
588
|
SetPoolCommand,
|
|
594
589
|
]
|
|
@@ -66,10 +66,7 @@ class FetchRepoCommand(NodeCommand):
|
|
|
66
66
|
"""
|
|
67
67
|
session = ctx.context.data
|
|
68
68
|
assert session
|
|
69
|
-
|
|
70
|
-
# Generate tool call ID
|
|
71
|
-
tool_call_id = f"fetch-repo-{uuid.uuid4().hex[:8]}"
|
|
72
|
-
|
|
69
|
+
tc_id = f"fetch-repo-{uuid.uuid4().hex[:8]}"
|
|
73
70
|
try:
|
|
74
71
|
# Build URL
|
|
75
72
|
base_url = f"https://uithub.com/{repo}"
|
|
@@ -78,12 +75,14 @@ class FetchRepoCommand(NodeCommand):
|
|
|
78
75
|
if path:
|
|
79
76
|
base_url += f"/{path}"
|
|
80
77
|
|
|
81
|
-
# Build
|
|
82
|
-
|
|
78
|
+
# Build headers with Bearer token
|
|
79
|
+
headers = {"accept": "text/markdown"}
|
|
83
80
|
api_key = os.getenv("UITHUB_API_KEY")
|
|
84
81
|
if api_key:
|
|
85
|
-
|
|
82
|
+
headers["Authorization"] = f"Bearer {api_key}"
|
|
86
83
|
|
|
84
|
+
# Build parameters
|
|
85
|
+
params = {}
|
|
87
86
|
if include_dirs:
|
|
88
87
|
params["dir"] = ",".join(include_dirs)
|
|
89
88
|
if disable_genignore:
|
|
@@ -113,7 +112,7 @@ class FetchRepoCommand(NodeCommand):
|
|
|
113
112
|
display_path += f":{path}"
|
|
114
113
|
|
|
115
114
|
await session.notifications.tool_call_start(
|
|
116
|
-
tool_call_id=
|
|
115
|
+
tool_call_id=tc_id,
|
|
117
116
|
title=f"Fetching repository: {display_path}",
|
|
118
117
|
kind="fetch",
|
|
119
118
|
)
|
|
@@ -123,22 +122,20 @@ class FetchRepoCommand(NodeCommand):
|
|
|
123
122
|
response = await client.get(
|
|
124
123
|
base_url,
|
|
125
124
|
params=params,
|
|
126
|
-
headers=
|
|
125
|
+
headers=headers,
|
|
127
126
|
timeout=30.0,
|
|
128
127
|
)
|
|
129
128
|
response.raise_for_status()
|
|
130
129
|
content = response.text
|
|
131
130
|
|
|
132
131
|
# Stage the content for use in agent context
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
)
|
|
132
|
+
part_content = f"Repository contents from {display_path}:\n\n{content}"
|
|
133
|
+
staged_part = UserPromptPart(content=part_content)
|
|
136
134
|
session.staged_content.add([staged_part])
|
|
137
|
-
|
|
138
135
|
# Send successful result - wrap in code block for proper display
|
|
139
136
|
staged_count = len(session.staged_content)
|
|
140
137
|
await session.notifications.tool_call_progress(
|
|
141
|
-
tool_call_id=
|
|
138
|
+
tool_call_id=tc_id,
|
|
142
139
|
status="completed",
|
|
143
140
|
title=f"Repository {display_path} fetched and staged ({staged_count} total parts)",
|
|
144
141
|
content=[f"```\n{content}\n```"],
|
|
@@ -149,21 +146,25 @@ class FetchRepoCommand(NodeCommand):
|
|
|
149
146
|
"HTTP error fetching repository", repo=repo, status=e.response.status_code
|
|
150
147
|
)
|
|
151
148
|
await session.notifications.tool_call_progress(
|
|
152
|
-
tool_call_id=
|
|
149
|
+
tool_call_id=tc_id,
|
|
153
150
|
status="failed",
|
|
154
151
|
title=f"HTTP {e.response.status_code}: Failed to fetch {repo}",
|
|
155
152
|
)
|
|
156
153
|
except httpx.RequestError as e:
|
|
157
154
|
logger.exception("Request error fetching repository", repo=repo)
|
|
158
155
|
await session.notifications.tool_call_progress(
|
|
159
|
-
tool_call_id=
|
|
156
|
+
tool_call_id=tc_id,
|
|
160
157
|
status="failed",
|
|
161
158
|
title=f"Network error: {e}",
|
|
162
159
|
)
|
|
163
160
|
except Exception as e:
|
|
164
161
|
logger.exception("Unexpected error fetching repository", repo=repo)
|
|
165
162
|
await session.notifications.tool_call_progress(
|
|
166
|
-
tool_call_id=
|
|
163
|
+
tool_call_id=tc_id,
|
|
167
164
|
status="failed",
|
|
168
165
|
title=f"Error: {e}",
|
|
169
166
|
)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
if __name__ == "__main__":
|
|
170
|
+
cmd = FetchRepoCommand()
|