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.
Files changed (311) hide show
  1. acp/__init__.py +13 -4
  2. acp/acp_requests.py +20 -77
  3. acp/agent/connection.py +8 -0
  4. acp/agent/implementations/debug_server/debug_server.py +6 -2
  5. acp/agent/protocol.py +6 -0
  6. acp/bridge/README.md +15 -2
  7. acp/bridge/__init__.py +3 -2
  8. acp/bridge/__main__.py +60 -19
  9. acp/bridge/ws_server.py +173 -0
  10. acp/bridge/ws_server_cli.py +89 -0
  11. acp/client/connection.py +38 -29
  12. acp/client/implementations/default_client.py +3 -2
  13. acp/client/implementations/headless_client.py +2 -2
  14. acp/connection.py +2 -2
  15. acp/notifications.py +20 -50
  16. acp/schema/__init__.py +2 -0
  17. acp/schema/agent_responses.py +21 -0
  18. acp/schema/client_requests.py +3 -3
  19. acp/schema/session_state.py +63 -29
  20. acp/stdio.py +39 -9
  21. acp/task/supervisor.py +2 -2
  22. acp/transports.py +362 -2
  23. acp/utils.py +17 -4
  24. agentpool/__init__.py +6 -1
  25. agentpool/agents/__init__.py +2 -0
  26. agentpool/agents/acp_agent/acp_agent.py +407 -277
  27. agentpool/agents/acp_agent/acp_converters.py +196 -38
  28. agentpool/agents/acp_agent/client_handler.py +191 -26
  29. agentpool/agents/acp_agent/session_state.py +17 -6
  30. agentpool/agents/agent.py +607 -572
  31. agentpool/agents/agui_agent/__init__.py +0 -2
  32. agentpool/agents/agui_agent/agui_agent.py +176 -110
  33. agentpool/agents/agui_agent/agui_converters.py +0 -131
  34. agentpool/agents/agui_agent/helpers.py +3 -4
  35. agentpool/agents/base_agent.py +632 -17
  36. agentpool/agents/claude_code_agent/FORKING.md +191 -0
  37. agentpool/agents/claude_code_agent/__init__.py +13 -1
  38. agentpool/agents/claude_code_agent/claude_code_agent.py +1058 -291
  39. agentpool/agents/claude_code_agent/converters.py +74 -143
  40. agentpool/agents/claude_code_agent/history.py +474 -0
  41. agentpool/agents/claude_code_agent/models.py +77 -0
  42. agentpool/agents/claude_code_agent/static_info.py +100 -0
  43. agentpool/agents/claude_code_agent/usage.py +242 -0
  44. agentpool/agents/context.py +40 -0
  45. agentpool/agents/events/__init__.py +24 -0
  46. agentpool/agents/events/builtin_handlers.py +67 -1
  47. agentpool/agents/events/event_emitter.py +32 -2
  48. agentpool/agents/events/events.py +104 -3
  49. agentpool/agents/events/infer_info.py +145 -0
  50. agentpool/agents/events/processors.py +254 -0
  51. agentpool/agents/interactions.py +41 -6
  52. agentpool/agents/modes.py +67 -0
  53. agentpool/agents/slashed_agent.py +5 -4
  54. agentpool/agents/tool_call_accumulator.py +213 -0
  55. agentpool/agents/tool_wrapping.py +18 -6
  56. agentpool/common_types.py +56 -21
  57. agentpool/config_resources/__init__.py +38 -1
  58. agentpool/config_resources/acp_assistant.yml +2 -2
  59. agentpool/config_resources/agents.yml +3 -0
  60. agentpool/config_resources/agents_template.yml +1 -0
  61. agentpool/config_resources/claude_code_agent.yml +10 -6
  62. agentpool/config_resources/external_acp_agents.yml +2 -1
  63. agentpool/delegation/base_team.py +4 -30
  64. agentpool/delegation/pool.py +136 -289
  65. agentpool/delegation/team.py +58 -57
  66. agentpool/delegation/teamrun.py +51 -55
  67. agentpool/diagnostics/__init__.py +53 -0
  68. agentpool/diagnostics/lsp_manager.py +1593 -0
  69. agentpool/diagnostics/lsp_proxy.py +41 -0
  70. agentpool/diagnostics/lsp_proxy_script.py +229 -0
  71. agentpool/diagnostics/models.py +398 -0
  72. agentpool/functional/run.py +10 -4
  73. agentpool/mcp_server/__init__.py +0 -2
  74. agentpool/mcp_server/client.py +76 -32
  75. agentpool/mcp_server/conversions.py +54 -13
  76. agentpool/mcp_server/manager.py +34 -54
  77. agentpool/mcp_server/registries/official_registry_client.py +35 -1
  78. agentpool/mcp_server/tool_bridge.py +186 -139
  79. agentpool/messaging/__init__.py +0 -2
  80. agentpool/messaging/compaction.py +72 -197
  81. agentpool/messaging/connection_manager.py +11 -10
  82. agentpool/messaging/event_manager.py +5 -5
  83. agentpool/messaging/message_container.py +6 -30
  84. agentpool/messaging/message_history.py +99 -8
  85. agentpool/messaging/messagenode.py +52 -14
  86. agentpool/messaging/messages.py +54 -35
  87. agentpool/messaging/processing.py +12 -22
  88. agentpool/models/__init__.py +1 -1
  89. agentpool/models/acp_agents/base.py +6 -24
  90. agentpool/models/acp_agents/mcp_capable.py +126 -157
  91. agentpool/models/acp_agents/non_mcp.py +129 -95
  92. agentpool/models/agents.py +98 -76
  93. agentpool/models/agui_agents.py +1 -1
  94. agentpool/models/claude_code_agents.py +144 -19
  95. agentpool/models/file_parsing.py +0 -1
  96. agentpool/models/manifest.py +113 -50
  97. agentpool/prompts/conversion_manager.py +1 -1
  98. agentpool/prompts/prompts.py +5 -2
  99. agentpool/repomap.py +1 -1
  100. agentpool/resource_providers/__init__.py +11 -1
  101. agentpool/resource_providers/aggregating.py +56 -5
  102. agentpool/resource_providers/base.py +70 -4
  103. agentpool/resource_providers/codemode/code_executor.py +72 -5
  104. agentpool/resource_providers/codemode/helpers.py +2 -2
  105. agentpool/resource_providers/codemode/provider.py +64 -12
  106. agentpool/resource_providers/codemode/remote_mcp_execution.py +2 -2
  107. agentpool/resource_providers/codemode/remote_provider.py +9 -12
  108. agentpool/resource_providers/filtering.py +3 -1
  109. agentpool/resource_providers/mcp_provider.py +89 -12
  110. agentpool/resource_providers/plan_provider.py +228 -46
  111. agentpool/resource_providers/pool.py +7 -3
  112. agentpool/resource_providers/resource_info.py +111 -0
  113. agentpool/resource_providers/static.py +4 -2
  114. agentpool/sessions/__init__.py +4 -1
  115. agentpool/sessions/manager.py +33 -5
  116. agentpool/sessions/models.py +59 -6
  117. agentpool/sessions/protocol.py +28 -0
  118. agentpool/sessions/session.py +11 -55
  119. agentpool/skills/registry.py +13 -8
  120. agentpool/storage/manager.py +572 -49
  121. agentpool/talk/registry.py +4 -4
  122. agentpool/talk/talk.py +9 -10
  123. agentpool/testing.py +538 -20
  124. agentpool/tool_impls/__init__.py +6 -0
  125. agentpool/tool_impls/agent_cli/__init__.py +42 -0
  126. agentpool/tool_impls/agent_cli/tool.py +95 -0
  127. agentpool/tool_impls/bash/__init__.py +64 -0
  128. agentpool/tool_impls/bash/helpers.py +35 -0
  129. agentpool/tool_impls/bash/tool.py +171 -0
  130. agentpool/tool_impls/delete_path/__init__.py +70 -0
  131. agentpool/tool_impls/delete_path/tool.py +142 -0
  132. agentpool/tool_impls/download_file/__init__.py +80 -0
  133. agentpool/tool_impls/download_file/tool.py +183 -0
  134. agentpool/tool_impls/execute_code/__init__.py +55 -0
  135. agentpool/tool_impls/execute_code/tool.py +163 -0
  136. agentpool/tool_impls/grep/__init__.py +80 -0
  137. agentpool/tool_impls/grep/tool.py +200 -0
  138. agentpool/tool_impls/list_directory/__init__.py +73 -0
  139. agentpool/tool_impls/list_directory/tool.py +197 -0
  140. agentpool/tool_impls/question/__init__.py +42 -0
  141. agentpool/tool_impls/question/tool.py +127 -0
  142. agentpool/tool_impls/read/__init__.py +104 -0
  143. agentpool/tool_impls/read/tool.py +305 -0
  144. agentpool/tools/__init__.py +2 -1
  145. agentpool/tools/base.py +114 -34
  146. agentpool/tools/manager.py +57 -1
  147. agentpool/ui/base.py +2 -2
  148. agentpool/ui/mock_provider.py +2 -2
  149. agentpool/ui/stdlib_provider.py +2 -2
  150. agentpool/utils/file_watcher.py +269 -0
  151. agentpool/utils/identifiers.py +121 -0
  152. agentpool/utils/pydantic_ai_helpers.py +46 -0
  153. agentpool/utils/streams.py +616 -2
  154. agentpool/utils/subprocess_utils.py +155 -0
  155. agentpool/utils/token_breakdown.py +461 -0
  156. agentpool/vfs_registry.py +7 -2
  157. {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/METADATA +41 -27
  158. agentpool-2.5.0.dist-info/RECORD +579 -0
  159. {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/WHEEL +1 -1
  160. agentpool_cli/__main__.py +24 -0
  161. agentpool_cli/create.py +1 -1
  162. agentpool_cli/serve_acp.py +100 -21
  163. agentpool_cli/serve_agui.py +87 -0
  164. agentpool_cli/serve_opencode.py +119 -0
  165. agentpool_cli/ui.py +557 -0
  166. agentpool_commands/__init__.py +42 -5
  167. agentpool_commands/agents.py +75 -2
  168. agentpool_commands/history.py +62 -0
  169. agentpool_commands/mcp.py +176 -0
  170. agentpool_commands/models.py +56 -3
  171. agentpool_commands/pool.py +260 -0
  172. agentpool_commands/session.py +1 -1
  173. agentpool_commands/text_sharing/__init__.py +119 -0
  174. agentpool_commands/text_sharing/base.py +123 -0
  175. agentpool_commands/text_sharing/github_gist.py +80 -0
  176. agentpool_commands/text_sharing/opencode.py +462 -0
  177. agentpool_commands/text_sharing/paste_rs.py +59 -0
  178. agentpool_commands/text_sharing/pastebin.py +116 -0
  179. agentpool_commands/text_sharing/shittycodingagent.py +112 -0
  180. agentpool_commands/tools.py +57 -0
  181. agentpool_commands/utils.py +80 -30
  182. agentpool_config/__init__.py +30 -2
  183. agentpool_config/agentpool_tools.py +498 -0
  184. agentpool_config/builtin_tools.py +77 -22
  185. agentpool_config/commands.py +24 -1
  186. agentpool_config/compaction.py +258 -0
  187. agentpool_config/converters.py +1 -1
  188. agentpool_config/event_handlers.py +42 -0
  189. agentpool_config/events.py +1 -1
  190. agentpool_config/forward_targets.py +1 -4
  191. agentpool_config/jinja.py +3 -3
  192. agentpool_config/mcp_server.py +132 -6
  193. agentpool_config/nodes.py +1 -1
  194. agentpool_config/observability.py +44 -0
  195. agentpool_config/session.py +0 -3
  196. agentpool_config/storage.py +82 -38
  197. agentpool_config/task.py +3 -3
  198. agentpool_config/tools.py +11 -22
  199. agentpool_config/toolsets.py +109 -233
  200. agentpool_server/a2a_server/agent_worker.py +307 -0
  201. agentpool_server/a2a_server/server.py +23 -18
  202. agentpool_server/acp_server/acp_agent.py +234 -181
  203. agentpool_server/acp_server/commands/acp_commands.py +151 -156
  204. agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +18 -17
  205. agentpool_server/acp_server/event_converter.py +651 -0
  206. agentpool_server/acp_server/input_provider.py +53 -10
  207. agentpool_server/acp_server/server.py +24 -90
  208. agentpool_server/acp_server/session.py +173 -331
  209. agentpool_server/acp_server/session_manager.py +8 -34
  210. agentpool_server/agui_server/server.py +3 -1
  211. agentpool_server/mcp_server/server.py +5 -2
  212. agentpool_server/opencode_server/.rules +95 -0
  213. agentpool_server/opencode_server/ENDPOINTS.md +401 -0
  214. agentpool_server/opencode_server/OPENCODE_UI_TOOLS_COMPLETE.md +202 -0
  215. agentpool_server/opencode_server/__init__.py +19 -0
  216. agentpool_server/opencode_server/command_validation.py +172 -0
  217. agentpool_server/opencode_server/converters.py +975 -0
  218. agentpool_server/opencode_server/dependencies.py +24 -0
  219. agentpool_server/opencode_server/input_provider.py +421 -0
  220. agentpool_server/opencode_server/models/__init__.py +250 -0
  221. agentpool_server/opencode_server/models/agent.py +53 -0
  222. agentpool_server/opencode_server/models/app.py +72 -0
  223. agentpool_server/opencode_server/models/base.py +26 -0
  224. agentpool_server/opencode_server/models/common.py +23 -0
  225. agentpool_server/opencode_server/models/config.py +37 -0
  226. agentpool_server/opencode_server/models/events.py +821 -0
  227. agentpool_server/opencode_server/models/file.py +88 -0
  228. agentpool_server/opencode_server/models/mcp.py +44 -0
  229. agentpool_server/opencode_server/models/message.py +179 -0
  230. agentpool_server/opencode_server/models/parts.py +323 -0
  231. agentpool_server/opencode_server/models/provider.py +81 -0
  232. agentpool_server/opencode_server/models/pty.py +43 -0
  233. agentpool_server/opencode_server/models/question.py +56 -0
  234. agentpool_server/opencode_server/models/session.py +111 -0
  235. agentpool_server/opencode_server/routes/__init__.py +29 -0
  236. agentpool_server/opencode_server/routes/agent_routes.py +473 -0
  237. agentpool_server/opencode_server/routes/app_routes.py +202 -0
  238. agentpool_server/opencode_server/routes/config_routes.py +302 -0
  239. agentpool_server/opencode_server/routes/file_routes.py +571 -0
  240. agentpool_server/opencode_server/routes/global_routes.py +94 -0
  241. agentpool_server/opencode_server/routes/lsp_routes.py +319 -0
  242. agentpool_server/opencode_server/routes/message_routes.py +761 -0
  243. agentpool_server/opencode_server/routes/permission_routes.py +63 -0
  244. agentpool_server/opencode_server/routes/pty_routes.py +300 -0
  245. agentpool_server/opencode_server/routes/question_routes.py +128 -0
  246. agentpool_server/opencode_server/routes/session_routes.py +1276 -0
  247. agentpool_server/opencode_server/routes/tui_routes.py +139 -0
  248. agentpool_server/opencode_server/server.py +475 -0
  249. agentpool_server/opencode_server/state.py +151 -0
  250. agentpool_server/opencode_server/time_utils.py +8 -0
  251. agentpool_storage/__init__.py +12 -0
  252. agentpool_storage/base.py +184 -2
  253. agentpool_storage/claude_provider/ARCHITECTURE.md +433 -0
  254. agentpool_storage/claude_provider/__init__.py +42 -0
  255. agentpool_storage/claude_provider/provider.py +1089 -0
  256. agentpool_storage/file_provider.py +278 -15
  257. agentpool_storage/memory_provider.py +193 -12
  258. agentpool_storage/models.py +3 -0
  259. agentpool_storage/opencode_provider/ARCHITECTURE.md +386 -0
  260. agentpool_storage/opencode_provider/__init__.py +16 -0
  261. agentpool_storage/opencode_provider/helpers.py +414 -0
  262. agentpool_storage/opencode_provider/provider.py +895 -0
  263. agentpool_storage/project_store.py +325 -0
  264. agentpool_storage/session_store.py +26 -6
  265. agentpool_storage/sql_provider/__init__.py +4 -2
  266. agentpool_storage/sql_provider/models.py +48 -0
  267. agentpool_storage/sql_provider/sql_provider.py +269 -3
  268. agentpool_storage/sql_provider/utils.py +12 -13
  269. agentpool_storage/zed_provider/__init__.py +16 -0
  270. agentpool_storage/zed_provider/helpers.py +281 -0
  271. agentpool_storage/zed_provider/models.py +130 -0
  272. agentpool_storage/zed_provider/provider.py +442 -0
  273. agentpool_storage/zed_provider.py +803 -0
  274. agentpool_toolsets/__init__.py +0 -2
  275. agentpool_toolsets/builtin/__init__.py +2 -12
  276. agentpool_toolsets/builtin/code.py +96 -57
  277. agentpool_toolsets/builtin/debug.py +118 -48
  278. agentpool_toolsets/builtin/execution_environment.py +115 -230
  279. agentpool_toolsets/builtin/file_edit/file_edit.py +115 -7
  280. agentpool_toolsets/builtin/skills.py +9 -4
  281. agentpool_toolsets/builtin/subagent_tools.py +64 -51
  282. agentpool_toolsets/builtin/workers.py +4 -2
  283. agentpool_toolsets/composio_toolset.py +2 -2
  284. agentpool_toolsets/entry_points.py +3 -1
  285. agentpool_toolsets/fsspec_toolset/__init__.py +13 -1
  286. agentpool_toolsets/fsspec_toolset/diagnostics.py +860 -73
  287. agentpool_toolsets/fsspec_toolset/grep.py +99 -7
  288. agentpool_toolsets/fsspec_toolset/helpers.py +3 -2
  289. agentpool_toolsets/fsspec_toolset/image_utils.py +161 -0
  290. agentpool_toolsets/fsspec_toolset/toolset.py +500 -95
  291. agentpool_toolsets/mcp_discovery/__init__.py +5 -0
  292. agentpool_toolsets/mcp_discovery/data/mcp_servers.parquet +0 -0
  293. agentpool_toolsets/mcp_discovery/toolset.py +511 -0
  294. agentpool_toolsets/mcp_run_toolset.py +87 -12
  295. agentpool_toolsets/notifications.py +33 -33
  296. agentpool_toolsets/openapi.py +3 -1
  297. agentpool_toolsets/search_toolset.py +3 -1
  298. agentpool-2.1.9.dist-info/RECORD +0 -474
  299. agentpool_config/resources.py +0 -33
  300. agentpool_server/acp_server/acp_tools.py +0 -43
  301. agentpool_server/acp_server/commands/spawn.py +0 -210
  302. agentpool_storage/text_log_provider.py +0 -275
  303. agentpool_toolsets/builtin/agent_management.py +0 -239
  304. agentpool_toolsets/builtin/chain.py +0 -288
  305. agentpool_toolsets/builtin/history.py +0 -36
  306. agentpool_toolsets/builtin/integration.py +0 -85
  307. agentpool_toolsets/builtin/tool_management.py +0 -90
  308. agentpool_toolsets/builtin/user_interaction.py +0 -52
  309. agentpool_toolsets/semantic_memory_toolset.py +0 -536
  310. {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/entry_points.txt +0 -0
  311. {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 typing import TYPE_CHECKING
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
- # Show active sessions
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
- if not active_sessions:
70
- output_lines.append("*No active sessions*\n")
71
- else:
72
- for session_id, sess in active_sessions.items():
73
- agent_name = sess.current_agent_name
74
- cwd = sess.cwd or "unknown"
75
- is_current = session_id == session.session_id
76
-
77
- # Get title from SessionData
78
- session_data = await session.manager.session_manager.store.load(session_id)
79
- title = session_data.title if session_data else None
80
-
81
- status = " *(current)*" if is_current else ""
82
- title_text = f": {title}" if title else ""
83
- output_lines.append(f"- **{session_id}**{status}{title_text}")
84
- output_lines.append(f" - Agent: `{agent_name}`")
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 showed them
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
- if not stored_session_ids:
101
- output_lines.append("*No stored sessions*\n")
102
- else:
103
- for session_id in stored_session_ids:
104
- session_data = await session.manager.session_manager.store.load(
105
- session_id
106
- )
107
- if session_data:
108
- title_text = f": {session_data.title}" if session_data.title else ""
109
- output_lines.append(f"- **{session_id}**{title_text}")
110
- output_lines.append(f" - Agent: `{session_data.agent_name}`")
111
- output_lines.append(
112
- f" - Directory: `{session_data.cwd or 'unknown'}`"
113
- )
114
- output_lines.append(
115
- f" - Last active: {session_data.last_active.strftime('%Y-%m-%d %H:%M')}" # noqa: E501
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
- if session_data.title:
194
- preview_lines.append(f"**Title:** {session_data.title}")
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 parameters
82
- params = {}
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
- params["apiKey"] = api_key
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=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={"accept": "text/markdown"},
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
- staged_part = UserPromptPart(
134
- content=f"Repository contents from {display_path}:\n\n{content}"
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=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=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=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=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()