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
@@ -6,18 +6,47 @@ from collections.abc import Sequence # noqa: TC003
6
6
  from typing import TYPE_CHECKING, Literal
7
7
 
8
8
  from pydantic import ConfigDict, Field
9
-
9
+ from tokonomics.model_names import AnthropicMaxModelName # noqa: TC002
10
+
11
+ from agentpool import log
12
+ from agentpool.resource_providers import StaticResourceProvider
13
+ from agentpool_config import (
14
+ AnyToolConfig, # noqa: TC001
15
+ BaseToolConfig,
16
+ )
10
17
  from agentpool_config.nodes import BaseAgentConfig
11
18
  from agentpool_config.output_types import StructuredResponseConfig # noqa: TC001
12
19
  from agentpool_config.system_prompts import PromptConfig # noqa: TC001
13
- from agentpool_config.toolsets import ToolsetConfig # noqa: TC001
14
20
 
15
21
 
16
22
  if TYPE_CHECKING:
17
23
  from agentpool.resource_providers import ResourceProvider
18
24
 
25
+ logger = log.get_logger(__name__)
19
26
 
20
27
  PermissionMode = Literal["default", "acceptEdits", "plan", "bypassPermissions"]
28
+ SettingSource = Literal["user", "project", "local"]
29
+ ToolName = Literal[
30
+ "Task",
31
+ "TaskOutput",
32
+ "Bash",
33
+ "Glob",
34
+ "Grep",
35
+ "ExitPlanMode",
36
+ "Read",
37
+ "Edit",
38
+ "Write",
39
+ "NotebookEdit",
40
+ "WebFetch",
41
+ "TodoWrite",
42
+ "WebSearch",
43
+ "KillShell",
44
+ "AskUserQuestion",
45
+ "Skill",
46
+ "EnterPlanMode",
47
+ "LSP",
48
+ "Chrome",
49
+ ]
21
50
 
22
51
 
23
52
  class ClaudeCodeAgentConfig(BaseAgentConfig):
@@ -67,14 +96,14 @@ class ClaudeCodeAgentConfig(BaseAgentConfig):
67
96
  )
68
97
  """Working directory for Claude Code operations."""
69
98
 
70
- model: str | None = Field(
99
+ model: AnthropicMaxModelName | str | None = Field(
71
100
  default=None,
72
101
  title="Model",
73
102
  examples=["claude-sonnet-4-5", "claude-opus-4", "claude-haiku-3-5"],
74
103
  )
75
104
  """Model to use for this agent. Defaults to Claude's default model."""
76
105
 
77
- allowed_tools: list[str] | None = Field(
106
+ allowed_tools: list[ToolName | str] | None = Field(
78
107
  default=None,
79
108
  title="Allowed Tools",
80
109
  examples=[["Read", "Write", "Bash"], ["Read", "Grep", "Glob"]],
@@ -85,7 +114,7 @@ class ClaudeCodeAgentConfig(BaseAgentConfig):
85
114
  Common tools: Read, Write, Edit, Bash, Glob, Grep, Task, WebFetch, etc.
86
115
  """
87
116
 
88
- disallowed_tools: list[str] | None = Field(
117
+ disallowed_tools: list[ToolName | str] | None = Field(
89
118
  default=None,
90
119
  title="Disallowed Tools",
91
120
  examples=[["Bash", "Write"], ["Task"]],
@@ -132,6 +161,17 @@ class ClaudeCodeAgentConfig(BaseAgentConfig):
132
161
  )
133
162
  """Maximum number of conversation turns before stopping."""
134
163
 
164
+ max_budget_usd: float | None = Field(
165
+ default=None,
166
+ title="Max Budget (USD)",
167
+ ge=0.0,
168
+ examples=[1.0, 5.0, 10.0],
169
+ )
170
+ """Maximum budget in USD before stopping.
171
+
172
+ When set, the agent will stop once the estimated cost exceeds this limit.
173
+ """
174
+
135
175
  max_thinking_tokens: int | None = Field(
136
176
  default=None,
137
177
  title="Max Thinking Tokens",
@@ -188,15 +228,23 @@ class ClaudeCodeAgentConfig(BaseAgentConfig):
188
228
  builtin_tools: list[str] | None = Field(
189
229
  default=None,
190
230
  title="Built-in Tools",
191
- examples=[["Bash", "Edit", "Read"], []],
231
+ examples=[["Bash", "Edit", "Read"], ["Read", "Write", "LSP"], ["Bash", "Chrome"]],
192
232
  )
193
233
  """Available tools from Claude Code's built-in set.
194
234
 
195
235
  Empty list disables all tools. If not specified, all tools are available.
196
236
  Different from allowed_tools which filters an already-available set.
237
+
238
+ Special tools:
239
+ - "LSP": Enable Language Server Protocol support for code intelligence
240
+ (go to definition, find references, symbol info, etc.)
241
+ - "Chrome": Enable Claude in Chrome integration for browser control
242
+ (opens, navigates, interacts with browser tabs)
243
+
244
+ Both LSP and Chrome require additional setup in your environment.
197
245
  """
198
246
 
199
- fallback_model: str | None = Field(
247
+ fallback_model: AnthropicMaxModelName | str | None = Field(
200
248
  default=None,
201
249
  title="Fallback Model",
202
250
  examples=["claude-sonnet-4-5", "claude-haiku-3-5"],
@@ -209,30 +257,107 @@ class ClaudeCodeAgentConfig(BaseAgentConfig):
209
257
  )
210
258
  """Bypass all permission checks. Only for sandboxed environments."""
211
259
 
212
- toolsets: list[ToolsetConfig] = Field(
260
+ setting_sources: list[SettingSource] | None = Field(
261
+ default=None,
262
+ title="Setting Sources",
263
+ examples=[["user", "project"], ["local"], ["user", "project", "local"]],
264
+ )
265
+ """Setting sources to load configuration from.
266
+
267
+ Controls which Claude Code settings files are loaded:
268
+ - "user": User-level settings (~/.config/claude/settings.json)
269
+ - "project": Project-level settings (.claude/settings.json in project root)
270
+ - "local": Local settings (.claude/settings.local.json, git-ignored)
271
+
272
+ If not specified, Claude Code will load all available settings.
273
+ """
274
+
275
+ use_subscription: bool = Field(
276
+ default=False,
277
+ title="Use Claude Subscription",
278
+ )
279
+ """Force usage of Claude subscription instead of API key.
280
+
281
+ When True, sets ANTHROPIC_API_KEY to empty string, forcing Claude Code
282
+ to use your Claude.ai subscription for authentication instead of an API key.
283
+
284
+ This is useful when:
285
+ - You have a Claude Pro/Team subscription with higher rate limits
286
+ - You want to use subscription credits instead of API credits
287
+ - You're using features only available to subscribers
288
+
289
+ Note: Requires an active Claude subscription and logged-in session.
290
+ """
291
+
292
+ tools: list[AnyToolConfig | str] = Field(
213
293
  default_factory=list,
214
- title="Toolsets",
294
+ title="Tools",
215
295
  examples=[
216
296
  [
217
297
  {"type": "subagent"},
218
298
  {"type": "agent_management"},
299
+ "webbrowser:open",
300
+ {
301
+ "type": "import",
302
+ "import_path": "webbrowser:open",
303
+ "name": "web_browser",
304
+ },
219
305
  ],
220
306
  ],
221
307
  )
222
- """Toolsets to expose to this Claude Code agent via MCP bridge.
308
+ """Tools and toolsets to expose to this Claude Code agent via MCP bridge.
223
309
 
224
- These toolsets will be started as an in-process MCP server and made
225
- available to Claude Code. This allows Claude Code to use internal
226
- agentpool toolsets like subagent delegation, agent management, etc.
310
+ Supports both single tools and toolsets. These will be started as an
311
+ in-process MCP server and made available to Claude Code.
227
312
 
228
- The toolsets are exposed using the Claude SDK's native MCP support,
229
- which passes the FastMCP server instance directly without HTTP overhead.
313
+ Docs: https://phil65.github.io/agentpool/YAML%20Configuration/tool_configuration/
230
314
  """
231
315
 
232
- def get_toolset_providers(self) -> list[ResourceProvider]:
233
- """Get resource providers for all configured toolsets.
316
+ def get_tool_providers(self) -> list[ResourceProvider]:
317
+ """Get all resource providers for this agent's tools.
318
+
319
+ Processes the unified tools list, separating:
320
+ - Toolsets: Each becomes its own ResourceProvider
321
+ - Single tools: Aggregated into a single StaticResourceProvider
234
322
 
235
323
  Returns:
236
- List of initialized ResourceProvider instances
324
+ List of ResourceProvider instances
237
325
  """
238
- return [toolset.get_provider() for toolset in self.toolsets]
326
+ from agentpool.tools.base import Tool
327
+ from agentpool_config.toolsets import BaseToolsetConfig
328
+
329
+ providers: list[ResourceProvider] = []
330
+ static_tools: list[Tool] = []
331
+
332
+ for tool_config in self.tools:
333
+ try:
334
+ if isinstance(tool_config, BaseToolsetConfig):
335
+ providers.append(tool_config.get_provider())
336
+ elif isinstance(tool_config, str):
337
+ static_tools.append(Tool.from_callable(tool_config))
338
+ elif isinstance(tool_config, BaseToolConfig):
339
+ static_tools.append(tool_config.get_tool())
340
+ except Exception:
341
+ logger.exception("Failed to load tool", config=tool_config)
342
+ continue
343
+
344
+ if static_tools:
345
+ providers.append(StaticResourceProvider(name="tools", tools=static_tools))
346
+
347
+ return providers
348
+
349
+ # Backward compatibility
350
+ def get_toolset_providers(self) -> list[ResourceProvider]:
351
+ """Deprecated: use get_tool_providers() instead."""
352
+ return [
353
+ p
354
+ for p in self.get_tool_providers()
355
+ if not isinstance(p, StaticResourceProvider) or p.name != "tools"
356
+ ]
357
+
358
+ def get_tool_provider(self) -> ResourceProvider | None:
359
+ """Deprecated: use get_tool_providers() instead."""
360
+ for p in self.get_tool_providers():
361
+ if isinstance(p, StaticResourceProvider) and p.name == "tools":
362
+ return p
363
+ return None
@@ -41,7 +41,6 @@ PERMISSION_MODE_MAP: dict[str, Literal["always", "never", "per_tool"]] = {
41
41
 
42
42
  # Fields that pass through directly to NativeAgentConfig
43
43
  PASSTHROUGH_FIELDS = {
44
- "inherits",
45
44
  "toolsets",
46
45
  "session",
47
46
  "output_type",
@@ -5,18 +5,20 @@ from __future__ import annotations
5
5
  from functools import cached_property
6
6
  from typing import TYPE_CHECKING, Annotated, Any, Self
7
7
 
8
+ from llmling_models_config import AnyModelConfig, StringModelConfig
8
9
  from pydantic import ConfigDict, Field, model_validator
9
10
  from schemez import Schema
10
- from upathtools.configs import FilesystemConfigType
11
- from upathtools.configs.base import URIFileSystemConfig
11
+ from upathtools_config import FilesystemConfigType
12
+ from upathtools_config.base import URIFileSystemConfig
12
13
 
13
14
  from agentpool import log
14
15
  from agentpool.models.acp_agents import ACPAgentConfigTypes
15
- from agentpool.models.agents import NativeAgentConfig
16
+ from agentpool.models.agents import AnyToolConfig, NativeAgentConfig # noqa: F401
16
17
  from agentpool.models.agui_agents import AGUIAgentConfig
17
18
  from agentpool.models.claude_code_agents import ClaudeCodeAgentConfig
18
19
  from agentpool.models.file_agents import FileAgentConfig
19
20
  from agentpool_config.commands import CommandConfig, StaticCommandConfig
21
+ from agentpool_config.compaction import CompactionConfig
20
22
  from agentpool_config.converters import ConversionConfig
21
23
  from agentpool_config.mcp_server import BaseMCPServerConfig, MCPServerConfig
22
24
  from agentpool_config.observability import ObservabilityConfig
@@ -38,6 +40,7 @@ from agentpool_config.workers import (
38
40
  if TYPE_CHECKING:
39
41
  from upathtools import JoinablePathLike
40
42
 
43
+ from agentpool.messaging.compaction import CompactionPipeline
41
44
  from agentpool.models.acp_agents import BaseACPAgentConfig
42
45
  from agentpool.prompts.manager import PromptManager
43
46
  from agentpool.vfs_registry import VFSRegistry
@@ -77,6 +80,12 @@ class AgentsManifest(Schema):
77
80
  INHERIT: str | list[str] | None = None
78
81
  """Inheritance references."""
79
82
 
83
+ name: str | None = None
84
+ """Optional name for this manifest.
85
+
86
+ Useful for identification when working with multiple configurations.
87
+ """
88
+
80
89
  resources: dict[str, ResourceConfig] = Field(
81
90
  default_factory=dict,
82
91
  examples=[
@@ -212,6 +221,52 @@ class AgentsManifest(Schema):
212
221
  Docs: https://phil65.github.io/agentpool/YAML%20Configuration/response_configuration/
213
222
  """
214
223
 
224
+ model_variants: dict[str, AnyModelConfig] = Field(
225
+ default_factory=dict,
226
+ examples=[
227
+ {
228
+ "thinking_high": {
229
+ "type": "anthropic",
230
+ "model": "claude-sonnet-4-5",
231
+ "max_thinking_tokens": 10000,
232
+ },
233
+ "fast_gpt": {
234
+ "type": "string",
235
+ "model": "openai:gpt-4o-mini",
236
+ "temperature": 0.3,
237
+ },
238
+ }
239
+ ],
240
+ )
241
+ """Named model variants with pre-configured settings.
242
+
243
+ Define reusable model configurations that can be referenced by name
244
+ in agent configs. Each variant specifies a base model and its settings.
245
+
246
+ Note: Currently only applies to native agents.
247
+
248
+ Example:
249
+ ```yaml
250
+ model_variants:
251
+ thinking_high:
252
+ type: anthropic
253
+ model: claude-sonnet-4-5
254
+ max_thinking_tokens: 10000
255
+
256
+ fast_gpt:
257
+ type: string
258
+ model: openai:gpt-4o-mini
259
+ temperature: 0.3
260
+ ```
261
+
262
+ Then use in agents:
263
+ ```yaml
264
+ agents:
265
+ assistant:
266
+ model: thinking_high # References the variant
267
+ ```
268
+ """
269
+
215
270
  jobs: dict[str, Job[Any]] = Field(default_factory=dict)
216
271
  """Pre-defined jobs, ready to be used by nodes."""
217
272
 
@@ -272,6 +327,30 @@ class AgentsManifest(Schema):
272
327
  path: "./prompts/analysis.md"
273
328
  """
274
329
 
330
+ compaction: CompactionConfig | None = None
331
+ """Compaction configuration for message history management.
332
+
333
+ Controls how conversation history is compacted/summarized to manage context size.
334
+ Can use a preset or define custom steps:
335
+ compaction:
336
+ preset: balanced # or: minimal, summarizing
337
+
338
+ Or custom steps:
339
+ compaction:
340
+ steps:
341
+ - type: filter_thinking
342
+ - type: summarize
343
+ model: openai:gpt-4o-mini
344
+ threshold: 15
345
+ """
346
+
347
+ config_file_path: str | None = Field(default=None, exclude=True)
348
+ """Path to the configuration file this manifest was loaded from.
349
+
350
+ Set automatically by `from_file()`. Used for resolving relative paths.
351
+ Excluded from serialization.
352
+ """
353
+
275
354
  model_config = ConfigDict(
276
355
  json_schema_extra={
277
356
  "x-icon": "octicon:file-code-16",
@@ -389,6 +468,25 @@ class AgentsManifest(Schema):
389
468
  registry.register_from_config(name, config)
390
469
  return registry
391
470
 
471
+ def resolve_model(self, model: AnyModelConfig | str) -> AnyModelConfig:
472
+ """Resolve a model specification to a model config.
473
+
474
+ If model is a string, checks model_variants first, then wraps in StringModelConfig.
475
+ If model is already an AnyModelConfig, returns it unchanged.
476
+
477
+ Args:
478
+ model: Model identifier, variant name, or config
479
+
480
+ Returns:
481
+ AnyModelConfig
482
+ """
483
+ if isinstance(model, str):
484
+ if model in self.model_variants:
485
+ return self.model_variants[model]
486
+ return StringModelConfig(identifier=model)
487
+ # Already a config
488
+ return model
489
+
392
490
  def clone_agent_config(
393
491
  self,
394
492
  name: str,
@@ -437,52 +535,6 @@ class AgentsManifest(Schema):
437
535
  self.agents[actual_name] = config
438
536
  return actual_name
439
537
 
440
- @model_validator(mode="before")
441
- @classmethod
442
- def resolve_inheritance(cls, data: dict[str, Any]) -> dict[str, Any]:
443
- """Resolve agent inheritance chains."""
444
- nodes = data.get("agents", {})
445
- resolved: dict[str, dict[str, Any]] = {}
446
- seen: set[str] = set()
447
-
448
- def resolve_node(name: str) -> dict[str, Any] | Any:
449
- if name in resolved:
450
- return resolved[name]
451
-
452
- node = nodes[name]
453
- # Skip model instances - they're already validated
454
- if not isinstance(node, dict):
455
- return node
456
-
457
- if name in seen:
458
- msg = f"Circular inheritance detected: {name}"
459
- raise ValueError(msg)
460
-
461
- seen.add(name)
462
- config = node.copy()
463
- inherit = config.get("inherits")
464
- if inherit:
465
- if inherit not in nodes:
466
- msg = f"Parent agent {inherit} not found"
467
- raise ValueError(msg)
468
-
469
- parent = resolve_node(inherit) # Get resolved parent config
470
- if isinstance(parent, dict):
471
- merged = parent.copy()
472
- merged.update(config)
473
- config = merged
474
-
475
- seen.remove(name)
476
- resolved[name] = config
477
- return config
478
-
479
- for name in nodes:
480
- resolved[name] = resolve_node(name)
481
-
482
- # Update nodes with resolved configs
483
- data["agents"] = resolved
484
- return data
485
-
486
538
  @cached_property
487
539
  def _loaded_file_agents(self) -> dict[str, NativeAgentConfig]:
488
540
  """Load and cache file-based agent configurations.
@@ -583,6 +635,16 @@ class AgentsManifest(Schema):
583
635
 
584
636
  return PromptManager(self.prompts)
585
637
 
638
+ def get_compaction_pipeline(self) -> CompactionPipeline | None:
639
+ """Get the configured compaction pipeline, if any.
640
+
641
+ Returns:
642
+ CompactionPipeline instance or None if not configured
643
+ """
644
+ if self.compaction is None:
645
+ return None
646
+ return self.compaction.build()
647
+
586
648
  # @model_validator(mode="after")
587
649
  # def validate_response_types(self) -> AgentsManifest:
588
650
  # """Ensure all agent output_types exist in responses or are inline."""
@@ -623,6 +685,7 @@ class AgentsManifest(Schema):
623
685
 
624
686
  return agent_def.model_copy(
625
687
  update={
688
+ "config_file_path": path_str,
626
689
  "agents": update_with_path(agent_def.agents),
627
690
  "teams": update_with_path(agent_def.teams),
628
691
  }
@@ -650,7 +713,7 @@ class AgentsManifest(Schema):
650
713
 
651
714
 
652
715
  if __name__ == "__main__":
653
- from llmling_models.configs import InputModelConfig
716
+ from llmling_models_config import InputModelConfig
654
717
 
655
718
  model = InputModelConfig()
656
719
  agent_cfg = NativeAgentConfig(name="test_agent", model=model)
@@ -87,7 +87,7 @@ class ConversionManager:
87
87
 
88
88
 
89
89
  if __name__ == "__main__":
90
- from docler.configs.converter_configs import MarkItDownConfig
90
+ from docler_config.converter_configs import MarkItDownConfig
91
91
 
92
92
  from agentpool_config.converters import ConversionConfig
93
93
 
@@ -8,7 +8,6 @@ import inspect
8
8
  import os
9
9
  from typing import TYPE_CHECKING, Annotated, Any, Literal, Self, assert_never
10
10
 
11
- from mcp.types import Prompt as MCPPrompt, PromptArgument
12
11
  from pydantic import ConfigDict, Field
13
12
  from pydantic_ai import BinaryContent, ImageUrl, SystemPromptPart, UserPromptPart
14
13
  from schemez import Schema
@@ -24,9 +23,9 @@ if TYPE_CHECKING:
24
23
  from collections.abc import Mapping
25
24
 
26
25
  from fastmcp.prompts.prompt import FunctionPrompt, Prompt as FastMCPPrompt
26
+ from mcp.types import Prompt as MCPPrompt, PromptArgument
27
27
  from pydantic_ai import ModelRequestPart
28
28
 
29
-
30
29
  logger = get_logger(__name__)
31
30
 
32
31
  MessageContentType = Literal["text", "resource", "image_url", "image_base64"]
@@ -421,6 +420,8 @@ class MCPClientPrompt(BasePrompt):
421
420
 
422
421
  def to_mcp_prompt(self) -> MCPPrompt:
423
422
  """Convert to MCP Prompt."""
423
+ from mcp.types import Prompt as MCPPrompt, PromptArgument
424
+
424
425
  args = [
425
426
  PromptArgument(name=i["name"], description=i["description"], required=i["required"])
426
427
  for i in self.arguments
@@ -516,6 +517,8 @@ class FilePrompt(BasePrompt):
516
517
 
517
518
  def to_mcp_prompt(self) -> MCPPrompt:
518
519
  """Convert to MCP Prompt."""
520
+ from mcp.types import Prompt as MCPPrompt
521
+
519
522
  return MCPPrompt(
520
523
  name=self.name or to_upath(self.path).name,
521
524
  description=self.description,
agentpool/repomap.py CHANGED
@@ -1109,7 +1109,7 @@ def get_file_map_from_content( # noqa: PLR0915
1109
1109
 
1110
1110
  header = (
1111
1111
  f"# File: {filename} ({lines} lines)\n"
1112
- f"# Structure map (~{tokens_approx} tokens). Use read_file with line/limit for details.\n\n"
1112
+ f"# Structure map (~{tokens_approx} tokens). Use read with line/limit for details.\n\n"
1113
1113
  )
1114
1114
 
1115
1115
  result = header + f"{filename}:\n" + tree_output
@@ -1,6 +1,12 @@
1
1
  """Resource provider implementations."""
2
2
 
3
- from agentpool.resource_providers.base import ResourceProvider
3
+ from agentpool.resource_providers.base import (
4
+ ProviderKind,
5
+ ResourceChangeEvent,
6
+ ResourceProvider,
7
+ ResourceType,
8
+ )
9
+ from agentpool.resource_providers.resource_info import ResourceInfo
4
10
  from agentpool.resource_providers.static import StaticResourceProvider
5
11
  from agentpool.resource_providers.filtering import FilteringResourceProvider
6
12
  from agentpool.resource_providers.aggregating import AggregatingResourceProvider
@@ -12,6 +18,10 @@ __all__ = [
12
18
  "FilteringResourceProvider",
13
19
  "MCPResourceProvider",
14
20
  "PlanProvider",
21
+ "ProviderKind",
22
+ "ResourceChangeEvent",
23
+ "ResourceInfo",
15
24
  "ResourceProvider",
25
+ "ResourceType",
16
26
  "StaticResourceProvider",
17
27
  ]
@@ -4,19 +4,29 @@ from __future__ import annotations
4
4
 
5
5
  from typing import TYPE_CHECKING
6
6
 
7
- from agentpool.resource_providers import ResourceProvider
7
+ from agentpool.resource_providers.base import ResourceChangeEvent, ResourceProvider
8
8
 
9
9
 
10
10
  if TYPE_CHECKING:
11
+ from collections.abc import Sequence
12
+
11
13
  from pydantic_ai import ModelRequestPart
12
14
 
13
15
  from agentpool.prompts.prompts import BasePrompt
16
+ from agentpool.resource_providers.resource_info import ResourceInfo
14
17
  from agentpool.tools.base import Tool
15
- from agentpool_config.resources import ResourceInfo
18
+
19
+ _ = ResourceChangeEvent # Used at runtime in method signatures
16
20
 
17
21
 
18
22
  class AggregatingResourceProvider(ResourceProvider):
19
- """Provider that combines resources from multiple providers."""
23
+ """Provider that combines resources from multiple providers.
24
+
25
+ Automatically forwards change signals from child providers.
26
+ When a child emits tools_changed, this provider re-emits it.
27
+ """
28
+
29
+ kind = "aggregating"
20
30
 
21
31
  def __init__(self, providers: list[ResourceProvider], name: str = "aggregating") -> None:
22
32
  """Initialize provider with list of providers to aggregate.
@@ -26,10 +36,51 @@ class AggregatingResourceProvider(ResourceProvider):
26
36
  name: Name for this provider
27
37
  """
28
38
  super().__init__(name=name)
29
- # Store reference to the providers list for dynamic updates
39
+ self._providers: list[ResourceProvider] = []
40
+ # Use property setter to set up signal forwarding
30
41
  self.providers = providers
31
42
 
32
- async def get_tools(self) -> list[Tool]:
43
+ @property
44
+ def providers(self) -> list[ResourceProvider]:
45
+ """Get the list of child providers."""
46
+ return self._providers
47
+
48
+ @providers.setter
49
+ def providers(self, value: list[ResourceProvider]) -> None:
50
+ """Set the list of child providers and set up signal forwarding."""
51
+ # Disconnect from old providers
52
+ for provider in self._providers:
53
+ provider.tools_changed.disconnect(self._forward_tools_changed)
54
+ provider.prompts_changed.disconnect(self._forward_prompts_changed)
55
+ provider.resources_changed.disconnect(self._forward_resources_changed)
56
+ provider.skills_changed.disconnect(self._forward_skills_changed)
57
+
58
+ self._providers = value
59
+
60
+ # Connect to new providers
61
+ for provider in self._providers:
62
+ provider.tools_changed.connect(self._forward_tools_changed)
63
+ provider.prompts_changed.connect(self._forward_prompts_changed)
64
+ provider.resources_changed.connect(self._forward_resources_changed)
65
+ provider.skills_changed.connect(self._forward_skills_changed)
66
+
67
+ async def _forward_tools_changed(self, event: ResourceChangeEvent) -> None:
68
+ """Forward tools_changed signal from child provider."""
69
+ await self.tools_changed.emit(event)
70
+
71
+ async def _forward_prompts_changed(self, event: ResourceChangeEvent) -> None:
72
+ """Forward prompts_changed signal from child provider."""
73
+ await self.prompts_changed.emit(event)
74
+
75
+ async def _forward_resources_changed(self, event: ResourceChangeEvent) -> None:
76
+ """Forward resources_changed signal from child provider."""
77
+ await self.resources_changed.emit(event)
78
+
79
+ async def _forward_skills_changed(self, event: ResourceChangeEvent) -> None:
80
+ """Forward skills_changed signal from child provider."""
81
+ await self.skills_changed.emit(event)
82
+
83
+ async def get_tools(self) -> Sequence[Tool]:
33
84
  """Get tools from all providers."""
34
85
  return [t for provider in self.providers for t in await provider.get_tools()]
35
86