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.
Files changed (250) hide show
  1. acp/__init__.py +0 -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/client/connection.py +38 -29
  7. acp/client/implementations/default_client.py +3 -2
  8. acp/client/implementations/headless_client.py +2 -2
  9. acp/connection.py +2 -2
  10. acp/notifications.py +18 -49
  11. acp/schema/__init__.py +2 -0
  12. acp/schema/agent_responses.py +21 -0
  13. acp/schema/client_requests.py +3 -3
  14. acp/schema/session_state.py +63 -29
  15. acp/task/supervisor.py +2 -2
  16. acp/utils.py +2 -2
  17. agentpool/__init__.py +2 -0
  18. agentpool/agents/acp_agent/acp_agent.py +278 -263
  19. agentpool/agents/acp_agent/acp_converters.py +150 -17
  20. agentpool/agents/acp_agent/client_handler.py +35 -24
  21. agentpool/agents/acp_agent/session_state.py +14 -6
  22. agentpool/agents/agent.py +471 -643
  23. agentpool/agents/agui_agent/agui_agent.py +104 -107
  24. agentpool/agents/agui_agent/helpers.py +3 -4
  25. agentpool/agents/base_agent.py +485 -32
  26. agentpool/agents/claude_code_agent/FORKING.md +191 -0
  27. agentpool/agents/claude_code_agent/__init__.py +13 -1
  28. agentpool/agents/claude_code_agent/claude_code_agent.py +654 -334
  29. agentpool/agents/claude_code_agent/converters.py +4 -141
  30. agentpool/agents/claude_code_agent/models.py +77 -0
  31. agentpool/agents/claude_code_agent/static_info.py +100 -0
  32. agentpool/agents/claude_code_agent/usage.py +242 -0
  33. agentpool/agents/events/__init__.py +22 -0
  34. agentpool/agents/events/builtin_handlers.py +65 -0
  35. agentpool/agents/events/event_emitter.py +3 -0
  36. agentpool/agents/events/events.py +84 -3
  37. agentpool/agents/events/infer_info.py +145 -0
  38. agentpool/agents/events/processors.py +254 -0
  39. agentpool/agents/interactions.py +41 -6
  40. agentpool/agents/modes.py +13 -0
  41. agentpool/agents/slashed_agent.py +5 -4
  42. agentpool/agents/tool_wrapping.py +18 -6
  43. agentpool/common_types.py +35 -21
  44. agentpool/config_resources/acp_assistant.yml +2 -2
  45. agentpool/config_resources/agents.yml +3 -0
  46. agentpool/config_resources/agents_template.yml +1 -0
  47. agentpool/config_resources/claude_code_agent.yml +9 -8
  48. agentpool/config_resources/external_acp_agents.yml +2 -1
  49. agentpool/delegation/base_team.py +4 -30
  50. agentpool/delegation/pool.py +104 -265
  51. agentpool/delegation/team.py +57 -57
  52. agentpool/delegation/teamrun.py +50 -55
  53. agentpool/functional/run.py +10 -4
  54. agentpool/mcp_server/client.py +73 -38
  55. agentpool/mcp_server/conversions.py +54 -13
  56. agentpool/mcp_server/manager.py +9 -23
  57. agentpool/mcp_server/registries/official_registry_client.py +10 -1
  58. agentpool/mcp_server/tool_bridge.py +114 -79
  59. agentpool/messaging/connection_manager.py +11 -10
  60. agentpool/messaging/event_manager.py +5 -5
  61. agentpool/messaging/message_container.py +6 -30
  62. agentpool/messaging/message_history.py +87 -8
  63. agentpool/messaging/messagenode.py +52 -14
  64. agentpool/messaging/messages.py +2 -26
  65. agentpool/messaging/processing.py +10 -22
  66. agentpool/models/__init__.py +1 -1
  67. agentpool/models/acp_agents/base.py +6 -2
  68. agentpool/models/acp_agents/mcp_capable.py +124 -15
  69. agentpool/models/acp_agents/non_mcp.py +0 -23
  70. agentpool/models/agents.py +66 -66
  71. agentpool/models/agui_agents.py +1 -1
  72. agentpool/models/claude_code_agents.py +111 -17
  73. agentpool/models/file_parsing.py +0 -1
  74. agentpool/models/manifest.py +70 -50
  75. agentpool/prompts/conversion_manager.py +1 -1
  76. agentpool/prompts/prompts.py +5 -2
  77. agentpool/resource_providers/__init__.py +2 -0
  78. agentpool/resource_providers/aggregating.py +4 -2
  79. agentpool/resource_providers/base.py +13 -3
  80. agentpool/resource_providers/codemode/code_executor.py +72 -5
  81. agentpool/resource_providers/codemode/helpers.py +2 -2
  82. agentpool/resource_providers/codemode/provider.py +64 -12
  83. agentpool/resource_providers/codemode/remote_mcp_execution.py +2 -2
  84. agentpool/resource_providers/codemode/remote_provider.py +9 -12
  85. agentpool/resource_providers/filtering.py +3 -1
  86. agentpool/resource_providers/mcp_provider.py +66 -12
  87. agentpool/resource_providers/plan_provider.py +111 -18
  88. agentpool/resource_providers/pool.py +5 -3
  89. agentpool/resource_providers/resource_info.py +111 -0
  90. agentpool/resource_providers/static.py +2 -2
  91. agentpool/sessions/__init__.py +2 -0
  92. agentpool/sessions/manager.py +2 -3
  93. agentpool/sessions/models.py +9 -6
  94. agentpool/sessions/protocol.py +28 -0
  95. agentpool/sessions/session.py +11 -55
  96. agentpool/storage/manager.py +361 -54
  97. agentpool/talk/registry.py +4 -4
  98. agentpool/talk/talk.py +9 -10
  99. agentpool/testing.py +1 -1
  100. agentpool/tool_impls/__init__.py +6 -0
  101. agentpool/tool_impls/agent_cli/__init__.py +42 -0
  102. agentpool/tool_impls/agent_cli/tool.py +95 -0
  103. agentpool/tool_impls/bash/__init__.py +64 -0
  104. agentpool/tool_impls/bash/helpers.py +35 -0
  105. agentpool/tool_impls/bash/tool.py +171 -0
  106. agentpool/tool_impls/delete_path/__init__.py +70 -0
  107. agentpool/tool_impls/delete_path/tool.py +142 -0
  108. agentpool/tool_impls/download_file/__init__.py +80 -0
  109. agentpool/tool_impls/download_file/tool.py +183 -0
  110. agentpool/tool_impls/execute_code/__init__.py +55 -0
  111. agentpool/tool_impls/execute_code/tool.py +163 -0
  112. agentpool/tool_impls/grep/__init__.py +80 -0
  113. agentpool/tool_impls/grep/tool.py +200 -0
  114. agentpool/tool_impls/list_directory/__init__.py +73 -0
  115. agentpool/tool_impls/list_directory/tool.py +197 -0
  116. agentpool/tool_impls/question/__init__.py +42 -0
  117. agentpool/tool_impls/question/tool.py +127 -0
  118. agentpool/tool_impls/read/__init__.py +104 -0
  119. agentpool/tool_impls/read/tool.py +305 -0
  120. agentpool/tools/__init__.py +2 -1
  121. agentpool/tools/base.py +114 -34
  122. agentpool/tools/manager.py +57 -1
  123. agentpool/ui/base.py +2 -2
  124. agentpool/ui/mock_provider.py +2 -2
  125. agentpool/ui/stdlib_provider.py +2 -2
  126. agentpool/utils/streams.py +21 -96
  127. agentpool/vfs_registry.py +7 -2
  128. {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/METADATA +16 -22
  129. {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/RECORD +242 -195
  130. {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/WHEEL +1 -1
  131. agentpool_cli/__main__.py +20 -0
  132. agentpool_cli/create.py +1 -1
  133. agentpool_cli/serve_acp.py +59 -1
  134. agentpool_cli/serve_opencode.py +1 -1
  135. agentpool_cli/ui.py +557 -0
  136. agentpool_commands/__init__.py +12 -5
  137. agentpool_commands/agents.py +1 -1
  138. agentpool_commands/pool.py +260 -0
  139. agentpool_commands/session.py +1 -1
  140. agentpool_commands/text_sharing/__init__.py +119 -0
  141. agentpool_commands/text_sharing/base.py +123 -0
  142. agentpool_commands/text_sharing/github_gist.py +80 -0
  143. agentpool_commands/text_sharing/opencode.py +462 -0
  144. agentpool_commands/text_sharing/paste_rs.py +59 -0
  145. agentpool_commands/text_sharing/pastebin.py +116 -0
  146. agentpool_commands/text_sharing/shittycodingagent.py +112 -0
  147. agentpool_commands/utils.py +31 -32
  148. agentpool_config/__init__.py +30 -2
  149. agentpool_config/agentpool_tools.py +498 -0
  150. agentpool_config/converters.py +1 -1
  151. agentpool_config/event_handlers.py +42 -0
  152. agentpool_config/events.py +1 -1
  153. agentpool_config/forward_targets.py +1 -4
  154. agentpool_config/jinja.py +3 -3
  155. agentpool_config/mcp_server.py +1 -5
  156. agentpool_config/nodes.py +1 -1
  157. agentpool_config/observability.py +44 -0
  158. agentpool_config/session.py +0 -3
  159. agentpool_config/storage.py +38 -39
  160. agentpool_config/task.py +3 -3
  161. agentpool_config/tools.py +11 -28
  162. agentpool_config/toolsets.py +22 -90
  163. agentpool_server/a2a_server/agent_worker.py +307 -0
  164. agentpool_server/a2a_server/server.py +23 -18
  165. agentpool_server/acp_server/acp_agent.py +125 -56
  166. agentpool_server/acp_server/commands/acp_commands.py +46 -216
  167. agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +8 -7
  168. agentpool_server/acp_server/event_converter.py +651 -0
  169. agentpool_server/acp_server/input_provider.py +53 -10
  170. agentpool_server/acp_server/server.py +1 -11
  171. agentpool_server/acp_server/session.py +90 -410
  172. agentpool_server/acp_server/session_manager.py +8 -34
  173. agentpool_server/agui_server/server.py +3 -1
  174. agentpool_server/mcp_server/server.py +5 -2
  175. agentpool_server/opencode_server/ENDPOINTS.md +53 -14
  176. agentpool_server/opencode_server/OPENCODE_UI_TOOLS_COMPLETE.md +202 -0
  177. agentpool_server/opencode_server/__init__.py +0 -8
  178. agentpool_server/opencode_server/converters.py +132 -26
  179. agentpool_server/opencode_server/input_provider.py +160 -8
  180. agentpool_server/opencode_server/models/__init__.py +42 -20
  181. agentpool_server/opencode_server/models/app.py +12 -0
  182. agentpool_server/opencode_server/models/events.py +203 -29
  183. agentpool_server/opencode_server/models/mcp.py +19 -0
  184. agentpool_server/opencode_server/models/message.py +18 -1
  185. agentpool_server/opencode_server/models/parts.py +134 -1
  186. agentpool_server/opencode_server/models/question.py +56 -0
  187. agentpool_server/opencode_server/models/session.py +13 -1
  188. agentpool_server/opencode_server/routes/__init__.py +4 -0
  189. agentpool_server/opencode_server/routes/agent_routes.py +33 -2
  190. agentpool_server/opencode_server/routes/app_routes.py +66 -3
  191. agentpool_server/opencode_server/routes/config_routes.py +66 -5
  192. agentpool_server/opencode_server/routes/file_routes.py +184 -5
  193. agentpool_server/opencode_server/routes/global_routes.py +1 -1
  194. agentpool_server/opencode_server/routes/lsp_routes.py +1 -1
  195. agentpool_server/opencode_server/routes/message_routes.py +122 -66
  196. agentpool_server/opencode_server/routes/permission_routes.py +63 -0
  197. agentpool_server/opencode_server/routes/pty_routes.py +23 -22
  198. agentpool_server/opencode_server/routes/question_routes.py +128 -0
  199. agentpool_server/opencode_server/routes/session_routes.py +139 -68
  200. agentpool_server/opencode_server/routes/tui_routes.py +1 -1
  201. agentpool_server/opencode_server/server.py +47 -2
  202. agentpool_server/opencode_server/state.py +30 -0
  203. agentpool_storage/__init__.py +0 -4
  204. agentpool_storage/base.py +81 -2
  205. agentpool_storage/claude_provider/ARCHITECTURE.md +433 -0
  206. agentpool_storage/claude_provider/__init__.py +42 -0
  207. agentpool_storage/{claude_provider.py → claude_provider/provider.py} +190 -8
  208. agentpool_storage/file_provider.py +149 -15
  209. agentpool_storage/memory_provider.py +132 -12
  210. agentpool_storage/opencode_provider/ARCHITECTURE.md +386 -0
  211. agentpool_storage/opencode_provider/__init__.py +16 -0
  212. agentpool_storage/opencode_provider/helpers.py +414 -0
  213. agentpool_storage/opencode_provider/provider.py +895 -0
  214. agentpool_storage/session_store.py +20 -6
  215. agentpool_storage/sql_provider/sql_provider.py +135 -2
  216. agentpool_storage/sql_provider/utils.py +2 -12
  217. agentpool_storage/zed_provider/__init__.py +16 -0
  218. agentpool_storage/zed_provider/helpers.py +281 -0
  219. agentpool_storage/zed_provider/models.py +130 -0
  220. agentpool_storage/zed_provider/provider.py +442 -0
  221. agentpool_storage/zed_provider.py +803 -0
  222. agentpool_toolsets/__init__.py +0 -2
  223. agentpool_toolsets/builtin/__init__.py +2 -4
  224. agentpool_toolsets/builtin/code.py +4 -4
  225. agentpool_toolsets/builtin/debug.py +115 -40
  226. agentpool_toolsets/builtin/execution_environment.py +54 -165
  227. agentpool_toolsets/builtin/skills.py +0 -77
  228. agentpool_toolsets/builtin/subagent_tools.py +64 -51
  229. agentpool_toolsets/builtin/workers.py +4 -2
  230. agentpool_toolsets/composio_toolset.py +2 -2
  231. agentpool_toolsets/entry_points.py +3 -1
  232. agentpool_toolsets/fsspec_toolset/grep.py +25 -5
  233. agentpool_toolsets/fsspec_toolset/helpers.py +3 -2
  234. agentpool_toolsets/fsspec_toolset/toolset.py +350 -66
  235. agentpool_toolsets/mcp_discovery/data/mcp_servers.parquet +0 -0
  236. agentpool_toolsets/mcp_discovery/toolset.py +74 -17
  237. agentpool_toolsets/mcp_run_toolset.py +8 -11
  238. agentpool_toolsets/notifications.py +33 -33
  239. agentpool_toolsets/openapi.py +3 -1
  240. agentpool_toolsets/search_toolset.py +3 -1
  241. agentpool_config/resources.py +0 -33
  242. agentpool_server/acp_server/acp_tools.py +0 -43
  243. agentpool_server/acp_server/commands/spawn.py +0 -210
  244. agentpool_storage/opencode_provider.py +0 -730
  245. agentpool_storage/text_log_provider.py +0 -276
  246. agentpool_toolsets/builtin/chain.py +0 -288
  247. agentpool_toolsets/builtin/user_interaction.py +0 -52
  248. agentpool_toolsets/semantic_memory_toolset.py +0 -536
  249. {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/entry_points.txt +0 -0
  250. {agentpool-2.2.3.dist-info → agentpool-2.5.0.dist-info}/licenses/LICENSE +0 -0
@@ -31,11 +31,10 @@ from agentpool.agents.agui_agent.chunk_transformer import ChunkTransformer
31
31
  from agentpool.agents.agui_agent.helpers import execute_tool_calls, parse_sse_stream
32
32
  from agentpool.agents.base_agent import BaseAgent
33
33
  from agentpool.agents.events import RunStartedEvent, StreamCompleteEvent
34
+ from agentpool.agents.events.processors import FileTracker
34
35
  from agentpool.log import get_logger
35
36
  from agentpool.messaging import ChatMessage
36
- from agentpool.messaging.processing import prepare_prompts
37
37
  from agentpool.tools import ToolManager
38
- from agentpool.utils.streams import FileTracker
39
38
  from agentpool.utils.token_breakdown import calculate_usage_from_parts
40
39
 
41
40
 
@@ -45,25 +44,26 @@ if TYPE_CHECKING:
45
44
  from types import TracebackType
46
45
 
47
46
  from ag_ui.core import Message, ToolMessage
48
- from evented.configs import EventConfig
47
+ from evented_config import EventConfig
48
+ from pydantic_ai import UserContent
49
49
  from slashed import BaseCommand
50
50
  from tokonomics.model_discovery.model_info import ModelInfo
51
51
 
52
- from agentpool.agents.base_agent import ToolConfirmationMode
53
52
  from agentpool.agents.context import AgentContext
54
53
  from agentpool.agents.events import RichAgentStreamEvent
55
54
  from agentpool.agents.modes import ModeCategory, ModeInfo
56
55
  from agentpool.common_types import (
57
56
  BuiltinEventHandlerType,
58
57
  IndividualEventHandler,
59
- PromptCompatible,
60
58
  ToolType,
61
59
  )
62
60
  from agentpool.delegation import AgentPool
63
61
  from agentpool.messaging import MessageHistory
62
+ from agentpool.models.agui_agents import AGUIAgentConfig
64
63
  from agentpool.tools import Tool
65
64
  from agentpool.ui.base import InputProvider
66
65
  from agentpool_config.mcp_server import MCPServerConfig
66
+ from agentpool_config.nodes import ToolConfirmationMode
67
67
 
68
68
 
69
69
  logger = get_logger(__name__)
@@ -194,6 +194,50 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
194
194
  # Chunk transformer for normalizing CHUNK events
195
195
  self._chunk_transformer = ChunkTransformer()
196
196
 
197
+ @classmethod
198
+ def from_config(
199
+ cls,
200
+ config: AGUIAgentConfig,
201
+ *,
202
+ event_handlers: Sequence[IndividualEventHandler | BuiltinEventHandlerType] | None = None,
203
+ input_provider: InputProvider | None = None,
204
+ agent_pool: AgentPool[Any] | None = None,
205
+ ) -> Self:
206
+ """Create an AGUIAgent from a config object.
207
+
208
+ This is the preferred way to instantiate an AGUIAgent from configuration.
209
+
210
+ Args:
211
+ config: AG-UI agent configuration
212
+ event_handlers: Optional event handlers (merged with config handlers)
213
+ input_provider: Optional input provider for user interactions
214
+ agent_pool: Optional agent pool for coordination
215
+
216
+ Returns:
217
+ Configured AGUIAgent instance
218
+ """
219
+ # Merge config-level handlers with provided handlers
220
+ config_handlers = config.get_event_handlers()
221
+ merged_handlers: list[IndividualEventHandler | BuiltinEventHandlerType] = [
222
+ *config_handlers,
223
+ *(event_handlers or []),
224
+ ]
225
+ return cls(
226
+ endpoint=config.endpoint,
227
+ name=config.name or "agui-agent",
228
+ description=config.description,
229
+ display_name=config.display_name,
230
+ event_handlers=merged_handlers or None,
231
+ timeout=config.timeout,
232
+ headers=config.headers,
233
+ startup_command=config.startup_command,
234
+ startup_delay=config.startup_delay,
235
+ tools=[tool_config.get_tool() for tool_config in config.tools],
236
+ mcp_servers=config.mcp_servers,
237
+ tool_confirmation_mode=config.requires_tool_confirmation,
238
+ agent_pool=agent_pool,
239
+ )
240
+
197
241
  def get_context(self, data: Any = None) -> AgentContext:
198
242
  """Create a new context for this agent.
199
243
 
@@ -207,7 +251,7 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
207
251
  from agentpool.models.agui_agents import AGUIAgentConfig
208
252
  from agentpool.models.manifest import AgentsManifest
209
253
 
210
- cfg = AGUIAgentConfig(
254
+ cfg = AGUIAgentConfig( # type: ignore[call-arg]
211
255
  name=self.name,
212
256
  description=self.description,
213
257
  display_name=self.display_name,
@@ -219,7 +263,14 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
219
263
  startup_delay=self._startup_delay,
220
264
  )
221
265
  defn = self.agent_pool.manifest if self.agent_pool else AgentsManifest()
222
- return AgentContext(node=self, pool=self.agent_pool, config=cfg, definition=defn, data=data)
266
+ return AgentContext(
267
+ node=self,
268
+ pool=self.agent_pool,
269
+ config=cfg,
270
+ definition=defn,
271
+ input_provider=self._input_provider,
272
+ data=data,
273
+ )
223
274
 
224
275
  async def __aenter__(self) -> Self:
225
276
  """Enter async context - initialize client and base resources."""
@@ -309,71 +360,38 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
309
360
  self._startup_process = None
310
361
  self.log.info("AG-UI server stopped")
311
362
 
312
- async def run(
363
+ async def _stream_events( # noqa: PLR0915
313
364
  self,
314
- *prompts: PromptCompatible,
315
- message_id: str | None = None,
316
- input_provider: InputProvider | None = None,
317
- message_history: MessageHistory | None = None,
318
- **kwargs: Any,
319
- ) -> ChatMessage[str]:
320
- """Execute prompt against AG-UI agent.
321
-
322
- Sends the prompt to the AG-UI server and waits for completion.
323
- Events are collected via run_stream and event handlers are called.
324
- The final text content is returned as a ChatMessage.
325
-
326
- Args:
327
- prompts: Prompts to send (will be joined with spaces)
328
- message_id: Optional message id for the returned message
329
- input_provider: Optional input provider for tool confirmation requests
330
- message_history: Optional MessageHistory to use instead of agent's own
331
- **kwargs: Additional arguments (ignored for compatibility)
332
-
333
- Returns:
334
- ChatMessage containing the agent's aggregated text response
335
- """
336
- final_message: ChatMessage[str] | None = None
337
- async for event in self.run_stream(
338
- *prompts,
339
- message_id=message_id,
340
- input_provider=input_provider,
341
- message_history=message_history,
342
- ):
343
- if isinstance(event, StreamCompleteEvent):
344
- final_message = event.message
345
-
346
- if final_message is None:
347
- raise RuntimeError("No final message received from stream")
348
- return final_message
349
-
350
- async def run_stream( # noqa: PLR0915
351
- self,
352
- *prompts: PromptCompatible,
365
+ prompts: list[UserContent],
366
+ *,
367
+ user_msg: ChatMessage[Any],
368
+ effective_parent_id: str | None,
353
369
  message_id: str | None = None,
370
+ conversation_id: str | None = None,
371
+ parent_id: str | None = None,
354
372
  input_provider: InputProvider | None = None,
355
373
  message_history: MessageHistory | None = None,
356
- **kwargs: Any,
374
+ deps: TDeps | None = None,
375
+ event_handlers: Sequence[IndividualEventHandler | BuiltinEventHandlerType] | None = None,
376
+ wait_for_connections: bool | None = None,
377
+ store_history: bool = True,
357
378
  ) -> AsyncIterator[RichAgentStreamEvent[str]]:
358
- """Execute prompt with streaming events.
359
-
360
- Sends the prompt to the remote AG-UI agent along with any registered tools.
361
- When the agent requests a tool call, the tool is executed locally and the
362
- result is sent back in a continuation request.
363
-
364
- Args:
365
- prompts: Prompts to send
366
- message_id: Optional message ID
367
- input_provider: Optional input provider for tool confirmation requests
368
- message_history: Optional MessageHistory to use instead of agent's own
369
- **kwargs: Additional arguments (ignored for compatibility)
370
-
371
- Yields:
372
- Native streaming events converted from AG-UI protocol
373
- """
374
379
  # Update input provider if provided
375
380
  if input_provider is not None:
376
381
  self._input_provider = input_provider
382
+
383
+ # Use provided event handlers or fall back to agent's handlers
384
+ if event_handlers is not None:
385
+ from anyenv import MultiEventHandler
386
+
387
+ from agentpool.agents.events import resolve_event_handlers
388
+
389
+ handler: MultiEventHandler[IndividualEventHandler] = MultiEventHandler(
390
+ resolve_event_handlers(event_handlers)
391
+ )
392
+ else:
393
+ handler = self.event_handler
394
+
377
395
  from ag_ui.core import (
378
396
  RunAgentInput,
379
397
  TextMessageChunkEvent,
@@ -392,20 +410,21 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
392
410
  )
393
411
  from agentpool.agents.tool_call_accumulator import ToolCallAccumulator
394
412
 
395
- if not self._client or not self._thread_id:
413
+ if not self._client:
396
414
  msg = "Agent not initialized - use async context manager"
397
415
  raise RuntimeError(msg)
398
416
 
399
417
  # Reset cancellation state
400
418
  self._cancelled = False
401
- self._current_stream_task = asyncio.current_task()
419
+
420
+ # Conversation ID initialization handled by BaseAgent
421
+
422
+ # Set thread_id from conversation_id (needed for AG-UI protocol)
423
+ if self._thread_id is None:
424
+ self._thread_id = self.conversation_id
402
425
 
403
426
  conversation = message_history if message_history is not None else self.conversation
404
- # Get parent_id from last message in history for tree structure
405
- last_msg_id = conversation.get_last_message_id()
406
- user_msg, processed_prompts, _original_message = await prepare_prompts(
407
- *prompts, parent_id=last_msg_id
408
- )
427
+ processed_prompts = prompts
409
428
  self._run_id = str(uuid4()) # New run ID for each run
410
429
  self._chunk_transformer.reset() # Reset chunk transformer
411
430
  # Track messages in pydantic-ai format: ModelRequest -> ModelResponse -> ModelRequest...
@@ -417,13 +436,14 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
417
436
  current_response_parts: list[TextPart | ThinkingPart | ToolCallPart] = []
418
437
  text_chunks: list[str] = [] # For final content string
419
438
 
439
+ assert self.conversation_id is not None # Initialized by BaseAgent.run_stream()
420
440
  run_started = RunStartedEvent(
421
441
  thread_id=self._thread_id or self.conversation_id,
422
442
  run_id=self._run_id or str(uuid4()),
423
443
  agent_name=self.name,
424
444
  )
425
445
 
426
- await self.event_handler(None, run_started)
446
+ await handler(None, run_started)
427
447
  yield run_started
428
448
  # Get pending parts from conversation and convert them
429
449
  pending_parts = conversation.get_pending_parts()
@@ -527,18 +547,18 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
527
547
  while not self._event_queue.empty():
528
548
  try:
529
549
  custom_event = self._event_queue.get_nowait()
530
- await self.event_handler(None, custom_event)
550
+ await handler(None, custom_event)
531
551
  yield custom_event
532
552
  except asyncio.QueueEmpty:
533
553
  break
534
554
  # Distribute to handlers
535
- await self.event_handler(None, native_event)
555
+ await handler(None, native_event)
536
556
  yield native_event
537
557
 
538
558
  # Flush any pending chunk events at end of stream
539
559
  for event in self._chunk_transformer.flush():
540
560
  if native_event := agui_to_native_event(event):
541
- await self.event_handler(None, native_event)
561
+ await handler(None, native_event)
542
562
  yield native_event
543
563
 
544
564
  except httpx.HTTPError:
@@ -609,9 +629,8 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
609
629
  metadata=file_tracker.get_metadata(),
610
630
  )
611
631
  complete_event = StreamCompleteEvent(message=final_message)
612
- await self.event_handler(None, complete_event)
632
+ await handler(None, complete_event)
613
633
  yield complete_event
614
- self._current_stream_task = None
615
634
  return
616
635
 
617
636
  # Flush any remaining response parts
@@ -622,7 +641,7 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
622
641
  while not self._event_queue.empty():
623
642
  try:
624
643
  queued_event = self._event_queue.get_nowait()
625
- await self.event_handler(None, queued_event)
644
+ await handler(None, queued_event)
626
645
  yield queued_event
627
646
  except asyncio.QueueEmpty:
628
647
  break
@@ -651,30 +670,8 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
651
670
  cost_info=cost_info,
652
671
  )
653
672
  complete_event = StreamCompleteEvent(message=final_message)
654
- await self.event_handler(None, complete_event)
655
- yield complete_event
656
- # Record to conversation history
657
- conversation.add_chat_messages([user_msg, final_message])
658
-
659
- async def run_iter(
660
- self,
661
- *prompt_groups: Sequence[PromptCompatible],
662
- message_id: str | None = None,
663
- **kwargs: Any,
664
- ) -> AsyncIterator[ChatMessage[str]]:
665
- """Execute multiple prompt groups sequentially.
666
-
667
- Args:
668
- prompt_groups: Groups of prompts to execute
669
- message_id: Optional message ID base
670
- **kwargs: Additional arguments (ignored for compatibility)
671
-
672
- Yields:
673
- ChatMessage for each completed prompt group
674
- """
675
- for i, prompts in enumerate(prompt_groups):
676
- mid = f"{message_id or 'msg'}_{i}" if message_id else None
677
- yield await self.run(*prompts, message_id=mid)
673
+ await handler(None, complete_event)
674
+ yield complete_event # Post-processing handled by base class
678
675
 
679
676
  @property
680
677
  def model_name(self) -> str | None:
@@ -705,10 +702,10 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
705
702
  )
706
703
  ]
707
704
 
708
- def get_modes(self) -> list[ModeCategory]:
705
+ async def get_modes(self) -> list[ModeCategory]:
709
706
  """Get available modes for AG-UI agent.
710
707
 
711
- AG-UI doesn't expose mode information, so returns an empty list.
708
+ AG-UI doesn't expose any configurable modes - model is server-controlled.
712
709
 
713
710
  Returns:
714
711
  Empty list - no modes supported
@@ -718,16 +715,16 @@ class AGUIAgent[TDeps = None](BaseAgent[TDeps, str]):
718
715
  async def set_mode(self, mode: ModeInfo | str, category_id: str | None = None) -> None:
719
716
  """Set a mode for AG-UI agent.
720
717
 
721
- AG-UI doesn't support modes, so this always raises an error.
718
+ AG-UI doesn't support mode switching - model is controlled by remote server.
722
719
 
723
720
  Args:
724
721
  mode: The mode to set (not supported)
725
- category_id: Optional category ID (not supported)
722
+ category_id: Category ID (not supported)
726
723
 
727
724
  Raises:
728
725
  ValueError: Always - AG-UI doesn't support modes
729
726
  """
730
- msg = "AG-UI agent does not support modes"
727
+ msg = "AG-UI agent does not support mode switching - model is controlled by remote server"
731
728
  raise ValueError(msg)
732
729
 
733
730
 
@@ -16,8 +16,7 @@ if TYPE_CHECKING:
16
16
  from ag_ui.core import Event, ToolMessage
17
17
  import httpx
18
18
 
19
- from agentpool.agents.context import ConfirmationResult
20
- from agentpool.messaging.context import NodeContext
19
+ from agentpool.agents.context import AgentContext, ConfirmationResult
21
20
  from agentpool.tools import Tool
22
21
  from agentpool.ui.base import InputProvider
23
22
  from agentpool_config.nodes import ToolConfirmationMode
@@ -51,7 +50,7 @@ async def _get_tool_confirmation(
51
50
  tool: Tool,
52
51
  args: dict[str, Any],
53
52
  input_provider: InputProvider,
54
- context: NodeContext[Any],
53
+ context: AgentContext[Any],
55
54
  ) -> ConfirmationResult:
56
55
  """Get confirmation for tool execution.
57
56
 
@@ -78,7 +77,7 @@ async def execute_tool_calls(
78
77
  *,
79
78
  confirmation_mode: ToolConfirmationMode = "never",
80
79
  input_provider: InputProvider | None = None,
81
- context: NodeContext[Any] | None = None,
80
+ context: AgentContext[Any] | None = None,
82
81
  ) -> list[ToolMessage]:
83
82
  """Execute tool calls locally and return results.
84
83