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
@@ -0,0 +1,202 @@
1
+ # OpenCode Tools with UI Metadata Support - Complete List
2
+
3
+ ## ALL OpenCode Tools That Get Special UI Treatment
4
+
5
+ These are **all** tools registered in OpenCode's UI (`message-part.tsx`) that use metadata for enhanced rendering:
6
+
7
+ | # | Tool | AgentPool Status | Metadata Fields | UI Feature |
8
+ |---|------|------------------|-----------------|------------|
9
+ | 1 | `read` | ✅ **DONE** | `preview`, `truncated` | Shows file preview, truncation badge |
10
+ | 2 | `list` | ✅ **DONE** | `count`, `truncated` | File count, directory tree |
11
+ | 3 | `glob` | ❌ **MISSING** | `count`, `truncated` | File count, pattern display |
12
+ | 4 | `grep` | ✅ **DONE** | `matches`, `truncated` | Match count badge |
13
+ | 5 | `webfetch` | ❌ **MISSING** | `url`, `format` | URL display, format indicator |
14
+ | 6 | `task` | ❌ **MISSING** | `summary`, `sessionId` | Sub-agent tool list, navigation |
15
+ | 7 | `bash` | ✅ **DONE** | `output`, `exit`, `description` | Live output, exit code, command |
16
+ | 8 | `edit` | ✅ **DONE** | `diff`, `filediff`, `diagnostics` | **Diff viewer**, LSP errors |
17
+ | 9 | `write` | ⚠️ **PARTIAL** | `diagnostics`, `filepath`, `exists` | Code viewer, LSP errors |
18
+ | 10 | `todowrite` | ✅ **DONE** | `todos` | **Interactive checkbox list** |
19
+ | 11 | `question` | ✅ **DONE** | `answers` | **Q&A display** |
20
+
21
+ ---
22
+
23
+ ## Summary
24
+
25
+ **Total OpenCode UI Tools:** 11
26
+ **Implemented:** 6 (✅)
27
+ **Partial:** 1 (⚠️)
28
+ **Missing:** 4 (❌)
29
+
30
+ ### ✅ Implemented (6/11)
31
+ - `read`, `list`, `grep`, `bash`, `edit`, `todowrite`, `question`
32
+
33
+ ### ⚠️ Partial (1/11)
34
+ - `write` - exists but missing diagnostics integration
35
+
36
+ ### ❌ Missing (4/11)
37
+ 1. **`glob`** - File pattern matching (like grep but for filenames)
38
+ 2. **`webfetch`** - Fetch web content
39
+ 3. **`task`** - Sub-agent execution with tool summary
40
+ 4. **`write` diagnostics** - Need LSP integration
41
+
42
+ ---
43
+
44
+ ## Detailed Metadata Specifications
45
+
46
+ ### 1. read ✅
47
+ ```typescript
48
+ metadata: {
49
+ preview: string // First 20 lines
50
+ truncated: boolean // Was content cut off?
51
+ }
52
+ ```
53
+
54
+ ### 2. list ✅
55
+ ```typescript
56
+ metadata: {
57
+ count: number // Total files/dirs
58
+ truncated: boolean // Hit max limit?
59
+ }
60
+ ```
61
+
62
+ ### 3. glob ❌ NOT IMPLEMENTED
63
+ ```typescript
64
+ metadata: {
65
+ count: number // Files matched
66
+ truncated: boolean // Results limited?
67
+ }
68
+ ```
69
+
70
+ ### 4. grep ✅
71
+ ```typescript
72
+ metadata: {
73
+ matches: number // Match count
74
+ truncated: boolean // Results limited?
75
+ }
76
+ ```
77
+
78
+ ### 5. webfetch ❌ NOT IMPLEMENTED
79
+ ```typescript
80
+ metadata: {
81
+ url: string // Target URL
82
+ format: string // "markdown" | "html" | "text"
83
+ timeout?: number // Request timeout
84
+ }
85
+ ```
86
+
87
+ ### 6. task ❌ NOT IMPLEMENTED
88
+ ```typescript
89
+ metadata: {
90
+ summary: Array<{ // Sub-agent's tool calls
91
+ id: string
92
+ tool: string
93
+ state: {
94
+ status: string
95
+ title?: string
96
+ }
97
+ }>
98
+ sessionId: string // For navigation to sub-agent session
99
+ }
100
+ ```
101
+
102
+ ### 7. bash ✅
103
+ ```typescript
104
+ metadata: {
105
+ output: string // Combined stdout+stderr
106
+ exit: number | null // Exit code
107
+ description: string // Command description
108
+ }
109
+ ```
110
+
111
+ ### 8. edit ✅
112
+ ```typescript
113
+ metadata: {
114
+ diff: string // Unified diff format
115
+ filediff: {
116
+ file: string
117
+ before: string
118
+ after: string
119
+ additions: number
120
+ deletions: number
121
+ }
122
+ diagnostics: Record<string, Diagnostic[]>
123
+ }
124
+ ```
125
+
126
+ ### 9. write ⚠️ PARTIAL
127
+ ```typescript
128
+ metadata: {
129
+ diagnostics: Record<string, Diagnostic[]> // ⚠️ Not implemented
130
+ filepath: string
131
+ exists: boolean // Did file exist before?
132
+ }
133
+ ```
134
+
135
+ ### 10. todowrite ✅
136
+ ```typescript
137
+ metadata: {
138
+ todos: Array<{
139
+ content: string
140
+ status: "completed" | "pending" | "in_progress"
141
+ }>
142
+ }
143
+ ```
144
+
145
+ ### 11. question ✅
146
+ ```typescript
147
+ metadata: {
148
+ answers: Array<Array<string>> // One array per question
149
+ }
150
+ ```
151
+
152
+ ---
153
+
154
+ ## Implementation Priority
155
+
156
+ ### Must Have (P0) - Core Functionality
157
+ - ✅ All filesystem tools: read, list, grep
158
+ - ✅ Basic execution: bash
159
+ - ✅ File editing: edit
160
+ - ✅ Planning: todowrite
161
+ - ✅ Interaction: question
162
+
163
+ ### Should Have (P1) - Enhanced Features
164
+ - ❌ **`glob`** - File pattern search (HIGH - complements grep)
165
+ - ❌ **`task`** - Sub-agent tracking (HIGH - important for delegation)
166
+ - ⚠️ **`write` diagnostics** - LSP integration (MEDIUM)
167
+
168
+ ### Nice to Have (P2) - Optional
169
+ - ❌ **`webfetch`** - Web content (LOW - external dependency)
170
+
171
+ ---
172
+
173
+ ## What's Missing vs OpenCode
174
+
175
+ OpenCode has these additional tools that we don't implement:
176
+
177
+ | OpenCode Tool | Purpose | Why Not in AgentPool? |
178
+ |---------------|---------|----------------------|
179
+ | `plan` | Plan management | We use `get_plan`/`set_plan` instead |
180
+ | `todoread` | Read todos | Handled by `get_plan` |
181
+ | `batch` | Parallel tool execution | Generic utility, not core |
182
+ | `multiedit` | Multi-file edits | Advanced feature |
183
+ | `patch` | Apply git patches | Git-specific |
184
+ | `lsp` | LSP queries | We have LSP but not as a tool |
185
+ | `skill` | Execute skills | OpenCode-specific |
186
+ | `codesearch` | Semantic search | Advanced feature |
187
+ | `websearch` | Web search | External service |
188
+
189
+ **Note:** These are all valid tools but not part of the core UI metadata rendering system.
190
+
191
+ ---
192
+
193
+ ## Next Steps
194
+
195
+ To achieve 100% OpenCode UI compatibility:
196
+
197
+ 1. **Implement `glob` tool** - File pattern matching with metadata
198
+ 2. **Implement `task` tool** - Sub-agent execution tracking
199
+ 3. **Add diagnostics to `write`** - LSP integration
200
+ 4. **Implement `webfetch`** - Web content fetching (optional)
201
+
202
+ After these 4 implementations, we'll have **complete** OpenCode UI metadata support!
@@ -0,0 +1,19 @@
1
+ """OpenCode-compatible API server.
2
+
3
+ This module provides a FastAPI-based server that implements the OpenCode API,
4
+ allowing OpenCode SDK clients to interact with AgentPool agents.
5
+
6
+ Example usage:
7
+
8
+ from agentpool_server.opencode_server import OpenCodeServer
9
+
10
+ server = OpenCodeServer(port=4096)
11
+ server.run()
12
+
13
+ Or programmatically:
14
+
15
+ from agentpool_server.opencode_server import create_app
16
+
17
+ app = create_app(working_dir="/path/to/project")
18
+ # Use with uvicorn or other ASGI server
19
+ """
@@ -0,0 +1,172 @@
1
+ """Shell command validation and security checks.
2
+
3
+ Provides validation for shell commands to prevent dangerous operations
4
+ like destructive commands, privilege escalation, and path traversal.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from pathlib import Path
10
+ import re
11
+ import shlex
12
+
13
+ from fastapi import HTTPException
14
+
15
+
16
+ # Patterns for dangerous commands that should always be blocked
17
+ DANGEROUS_PATTERNS: list[tuple[re.Pattern[str], str]] = [
18
+ # Destructive file operations
19
+ (re.compile(r"\brm\s+(-[a-zA-Z]*)?.*\s+/\s*$"), "rm on root directory"),
20
+ (re.compile(r"\brm\s+-[a-zA-Z]*r[a-zA-Z]*f.*\s+/"), "recursive force delete"),
21
+ (re.compile(r"\brm\s+-[a-zA-Z]*f[a-zA-Z]*r.*\s+/"), "recursive force delete"),
22
+ (re.compile(r"\bmkfs\b"), "filesystem format"),
23
+ (re.compile(r"\bdd\s+.*of=/dev/"), "direct disk write"),
24
+ (re.compile(r">\s*/dev/sd[a-z]"), "overwrite disk device"),
25
+ # Privilege escalation
26
+ (re.compile(r"\bsudo\b"), "sudo command"),
27
+ (re.compile(r"\bsu\s+-?\s*$"), "switch user"),
28
+ (re.compile(r"\bsu\s+root\b"), "switch to root"),
29
+ (re.compile(r"\bdoas\b"), "doas command"),
30
+ # Remote code execution patterns
31
+ (re.compile(r"\bcurl\b.*\|\s*(ba)?sh"), "curl pipe to shell"),
32
+ (re.compile(r"\bwget\b.*\|\s*(ba)?sh"), "wget pipe to shell"),
33
+ (re.compile(r"\bcurl\b.*\|\s*python"), "curl pipe to python"),
34
+ (re.compile(r"\bwget\b.*\|\s*python"), "wget pipe to python"),
35
+ # Fork bombs and resource exhaustion
36
+ (re.compile(r":\(\)\s*\{\s*:\|:&\s*\}\s*;"), "fork bomb"),
37
+ (re.compile(r"\bfork\s*bomb\b", re.IGNORECASE), "fork bomb"),
38
+ # History/credential theft
39
+ (re.compile(r">\s*~/.bash_history"), "history manipulation"),
40
+ (re.compile(r"cat.*\.ssh/"), "SSH key access"),
41
+ (re.compile(r"cat.*/etc/shadow"), "shadow file access"),
42
+ # Shutdown/reboot
43
+ (re.compile(r"\bshutdown\b"), "shutdown command"),
44
+ (re.compile(r"\breboot\b"), "reboot command"),
45
+ (re.compile(r"\binit\s+0\b"), "init shutdown"),
46
+ (re.compile(r"\binit\s+6\b"), "init reboot"),
47
+ ]
48
+
49
+ # Sensitive paths that should not be accessed
50
+ SENSITIVE_PATHS = {
51
+ "/etc/passwd",
52
+ "/etc/shadow",
53
+ "/etc/sudoers",
54
+ "/etc/ssh",
55
+ "/root",
56
+ "~/.ssh",
57
+ "~/.gnupg",
58
+ "~/.aws",
59
+ "~/.config/gcloud",
60
+ }
61
+
62
+ # Patterns that indicate path traversal attempts
63
+ PATH_TRAVERSAL_PATTERN = re.compile(r"\.\.(/|\\)")
64
+
65
+
66
+ def validate_command(command: str, working_dir: str) -> None:
67
+ """Validate a shell command for security issues.
68
+
69
+ Args:
70
+ command: The shell command to validate.
71
+ working_dir: The working directory for the command.
72
+
73
+ Raises:
74
+ HTTPException: If the command is dangerous or restricted.
75
+ """
76
+ # Check for dangerous patterns
77
+ for pattern, description in DANGEROUS_PATTERNS:
78
+ if pattern.search(command):
79
+ raise HTTPException(
80
+ status_code=403,
81
+ detail=f"Command restricted: {description}",
82
+ )
83
+
84
+ # Check for sensitive path access
85
+ command_lower = command.lower()
86
+ for sensitive_path in SENSITIVE_PATHS:
87
+ # Normalize ~ to actual pattern
88
+ path_pattern = sensitive_path.replace("~", "(/home/[^/]+|~)")
89
+ if re.search(path_pattern, command_lower):
90
+ raise HTTPException(
91
+ status_code=403,
92
+ detail=f"Command restricted: access to sensitive path {sensitive_path}",
93
+ )
94
+
95
+ # Check for path traversal in the command
96
+ if PATH_TRAVERSAL_PATTERN.search(command):
97
+ # Parse the command to check if traversal escapes working_dir
98
+ _check_path_traversal(command, working_dir)
99
+
100
+
101
+ def _check_path_traversal(command: str, working_dir: str) -> None:
102
+ """Check if command contains path traversal that escapes working directory.
103
+
104
+ Args:
105
+ command: The shell command to check.
106
+ working_dir: The working directory.
107
+
108
+ Raises:
109
+ HTTPException: If path traversal escapes the working directory.
110
+ """
111
+ working_path = Path(working_dir).resolve()
112
+
113
+ # Try to extract paths from the command
114
+ try:
115
+ tokens = shlex.split(command)
116
+ except ValueError:
117
+ # If we can't parse, be conservative
118
+ tokens = command.split()
119
+
120
+ for token in tokens:
121
+ # Skip flags and operators
122
+ if token.startswith("-") or token in ("&&", "||", "|", ";", ">", "<", ">>"):
123
+ continue
124
+
125
+ # Check if token looks like a path with traversal
126
+ if ".." in token:
127
+ # Resolve the path relative to working_dir
128
+ try:
129
+ if token.startswith("/"):
130
+ resolved = Path(token).resolve()
131
+ else:
132
+ resolved = (working_path / token).resolve()
133
+
134
+ # Check if resolved path is within working_dir
135
+ try:
136
+ resolved.relative_to(working_path)
137
+ except ValueError:
138
+ raise HTTPException(
139
+ status_code=403,
140
+ detail="Command restricted: path escapes project directory",
141
+ ) from None
142
+ except (OSError, RuntimeError):
143
+ # Path resolution failed, be conservative and block
144
+ raise HTTPException(
145
+ status_code=403,
146
+ detail="Command restricted: invalid path in command",
147
+ ) from None
148
+
149
+
150
+ def validate_workdir(workdir: str | None, project_dir: str) -> None:
151
+ """Validate that a working directory is within the project.
152
+
153
+ Args:
154
+ workdir: The requested working directory (may be None).
155
+ project_dir: The project root directory.
156
+
157
+ Raises:
158
+ HTTPException: If workdir escapes the project directory.
159
+ """
160
+ if workdir is None:
161
+ return
162
+
163
+ project_path = Path(project_dir).resolve()
164
+ work_path = Path(workdir).resolve()
165
+
166
+ try:
167
+ work_path.relative_to(project_path)
168
+ except ValueError:
169
+ raise HTTPException(
170
+ status_code=403,
171
+ detail="Command restricted: working directory outside project",
172
+ ) from None