agentpool 2.1.9__py3-none-any.whl → 2.2.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. acp/__init__.py +13 -0
  2. acp/bridge/README.md +15 -2
  3. acp/bridge/__init__.py +3 -2
  4. acp/bridge/__main__.py +60 -19
  5. acp/bridge/ws_server.py +173 -0
  6. acp/bridge/ws_server_cli.py +89 -0
  7. acp/notifications.py +2 -1
  8. acp/stdio.py +39 -9
  9. acp/transports.py +362 -2
  10. acp/utils.py +15 -2
  11. agentpool/__init__.py +4 -1
  12. agentpool/agents/__init__.py +2 -0
  13. agentpool/agents/acp_agent/acp_agent.py +203 -88
  14. agentpool/agents/acp_agent/acp_converters.py +46 -21
  15. agentpool/agents/acp_agent/client_handler.py +157 -3
  16. agentpool/agents/acp_agent/session_state.py +4 -1
  17. agentpool/agents/agent.py +314 -107
  18. agentpool/agents/agui_agent/__init__.py +0 -2
  19. agentpool/agents/agui_agent/agui_agent.py +90 -21
  20. agentpool/agents/agui_agent/agui_converters.py +0 -131
  21. agentpool/agents/base_agent.py +163 -1
  22. agentpool/agents/claude_code_agent/claude_code_agent.py +626 -179
  23. agentpool/agents/claude_code_agent/converters.py +71 -3
  24. agentpool/agents/claude_code_agent/history.py +474 -0
  25. agentpool/agents/context.py +40 -0
  26. agentpool/agents/events/__init__.py +2 -0
  27. agentpool/agents/events/builtin_handlers.py +2 -1
  28. agentpool/agents/events/event_emitter.py +29 -2
  29. agentpool/agents/events/events.py +20 -0
  30. agentpool/agents/modes.py +54 -0
  31. agentpool/agents/tool_call_accumulator.py +213 -0
  32. agentpool/common_types.py +21 -0
  33. agentpool/config_resources/__init__.py +38 -1
  34. agentpool/config_resources/claude_code_agent.yml +3 -0
  35. agentpool/delegation/pool.py +37 -29
  36. agentpool/delegation/team.py +1 -0
  37. agentpool/delegation/teamrun.py +1 -0
  38. agentpool/diagnostics/__init__.py +53 -0
  39. agentpool/diagnostics/lsp_manager.py +1593 -0
  40. agentpool/diagnostics/lsp_proxy.py +41 -0
  41. agentpool/diagnostics/lsp_proxy_script.py +229 -0
  42. agentpool/diagnostics/models.py +398 -0
  43. agentpool/mcp_server/__init__.py +0 -2
  44. agentpool/mcp_server/client.py +12 -3
  45. agentpool/mcp_server/manager.py +25 -31
  46. agentpool/mcp_server/registries/official_registry_client.py +25 -0
  47. agentpool/mcp_server/tool_bridge.py +78 -66
  48. agentpool/messaging/__init__.py +0 -2
  49. agentpool/messaging/compaction.py +72 -197
  50. agentpool/messaging/message_history.py +12 -0
  51. agentpool/messaging/messages.py +52 -9
  52. agentpool/messaging/processing.py +3 -1
  53. agentpool/models/acp_agents/base.py +0 -22
  54. agentpool/models/acp_agents/mcp_capable.py +8 -148
  55. agentpool/models/acp_agents/non_mcp.py +129 -72
  56. agentpool/models/agents.py +35 -13
  57. agentpool/models/claude_code_agents.py +33 -2
  58. agentpool/models/manifest.py +43 -0
  59. agentpool/repomap.py +1 -1
  60. agentpool/resource_providers/__init__.py +9 -1
  61. agentpool/resource_providers/aggregating.py +52 -3
  62. agentpool/resource_providers/base.py +57 -1
  63. agentpool/resource_providers/mcp_provider.py +23 -0
  64. agentpool/resource_providers/plan_provider.py +130 -41
  65. agentpool/resource_providers/pool.py +2 -0
  66. agentpool/resource_providers/static.py +2 -0
  67. agentpool/sessions/__init__.py +2 -1
  68. agentpool/sessions/manager.py +31 -2
  69. agentpool/sessions/models.py +50 -0
  70. agentpool/skills/registry.py +13 -8
  71. agentpool/storage/manager.py +217 -1
  72. agentpool/testing.py +537 -19
  73. agentpool/utils/file_watcher.py +269 -0
  74. agentpool/utils/identifiers.py +121 -0
  75. agentpool/utils/pydantic_ai_helpers.py +46 -0
  76. agentpool/utils/streams.py +690 -1
  77. agentpool/utils/subprocess_utils.py +155 -0
  78. agentpool/utils/token_breakdown.py +461 -0
  79. {agentpool-2.1.9.dist-info → agentpool-2.2.3.dist-info}/METADATA +27 -7
  80. {agentpool-2.1.9.dist-info → agentpool-2.2.3.dist-info}/RECORD +170 -112
  81. {agentpool-2.1.9.dist-info → agentpool-2.2.3.dist-info}/WHEEL +1 -1
  82. agentpool_cli/__main__.py +4 -0
  83. agentpool_cli/serve_acp.py +41 -20
  84. agentpool_cli/serve_agui.py +87 -0
  85. agentpool_cli/serve_opencode.py +119 -0
  86. agentpool_commands/__init__.py +30 -0
  87. agentpool_commands/agents.py +74 -1
  88. agentpool_commands/history.py +62 -0
  89. agentpool_commands/mcp.py +176 -0
  90. agentpool_commands/models.py +56 -3
  91. agentpool_commands/tools.py +57 -0
  92. agentpool_commands/utils.py +51 -0
  93. agentpool_config/builtin_tools.py +77 -22
  94. agentpool_config/commands.py +24 -1
  95. agentpool_config/compaction.py +258 -0
  96. agentpool_config/mcp_server.py +131 -1
  97. agentpool_config/storage.py +46 -1
  98. agentpool_config/tools.py +7 -1
  99. agentpool_config/toolsets.py +92 -148
  100. agentpool_server/acp_server/acp_agent.py +134 -150
  101. agentpool_server/acp_server/commands/acp_commands.py +216 -51
  102. agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +10 -10
  103. agentpool_server/acp_server/server.py +23 -79
  104. agentpool_server/acp_server/session.py +181 -19
  105. agentpool_server/opencode_server/.rules +95 -0
  106. agentpool_server/opencode_server/ENDPOINTS.md +362 -0
  107. agentpool_server/opencode_server/__init__.py +27 -0
  108. agentpool_server/opencode_server/command_validation.py +172 -0
  109. agentpool_server/opencode_server/converters.py +869 -0
  110. agentpool_server/opencode_server/dependencies.py +24 -0
  111. agentpool_server/opencode_server/input_provider.py +269 -0
  112. agentpool_server/opencode_server/models/__init__.py +228 -0
  113. agentpool_server/opencode_server/models/agent.py +53 -0
  114. agentpool_server/opencode_server/models/app.py +60 -0
  115. agentpool_server/opencode_server/models/base.py +26 -0
  116. agentpool_server/opencode_server/models/common.py +23 -0
  117. agentpool_server/opencode_server/models/config.py +37 -0
  118. agentpool_server/opencode_server/models/events.py +647 -0
  119. agentpool_server/opencode_server/models/file.py +88 -0
  120. agentpool_server/opencode_server/models/mcp.py +25 -0
  121. agentpool_server/opencode_server/models/message.py +162 -0
  122. agentpool_server/opencode_server/models/parts.py +190 -0
  123. agentpool_server/opencode_server/models/provider.py +81 -0
  124. agentpool_server/opencode_server/models/pty.py +43 -0
  125. agentpool_server/opencode_server/models/session.py +99 -0
  126. agentpool_server/opencode_server/routes/__init__.py +25 -0
  127. agentpool_server/opencode_server/routes/agent_routes.py +442 -0
  128. agentpool_server/opencode_server/routes/app_routes.py +139 -0
  129. agentpool_server/opencode_server/routes/config_routes.py +241 -0
  130. agentpool_server/opencode_server/routes/file_routes.py +392 -0
  131. agentpool_server/opencode_server/routes/global_routes.py +94 -0
  132. agentpool_server/opencode_server/routes/lsp_routes.py +319 -0
  133. agentpool_server/opencode_server/routes/message_routes.py +705 -0
  134. agentpool_server/opencode_server/routes/pty_routes.py +299 -0
  135. agentpool_server/opencode_server/routes/session_routes.py +1205 -0
  136. agentpool_server/opencode_server/routes/tui_routes.py +139 -0
  137. agentpool_server/opencode_server/server.py +430 -0
  138. agentpool_server/opencode_server/state.py +121 -0
  139. agentpool_server/opencode_server/time_utils.py +8 -0
  140. agentpool_storage/__init__.py +16 -0
  141. agentpool_storage/base.py +103 -0
  142. agentpool_storage/claude_provider.py +907 -0
  143. agentpool_storage/file_provider.py +129 -0
  144. agentpool_storage/memory_provider.py +61 -0
  145. agentpool_storage/models.py +3 -0
  146. agentpool_storage/opencode_provider.py +730 -0
  147. agentpool_storage/project_store.py +325 -0
  148. agentpool_storage/session_store.py +6 -0
  149. agentpool_storage/sql_provider/__init__.py +4 -2
  150. agentpool_storage/sql_provider/models.py +48 -0
  151. agentpool_storage/sql_provider/sql_provider.py +134 -1
  152. agentpool_storage/sql_provider/utils.py +10 -1
  153. agentpool_storage/text_log_provider.py +1 -0
  154. agentpool_toolsets/builtin/__init__.py +0 -8
  155. agentpool_toolsets/builtin/code.py +95 -56
  156. agentpool_toolsets/builtin/debug.py +16 -21
  157. agentpool_toolsets/builtin/execution_environment.py +99 -103
  158. agentpool_toolsets/builtin/file_edit/file_edit.py +115 -7
  159. agentpool_toolsets/builtin/skills.py +86 -4
  160. agentpool_toolsets/fsspec_toolset/__init__.py +13 -1
  161. agentpool_toolsets/fsspec_toolset/diagnostics.py +860 -73
  162. agentpool_toolsets/fsspec_toolset/grep.py +74 -2
  163. agentpool_toolsets/fsspec_toolset/image_utils.py +161 -0
  164. agentpool_toolsets/fsspec_toolset/toolset.py +159 -38
  165. agentpool_toolsets/mcp_discovery/__init__.py +5 -0
  166. agentpool_toolsets/mcp_discovery/data/mcp_servers.parquet +0 -0
  167. agentpool_toolsets/mcp_discovery/toolset.py +454 -0
  168. agentpool_toolsets/mcp_run_toolset.py +84 -6
  169. agentpool_toolsets/builtin/agent_management.py +0 -239
  170. agentpool_toolsets/builtin/history.py +0 -36
  171. agentpool_toolsets/builtin/integration.py +0 -85
  172. agentpool_toolsets/builtin/tool_management.py +0 -90
  173. {agentpool-2.1.9.dist-info → agentpool-2.2.3.dist-info}/entry_points.txt +0 -0
  174. {agentpool-2.1.9.dist-info → agentpool-2.2.3.dist-info}/licenses/LICENSE +0 -0
@@ -9,6 +9,7 @@ from anyenv import method_spawner
9
9
  from pydantic_ai import Agent
10
10
 
11
11
  from agentpool.log import get_logger
12
+ from agentpool.messaging import ChatMessage
12
13
  from agentpool.storage.serialization import serialize_messages
13
14
  from agentpool.utils.tasks import TaskManager
14
15
  from agentpool_config.storage import (
@@ -25,7 +26,7 @@ if TYPE_CHECKING:
25
26
  from types import TracebackType
26
27
 
27
28
  from agentpool.common_types import JsonValue
28
- from agentpool.messaging import ChatMessage
29
+ from agentpool.sessions.models import ProjectData
29
30
  from agentpool_config.session import SessionQuery
30
31
  from agentpool_config.storage import BaseStorageProviderConfig, StorageConfig
31
32
  from agentpool_storage.base import StorageProvider
@@ -209,6 +210,7 @@ class StorageManager:
209
210
  content=str(message.content),
210
211
  role=message.role,
211
212
  name=message.name,
213
+ parent_id=message.parent_id,
212
214
  cost_info=message.cost_info,
213
215
  model=message.model_name,
214
216
  response_time=message.response_time,
@@ -363,6 +365,87 @@ class StorageManager:
363
365
  provider = self.get_history_provider()
364
366
  return await provider.get_conversation_title(conversation_id)
365
367
 
368
+ @method_spawner
369
+ async def delete_conversation_messages(
370
+ self,
371
+ conversation_id: str,
372
+ ) -> int:
373
+ """Delete all messages for a conversation in all providers.
374
+
375
+ Used for compaction - removes existing messages so they can be
376
+ replaced with compacted versions.
377
+
378
+ Args:
379
+ conversation_id: ID of the conversation to clear
380
+
381
+ Returns:
382
+ Total number of messages deleted across all providers
383
+ """
384
+ total_deleted = 0
385
+ for provider in self.providers:
386
+ try:
387
+ deleted = await provider.delete_conversation_messages(conversation_id)
388
+ total_deleted += deleted
389
+ except NotImplementedError:
390
+ # Provider doesn't support deletion (e.g., write-only log)
391
+ pass
392
+ except Exception:
393
+ logger.exception(
394
+ "Error deleting messages from provider",
395
+ provider=provider.__class__.__name__,
396
+ conversation_id=conversation_id,
397
+ )
398
+ return total_deleted
399
+
400
+ @method_spawner
401
+ async def replace_conversation_messages(
402
+ self,
403
+ conversation_id: str,
404
+ messages: Sequence[ChatMessage[Any]],
405
+ ) -> tuple[int, int]:
406
+ """Replace all messages for a conversation with new ones.
407
+
408
+ Deletes existing messages and logs new ones. Used for compaction
409
+ where the full history is replaced with a compacted version.
410
+
411
+ Args:
412
+ conversation_id: ID of the conversation
413
+ messages: New messages to store
414
+
415
+ Returns:
416
+ Tuple of (deleted_count, added_count)
417
+ """
418
+ # First delete existing messages
419
+ deleted = await self.delete_conversation_messages(conversation_id)
420
+
421
+ # Then log new messages
422
+ added = 0
423
+ for message in messages:
424
+ # Ensure conversation_id is set on the message
425
+ msg_to_log: ChatMessage[Any] = message
426
+ if not message.conversation_id:
427
+ msg_to_log = ChatMessage(
428
+ content=message.content,
429
+ role=message.role,
430
+ name=message.name,
431
+ conversation_id=conversation_id,
432
+ message_id=message.message_id,
433
+ parent_id=message.parent_id,
434
+ model_name=message.model_name,
435
+ cost_info=message.cost_info,
436
+ response_time=message.response_time,
437
+ forwarded_from=message.forwarded_from,
438
+ timestamp=message.timestamp,
439
+ provider_name=message.provider_name,
440
+ provider_response_id=message.provider_response_id,
441
+ messages=message.messages,
442
+ finish_reason=message.finish_reason,
443
+ )
444
+ await self.log_message(msg_to_log)
445
+ added += 1
446
+
447
+ return deleted, added
448
+
366
449
  async def generate_conversation_title(
367
450
  self,
368
451
  conversation_id: str,
@@ -417,3 +500,136 @@ class StorageManager:
417
500
  return None
418
501
  else:
419
502
  return title
503
+
504
+ # Project methods
505
+
506
+ def get_project_provider(self) -> StorageProvider:
507
+ """Get provider capable of storing projects.
508
+
509
+ Returns:
510
+ First provider that supports project storage.
511
+
512
+ Raises:
513
+ RuntimeError: If no capable provider found.
514
+ """
515
+ for provider in self.providers:
516
+ # TextLogProvider doesn't support projects, others do
517
+ if hasattr(provider, "save_project") and not getattr(provider, "write_only", False):
518
+ return provider
519
+ msg = "No provider found that supports project storage"
520
+ raise RuntimeError(msg)
521
+
522
+ @method_spawner
523
+ async def save_project(self, project: ProjectData) -> None:
524
+ """Save or update a project in all capable providers.
525
+
526
+ Args:
527
+ project: Project data to persist
528
+ """
529
+ for provider in self.providers:
530
+ try:
531
+ await provider.save_project(project)
532
+ except NotImplementedError:
533
+ pass
534
+ except Exception:
535
+ logger.exception(
536
+ "Error saving project",
537
+ provider=provider.__class__.__name__,
538
+ project_id=project.project_id,
539
+ )
540
+
541
+ @method_spawner
542
+ async def get_project(self, project_id: str) -> ProjectData | None:
543
+ """Get a project by ID.
544
+
545
+ Args:
546
+ project_id: Project identifier
547
+
548
+ Returns:
549
+ Project data if found, None otherwise
550
+ """
551
+ provider = self.get_project_provider()
552
+ return await provider.get_project(project_id)
553
+
554
+ @method_spawner
555
+ async def get_project_by_worktree(self, worktree: str) -> ProjectData | None:
556
+ """Get a project by worktree path.
557
+
558
+ Args:
559
+ worktree: Absolute path to the project worktree
560
+
561
+ Returns:
562
+ Project data if found, None otherwise
563
+ """
564
+ provider = self.get_project_provider()
565
+ return await provider.get_project_by_worktree(worktree)
566
+
567
+ @method_spawner
568
+ async def get_project_by_name(self, name: str) -> ProjectData | None:
569
+ """Get a project by friendly name.
570
+
571
+ Args:
572
+ name: Project name
573
+
574
+ Returns:
575
+ Project data if found, None otherwise
576
+ """
577
+ provider = self.get_project_provider()
578
+ return await provider.get_project_by_name(name)
579
+
580
+ @method_spawner
581
+ async def list_projects(self, limit: int | None = None) -> list[ProjectData]:
582
+ """List all projects, ordered by last_active descending.
583
+
584
+ Args:
585
+ limit: Maximum number of projects to return
586
+
587
+ Returns:
588
+ List of project data objects
589
+ """
590
+ provider = self.get_project_provider()
591
+ return await provider.list_projects(limit=limit)
592
+
593
+ @method_spawner
594
+ async def delete_project(self, project_id: str) -> bool:
595
+ """Delete a project from all providers.
596
+
597
+ Args:
598
+ project_id: Project identifier
599
+
600
+ Returns:
601
+ True if project was deleted from at least one provider
602
+ """
603
+ deleted = False
604
+ for provider in self.providers:
605
+ try:
606
+ if await provider.delete_project(project_id):
607
+ deleted = True
608
+ except NotImplementedError:
609
+ pass
610
+ except Exception:
611
+ logger.exception(
612
+ "Error deleting project",
613
+ provider=provider.__class__.__name__,
614
+ project_id=project_id,
615
+ )
616
+ return deleted
617
+
618
+ @method_spawner
619
+ async def touch_project(self, project_id: str) -> None:
620
+ """Update project's last_active timestamp in all providers.
621
+
622
+ Args:
623
+ project_id: Project identifier
624
+ """
625
+ for provider in self.providers:
626
+ try:
627
+ await provider.touch_project(project_id)
628
+ except NotImplementedError:
629
+ pass
630
+ except Exception:
631
+ logger.exception(
632
+ "Error touching project",
633
+ provider=provider.__class__.__name__,
634
+ project_id=project_id,
635
+ )