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.
- acp/__init__.py +13 -4
- acp/acp_requests.py +20 -77
- acp/agent/connection.py +8 -0
- acp/agent/implementations/debug_server/debug_server.py +6 -2
- acp/agent/protocol.py +6 -0
- acp/bridge/README.md +15 -2
- acp/bridge/__init__.py +3 -2
- acp/bridge/__main__.py +60 -19
- acp/bridge/ws_server.py +173 -0
- acp/bridge/ws_server_cli.py +89 -0
- acp/client/connection.py +38 -29
- acp/client/implementations/default_client.py +3 -2
- acp/client/implementations/headless_client.py +2 -2
- acp/connection.py +2 -2
- acp/notifications.py +20 -50
- acp/schema/__init__.py +2 -0
- acp/schema/agent_responses.py +21 -0
- acp/schema/client_requests.py +3 -3
- acp/schema/session_state.py +63 -29
- acp/stdio.py +39 -9
- acp/task/supervisor.py +2 -2
- acp/transports.py +362 -2
- acp/utils.py +17 -4
- agentpool/__init__.py +6 -1
- agentpool/agents/__init__.py +2 -0
- agentpool/agents/acp_agent/acp_agent.py +407 -277
- agentpool/agents/acp_agent/acp_converters.py +196 -38
- agentpool/agents/acp_agent/client_handler.py +191 -26
- agentpool/agents/acp_agent/session_state.py +17 -6
- agentpool/agents/agent.py +607 -572
- agentpool/agents/agui_agent/__init__.py +0 -2
- agentpool/agents/agui_agent/agui_agent.py +176 -110
- agentpool/agents/agui_agent/agui_converters.py +0 -131
- agentpool/agents/agui_agent/helpers.py +3 -4
- agentpool/agents/base_agent.py +632 -17
- agentpool/agents/claude_code_agent/FORKING.md +191 -0
- agentpool/agents/claude_code_agent/__init__.py +13 -1
- agentpool/agents/claude_code_agent/claude_code_agent.py +1058 -291
- agentpool/agents/claude_code_agent/converters.py +74 -143
- agentpool/agents/claude_code_agent/history.py +474 -0
- agentpool/agents/claude_code_agent/models.py +77 -0
- agentpool/agents/claude_code_agent/static_info.py +100 -0
- agentpool/agents/claude_code_agent/usage.py +242 -0
- agentpool/agents/context.py +40 -0
- agentpool/agents/events/__init__.py +24 -0
- agentpool/agents/events/builtin_handlers.py +67 -1
- agentpool/agents/events/event_emitter.py +32 -2
- agentpool/agents/events/events.py +104 -3
- agentpool/agents/events/infer_info.py +145 -0
- agentpool/agents/events/processors.py +254 -0
- agentpool/agents/interactions.py +41 -6
- agentpool/agents/modes.py +67 -0
- agentpool/agents/slashed_agent.py +5 -4
- agentpool/agents/tool_call_accumulator.py +213 -0
- agentpool/agents/tool_wrapping.py +18 -6
- agentpool/common_types.py +56 -21
- agentpool/config_resources/__init__.py +38 -1
- agentpool/config_resources/acp_assistant.yml +2 -2
- agentpool/config_resources/agents.yml +3 -0
- agentpool/config_resources/agents_template.yml +1 -0
- agentpool/config_resources/claude_code_agent.yml +10 -6
- agentpool/config_resources/external_acp_agents.yml +2 -1
- agentpool/delegation/base_team.py +4 -30
- agentpool/delegation/pool.py +136 -289
- agentpool/delegation/team.py +58 -57
- agentpool/delegation/teamrun.py +51 -55
- agentpool/diagnostics/__init__.py +53 -0
- agentpool/diagnostics/lsp_manager.py +1593 -0
- agentpool/diagnostics/lsp_proxy.py +41 -0
- agentpool/diagnostics/lsp_proxy_script.py +229 -0
- agentpool/diagnostics/models.py +398 -0
- agentpool/functional/run.py +10 -4
- agentpool/mcp_server/__init__.py +0 -2
- agentpool/mcp_server/client.py +76 -32
- agentpool/mcp_server/conversions.py +54 -13
- agentpool/mcp_server/manager.py +34 -54
- agentpool/mcp_server/registries/official_registry_client.py +35 -1
- agentpool/mcp_server/tool_bridge.py +186 -139
- agentpool/messaging/__init__.py +0 -2
- agentpool/messaging/compaction.py +72 -197
- agentpool/messaging/connection_manager.py +11 -10
- agentpool/messaging/event_manager.py +5 -5
- agentpool/messaging/message_container.py +6 -30
- agentpool/messaging/message_history.py +99 -8
- agentpool/messaging/messagenode.py +52 -14
- agentpool/messaging/messages.py +54 -35
- agentpool/messaging/processing.py +12 -22
- agentpool/models/__init__.py +1 -1
- agentpool/models/acp_agents/base.py +6 -24
- agentpool/models/acp_agents/mcp_capable.py +126 -157
- agentpool/models/acp_agents/non_mcp.py +129 -95
- agentpool/models/agents.py +98 -76
- agentpool/models/agui_agents.py +1 -1
- agentpool/models/claude_code_agents.py +144 -19
- agentpool/models/file_parsing.py +0 -1
- agentpool/models/manifest.py +113 -50
- agentpool/prompts/conversion_manager.py +1 -1
- agentpool/prompts/prompts.py +5 -2
- agentpool/repomap.py +1 -1
- agentpool/resource_providers/__init__.py +11 -1
- agentpool/resource_providers/aggregating.py +56 -5
- agentpool/resource_providers/base.py +70 -4
- agentpool/resource_providers/codemode/code_executor.py +72 -5
- agentpool/resource_providers/codemode/helpers.py +2 -2
- agentpool/resource_providers/codemode/provider.py +64 -12
- agentpool/resource_providers/codemode/remote_mcp_execution.py +2 -2
- agentpool/resource_providers/codemode/remote_provider.py +9 -12
- agentpool/resource_providers/filtering.py +3 -1
- agentpool/resource_providers/mcp_provider.py +89 -12
- agentpool/resource_providers/plan_provider.py +228 -46
- agentpool/resource_providers/pool.py +7 -3
- agentpool/resource_providers/resource_info.py +111 -0
- agentpool/resource_providers/static.py +4 -2
- agentpool/sessions/__init__.py +4 -1
- agentpool/sessions/manager.py +33 -5
- agentpool/sessions/models.py +59 -6
- agentpool/sessions/protocol.py +28 -0
- agentpool/sessions/session.py +11 -55
- agentpool/skills/registry.py +13 -8
- agentpool/storage/manager.py +572 -49
- agentpool/talk/registry.py +4 -4
- agentpool/talk/talk.py +9 -10
- agentpool/testing.py +538 -20
- agentpool/tool_impls/__init__.py +6 -0
- agentpool/tool_impls/agent_cli/__init__.py +42 -0
- agentpool/tool_impls/agent_cli/tool.py +95 -0
- agentpool/tool_impls/bash/__init__.py +64 -0
- agentpool/tool_impls/bash/helpers.py +35 -0
- agentpool/tool_impls/bash/tool.py +171 -0
- agentpool/tool_impls/delete_path/__init__.py +70 -0
- agentpool/tool_impls/delete_path/tool.py +142 -0
- agentpool/tool_impls/download_file/__init__.py +80 -0
- agentpool/tool_impls/download_file/tool.py +183 -0
- agentpool/tool_impls/execute_code/__init__.py +55 -0
- agentpool/tool_impls/execute_code/tool.py +163 -0
- agentpool/tool_impls/grep/__init__.py +80 -0
- agentpool/tool_impls/grep/tool.py +200 -0
- agentpool/tool_impls/list_directory/__init__.py +73 -0
- agentpool/tool_impls/list_directory/tool.py +197 -0
- agentpool/tool_impls/question/__init__.py +42 -0
- agentpool/tool_impls/question/tool.py +127 -0
- agentpool/tool_impls/read/__init__.py +104 -0
- agentpool/tool_impls/read/tool.py +305 -0
- agentpool/tools/__init__.py +2 -1
- agentpool/tools/base.py +114 -34
- agentpool/tools/manager.py +57 -1
- agentpool/ui/base.py +2 -2
- agentpool/ui/mock_provider.py +2 -2
- agentpool/ui/stdlib_provider.py +2 -2
- agentpool/utils/file_watcher.py +269 -0
- agentpool/utils/identifiers.py +121 -0
- agentpool/utils/pydantic_ai_helpers.py +46 -0
- agentpool/utils/streams.py +616 -2
- agentpool/utils/subprocess_utils.py +155 -0
- agentpool/utils/token_breakdown.py +461 -0
- agentpool/vfs_registry.py +7 -2
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/METADATA +41 -27
- agentpool-2.5.0.dist-info/RECORD +579 -0
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/WHEEL +1 -1
- agentpool_cli/__main__.py +24 -0
- agentpool_cli/create.py +1 -1
- agentpool_cli/serve_acp.py +100 -21
- agentpool_cli/serve_agui.py +87 -0
- agentpool_cli/serve_opencode.py +119 -0
- agentpool_cli/ui.py +557 -0
- agentpool_commands/__init__.py +42 -5
- agentpool_commands/agents.py +75 -2
- agentpool_commands/history.py +62 -0
- agentpool_commands/mcp.py +176 -0
- agentpool_commands/models.py +56 -3
- agentpool_commands/pool.py +260 -0
- agentpool_commands/session.py +1 -1
- agentpool_commands/text_sharing/__init__.py +119 -0
- agentpool_commands/text_sharing/base.py +123 -0
- agentpool_commands/text_sharing/github_gist.py +80 -0
- agentpool_commands/text_sharing/opencode.py +462 -0
- agentpool_commands/text_sharing/paste_rs.py +59 -0
- agentpool_commands/text_sharing/pastebin.py +116 -0
- agentpool_commands/text_sharing/shittycodingagent.py +112 -0
- agentpool_commands/tools.py +57 -0
- agentpool_commands/utils.py +80 -30
- agentpool_config/__init__.py +30 -2
- agentpool_config/agentpool_tools.py +498 -0
- agentpool_config/builtin_tools.py +77 -22
- agentpool_config/commands.py +24 -1
- agentpool_config/compaction.py +258 -0
- agentpool_config/converters.py +1 -1
- agentpool_config/event_handlers.py +42 -0
- agentpool_config/events.py +1 -1
- agentpool_config/forward_targets.py +1 -4
- agentpool_config/jinja.py +3 -3
- agentpool_config/mcp_server.py +132 -6
- agentpool_config/nodes.py +1 -1
- agentpool_config/observability.py +44 -0
- agentpool_config/session.py +0 -3
- agentpool_config/storage.py +82 -38
- agentpool_config/task.py +3 -3
- agentpool_config/tools.py +11 -22
- agentpool_config/toolsets.py +109 -233
- agentpool_server/a2a_server/agent_worker.py +307 -0
- agentpool_server/a2a_server/server.py +23 -18
- agentpool_server/acp_server/acp_agent.py +234 -181
- agentpool_server/acp_server/commands/acp_commands.py +151 -156
- agentpool_server/acp_server/commands/docs_commands/fetch_repo.py +18 -17
- agentpool_server/acp_server/event_converter.py +651 -0
- agentpool_server/acp_server/input_provider.py +53 -10
- agentpool_server/acp_server/server.py +24 -90
- agentpool_server/acp_server/session.py +173 -331
- agentpool_server/acp_server/session_manager.py +8 -34
- agentpool_server/agui_server/server.py +3 -1
- agentpool_server/mcp_server/server.py +5 -2
- agentpool_server/opencode_server/.rules +95 -0
- agentpool_server/opencode_server/ENDPOINTS.md +401 -0
- agentpool_server/opencode_server/OPENCODE_UI_TOOLS_COMPLETE.md +202 -0
- agentpool_server/opencode_server/__init__.py +19 -0
- agentpool_server/opencode_server/command_validation.py +172 -0
- agentpool_server/opencode_server/converters.py +975 -0
- agentpool_server/opencode_server/dependencies.py +24 -0
- agentpool_server/opencode_server/input_provider.py +421 -0
- agentpool_server/opencode_server/models/__init__.py +250 -0
- agentpool_server/opencode_server/models/agent.py +53 -0
- agentpool_server/opencode_server/models/app.py +72 -0
- agentpool_server/opencode_server/models/base.py +26 -0
- agentpool_server/opencode_server/models/common.py +23 -0
- agentpool_server/opencode_server/models/config.py +37 -0
- agentpool_server/opencode_server/models/events.py +821 -0
- agentpool_server/opencode_server/models/file.py +88 -0
- agentpool_server/opencode_server/models/mcp.py +44 -0
- agentpool_server/opencode_server/models/message.py +179 -0
- agentpool_server/opencode_server/models/parts.py +323 -0
- agentpool_server/opencode_server/models/provider.py +81 -0
- agentpool_server/opencode_server/models/pty.py +43 -0
- agentpool_server/opencode_server/models/question.py +56 -0
- agentpool_server/opencode_server/models/session.py +111 -0
- agentpool_server/opencode_server/routes/__init__.py +29 -0
- agentpool_server/opencode_server/routes/agent_routes.py +473 -0
- agentpool_server/opencode_server/routes/app_routes.py +202 -0
- agentpool_server/opencode_server/routes/config_routes.py +302 -0
- agentpool_server/opencode_server/routes/file_routes.py +571 -0
- agentpool_server/opencode_server/routes/global_routes.py +94 -0
- agentpool_server/opencode_server/routes/lsp_routes.py +319 -0
- agentpool_server/opencode_server/routes/message_routes.py +761 -0
- agentpool_server/opencode_server/routes/permission_routes.py +63 -0
- agentpool_server/opencode_server/routes/pty_routes.py +300 -0
- agentpool_server/opencode_server/routes/question_routes.py +128 -0
- agentpool_server/opencode_server/routes/session_routes.py +1276 -0
- agentpool_server/opencode_server/routes/tui_routes.py +139 -0
- agentpool_server/opencode_server/server.py +475 -0
- agentpool_server/opencode_server/state.py +151 -0
- agentpool_server/opencode_server/time_utils.py +8 -0
- agentpool_storage/__init__.py +12 -0
- agentpool_storage/base.py +184 -2
- agentpool_storage/claude_provider/ARCHITECTURE.md +433 -0
- agentpool_storage/claude_provider/__init__.py +42 -0
- agentpool_storage/claude_provider/provider.py +1089 -0
- agentpool_storage/file_provider.py +278 -15
- agentpool_storage/memory_provider.py +193 -12
- agentpool_storage/models.py +3 -0
- agentpool_storage/opencode_provider/ARCHITECTURE.md +386 -0
- agentpool_storage/opencode_provider/__init__.py +16 -0
- agentpool_storage/opencode_provider/helpers.py +414 -0
- agentpool_storage/opencode_provider/provider.py +895 -0
- agentpool_storage/project_store.py +325 -0
- agentpool_storage/session_store.py +26 -6
- agentpool_storage/sql_provider/__init__.py +4 -2
- agentpool_storage/sql_provider/models.py +48 -0
- agentpool_storage/sql_provider/sql_provider.py +269 -3
- agentpool_storage/sql_provider/utils.py +12 -13
- agentpool_storage/zed_provider/__init__.py +16 -0
- agentpool_storage/zed_provider/helpers.py +281 -0
- agentpool_storage/zed_provider/models.py +130 -0
- agentpool_storage/zed_provider/provider.py +442 -0
- agentpool_storage/zed_provider.py +803 -0
- agentpool_toolsets/__init__.py +0 -2
- agentpool_toolsets/builtin/__init__.py +2 -12
- agentpool_toolsets/builtin/code.py +96 -57
- agentpool_toolsets/builtin/debug.py +118 -48
- agentpool_toolsets/builtin/execution_environment.py +115 -230
- agentpool_toolsets/builtin/file_edit/file_edit.py +115 -7
- agentpool_toolsets/builtin/skills.py +9 -4
- agentpool_toolsets/builtin/subagent_tools.py +64 -51
- agentpool_toolsets/builtin/workers.py +4 -2
- agentpool_toolsets/composio_toolset.py +2 -2
- agentpool_toolsets/entry_points.py +3 -1
- agentpool_toolsets/fsspec_toolset/__init__.py +13 -1
- agentpool_toolsets/fsspec_toolset/diagnostics.py +860 -73
- agentpool_toolsets/fsspec_toolset/grep.py +99 -7
- agentpool_toolsets/fsspec_toolset/helpers.py +3 -2
- agentpool_toolsets/fsspec_toolset/image_utils.py +161 -0
- agentpool_toolsets/fsspec_toolset/toolset.py +500 -95
- agentpool_toolsets/mcp_discovery/__init__.py +5 -0
- agentpool_toolsets/mcp_discovery/data/mcp_servers.parquet +0 -0
- agentpool_toolsets/mcp_discovery/toolset.py +511 -0
- agentpool_toolsets/mcp_run_toolset.py +87 -12
- agentpool_toolsets/notifications.py +33 -33
- agentpool_toolsets/openapi.py +3 -1
- agentpool_toolsets/search_toolset.py +3 -1
- agentpool-2.1.9.dist-info/RECORD +0 -474
- agentpool_config/resources.py +0 -33
- agentpool_server/acp_server/acp_tools.py +0 -43
- agentpool_server/acp_server/commands/spawn.py +0 -210
- agentpool_storage/text_log_provider.py +0 -275
- agentpool_toolsets/builtin/agent_management.py +0 -239
- agentpool_toolsets/builtin/chain.py +0 -288
- agentpool_toolsets/builtin/history.py +0 -36
- agentpool_toolsets/builtin/integration.py +0 -85
- agentpool_toolsets/builtin/tool_management.py +0 -90
- agentpool_toolsets/builtin/user_interaction.py +0 -52
- agentpool_toolsets/semantic_memory_toolset.py +0 -536
- {agentpool-2.1.9.dist-info → agentpool-2.5.0.dist-info}/entry_points.txt +0 -0
- {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
|