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
@@ -477,6 +477,18 @@ class MessageHistory:
477
477
  # Use cost_info if available
478
478
  return self.chat_messages.get_history_tokens()
479
479
 
480
+ def get_last_message_id(self) -> str | None:
481
+ """Get the message_id of the last message in history.
482
+
483
+ Used for setting parent_id on new messages to build the message tree.
484
+
485
+ Returns:
486
+ The message_id of the last message, or None if history is empty.
487
+ """
488
+ if not self.chat_messages:
489
+ return None
490
+ return self.chat_messages[-1].message_id
491
+
480
492
 
481
493
  if __name__ == "__main__":
482
494
  from agentpool import Agent
@@ -30,6 +30,7 @@ from agentpool.common_types import MessageRole, SimpleJsonType # noqa: TC001
30
30
  from agentpool.log import get_logger
31
31
  from agentpool.utils.inspection import dataclasses_no_defaults_repr
32
32
  from agentpool.utils.now import get_now
33
+ from agentpool.utils.pydantic_ai_helpers import safe_args_as_dict
33
34
 
34
35
 
35
36
  if TYPE_CHECKING:
@@ -198,6 +199,14 @@ class ChatMessage[TContent]:
198
199
  conversation_id: str | None = None
199
200
  """ID of the conversation this message belongs to."""
200
201
 
202
+ parent_id: str | None = None
203
+ """ID of the parent message for tree-structured conversations.
204
+
205
+ This enables branching conversations where each message knows its predecessor.
206
+ For user messages, this typically points to the previous assistant response.
207
+ For assistant responses, this points to the user message being responded to.
208
+ """
209
+
201
210
  response_time: float | None = None
202
211
  """Time it took the LLM to respond."""
203
212
 
@@ -295,12 +304,29 @@ class ChatMessage[TContent]:
295
304
  message: TPromptContent,
296
305
  conversation_id: str | None = None,
297
306
  instructions: str | None = None,
307
+ parent_id: str | None = None,
298
308
  ) -> ChatMessage[TPromptContent]:
299
- """Create a user prompt message."""
309
+ """Create a user prompt message.
310
+
311
+ Args:
312
+ message: The prompt content
313
+ conversation_id: ID of the conversation
314
+ instructions: Optional instructions for the model
315
+ parent_id: ID of the parent message (typically the previous assistant response)
316
+
317
+ Returns:
318
+ A ChatMessage representing the user prompt
319
+ """
300
320
  part = UserPromptPart(content=message)
301
321
  request = ModelRequest(parts=[part], instructions=instructions)
302
322
  id_ = conversation_id or str(uuid4())
303
- return ChatMessage(messages=[request], role="user", content=message, conversation_id=id_)
323
+ return ChatMessage(
324
+ messages=[request],
325
+ role="user",
326
+ content=message,
327
+ conversation_id=id_,
328
+ parent_id=parent_id,
329
+ )
304
330
 
305
331
  @classmethod
306
332
  def from_pydantic_ai[TContentType](
@@ -310,6 +336,7 @@ class ChatMessage[TContent]:
310
336
  conversation_id: str | None = None,
311
337
  name: str | None = None,
312
338
  forwarded_from: list[str] | None = None,
339
+ parent_id: str | None = None,
313
340
  ) -> ChatMessage[TContentType]:
314
341
  """Convert a Pydantic model to a ChatMessage."""
315
342
  match message:
@@ -322,6 +349,7 @@ class ChatMessage[TContent]:
322
349
  # instructions=instructions,
323
350
  forwarded_from=forwarded_from or [],
324
351
  name=name,
352
+ parent_id=parent_id,
325
353
  )
326
354
  case ModelResponse(
327
355
  usage=usage,
@@ -348,6 +376,7 @@ class ChatMessage[TContent]:
348
376
  provider_response_id=provider_response_id,
349
377
  name=name,
350
378
  forwarded_from=forwarded_from or [],
379
+ parent_id=parent_id,
351
380
  )
352
381
  case _ as unreachable:
353
382
  assert_never(unreachable)
@@ -360,7 +389,9 @@ class ChatMessage[TContent]:
360
389
  agent_name: str | None = None,
361
390
  message_id: str | None = None,
362
391
  conversation_id: str | None = None,
392
+ parent_id: str | None = None,
363
393
  response_time: float,
394
+ metadata: SimpleJsonType | None = None,
364
395
  ) -> ChatMessage[OutputDataT]:
365
396
  """Create a ChatMessage from a PydanticAI run result.
366
397
 
@@ -369,19 +400,29 @@ class ChatMessage[TContent]:
369
400
  agent_name: Name of the agent that generated this response
370
401
  message_id: Unique message identifier
371
402
  conversation_id: Conversation identifier
403
+ parent_id: ID of the parent message (typically the user message)
372
404
  response_time: Total time taken for the response
405
+ metadata: Optional metadata to attach to the message
373
406
 
374
407
  Returns:
375
408
  A ChatMessage with all fields populated from the result
376
409
  """
377
- # Calculate costs
410
+ # Calculate costs - prefer provider-reported cost if available
378
411
  run_usage = result.usage()
379
412
  usage = result.response.usage
380
- cost_info = await TokenCost.from_usage(
381
- model=result.response.model_name or "",
382
- usage=run_usage,
383
- provider=result.response.provider_name,
384
- )
413
+ provider_cost = (result.response.provider_details or {}).get("cost")
414
+ if provider_cost is not None:
415
+ # Use actual cost from provider (e.g., OpenRouter returns this)
416
+ cost_info: TokenCost | None = TokenCost(
417
+ token_usage=run_usage, total_cost=Decimal(str(provider_cost))
418
+ )
419
+ else:
420
+ # Fall back to calculated cost
421
+ cost_info = await TokenCost.from_usage(
422
+ model=result.response.model_name or "",
423
+ usage=run_usage,
424
+ provider=result.response.provider_name,
425
+ )
385
426
 
386
427
  return ChatMessage[OutputDataT](
387
428
  content=result.output,
@@ -395,9 +436,11 @@ class ChatMessage[TContent]:
395
436
  provider_name=result.response.provider_name,
396
437
  message_id=message_id or str(uuid4()),
397
438
  conversation_id=conversation_id,
439
+ parent_id=parent_id,
398
440
  cost_info=cost_info,
399
441
  response_time=response_time,
400
442
  provider_details={},
443
+ metadata=metadata or {},
401
444
  )
402
445
 
403
446
  def forwarded(self, previous_message: ChatMessage[Any]) -> Self:
@@ -509,7 +552,7 @@ class ChatMessage[TContent]:
509
552
  call_part = call_parts[part.tool_call_id]
510
553
  tool_info = ToolCallInfo(
511
554
  tool_name=call_part.tool_name,
512
- args=call_part.args_as_dict(),
555
+ args=safe_args_as_dict(call_part),
513
556
  agent_name=agent_name or "UNSET",
514
557
  result=part.content,
515
558
  tool_call_id=call_part.tool_call_id or str(uuid4()),
@@ -18,6 +18,7 @@ if TYPE_CHECKING:
18
18
 
19
19
  async def prepare_prompts(
20
20
  *prompt: PromptCompatible | ChatMessage[Any],
21
+ parent_id: str | None = None,
21
22
  ) -> tuple[ChatMessage[Any], list[UserContent], ChatMessage[Any] | None]:
22
23
  """Prepare prompts for processing.
23
24
 
@@ -25,6 +26,7 @@ async def prepare_prompts(
25
26
 
26
27
  Args:
27
28
  *prompt: The prompt(s) to prepare.
29
+ parent_id: Optional ID of the parent message (typically the previous response).
28
30
 
29
31
  Returns:
30
32
  A tuple of:
@@ -41,7 +43,7 @@ async def prepare_prompts(
41
43
  # clear cost info to avoid double-counting
42
44
  return user_msg, prompts, original_msg
43
45
  prompts = await convert_prompts(prompt)
44
- user_msg = ChatMessage.user_prompt(message=prompts)
46
+ user_msg = ChatMessage.user_prompt(message=prompts, parent_id=parent_id)
45
47
  return user_msg, prompts, None
46
48
 
47
49
 
@@ -13,7 +13,6 @@ from exxec.configs import (
13
13
  ExecutionEnvironmentConfig, # noqa: TC002
14
14
  )
15
15
  from pydantic import ConfigDict, Field
16
- from tokonomics.model_discovery import ProviderType # noqa: TC002
17
16
 
18
17
  from agentpool_config.nodes import NodeConfig
19
18
  from agentpool_config.system_prompts import PromptConfig # noqa: TC001
@@ -239,15 +238,6 @@ class BaseACPAgentConfig(NodeConfig):
239
238
  return get_environment(self.client_execution_environment)
240
239
  return self.client_execution_environment.get_provider()
241
240
 
242
- @property
243
- def model_providers(self) -> list[ProviderType]:
244
- """Return the model providers used by this ACP agent.
245
-
246
- Override in subclasses to specify which providers the agent uses.
247
- Used for intelligent model discovery and fallback configuration.
248
- """
249
- return []
250
-
251
241
 
252
242
  class ACPAgentConfig(BaseACPAgentConfig):
253
243
  """Configuration for a custom ACP agent with explicit command.
@@ -286,18 +276,6 @@ class ACPAgentConfig(BaseACPAgentConfig):
286
276
  )
287
277
  """Arguments to pass to the command."""
288
278
 
289
- providers: list[ProviderType] = Field(
290
- default_factory=list,
291
- title="Providers",
292
- examples=[["openai", "anthropic"], ["gemini"]],
293
- )
294
- """Model providers this agent can use."""
295
-
296
- @property
297
- def model_providers(self) -> list[ProviderType]:
298
- """Return configured providers for custom ACP agents."""
299
- return list(self.providers)
300
-
301
279
  def get_command(self) -> str:
302
280
  """Get the command to spawn the ACP server."""
303
281
  return self.command
@@ -5,8 +5,8 @@ from __future__ import annotations
5
5
  import json
6
6
  from typing import TYPE_CHECKING, Any, Literal, assert_never, cast
7
7
 
8
+ import anyenv
8
9
  from pydantic import BaseModel, ConfigDict, Field
9
- from tokonomics.model_discovery import ProviderType # noqa: TC002
10
10
 
11
11
  from agentpool.models.acp_agents.base import BaseACPAgentConfig
12
12
  from agentpool_config.output_types import StructuredResponseConfig # noqa: TC001
@@ -211,9 +211,9 @@ class ClaudeACPAgentConfig(MCPCapableACPAgentConfig):
211
211
  )
212
212
  """Fallback model when default is overloaded."""
213
213
 
214
- dangerously_skip_permissions: bool = Field(
214
+ auto_approve: bool = Field(
215
215
  default=False,
216
- title="Dangerously Skip Permissions",
216
+ title="Auto Approve",
217
217
  )
218
218
  """Bypass all permission checks. Only for sandboxed environments."""
219
219
 
@@ -267,7 +267,7 @@ class ClaudeACPAgentConfig(MCPCapableACPAgentConfig):
267
267
  args.extend(["--tools", ""])
268
268
  if self.fallback_model:
269
269
  args.extend(["--fallback-model", self.fallback_model])
270
- if self.dangerously_skip_permissions:
270
+ if self.auto_approve:
271
271
  args.append("--dangerously-skip-permissions")
272
272
  if self.output_type:
273
273
  args.extend(["--output-format", "json"])
@@ -286,128 +286,7 @@ class ClaudeACPAgentConfig(MCPCapableACPAgentConfig):
286
286
  return None
287
287
  # StructuredResponseConfig - resolve schema via get_schema()
288
288
  model_cls = cast(type[BaseModel], self.output_type.response_schema.get_schema())
289
- return json.dumps(model_cls.model_json_schema())
290
-
291
- @property
292
- def model_providers(self) -> list[ProviderType]:
293
- """Claude Code uses Anthropic models."""
294
- return ["anthropic"]
295
-
296
-
297
- class GeminiACPAgentConfig(MCPCapableACPAgentConfig):
298
- """Configuration for Gemini CLI via ACP.
299
-
300
- Provides typed settings for the gemini CLI with ACP support.
301
-
302
- Example:
303
- ```yaml
304
- agents:
305
- coder:
306
- type: acp
307
- provider: gemini
308
- cwd: /path/to/project
309
- model: gemini-2.5-pro
310
- approval_mode: auto_edit
311
- allowed_tools:
312
- - read_file
313
- - write_file
314
- - terminal
315
- ```
316
- """
317
-
318
- model_config = ConfigDict(json_schema_extra={"title": "Gemini ACP Agent Configuration"})
319
-
320
- provider: Literal["gemini"] = Field("gemini", init=False)
321
- """Discriminator for Gemini ACP agent."""
322
-
323
- model: str | None = Field(
324
- default=None,
325
- title="Model",
326
- examples=["gemini-2.5-pro", "gemini-2.5-flash"],
327
- )
328
- """Model override."""
329
-
330
- approval_mode: Literal["default", "auto_edit", "yolo"] | None = Field(
331
- default=None,
332
- title="Approval Mode",
333
- examples=["auto_edit", "yolo"],
334
- )
335
- """Approval mode for tool execution."""
336
-
337
- sandbox: bool = Field(default=False, title="Sandbox")
338
- """Run in sandbox mode."""
339
-
340
- yolo: bool = Field(default=False, title="YOLO")
341
- """Automatically accept all actions."""
342
-
343
- allowed_tools: list[str] | None = Field(
344
- default=None,
345
- title="Allowed Tools",
346
- examples=[["read_file", "write_file", "terminal"], ["search"]],
347
- )
348
- """Tools allowed to run without confirmation."""
349
-
350
- allowed_mcp_server_names: list[str] | None = Field(
351
- default=None,
352
- title="Allowed MCP Server Names",
353
- examples=[["filesystem", "github"], ["slack"]],
354
- )
355
- """Allowed MCP server names."""
356
-
357
- extensions: list[str] | None = Field(
358
- default=None,
359
- title="Extensions",
360
- examples=[["python", "typescript"], ["rust", "go"]],
361
- )
362
- """List of extensions to use. If not provided, all are used."""
363
-
364
- include_directories: list[str] | None = Field(
365
- default=None,
366
- title="Include Directories",
367
- examples=[["/path/to/lib", "/path/to/shared"], ["./vendor"]],
368
- )
369
- """Additional directories to include in the workspace."""
370
-
371
- output_format: Literal["text", "json", "stream-json"] | None = Field(
372
- default=None,
373
- title="Output Format",
374
- examples=["json", "stream-json"],
375
- )
376
- """Output format."""
377
-
378
- def get_command(self) -> str:
379
- """Get the command to spawn the ACP server."""
380
- return "gemini"
381
-
382
- @property
383
- def model_providers(self) -> list[ProviderType]:
384
- """Gemini CLI uses Google Gemini models."""
385
- return ["gemini"]
386
-
387
- async def get_args(self, prompt_manager: PromptManager | None = None) -> list[str]:
388
- """Build command arguments from settings."""
389
- args: list[str] = ["--experimental-acp"]
390
-
391
- if self.model:
392
- args.extend(["--model", self.model])
393
- if self.approval_mode:
394
- args.extend(["--approval-mode", self.approval_mode])
395
- if self.sandbox:
396
- args.append("--sandbox")
397
- if self.yolo:
398
- args.append("--yolo")
399
- if self.allowed_tools:
400
- args.extend(["--allowed-tools", *self.allowed_tools])
401
- if self.allowed_mcp_server_names:
402
- args.extend(["--allowed-mcp-server-names", *self.allowed_mcp_server_names])
403
- if self.extensions:
404
- args.extend(["--extensions", *self.extensions])
405
- if self.include_directories:
406
- args.extend(["--include-directories", *self.include_directories])
407
- if self.output_format:
408
- args.extend(["--output-format", self.output_format])
409
-
410
- return args
289
+ return anyenv.dump_json(model_cls.model_json_schema())
411
290
 
412
291
 
413
292
  class FastAgentACPAgentConfig(MCPCapableACPAgentConfig):
@@ -513,11 +392,6 @@ class FastAgentACPAgentConfig(MCPCapableACPAgentConfig):
513
392
 
514
393
  return args
515
394
 
516
- @property
517
- def model_providers(self) -> list[ProviderType]:
518
- """fast-agent supports multiple providers."""
519
- return ["openai", "anthropic", "gemini", "openrouter"]
520
-
521
395
 
522
396
  class AuggieACPAgentConfig(MCPCapableACPAgentConfig):
523
397
  """Configuration for Auggie (Augment Code) via ACP.
@@ -681,11 +555,6 @@ class AuggieACPAgentConfig(MCPCapableACPAgentConfig):
681
555
 
682
556
  return args
683
557
 
684
- @property
685
- def model_providers(self) -> list[ProviderType]:
686
- """Auggie uses Augment Code's models."""
687
- return []
688
-
689
558
 
690
559
  class KimiACPAgentConfig(MCPCapableACPAgentConfig):
691
560
  """Configuration for Kimi CLI via ACP.
@@ -737,7 +606,7 @@ class KimiACPAgentConfig(MCPCapableACPAgentConfig):
737
606
  )
738
607
  """Working directory for the agent."""
739
608
 
740
- yolo: bool = Field(default=False, title="YOLO")
609
+ auto_approve: bool = Field(default=False, title="Auto Approve")
741
610
  """Automatically approve all actions."""
742
611
 
743
612
  thinking: bool | None = Field(default=None, title="Thinking")
@@ -767,24 +636,15 @@ class KimiACPAgentConfig(MCPCapableACPAgentConfig):
767
636
  if mcp_json:
768
637
  args.extend(["--mcp-config", mcp_json])
769
638
 
770
- if self.yolo:
639
+ if self.auto_approve:
771
640
  args.append("--yolo")
772
641
  if self.thinking is not None and self.thinking:
773
642
  args.append("--thinking")
774
643
 
775
644
  return args
776
645
 
777
- @property
778
- def model_providers(self) -> list[ProviderType]:
779
- """Kimi uses Moonshot AI's models."""
780
- return []
781
-
782
646
 
783
647
  # Union of all ACP agent config types
784
648
  MCPCapableACPAgentConfigTypes = (
785
- ClaudeACPAgentConfig
786
- | GeminiACPAgentConfig
787
- | FastAgentACPAgentConfig
788
- | AuggieACPAgentConfig
789
- | KimiACPAgentConfig
649
+ ClaudeACPAgentConfig | FastAgentACPAgentConfig | AuggieACPAgentConfig | KimiACPAgentConfig
790
650
  )